diff options
author | Benny Prijono <bennylp@teluu.com> | 2009-03-12 18:11:37 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2009-03-12 18:11:37 +0000 |
commit | 1dacdee696b7591a6dcc0b3c1d0f41573e473168 (patch) | |
tree | 302b09dcd989c0c05cf09f6aebaa63d870b421b9 /pjmedia/include | |
parent | ba9d8ca28eb209571c0bd6a080a8bb03d0fa2d33 (diff) |
(Major) Task #737 and #738: integration of APS-Direct and Audiodev from aps-direct branch to trunk.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2506 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia/include')
21 files changed, 2104 insertions, 130 deletions
diff --git a/pjmedia/include/pjmedia-audiodev/audiodev.h b/pjmedia/include/pjmedia-audiodev/audiodev.h new file mode 100644 index 00000000..8f2ab783 --- /dev/null +++ b/pjmedia/include/pjmedia-audiodev/audiodev.h @@ -0,0 +1,667 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_AUDIODEV_AUDIODEV_H__ +#define __PJMEDIA_AUDIODEV_AUDIODEV_H__ + +/** + * @file audiodev.h + * @brief Audio device API. + */ +#include <pjmedia-audiodev/config.h> +#include <pjmedia-audiodev/errno.h> +#include <pjmedia/types.h> +#include <pj/pool.h> + + +PJ_BEGIN_DECL + +/** + * @defgroup s2_audio_device_reference Audio Device API Reference + * @ingroup audio_device_api + * @brief API Reference + * @{ + */ + +/** + * Type for device index. + */ +typedef pj_int32_t pjmedia_aud_dev_index; + +/** + * Device index constants. + */ +enum +{ + /** + * Constant to denote default capture device + */ + PJMEDIA_AUD_DEFAULT_CAPTURE_DEV = -1, + + /** + * Constant to denote default playback device + */ + PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV = -2, + + /** + * Constant to denote invalid device index. + */ + PJMEDIA_AUD_INVALID_DEV = -3 +}; + + +/** + * This enumeration identifies various audio device capabilities. These audio + * capabilities indicates what features are supported by the underlying + * audio device implementation. + * + * Applications get these capabilities in the #pjmedia_aud_dev_info structure. + * + * Application can also set the specific features/capabilities when opening + * the audio stream by setting the \a flags member of #pjmedia_aud_param + * structure. + * + * Once audio stream is running, application can also retrieve or set some + * specific audio capability, by using #pjmedia_aud_stream_get_cap() and + * #pjmedia_aud_stream_set_cap() and specifying the desired capability. The + * value of the capability is specified as pointer, and application needs to + * supply the pointer with the correct value, according to the documentation + * of each of the capability. + */ +typedef enum pjmedia_aud_dev_cap +{ + /** + * Support for audio formats other than PCM. The value of this capability + * is represented by #pjmedia_format structure. + */ + PJMEDIA_AUD_DEV_CAP_EXT_FORMAT = 1, + + /** + * Support for audio input latency control or query. The value of this + * capability is an unsigned integer containing milliseconds value of + * the latency. + */ + PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY = 2, + + /** + * Support for audio output latency control or query. The value of this + * capability is an unsigned integer containing milliseconds value of + * the latency. + */ + PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY = 4, + + /** + * Support for setting/retrieving the audio input device volume level. + * The value of this capability is an unsigned integer representing + * the input audio volume setting in percent. + */ + PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING = 8, + + /** + * Support for setting/retrieving the audio output device volume level. + * The value of this capability is an unsigned integer representing + * the output audio volume setting in percent. + */ + PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING = 16, + + /** + * Support for monitoring the current audio input signal volume. + * The value of this capability is an unsigned integer representing + * the audio volume in percent. + */ + PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER = 32, + + /** + * Support for monitoring the current audio output signal volume. + * The value of this capability is an unsigned integer representing + * the audio volume in percent. + */ + PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER = 64, + + /** + * Support for audio input routing. The value of this capability is an + * integer containing #pjmedia_aud_dev_route enumeration. + */ + PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE = 128, + + /** + * Support for audio output routing (e.g. loudspeaker vs earpiece). The + * value of this capability is an integer containing #pjmedia_aud_dev_route + * enumeration. + */ + PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE = 256, + + /** + * The audio device has echo cancellation feature. The value of this + * capability is a pj_bool_t containing boolean PJ_TRUE or PJ_FALSE. + */ + PJMEDIA_AUD_DEV_CAP_EC = 512, + + /** + * The audio device supports setting echo cancellation fail length. The + * value of this capability is an unsigned integer representing the + * echo tail in milliseconds. + */ + PJMEDIA_AUD_DEV_CAP_EC_TAIL = 1024, + + /** + * The audio device has voice activity detection feature. The value + * of this capability is a pj_bool_t containing boolean PJ_TRUE or + * PJ_FALSE. + */ + PJMEDIA_AUD_DEV_CAP_VAD = 2048, + + /** + * The audio device has comfort noise generation feature. The value + * of this capability is a pj_bool_t containing boolean PJ_TRUE or + * PJ_FALSE. + */ + PJMEDIA_AUD_DEV_CAP_CNG = 4096, + + /** + * The audio device has packet loss concealment feature. The value + * of this capability is a pj_bool_t containing boolean PJ_TRUE or + * PJ_FALSE. + */ + PJMEDIA_AUD_DEV_CAP_PLC = 8192, + + /** + * End of capability + */ + PJMEDIA_AUD_DEV_CAP_MAX = 16384 + +} pjmedia_aud_dev_cap; + + +/** + * This enumeration describes audio routing setting. + */ +typedef enum pjmedia_aud_dev_route +{ + /** Default route. */ + PJMEDIA_AUD_DEV_ROUTE_DEFAULT = 0, + + /** Route to loudspeaker */ + PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER = 1, + + /** Route to earpiece */ + PJMEDIA_AUD_DEV_ROUTE_EARPIECE = 2 + +} pjmedia_aud_dev_route; + + +/** + * Device information structure returned by #pjmedia_aud_dev_get_info(). + */ +typedef struct pjmedia_aud_dev_info +{ + /** + * The device name + */ + char name[64]; + + /** + * Maximum number of input channels supported by this device. If the + * value is zero, the device does not support input operation (i.e. + * it is a playback only device). + */ + unsigned input_count; + + /** + * Maximum number of output channels supported by this device. If the + * value is zero, the device does not support output operation (i.e. + * it is an input only device). + */ + unsigned output_count; + + /** + * Default sampling rate. + */ + unsigned default_samples_per_sec; + + /** + * The underlying driver name + */ + char driver[32]; + + /** + * Device capabilities, as bitmask combination of #pjmedia_aud_dev_cap. + */ + unsigned caps; + + /** + * Supported audio device routes, as bitmask combination of + * #pjmedia_aud_dev_route. The value may be zero if the device + * does not support audio routing. + */ + unsigned routes; + + /** + * Number of audio formats supported by this device. The value may be + * zero if the device does not support non-PCM format. + */ + unsigned ext_fmt_cnt; + + /** + * Array of supported extended audio formats + */ + pjmedia_format ext_fmt[8]; + + +} pjmedia_aud_dev_info; + + +/** + * This callback is called by player stream when it needs additional data + * to be played by the device. Application must fill in the whole of output + * buffer with audio samples. + * + * The frame argument contains the following values: + * - timestamp Playback timestamp, in samples. + * - buf Buffer to be filled out by application. + * - size The size requested in bytes, which will be equal to + * the size of one whole packet. + * + * @param user_data User data associated with the stream. + * @param frame Audio frame, which buffer is to be filled in by + * the application. + * + * @return Returning non-PJ_SUCCESS will cause the audio stream + * to stop + */ +typedef pj_status_t (*pjmedia_aud_play_cb)(void *user_data, + pjmedia_frame *frame); + +/** + * This callback is called by recorder stream when it has captured the whole + * packet worth of audio samples. + * + * @param user_data User data associated with the stream. + * @param frame Captured frame. + * + * @return Returning non-PJ_SUCCESS will cause the audio stream + * to stop + */ +typedef pj_status_t (*pjmedia_aud_rec_cb)(void *user_data, + pjmedia_frame *frame); + +/** + * This structure specifies the parameters to open the audio stream. + */ +typedef struct pjmedia_aud_param +{ + /** + * The audio direction. This setting is mandatory. + */ + pjmedia_dir dir; + + /** + * The audio recorder device ID. This setting is mandatory if the audio + * direction includes input/capture direction. + */ + pjmedia_aud_dev_index rec_id; + + /** + * The audio playback device ID. This setting is mandatory if the audio + * direction includes output/playback direction. + */ + pjmedia_aud_dev_index play_id; + + /** + * Clock rate/sampling rate. This setting is mandatory. + */ + unsigned clock_rate; + + /** + * Number of channels. This setting is mandatory. + */ + unsigned channel_count; + + /** + * Number of samples per frame. This setting is mandatory. + */ + unsigned samples_per_frame; + + /** + * Number of bits per sample. This setting is mandatory. + */ + unsigned bits_per_sample; + + /** + * This flags specifies which of the optional settings are valid in this + * structure. The flags is bitmask combination of pjmedia_aud_dev_cap. + */ + unsigned flags; + + /** + * Set the audio format. This setting is optional, and will only be used + * if PJMEDIA_AUD_DEV_CAP_EXT_FORMAT is set in the flags. + */ + pjmedia_format ext_fmt; + + /** + * Input latency, in milliseconds. This setting is optional, and will + * only be used if PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY is set in the flags. + */ + unsigned input_latency_ms; + + /** + * Input latency, in milliseconds. This setting is optional, and will + * only be used if PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY is set in the flags. + */ + unsigned output_latency_ms; + + /** + * Input volume setting, in percent. This setting is optional, and will + * only be used if PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING is set in + * the flags. + */ + unsigned input_vol; + + /** + * Output volume setting, in percent. This setting is optional, and will + * only be used if PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING is set in + * the flags. + */ + unsigned output_vol; + + /** + * Set the audio input route. This setting is optional, and will only be + * used if PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE is set in the flags. + */ + pjmedia_aud_dev_route input_route; + + /** + * Set the audio output route. This setting is optional, and will only be + * used if PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE is set in the flags. + */ + pjmedia_aud_dev_route output_route; + + /** + * Enable/disable echo canceller, if the device supports it. This setting + * is optional, and will only be used if PJMEDIA_AUD_DEV_CAP_EC is set in + * the flags. + */ + pj_bool_t ec_enabled; + + /** + * Set echo canceller tail length in milliseconds, if the device supports + * it. This setting is optional, and will only be used if + * PJMEDIA_AUD_DEV_CAP_EC_TAIL is set in the flags. + */ + unsigned ec_tail_ms; + + /** + * Enable/disable PLC. This setting is optional, and will only be used + * if PJMEDIA_AUD_DEV_CAP_PLC is set in the flags. + */ + pj_bool_t plc_enabled; + + /** + * Enable/disable CNG. This setting is optional, and will only be used + * if PJMEDIA_AUD_DEV_CAP_CNG is set in the flags. + */ + pj_bool_t cng_enabled; + +} pjmedia_aud_param; + + +/** Forward declaration for pjmedia_aud_stream */ +typedef struct pjmedia_aud_stream pjmedia_aud_stream; + +/** Forward declaration for audio device factory */ +typedef struct pjmedia_aud_dev_factory pjmedia_aud_dev_factory; + +/** + * Get string info for the specified capability. + * + * @param cap The capability ID. + * @param p_desc Optional pointer which will be filled with longer + * description about the capability. + * + * @return Capability name. + */ +PJ_DECL(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, + const char **p_desc); + + +/** + * Set a capability field value in #pjmedia_aud_param structure. This will + * also set the flags field for the specified capability in the structure. + * + * @param param The structure. + * @param cap The audio capability which value is to be set. + * @param value Pointer to value. Please see the type of value to + * be supplied in the pjmedia_aud_dev_cap documentation. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_param_set_cap(pjmedia_aud_param *param, + pjmedia_aud_dev_cap cap, + const void *pval); + + +/** + * Get a capability field value from #pjmedia_aud_param structure. This + * function will return PJMEDIA_EAUD_INVCAP error if the flag for that + * capability is not set in the flags field in the structure. + * + * @param param The structure. + * @param cap The audio capability which value is to be retrieved. + * @param value Pointer to value. Please see the type of value to + * be supplied in the pjmedia_aud_dev_cap documentation. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_param_get_cap(const pjmedia_aud_param *param, + pjmedia_aud_dev_cap cap, + void *pval); + +/** + * Initialize the audio subsystem. This will register all supported audio + * device factories to the audio subsystem. This function may be called + * more than once, but each call to this function must have the + * corresponding #pjmedia_aud_subsys_shutdown() call. + * + * @param pf The pool factory. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_subsys_init(pj_pool_factory *pf); + + +/** + * Get the pool factory registered to the audio subsystem. + * + * @return The pool factory. + */ +PJ_DECL(pj_pool_factory*) pjmedia_aud_subsys_get_pool_factory(void); + + +/** + * Shutdown the audio subsystem. This will destroy all audio device factories + * registered in the audio subsystem. Note that currently opened audio streams + * may or may not be closed, depending on the implementation of the audio + * device factories. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_subsys_shutdown(void); + + +/** + * Get the number of sound devices installed in the system. + * + * @return The number of sound devices installed in the system. + */ +PJ_DECL(unsigned) pjmedia_aud_dev_count(void); + + +/** + * Get device information. + * + * @param id The audio device ID. + * @param info The device information which will be filled in by this + * function once it returns successfully. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, + pjmedia_aud_dev_info *info); + + +/** + * Lookup device index based on the driver and device name. + * + * @param drv_name The driver name. + * @param dev_name The device name. + * @param id Pointer to store the returned device ID. + * + * @return PJ_SUCCESS if the device can be found. + */ +PJ_DECL(pj_status_t) pjmedia_aud_dev_lookup(const char *drv_name, + const char *dev_name, + pjmedia_aud_dev_index *id); + + +/** + * Initialize the audio device parameters with default values for the + * specified device. + * + * @param id The audio device ID. + * @param param The audio device parameters which will be initialized + * by this function once it returns successfully. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, + pjmedia_aud_param *param); + + +/** + * Open audio stream object using the specified parameters. + * + * @param param Sound device parameters to be used for the stream. + * @param rec_cb Callback to be called on every input frame captured. + * @param play_cb Callback to be called everytime the sound device needs + * audio frames to be played back. + * @param user_data Arbitrary user data, which will be given back in the + * callbacks. + * @param p_strm Pointer to receive the audio stream. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *param, + pjmedia_aud_rec_cb rec_cb, + pjmedia_aud_play_cb play_cb, + void *user_data, + pjmedia_aud_stream **p_strm); + +/** + * Get the running parameters for the specified audio stream. + * + * @param strm The audio stream. + * @param param Audio stream parameters to be filled in by this + * function once it returns successfully. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, + pjmedia_aud_param *param); + +/** + * Get the value of a specific capability of the audio stream. + * + * @param strm The audio stream. + * @param cap The audio capability which value is to be retrieved. + * @param value Pointer to value to be filled in by this function + * once it returns successfully. Please see the type + * of value to be supplied in the pjmedia_aud_dev_cap + * documentation. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm, + pjmedia_aud_dev_cap cap, + void *value); + +/** + * Set the value of a specific capability of the audio stream. + * + * @param strm The audio stream. + * @param cap The audio capability which value is to be set. + * @param value Pointer to value. Please see the type of value to + * be supplied in the pjmedia_aud_dev_cap documentation. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm, + pjmedia_aud_dev_cap cap, + const void *value); + +/** + * Start the stream. + * + * @param strm The audio stream. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm); + +/** + * Stop the stream. + * + * @param strm The audio stream. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm); + +/** + * Destroy the stream. + * + * @param strm The audio stream. + * + * @return PJ_SUCCESS on successful operation or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm); + + +/** + * @} + */ + +PJ_END_DECL + + +#endif /* __PJMEDIA_AUDIODEV_AUDIODEV_H__ */ + diff --git a/pjmedia/include/pjmedia-audiodev/audiodev_imp.h b/pjmedia/include/pjmedia-audiodev/audiodev_imp.h new file mode 100644 index 00000000..e12c0f21 --- /dev/null +++ b/pjmedia/include/pjmedia-audiodev/audiodev_imp.h @@ -0,0 +1,181 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __AUDIODEV_IMP_H__ +#define __AUDIODEV_IMP_H__ + +#include <pjmedia-audiodev/audiodev.h> + +/** + * @defgroup s8_audio_device_implementors_api Audio Device Implementors API + * @ingroup audio_device_api + * @brief API for audio device implementors + * @{ + */ + +/** + * Sound device factory operations. + */ +typedef struct pjmedia_aud_dev_factory_op +{ + /** + * Initialize the audio device factory. + * + * @param f The audio device factory. + */ + pj_status_t (*init)(pjmedia_aud_dev_factory *f); + + /** + * Close this audio device factory and release all resources back to the + * operating system. + * + * @param f The audio device factory. + */ + pj_status_t (*destroy)(pjmedia_aud_dev_factory *f); + + /** + * Get the number of audio devices installed in the system. + * + * @param f The audio device factory. + */ + unsigned (*get_dev_count)(pjmedia_aud_dev_factory *f); + + /** + * Get the audio device information and capabilities. + * + * @param f The audio device factory. + * @param index Device index. + * @param info The audio device information structure which will be + * initialized by this function once it returns + * successfully. + */ + pj_status_t (*get_dev_info)(pjmedia_aud_dev_factory *f, + unsigned index, + pjmedia_aud_dev_info *info); + + /** + * Initialize the specified audio device parameter with the default + * values for the specified device. + * + * @param f The audio device factory. + * @param index Device index. + * @param param The audio device parameter. + */ + pj_status_t (*default_param)(pjmedia_aud_dev_factory *f, + unsigned index, + pjmedia_aud_param *param); + + /** + * Open the audio device and create audio stream. See + * #pjmedia_aud_stream_create() + */ + pj_status_t (*create_stream)(pjmedia_aud_dev_factory *f, + const pjmedia_aud_param *param, + pjmedia_aud_rec_cb rec_cb, + pjmedia_aud_play_cb play_cb, + void *user_data, + pjmedia_aud_stream **p_aud_strm); + +} pjmedia_aud_dev_factory_op; + + +/** + * This structure describes an audio device factory. + */ +struct pjmedia_aud_dev_factory +{ + /** Internal data to be initialized by audio subsystem. */ + struct { + /** Driver index */ + unsigned drv_idx; + } sys; + + /** Operations */ + pjmedia_aud_dev_factory_op *op; +}; + + +/** + * Sound stream operations. + */ +typedef struct pjmedia_aud_stream_op +{ + /** + * See #pjmedia_aud_stream_get_param() + */ + pj_status_t (*get_param)(pjmedia_aud_stream *strm, + pjmedia_aud_param *param); + + /** + * See #pjmedia_aud_stream_get_cap() + */ + pj_status_t (*get_cap)(pjmedia_aud_stream *strm, + pjmedia_aud_dev_cap cap, + void *value); + + /** + * See #pjmedia_aud_stream_set_cap() + */ + pj_status_t (*set_cap)(pjmedia_aud_stream *strm, + pjmedia_aud_dev_cap cap, + const void *value); + + /** + * See #pjmedia_aud_stream_start() + */ + pj_status_t (*start)(pjmedia_aud_stream *strm); + + /** + * See #pjmedia_aud_stream_stop(). + */ + pj_status_t (*stop)(pjmedia_aud_stream *strm); + + /** + * See #pjmedia_aud_stream_destroy(). + */ + pj_status_t (*destroy)(pjmedia_aud_stream *strm); + +} pjmedia_aud_stream_op; + + +/** + * This structure describes the audio device stream. + */ +struct pjmedia_aud_stream +{ + /** Internal data to be initialized by audio subsystem */ + struct { + /** Driver index */ + unsigned drv_idx; + } sys; + + /** Operations */ + pjmedia_aud_stream_op *op; +}; + + + + +/** + * @} + */ + + + +#endif /* __AUDIODEV_IMP_H__ */ diff --git a/pjmedia/include/pjmedia-audiodev/audiotest.h b/pjmedia/include/pjmedia-audiodev/audiotest.h new file mode 100644 index 00000000..8da3cc14 --- /dev/null +++ b/pjmedia/include/pjmedia-audiodev/audiotest.h @@ -0,0 +1,116 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_AUDIODEV_AUDIOTEST_H__ +#define __PJMEDIA_AUDIODEV_AUDIOTEST_H__ + +/** + * @file audiotest.h + * @brief Audio test utility. + */ +#include <pjmedia-audiodev/audiodev.h> + + +PJ_BEGIN_DECL + +/** + * @defgroup s30_audio_test_utility Audio tests utility. + * @ingroup audio_device_api + * @brief Audio test utility. + * @{ + */ + +/** + * Statistic for each direction. + */ +typedef struct pjmedia_aud_test_stat +{ + /** + * Number of frames processed during the test. + */ + unsigned frame_cnt; + + /** + * Minimum inter-frame arrival time, in milliseconds + */ + unsigned min_interval; + + /** + * Maximum inter-frame arrival time, in milliseconds + */ + unsigned max_interval; + + /** + * Average inter-frame arrival time, in milliseconds + */ + unsigned avg_interval; + + /** + * Standard deviation of inter-frame arrival time, in milliseconds + */ + unsigned dev_interval; + + /** + * Maximum number of frame burst + */ + unsigned max_burst; + +} pjmedia_aud_test_stat; + + +/** + * Test results. + */ +typedef struct pjmedia_aud_test_results +{ + /** + * Recording statistic. + */ + pjmedia_aud_test_stat rec; + + /** + * Playback statistic. + */ + pjmedia_aud_test_stat play; + + /** + * Clock drifts per second, in samples. Positive number indicates rec + * device is running faster than playback device. + */ + pj_int32_t rec_drift_per_sec; + +} pjmedia_aud_test_results; + + +/** + * Perform audio device testing. + */ +PJ_DECL(pj_status_t) pjmedia_aud_test(const pjmedia_aud_param *param, + pjmedia_aud_test_results *result); + +/** + * @} + */ + +PJ_END_DECL + + +#endif /* __PJMEDIA_AUDIODEV_AUDIOTEST_H__ */ + + diff --git a/pjmedia/include/pjmedia-audiodev/config.h b/pjmedia/include/pjmedia-audiodev/config.h new file mode 100644 index 00000000..b4603c15 --- /dev/null +++ b/pjmedia/include/pjmedia-audiodev/config.h @@ -0,0 +1,368 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_AUDIODEV_CONFIG_H__ +#define __PJMEDIA_AUDIODEV_CONFIG_H__ + +/** + * @file audiodev.h + * @brief Audio device API. + */ +#include <pjmedia/types.h> +#include <pj/pool.h> + + +PJ_BEGIN_DECL + +/** + * @defgroup audio_device_api Audio Device API + * @brief PJMEDIA audio device abstraction API. + */ + +/** + * @defgroup s1_audio_device_config Compile time configurations + * @ingroup audio_device_api + * @brief Compile time configurations + * @{ + */ + +/** + * This setting controls whether PortAudio support should be included. + */ +#ifndef PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO +# define PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 1 +#endif + + +/** + * This setting controls whether WMME support should be included. + */ +#ifndef PJMEDIA_AUDIO_DEV_HAS_WMME +# define PJMEDIA_AUDIO_DEV_HAS_WMME 1 +#endif + + +/** + * This setting controls whether Symbian APS support should be included. + */ +#ifndef PJMEDIA_AUDIO_DEV_HAS_SYMB_APS +# define PJMEDIA_AUDIO_DEV_HAS_SYMB_APS 0 +#endif + + +/** + * This setting controls whether Symbian audio (using built-in multimedia + * framework) support should be included. + */ +#ifndef PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA +# define PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA PJ_SYMBIAN +#endif + + +/** + * This setting controls whether the Audio Device API should support + * device implementation that is based on the old sound device API + * (sound.h). + * + * Enable this API if: + * - you have implemented your own sound device using the old sound + * device API (sound.h), and + * - you wish to be able to use your sound device implementation + * using the new Audio Device API. + * + * Please see http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more + * info. + */ +#ifndef PJMEDIA_AUDIO_DEV_HAS_LEGACY_DEVICE +# define PJMEDIA_AUDIO_DEV_HAS_LEGACY_DEVICE 0 +#endif + + +/** + * @} + */ + +PJ_END_DECL + + +#endif /* __PJMEDIA_AUDIODEV_CONFIG_H__ */ + +/* + --------------------- DOCUMENTATION FOLLOWS --------------------------- + */ + +/** + * @addtogroup audio_device_api Audio Device API + * @{ + +PJMEDIA Audio Device API is a cross-platform audio API appropriate for use with +VoIP applications and many other types of audio streaming applications. + +The API abstracts many different audio API's on various platforms, such as: + - PortAudio back-end for Win32, Windows Mobile, Linux, Unix, dan MacOS X. + - native WMME audio for Win32 and Windows Mobile devices + - native Symbian audio streaming/multimedia framework (MMF) implementation + - native Nokia Audio Proxy Server (APS) implementation + - null-audio implementation + - and more to be implemented in the future + +The Audio Device API/library is an evolution from PJMEDIA @ref PJMED_SND and +contains many enhancements: + + - Forward compatibility: +\n + The new API has been designed to be extensible, it will support new API's as + well as new features that may be introduced in the future without breaking + compatibility with applications that use this API as well as compatibility + with existing device implementations. + + - Device capabilities: +\n + At the heart of the API is device capabilities management, where all possible + audio capabilities of audio devices should be able to be handled in a generic + manner. With this framework, new capabilities that may be discovered in the + future can be handled in manner without breaking existing applications. + + - Built-in features: +\n + The device capabilities framework enables applications to use and control + audio features built-in in the device, such as: + - echo cancellation, + - built-in codecs, + - audio routing (e.g. to earpiece or loudspeaker), + - volume control, + - etc. + + - Codec support: +\n + Some audio devices such as Nokia/Symbian Audio Proxy Server (APS) and Nokia + VoIP Audio Services (VAS) support built-in hardware audio codecs (e.g. G.729, + iLBC, and AMR), and application can use the sound device in encoded mode to + make use of these hardware codecs. + + - Multiple backends: +\n + The new API supports multiple audio backends (called factories or drivers in + the code) to be active simultaneously, and audio backends may be added or + removed during run-time. + + +@section using Overview on using the API + +@subsection getting_started Getting started + + -# <b>Configure the application's project settings</b>.\n + Add the following + include: + \code + #include <pjmedia_audiodev.h>\endcode\n + And add <b>pjmedia-audiodev</b> library to your application link + specifications.\n + -# <b>Compile time settings</b>.\n + Use the compile time settings to enable or + disable specific audio drivers. For more information, please see + \ref s1_audio_device_config. + -# <b>API initialization and cleaning up</b>.\n + Before anything else, application must initialize the API by calling: + \code + pjmedia_aud_subsys_init(pf);\endcode\n + And add this in the application cleanup sequence + \code + pjmedia_aud_subsys_shutdown();\endcode + +@subsection devices Working with devices + + -# The following code prints the list of audio devices detected + in the system. + \code + int dev_count; + pjmedia_aud_dev_index dev_idx; + pj_status_t status; + + dev_count = pjmedia_aud_dev_count(); + printf("Got %d audio devices\n", dev_count); + + for (dev_idx=0; dev_idx<dev_count; ++i) { + pjmedia_aud_dev_info info; + + status = pjmedia_aud_dev_get_info(dev_idx, &info); + printf("%d. %s (in=%d, out=%d)\n", + dev_idx, info.name, + info.input_count, info.output_count); + } + \endcode\n + -# Info: The #PJMEDIA_AUD_DEFAULT_CAPTURE_DEV and #PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV + constants are used to denote default capture and playback devices + respectively. + -# Info: You may save the device and driver's name in your application + setting, for example to specify the prefered devices to be + used by your application. You can then retrieve the device index + for the device by calling: + \code + const char *drv_name = "WMME"; + const char *dev_name = "Wave mapper"; + pjmedia_aud_dev_index dev_idx; + + status = pjmedia_aud_dev_lookup(drv_name, dev_name, &dev_idx); + if (status==PJ_SUCCESS) + printf("Device index is %d\n", dev_idx); + \endcode + +@subsection caps Device capabilities + +Capabilities are encoded as #pjmedia_aud_dev_cap enumeration. Please see +#pjmedia_aud_dev_cap enumeration for more information. + + -# The following snippet prints the capabilities supported by the device: + \code + pjmedia_aud_dev_info info; + pj_status_t status; + + status = pjmedia_aud_dev_get_info(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, &info); + if (status == PJ_SUCCESS) { + unsigned i; + // Enumerate capability bits + printf("Device capabilities: "); + for (i=0; i<32; ++i) { + if (info.caps & (1 << i)) + printf("%s ", pjmedia_aud_dev_cap_name(1 << i, NULL)); + } + } + \endcode\n + -# Info: You can set the device settings when opening audio stream by setting + the flags and the appropriate setting in #pjmedia_aud_param when calling + #pjmedia_aud_stream_create()\n + -# Info: Once the audio stream is running, you can retrieve or change the stream + setting by specifying the capability in #pjmedia_aud_stream_get_cap() + and #pjmedia_aud_stream_set_cap() respectively. + + +@subsection creating_stream Creating audio streams + +The audio stream enables audio streaming to capture device, playback device, +or both. + + -# It is recommended to initialize the #pjmedia_aud_param with its default + values before using it: + \code + pjmedia_aud_param param; + pjmedia_aud_dev_index dev_idx; + pj_status_t status; + + dev_idx = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV; + status = pjmedia_aud_dev_default_param(dev_idx, ¶m); + \endcode\n + -# Configure the mandatory parameters: + \code + param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; + param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV; + param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; + param.clock_rate = 8000; + param.channel_count = 1; + param.samples_per_frame = 160; + param.bits_per_sample = 16; + \endcode\n + -# If you want the audio stream to use the device's built-in codec, specify + the codec in the #pjmedia_aud_param. You must make sure that the codec + is supported by the device, by looking at its supported format list in + the #pjmedia_aud_dev_info.\n + The snippet below sets the audio stream to use G.711 ULAW encoding: + \code + unsigned i; + + // Make sure Ulaw is supported + if ((info.caps & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) == 0) + error("Device does not support extended formats"); + for (i = 0; i < info.ext_fmt_cnt; ++i) { + if (info.ext_fmt[i].id == PJMEDIA_FORMAT_ULAW) + break; + } + if (i == info.ext_fmt_cnt) + error("Device does not support Ulaw format"); + + // Set Ulaw format + param.flags |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT; + param.ext_fmt.id = PJMEDIA_FORMAT_ULAW; + param.ext_fmt.bitrate = 64000; + param.ext_fmt.vad = PJ_FALSE; + \endcode\n + -# Note that if non-PCM format is configured on the audio stream, the + capture and/or playback functions (#pjmedia_aud_rec_cb and + #pjmedia_aud_play_cb respectively) will report the audio frame as + #pjmedia_frame_ext structure instead of the #pjmedia_frame. + -# Optionally configure other device's capabilities. The following snippet + shows how to enable echo cancellation on the device (note that this + snippet may not be necessary since the setting may have been enabled + when calling #pjmedia_aud_dev_default_param() above): + \code + if (info.caps & PJMEDIA_AUD_DEV_CAP_EC) { + param.flags |= PJMEDIA_AUD_DEV_CAP_EC; + param.ec_enabled = PJ_TRUE; + } + \endcode + -# Open the audio stream, specifying the capture and/or playback callback + functions: + \code + pjmedia_aud_stream *stream; + + status = pjmedia_aud_stream_create(¶m, &rec_cb, &play_cb, + user_data, &stream); + \endcode + +@subsection working_with_stream Working with audio streams + + -# To start the audio stream: + \code + status = pjmedia_aud_stream_start(stream); + \endcode\n + To stop the stream: + \code + status = pjmedia_aud_stream_stop(stream); + \endcode\n + And to destroy the stream: + \code + status = pjmedia_aud_stream_destroy(stream); + \endcode\n + -# Info: The following shows how to retrieve the capability value of the + stream (in this case, the current output volume setting). + \code + // Volume setting is an unsigned integer showing the level in percent. + unsigned vol; + status = pjmedia_aud_stream_get_cap(stream, + PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, + &vol); + \endcode + -# Info: And following shows how to modify the capability value of the + stream (in this case, the current output volume setting). + \code + // Volume setting is an unsigned integer showing the level in percent. + unsigned vol = 50; + status = pjmedia_aud_stream_set_cap(stream, + PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, + &vol); + \endcode + + +*/ + + +/** + * @} + */ + diff --git a/pjmedia/include/pjmedia-audiodev/errno.h b/pjmedia/include/pjmedia-audiodev/errno.h new file mode 100644 index 00000000..12830354 --- /dev/null +++ b/pjmedia/include/pjmedia-audiodev/errno.h @@ -0,0 +1,198 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_AUDIODEV_AUDIODEV_ERRNO_H__ +#define __PJMEDIA_AUDIODEV_AUDIODEV_ERRNO_H__ + +/** + * @file errno.h Error Codes + * @brief Audiodev specific error codes. + */ + +#include <pjmedia-audiodev/config.h> +#include <pj/errno.h> + +/** + * @defgroup error_codes Error Codes + * @ingroup audio_device_api + * @brief Audio devive library specific error codes. + * @{ + */ + + +PJ_BEGIN_DECL + + +/** + * Start of error code relative to PJ_ERRNO_START_USER. + * This value is 420000. + */ +#define PJMEDIA_AUDIODEV_ERRNO_START \ + (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*5) +#define PJMEDIA_AUDIODEV_ERRNO_END \ + (PJMEDIA_AUDIODEV_ERRNO_START + PJ_ERRNO_SPACE_SIZE - 1) + + +/** + * Mapping from PortAudio error codes to pjmedia error space. + */ +#define PJMEDIA_AUDIODEV_PORTAUDIO_ERRNO_START \ + (PJMEDIA_AUDIODEV_ERRNO_END-10000) +#define PJMEDIA_AUDIODEV_PORTAUDIO_ERRNO_END \ + (PJMEDIA_AUDIODEV_PORTAUDIO_ERRNO_START + 10000 -1) +/** + * Convert PortAudio error code to PJLIB error code. + * PortAudio error code range: 0 >= err >= -10000 + */ +#define PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err) \ + ((int)PJMEDIA_AUDIODEV_PORTAUDIO_ERRNO_START-err) + +/** + * Mapping from Windows multimedia WaveIn error codes. + */ +#define PJMEDIA_AUDIODEV_WMME_IN_ERROR_START \ + (PJMEDIA_AUDIODEV_ERRNO_START + 30000) +#define PJMEDIA_AUDIODEV_WMME_IN_ERROR_END \ + (PJMEDIA_AUDIODEV_WMME_IN_ERROR_START + 1000 - 1) +/** + * Convert WaveIn operation error codes to PJLIB error space. + */ +#define PJMEDIA_AUDIODEV_ERRNO_FROM_WMME_IN(err) \ + ((int)PJMEDIA_AUDIODEV_WMME_IN_ERROR_START+err) + + +/** + * Mapping from Windows multimedia WaveOut error codes. + */ +#define PJMEDIA_AUDIODEV_WMME_OUT_ERROR_START \ + (PJMEDIA_AUDIODEV_WMME_IN_ERROR_END + 1000) +#define PJMEDIA_AUDIODEV_WMME_OUT_ERROR_END \ + (PJMEDIA_AUDIODEV_WMME_OUT_ERROR_START + 1000) +/** + * Convert WaveOut operation error codes to PJLIB error space. + */ +#define PJMEDIA_AUDIODEV_ERRNO_FROM_WMME_OUT(err) \ + ((int)PJMEDIA_AUDIODEV_WMME_OUT_ERROR_START+err) + + +/************************************************************ + * Audio Device API error codes + ***********************************************************/ +/** + * @hideinitializer + * General/unknown error. + */ +#define PJMEDIA_EAUD_ERR (PJMEDIA_AUDIODEV_ERRNO_START+1) /* 420001 */ + +/** + * @hideinitializer + * Unknown error from audio driver + */ +#define PJMEDIA_EAUD_SYSERR (PJMEDIA_AUDIODEV_ERRNO_START+2) /* 420002 */ + +/** + * @hideinitializer + * Audio subsystem not initialized + */ +#define PJMEDIA_EAUD_INIT (PJMEDIA_AUDIODEV_ERRNO_START+3) /* 420003 */ + +/** + * @hideinitializer + * Invalid audio device + */ +#define PJMEDIA_EAUD_INVDEV (PJMEDIA_AUDIODEV_ERRNO_START+4) /* 420004 */ + +/** + * @hideinitializer + * Found no devices + */ +#define PJMEDIA_EAUD_NODEV (PJMEDIA_AUDIODEV_ERRNO_START+5) /* 420005 */ + +/** + * @hideinitializer + * Unable to find default device + */ +#define PJMEDIA_EAUD_NODEFDEV (PJMEDIA_AUDIODEV_ERRNO_START+6) /* 420006 */ + +/** + * @hideinitializer + * Device not ready + */ +#define PJMEDIA_EAUD_NOTREADY (PJMEDIA_AUDIODEV_ERRNO_START+7) /* 420007 */ + +/** + * @hideinitializer + * The audio capability is invalid or not supported + */ +#define PJMEDIA_EAUD_INVCAP (PJMEDIA_AUDIODEV_ERRNO_START+8) /* 420008 */ + +/** + * @hideinitializer + * The operation is invalid or not supported + */ +#define PJMEDIA_EAUD_INVOP (PJMEDIA_AUDIODEV_ERRNO_START+9) /* 420009 */ + +/** + * @hideinitializer + * Bad or invalid audio device format + */ +#define PJMEDIA_EAUD_BADFORMAT (PJMEDIA_AUDIODEV_ERRNO_START+10) /* 4200010 */ + +/** + * @hideinitializer + * Invalid audio device sample format + */ +#define PJMEDIA_EAUD_SAMPFORMAT (PJMEDIA_AUDIODEV_ERRNO_START+11) /* 4200011 */ + +/** + * @hideinitializer + * Bad latency setting + */ +#define PJMEDIA_EAUD_BADLATENCY (PJMEDIA_AUDIODEV_ERRNO_START+12) /* 4200012 */ + + + + + +/** + * Get error message for the specified error code. Note that this + * function is only able to decode PJMEDIA Audiodev specific error code. + * Application should use pj_strerror(), which should be able to + * decode all error codes belonging to all subsystems (e.g. pjlib, + * pjmedia, pjsip, etc). + * + * @param status The error code. + * @param buffer The buffer where to put the error message. + * @param bufsize Size of the buffer. + * + * @return The error message as NULL terminated string, + * wrapped with pj_str_t. + */ +PJ_DECL(pj_str_t) pjmedia_audiodev_strerror(pj_status_t status, char *buffer, + pj_size_t bufsize); + + +PJ_END_DECL + +/** + * @} + */ + + +#endif /* __PJMEDIA_AUDIODEV_AUDIODEV_ERRNO_H__ */ + diff --git a/pjmedia/include/pjmedia-codec.h b/pjmedia/include/pjmedia-codec.h index 3db581a6..8b7c3f64 100644 --- a/pjmedia/include/pjmedia-codec.h +++ b/pjmedia/include/pjmedia-codec.h @@ -31,6 +31,7 @@ #include <pjmedia-codec/ilbc.h> #include <pjmedia-codec/g722.h> #include <pjmedia-codec/ipp_codecs.h> +#include <pjmedia-codec/passthrough.h> #endif /* __PJMEDIA_CODEC_PJMEDIA_CODEC_H__ */ diff --git a/pjmedia/include/pjmedia-codec/amr_helper.h b/pjmedia/include/pjmedia-codec/amr_helper.h index cf900165..79d324af 100644 --- a/pjmedia/include/pjmedia-codec/amr_helper.h +++ b/pjmedia/include/pjmedia-codec/amr_helper.h @@ -632,7 +632,6 @@ typedef struct pjmedia_codec_amr_pack_setting { * * @return AMR mode. */ - PJ_INLINE(pj_int8_t) pjmedia_codec_amr_get_mode(unsigned bitrate) { pj_int8_t mode = -1; @@ -678,6 +677,35 @@ PJ_INLINE(pj_int8_t) pjmedia_codec_amr_get_mode(unsigned bitrate) } /** + * Get AMR mode based on frame length. + * + * @param amrnb Set to PJ_TRUE for AMR-NB domain or PJ_FALSE for AMR-WB. + * @param frame_len The frame length. + * + * @return AMR mode. + */ + +PJ_INLINE(pj_int8_t) pjmedia_codec_amr_get_mode2(pj_bool_t amrnb, + unsigned frame_len) +{ + int i; + + if (amrnb) { + for (i = 0; i < 9; ++i) + if (frame_len == pjmedia_codec_amrnb_framelen[i]) + return (pj_int8_t)i; + } else { + for (i = 0; i < 10; ++i) { + if (frame_len == pjmedia_codec_amrwb_framelen[i]) + return (pj_int8_t)i; + } + } + + pj_assert(!"Invalid AMR frame length"); + return -1; +} + +/** * Prepare a frame before pass it to decoder. This function will do: * - reorder AMR bitstream from descending sensitivity order into * encoder bits order. This can be enabled/disabled via param @@ -794,7 +822,6 @@ PJ_INLINE(pj_status_t) pjmedia_codec_amr_predecode( out_info->mode = FT_; out->size = 5; - PJ_ASSERT_RETURN(out->size <= in->size, PJMEDIA_CODEC_EFRMINLEN); pj_bzero(out->buf, out->size); for(i = 0; i < framelenbit_tbl[SID_FT]; ++i) { diff --git a/pjmedia/include/pjmedia-codec/config.h b/pjmedia/include/pjmedia-codec/config.h index e50185d1..49ac3214 100644 --- a/pjmedia/include/pjmedia-codec/config.h +++ b/pjmedia/include/pjmedia-codec/config.h @@ -194,5 +194,35 @@ # define PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1 1 #endif +/** + * Enable Passthrough codecs. + * + * Default: 0 + */ +#ifndef PJMEDIA_HAS_PASSTHROUGH_CODECS +# define PJMEDIA_HAS_PASSTHROUGH_CODECS 0 +#endif + +#ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR +# define PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR 1 +#endif + +#ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_G729 +# define PJMEDIA_HAS_PASSTHROUGH_CODEC_G729 1 +#endif + +#ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC +# define PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC 1 +#endif + +#ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU +# define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU 1 +# undef PJMEDIA_HAS_G711_CODEC +#endif + +#ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA +# define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA 1 +# undef PJMEDIA_HAS_G711_CODEC +#endif #endif /* __PJMEDIA_CODEC_CONFIG_H__ */ diff --git a/pjmedia/include/pjmedia-codec/passthrough.h b/pjmedia/include/pjmedia-codec/passthrough.h new file mode 100644 index 00000000..0705690a --- /dev/null +++ b/pjmedia/include/pjmedia-codec/passthrough.h @@ -0,0 +1,78 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_CODECS_PASSTHROUGH_H__ +#define __PJMEDIA_CODECS_PASSTHROUGH_H__ + +/** + * @file pjmedia-codec/passthrough.h + * @brief Passthrough codecs. + */ + +#include <pjmedia-codec/types.h> + +/** + * @defgroup PJMED_PASSTHROUGH_CODEC Passthrough Codecs + * @ingroup PJMEDIA_CODEC + * @brief Implementation of passthrough codecs + * @{ + * + * This section describes functions to register and register passthrough + * codecs factory to the codec manager. After the codec factory has been + * registered, application can use @ref PJMEDIA_CODEC API to manipulate + * the codec. This codec factory contains various codecs, e.g: G.729, iLBC, + * AMR, and G.711. + * + * Passthrough codecs are codecs wrapper that does not perform encoding + * or decoding, it just pack and parse encoded audio data from/into RTP + * payload. This will accomodate pjmedia ports which work with encoded + * audio data, e.g: encoded audio files, sound device with capability + * of playing/recording encoded audio data. + */ + +PJ_BEGIN_DECL + +/** + * Initialize and register passthrough codecs factory to pjmedia endpoint. + * + * @param endpt The pjmedia endpoint. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_passthrough_init( pjmedia_endpt *endpt ); + + + +/** + * Unregister passthrough codecs factory from pjmedia endpoint. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_passthrough_deinit(void); + + +PJ_END_DECL + + +/** + * @} + */ + +#endif /* __PJMEDIA_CODECS_PASSTHROUGH_H__ */ + diff --git a/pjmedia/include/pjmedia/alaw_ulaw.h b/pjmedia/include/pjmedia/alaw_ulaw.h index 3b97ad3d..a6aae811 100644 --- a/pjmedia/include/pjmedia/alaw_ulaw.h +++ b/pjmedia/include/pjmedia/alaw_ulaw.h @@ -144,12 +144,12 @@ PJ_DECL(unsigned char) pjmedia_ulaw2alaw(unsigned char uval); * * @param dst Destination buffer for 8-bit U-Law data. * @param src Source, 16-bit linear PCM data. - * @param len Number of samples. + * @param count Number of samples. */ PJ_INLINE(void) pjmedia_ulaw_encode(pj_uint8_t *dst, const pj_int16_t *src, - pj_size_t len) + pj_size_t count) { - const pj_int16_t *end = src + len; + const pj_int16_t *end = src + count; while (src < end) { *dst++ = pjmedia_linear2ulaw(*src++); @@ -161,12 +161,12 @@ PJ_INLINE(void) pjmedia_ulaw_encode(pj_uint8_t *dst, const pj_int16_t *src, * * @param dst Destination buffer for 8-bit A-Law data. * @param src Source, 16-bit linear PCM data. - * @param len Number of samples. + * @param count Number of samples. */ PJ_INLINE(void) pjmedia_alaw_encode(pj_uint8_t *dst, const pj_int16_t *src, - pj_size_t len) + pj_size_t count) { - const pj_int16_t *end = src + len; + const pj_int16_t *end = src + count; while (src < end) { *dst++ = pjmedia_linear2alaw(*src++); @@ -178,7 +178,7 @@ PJ_INLINE(void) pjmedia_alaw_encode(pj_uint8_t *dst, const pj_int16_t *src, * * @param dst Destination buffer for 16-bit PCM data. * @param src Source, 8-bit U-Law data. - * @param len Number of samples. + * @param len Encoded frame/source length in bytes. */ PJ_INLINE(void) pjmedia_ulaw_decode(pj_int16_t *dst, const pj_uint8_t *src, pj_size_t len) @@ -195,7 +195,7 @@ PJ_INLINE(void) pjmedia_ulaw_decode(pj_int16_t *dst, const pj_uint8_t *src, * * @param dst Destination buffer for 16-bit PCM data. * @param src Source, 8-bit A-Law data. - * @param len Number of samples. + * @param len Encoded frame/source length in bytes. */ PJ_INLINE(void) pjmedia_alaw_decode(pj_int16_t *dst, const pj_uint8_t *src, pj_size_t len) diff --git a/pjmedia/include/pjmedia/codec.h b/pjmedia/include/pjmedia/codec.h index 199e3989..dcaae626 100644 --- a/pjmedia/include/pjmedia/codec.h +++ b/pjmedia/include/pjmedia/codec.h @@ -275,6 +275,9 @@ typedef struct pjmedia_codec_param equal to decoder ptime. */ pj_uint8_t pcm_bits_per_sample; /**< Bits/sample in the PCM side */ pj_uint8_t pt; /**< Payload type. */ + pjmedia_format_id fmt_id; /**< Source format, it's format of + encoder input and decoder + output. */ } info; /** diff --git a/pjmedia/include/pjmedia/conference.h b/pjmedia/include/pjmedia/conference.h index bc14c543..584e56ce 100644 --- a/pjmedia/include/pjmedia/conference.h +++ b/pjmedia/include/pjmedia/conference.h @@ -43,6 +43,18 @@ PJ_BEGIN_DECL +/** + * The conference bridge signature in pjmedia_port_info. + */ +#define PJMEDIA_CONF_BRIDGE_SIGNATURE \ + PJMEDIA_PORT_SIGNATURE('C', 'O', 'N', 'F') + +/** + * The audio switchboard signature in pjmedia_port_info. + */ +#define PJMEDIA_CONF_SWITCH_SIGNATURE \ + PJMEDIA_PORT_SIGNATURE('A', 'S', 'W', 'I') + /** * Opaque type for conference bridge. @@ -56,10 +68,12 @@ typedef struct pjmedia_conf_port_info { unsigned slot; /**< Slot number. */ pj_str_t name; /**< Port name. */ + pjmedia_format format; /**< Format. */ pjmedia_port_op tx_setting; /**< Transmit settings. */ pjmedia_port_op rx_setting; /**< Receive settings. */ unsigned listener_cnt; /**< Number of listeners. */ unsigned *listener_slots; /**< Array of listeners. */ + unsigned transmitter_cnt; /**< Number of transmitter. */ unsigned clock_rate; /**< Clock rate of the port. */ unsigned channel_count; /**< Number of channels. */ unsigned samples_per_frame; /**< Samples per frame */ diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index 735192ef..9a3eea9b 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -44,79 +44,69 @@ # include <pjmedia/config_auto.h> #endif +/** + * Specify whether we prefer to use audio switch board rather than + * conference bridge. + * + * Audio switch board is a kind of simplified version of conference + * bridge, but not really the subset of conference bridge. It has + * stricter rules on audio routing among the pjmedia ports and has + * no audio mixing capability. The power of it is it could work with + * encoded audio frames where conference brigde couldn't. + * + * Default: 0 + */ +#ifndef PJMEDIA_CONF_USE_SWITCH_BOARD +# define PJMEDIA_CONF_USE_SWITCH_BOARD 0 +#endif + /* * Types of sound stream backends. */ -/** Constant for NULL sound backend. */ -#define PJMEDIA_SOUND_NULL_SOUND 0 - -/** Constant for PortAudio sound backend. */ -#define PJMEDIA_SOUND_PORTAUDIO_SOUND 1 - -/** Constant for Win32 DirectSound sound backend. */ -#define PJMEDIA_SOUND_WIN32_DIRECT_SOUND 2 - -/** Constant for Win32 MME sound backend. */ -#define PJMEDIA_SOUND_WIN32_MME_SOUND 3 - -/** When this is set, pjmedia will not provide any sound device backend. - * Application will have to provide its own sound device backend - * and link the application with it. +/** + * This macro has been deprecated in releasee 1.1. Please see + * http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more information. */ -#define PJMEDIA_SOUND_EXTERNAL 255 - +#if defined(PJMEDIA_SOUND_IMPLEMENTATION) +# error PJMEDIA_SOUND_IMPLEMENTATION has been deprecated +#endif /** - * Unless specified otherwise, sound device uses PortAudio implementation - * by default. + * This macro has been deprecated in releasee 1.1. Please see + * http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more information. */ -#ifndef PJMEDIA_SOUND_IMPLEMENTATION -# if defined(PJ_WIN32) && PJ_WIN32!=0 -/*# define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_WIN32_DIRECT_SOUND*/ -/*# define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_WIN32_MME_SOUND*/ -# define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_PORTAUDIO_SOUND -# else -# define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_PORTAUDIO_SOUND -# endif +#if defined(PJMEDIA_PREFER_DIRECT_SOUND) +# error PJMEDIA_PREFER_DIRECT_SOUND has been deprecated #endif - /** - * Specify whether we prefer to use DirectSound on Windows. + * This macro controls whether the legacy sound device API is to be + * implemented, for applications that still use the old sound device + * API (sound.h). If this macro is set to non-zero, the sound_legacy.c + * will be included in the compilation. The sound_legacy.c is an + * implementation of old sound device (sound.h) using the new Audio + * Device API. * - * Default: 0 + * Please see http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more + * info. */ -#ifndef PJMEDIA_PREFER_DIRECT_SOUND -# define PJMEDIA_PREFER_DIRECT_SOUND 0 +#ifndef PJMEDIA_HAS_LEGACY_SOUND_API +# define PJMEDIA_HAS_LEGACY_SOUND_API 1 #endif - /** - * Specify sound device latency default, in milisecond. + * Specify default sound device latency, in milisecond. */ #ifndef PJMEDIA_SND_DEFAULT_REC_LATENCY # define PJMEDIA_SND_DEFAULT_REC_LATENCY 100 #endif -#ifndef PJMEDIA_SND_DEFAULT_PLAY_LATENCY -# define PJMEDIA_SND_DEFAULT_PLAY_LATENCY 100 -#endif - - /** - * Specify whether delay buffer is used for sound device. - * When delay buffer is enabled, the sound device callback - * will be called one after another evenly. - * The delay buffer also performs the best delay calculation - * for the sound device, and will try to limit the delay caused - * by uneven callback calls to this delay. - * - * When this setting is enabled, the PJMEDIA_SOUND_BUFFER_COUNT - * macro will specify the maximum size of the delay buffer. + * Specify default sound device latency, in milisecond. */ -#ifndef PJMEDIA_SOUND_USE_DELAYBUF -# define PJMEDIA_SOUND_USE_DELAYBUF 0 +#ifndef PJMEDIA_SND_DEFAULT_PLAY_LATENCY +# define PJMEDIA_SND_DEFAULT_PLAY_LATENCY 100 #endif @@ -285,7 +275,7 @@ * Default file player/writer buffer size. */ #ifndef PJMEDIA_FILE_PORT_BUFSIZE -# define PJMEDIA_FILE_PORT_BUFSIZE 4000 +# define PJMEDIA_FILE_PORT_BUFSIZE 4000 #endif diff --git a/pjmedia/include/pjmedia/endpoint.h b/pjmedia/include/pjmedia/endpoint.h index 0d8dd39d..2cc386f5 100644 --- a/pjmedia/include/pjmedia/endpoint.h +++ b/pjmedia/include/pjmedia/endpoint.h @@ -37,7 +37,6 @@ * to create a media session (#pjmedia_session_create()). */ -#include <pjmedia/sound.h> #include <pjmedia/codec.h> #include <pjmedia/sdp.h> diff --git a/pjmedia/include/pjmedia/port.h b/pjmedia/include/pjmedia/port.h index 9d7c86c6..447c429d 100644 --- a/pjmedia/include/pjmedia/port.h +++ b/pjmedia/include/pjmedia/port.h @@ -25,6 +25,7 @@ * @brief Port interface declaration */ #include <pjmedia/types.h> +#include <pj/assert.h> #include <pj/os.h> @@ -211,6 +212,7 @@ typedef struct pjmedia_port_info pj_bool_t has_info; /**< Has info? */ pj_bool_t need_info; /**< Need info on connect? */ unsigned pt; /**< Payload type (can be dynamic). */ + pjmedia_format format; /**< Format. */ pj_str_t encoding_name; /**< Encoding name. */ unsigned clock_rate; /**< Sampling rate. */ unsigned channel_count; /**< Number of channels. */ @@ -220,34 +222,6 @@ typedef struct pjmedia_port_info } pjmedia_port_info; -/** - * Types of media frame. - */ -typedef enum pjmedia_frame_type -{ - PJMEDIA_FRAME_TYPE_NONE, /**< No frame. */ - PJMEDIA_FRAME_TYPE_AUDIO /**< Normal audio frame. */ - -} pjmedia_frame_type; - - -/** - * This structure describes a media frame. - */ -typedef struct pjmedia_frame -{ - pjmedia_frame_type type; /**< Frame type. */ - void *buf; /**< Pointer to buffer. */ - pj_size_t size; /**< Frame size in bytes. */ - pj_timestamp timestamp; /**< Frame timestamp. */ - pj_uint32_t bit_info; /**< Bit info of the frame, sample case: - a frame may not exactly start and end - at the octet boundary, so this field - may be used for specifying start & - end bit offset. */ -} pjmedia_frame; - - /** * Port interface. */ diff --git a/pjmedia/include/pjmedia/sound.h b/pjmedia/include/pjmedia/sound.h index 962bfe96..dca9905b 100644 --- a/pjmedia/include/pjmedia/sound.h +++ b/pjmedia/include/pjmedia/sound.h @@ -23,10 +23,11 @@ /** * @file sound.h - * @brief Sound player and recorder device framework. + * @brief Legacy sound device API */ +#include <pjmedia-audiodev/audiodev.h> #include <pjmedia/types.h> -#include <pj/pool.h> + PJ_BEGIN_DECL @@ -36,6 +37,11 @@ PJ_BEGIN_DECL * @brief PJMEDIA abstraction for sound device hardware * @{ * + * <strong>Warning: this sound device API has been deprecated + * and replaced by PJMEDIA Audio Device API. Please see + * http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more + * information.</strong> + * * This section describes lower level abstraction for sound device * hardware. Application normally uses the higher layer @ref * PJMED_SND_PORT abstraction since it works seamlessly with @@ -61,7 +67,7 @@ PJ_BEGIN_DECL * frames from/to the sound device. */ -/** Opaque data type for audio stream. */ +/** Opaque declaration for pjmedia_snd_stream. */ typedef struct pjmedia_snd_stream pjmedia_snd_stream; /** @@ -92,7 +98,6 @@ typedef struct pjmedia_snd_stream_info unsigned play_latency; /**< Playback latency, in samples. */ } pjmedia_snd_stream_info; - /** * This callback is called by player stream when it needs additional data * to be played by the device. Application must fill in the whole of output diff --git a/pjmedia/include/pjmedia/sound_port.h b/pjmedia/include/pjmedia/sound_port.h index a41357c8..7293a4d7 100644 --- a/pjmedia/include/pjmedia/sound_port.h +++ b/pjmedia/include/pjmedia/sound_port.h @@ -24,7 +24,7 @@ * @file sound_port.h * @brief Media port connection abstraction to sound device. */ -#include <pjmedia/sound.h> +#include <pjmedia-audiodev/audiodev.h> #include <pjmedia/port.h> PJ_BEGIN_DECL @@ -159,7 +159,22 @@ PJ_DECL(pj_status_t) pjmedia_snd_port_create_player(pj_pool_t *pool, unsigned bits_per_sample, unsigned options, pjmedia_snd_port **p_port); - + + +/** + * Create sound device port according to the specified parameters. + * + * @param pool Pool to allocate sound port structure. + * @param prm Sound device settings. + * @param p_port Pointer to receive the sound device port instance. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, + const pjmedia_aud_param *prm, + pjmedia_snd_port **p_port); + /** * Destroy sound device port. @@ -179,19 +194,23 @@ PJ_DECL(pj_status_t) pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port); * * @return The sound stream instance. */ -PJ_DECL(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream( +PJ_DECL(pjmedia_aud_stream*) pjmedia_snd_port_get_snd_stream( pjmedia_snd_port *snd_port); /** - * Configure the echo cancellation tail length. By default, echo canceller - * is enabled in the sound device with the default tail length. After the - * sound port is created, application can query the current echo canceller - * tail length by calling #pjmedia_snd_port_get_ec_tail. + * Change the echo cancellation settings. The echo cancellation settings + * should have been specified when this sound port was created, by setting + * the appropriate fields in the pjmedia_aud_param, because not all sound + * device implementation supports changing the EC setting once the device + * has been opened. * - * Note that you should only change the EC settings when the sound port - * is not connected to any downstream ports, otherwise race condition may - * occur. + * The behavior of this function depends on whether device or software AEC + * is being used. If the device supports AEC, this function will forward + * the change request to the device and it will be up to the device whether + * to support the request. If software AEC is being used (the software EC + * will be used if the device does not support AEC), this function will + * change the software EC settings. * * @param snd_port The sound device port. * @param pool Pool to re-create the echo canceller if necessary. @@ -199,6 +218,7 @@ PJ_DECL(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream( * miliseconds. If zero is specified, the EC would * be disabled. * @param options The options to be passed to #pjmedia_echo_create(). + * This is only used if software EC is being used. * * @return PJ_SUCCESS on success. */ diff --git a/pjmedia/include/pjmedia/stream.h b/pjmedia/include/pjmedia/stream.h index cf5ef47f..0227f645 100644 --- a/pjmedia/include/pjmedia/stream.h +++ b/pjmedia/include/pjmedia/stream.h @@ -26,7 +26,6 @@ * @brief Media Stream. */ -#include <pjmedia/sound.h> #include <pjmedia/codec.h> #include <pjmedia/endpoint.h> #include <pjmedia/port.h> diff --git a/pjmedia/include/pjmedia/symbian_sound_aps.h b/pjmedia/include/pjmedia/symbian_sound_aps.h index 3208b416..bd9e0439 100644 --- a/pjmedia/include/pjmedia/symbian_sound_aps.h +++ b/pjmedia/include/pjmedia/symbian_sound_aps.h @@ -31,21 +31,16 @@ PJ_BEGIN_DECL /** - * Activate/deactivate loudspeaker, when loudspeaker is inactive, audio - * will be routed to earpiece. + * Set audio routing for APS sound device. * * @param stream The sound device stream, the stream should be started - * before calling this function. This param can be NULL - * to set the behaviour of next opened stream. - * @param active Specify PJ_TRUE to activate loudspeaker, and PJ_FALSE - * otherwise. + * before calling this function. + * @param route Audio routing to be set. * * @return PJ_SUCCESS on success. */ -PJ_DECL(pj_status_t) pjmedia_snd_aps_activate_loudspeaker( - pjmedia_snd_stream *stream, - pj_bool_t active); - +PJ_DECL(pj_status_t) pjmedia_snd_aps_set_route( pjmedia_snd_stream *stream, + pjmedia_snd_route route); PJ_END_DECL diff --git a/pjmedia/include/pjmedia/types.h b/pjmedia/include/pjmedia/types.h index e456e34e..a4c71743 100644 --- a/pjmedia/include/pjmedia/types.h +++ b/pjmedia/include/pjmedia/types.h @@ -47,8 +47,8 @@ * @{ */ -/** - * Top most media type. +/** + * Top most media type. */ typedef enum pjmedia_type { @@ -61,7 +61,7 @@ typedef enum pjmedia_type /** The media is video. */ PJMEDIA_TYPE_VIDEO = 2, - /** Unknown media type, in this case the name will be specified in + /** Unknown media type, in this case the name will be specified in * encoding_name. */ PJMEDIA_TYPE_UNKNOWN = 3, @@ -72,8 +72,8 @@ typedef enum pjmedia_type } pjmedia_type; -/** - * Media transport protocol. +/** + * Media transport protocol. */ typedef enum pjmedia_tp_proto { @@ -92,8 +92,8 @@ typedef enum pjmedia_tp_proto } pjmedia_tp_proto; -/** - * Media direction. +/** + * Media direction. */ typedef enum pjmedia_dir { @@ -138,8 +138,8 @@ typedef enum pjmedia_dir (a<<24 | b<<16 | c<<8 | d) -/** - * Opague declaration of media endpoint. +/** + * Opaque declaration of media endpoint. */ typedef struct pjmedia_endpt pjmedia_endpt; @@ -150,7 +150,7 @@ typedef struct pjmedia_endpt pjmedia_endpt; typedef struct pjmedia_stream pjmedia_stream; -/** +/** * Media socket info is used to describe the underlying sockets * to be used as media transport. */ @@ -180,8 +180,84 @@ typedef struct pjmedia_sock_info /** + * Macro for packing format. + */ +#define PJMEDIA_FORMAT_PACK(C1, C2, C3, C4) ( C4<<24 | C3<<16 | C2<<8 | C1 ) + +/** + * This enumeration describes format ID. + */ +typedef enum pjmedia_format_id +{ + /** + * 16bit linear + */ + PJMEDIA_FORMAT_L16 = 0, + + /** + * Alias for PJMEDIA_FORMAT_L16 + */ + PJMEDIA_FORMAT_PCM = PJMEDIA_FORMAT_L16, + + /** + * G.711 ALAW + */ + PJMEDIA_FORMAT_PCMA = PJMEDIA_FORMAT_PACK('A', 'L', 'A', 'W'), + + /** + * Alias for PJMEDIA_FORMAT_PCMA + */ + PJMEDIA_FORMAT_ALAW = PJMEDIA_FORMAT_PCMA, + + /** + * G.711 ULAW + */ + PJMEDIA_FORMAT_PCMU = PJMEDIA_FORMAT_PACK('u', 'L', 'A', 'W'), + + /** + * Aliaw for PJMEDIA_FORMAT_PCMU + */ + PJMEDIA_FORMAT_ULAW = PJMEDIA_FORMAT_PCMU, + + /** + * AMR narrowband + */ + PJMEDIA_FORMAT_AMR = PJMEDIA_FORMAT_PACK(' ', 'A', 'M', 'R'), + + /** + * ITU G.729 + */ + PJMEDIA_FORMAT_G729 = PJMEDIA_FORMAT_PACK('G', '7', '2', '9'), + + /** + * Internet Low Bit-Rate Codec (ILBC) + */ + PJMEDIA_FORMAT_ILBC = PJMEDIA_FORMAT_PACK('I', 'L', 'B', 'C') + +} pjmedia_format_id; + + +/** + * Media format information. + */ +typedef struct pjmedia_format +{ + /** Format ID */ + pjmedia_format_id id; + + /** Bitrate. */ + pj_uint32_t bitrate; + + /** Flag to indicate whether VAD is enabled */ + pj_bool_t vad; + +} pjmedia_format; + + + +/** * This is a general purpose function set PCM samples to zero. - * Since this function is needed by many parts of the library, + * Since this function is needed by many parts of the library, * by putting this functionality in one place, it enables some. * clever people to optimize this function. * @@ -205,7 +281,7 @@ PJ_INLINE(void) pjmedia_zero_samples(pj_int16_t *samples, unsigned count) /** * This is a general purpose function to copy samples from/to buffers with - * equal size. Since this function is needed by many parts of the library, + * equal size. Since this function is needed by many parts of the library, * by putting this functionality in one place, it enables some. * clever people to optimize this function. */ @@ -220,7 +296,7 @@ PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src, #else unsigned i; count >>= 1; - for (i=0; i<count; ++i) + for (i=0; i<count; ++i) ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i]; #endif } @@ -228,7 +304,7 @@ PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src, /** * This is a general purpose function to copy samples from/to buffers with - * equal size. Since this function is needed by many parts of the library, + * equal size. Since this function is needed by many parts of the library, * by putting this functionality in one place, it enables some. * clever people to optimize this function. */ @@ -243,11 +319,211 @@ PJ_INLINE(void) pjmedia_move_samples(pj_int16_t *dst, const pj_int16_t *src, #else unsigned i; count >>= 1; - for (i=0; i<count; ++i) + for (i=0; i<count; ++i) ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i]; #endif } +/** + * Types of media frame. + */ +typedef enum pjmedia_frame_type +{ + PJMEDIA_FRAME_TYPE_NONE, /**< No frame. */ + PJMEDIA_FRAME_TYPE_AUDIO, /**< Normal audio frame. */ + PJMEDIA_FRAME_TYPE_EXTENDED /**< Extended audio frame. */ + +} pjmedia_frame_type; + + +/** + * This structure describes a media frame. + */ +typedef struct pjmedia_frame +{ + pjmedia_frame_type type; /**< Frame type. */ + void *buf; /**< Pointer to buffer. */ + pj_size_t size; /**< Frame size in bytes. */ + pj_timestamp timestamp; /**< Frame timestamp. */ + pj_uint32_t bit_info; /**< Bit info of the frame, sample case: + a frame may not exactly start and end + at the octet boundary, so this field + may be used for specifying start & + end bit offset. */ +} pjmedia_frame; + + +/** + * The pjmedia_frame_ext is used to carry a more complex audio frames than + * the typical PCM audio frames, and it is signaled by setting the "type" + * field of a pjmedia_frame to PJMEDIA_FRAME_TYPE_EXTENDED. With this set, + * application may typecast pjmedia_frame to pjmedia_frame_ext. + * + * This structure may contain more than one audio frames, which subsequently + * will be called subframes in this structure. The subframes section + * immediately follows the end of this structure, and each subframe is + * represented by pjmedia_frame_ext_subframe structure. Every next + * subframe immediately follows the previous subframe, and all subframes + * are byte-aligned although its payload may not be byte-aligned. + */ + +#pragma pack(1) +typedef struct pjmedia_frame_ext { + pjmedia_frame base; /**< Base frame info */ + pj_uint16_t samples_cnt; /**< Number of samples in this frame */ + pj_uint16_t subframe_cnt; /**< Number of (sub)frames in this frame */ + + /* Zero or more (sub)frames follows immediately after this, + * each will be represented by pjmedia_frame_ext_subframe + */ +} pjmedia_frame_ext; +#pragma pack() + +/** + * This structure represents the individual subframes in the + * pjmedia_frame_ext structure. + */ +#pragma pack(1) +typedef struct pjmedia_frame_ext_subframe { + pj_uint16_t bitlen; /**< Number of bits in the data */ + pj_uint8_t data[1]; /**< Start of encoded data */ +} pjmedia_frame_ext_subframe; + +#pragma pack() + + +/** + * Append one subframe to #pjmedia_frame_ext. + * + * @param frm The #pjmedia_frame_ext. + * @param src Subframe data. + * @param bitlen Lenght of subframe, in bits. + * @param samples_cnt Number of audio samples in subframe. + */ +PJ_INLINE(void) pjmedia_frame_ext_append_subframe(pjmedia_frame_ext *frm, + const void *src, + unsigned bitlen, + unsigned samples_cnt) +{ + pjmedia_frame_ext_subframe *fsub; + pj_uint8_t *p; + unsigned i; + + p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext); + for (i = 0; i < frm->subframe_cnt; ++i) { + fsub = (pjmedia_frame_ext_subframe*) p; + p += sizeof(fsub->bitlen) + ((fsub->bitlen+7) >> 3); + } + + fsub = (pjmedia_frame_ext_subframe*) p; + fsub->bitlen = (pj_uint16_t)bitlen; + if (bitlen) + pj_memcpy(fsub->data, src, (bitlen+7) >> 3); + + frm->subframe_cnt++; + frm->samples_cnt = (pj_uint16_t)(frm->samples_cnt + samples_cnt); +} + +/** + * Get a subframe from #pjmedia_frame_ext. + * + * @param frm The #pjmedia_frame_ext. + * @param n Subframe index, zero based. + * + * @return The n-th subframe, or NULL if n is out-of-range. + */ +PJ_INLINE(pjmedia_frame_ext_subframe*) +pjmedia_frame_ext_get_subframe(const pjmedia_frame_ext *frm, unsigned n) +{ + pjmedia_frame_ext_subframe *sf = NULL; + + if (n < frm->subframe_cnt) { + pj_uint8_t *p; + unsigned i; + + p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext); + for (i = 0; i < n; ++i) { + sf = (pjmedia_frame_ext_subframe*) p; + p += sizeof(sf->bitlen) + ((sf->bitlen+7) >> 3); + } + + sf = (pjmedia_frame_ext_subframe*) p; + } + + return sf; +} + +/** + * Extract all frame payload to the specified buffer. + * + * @param frm The frame. + * @param dst Destination buffer. + * @param maxsize Maximum size to copy (i.e. the size of the + * destination buffer). + * + * @return Total size of payload copied. + */ +PJ_INLINE(unsigned) +pjmedia_frame_ext_copy_payload(const pjmedia_frame_ext *frm, + void *dst, + unsigned maxlen) +{ + unsigned i, copied=0; + for (i=0; i<frm->subframe_cnt; ++i) { + pjmedia_frame_ext_subframe *sf; + unsigned sz; + + sf = pjmedia_frame_ext_get_subframe(frm, i); + if (!sf) + continue; + + sz = ((sf->bitlen + 7) >> 3); + if (sz + copied > maxlen) + break; + + pj_memcpy(((pj_uint8_t*)dst) + copied, sf->data, sz); + copied += sz; + } + return copied; +} + + +/** + * Pop out first n subframes from #pjmedia_frame_ext. + * + * @param frm The #pjmedia_frame_ext. + * @param n Number of first subframes to be popped out. + * + * @return PJ_SUCCESS when successful. + */ +PJ_INLINE(pj_status_t) +pjmedia_frame_ext_pop_subframes(pjmedia_frame_ext *frm, unsigned n) +{ + pjmedia_frame_ext_subframe *sf; + pj_uint8_t *move_src; + unsigned move_len; + + if (frm->subframe_cnt <= n) { + frm->subframe_cnt = 0; + frm->samples_cnt = 0; + return PJ_SUCCESS; + } + + move_src = (pj_uint8_t*)pjmedia_frame_ext_get_subframe(frm, n); + sf = pjmedia_frame_ext_get_subframe(frm, frm->subframe_cnt-1); + move_len = (pj_uint8_t*)sf - move_src + sizeof(sf->bitlen) + + ((sf->bitlen+7) >> 3); + pj_memmove((pj_uint8_t*)frm+sizeof(pjmedia_frame_ext), + move_src, move_len); + + frm->samples_cnt = (pj_uint16_t) + (frm->samples_cnt - n*frm->samples_cnt/frm->subframe_cnt); + frm->subframe_cnt = (pj_uint16_t) (frm->subframe_cnt - n); + + return PJ_SUCCESS; +} + + /** * @} */ diff --git a/pjmedia/include/pjmedia_audiodev.h b/pjmedia/include/pjmedia_audiodev.h new file mode 100644 index 00000000..e011d1b9 --- /dev/null +++ b/pjmedia/include/pjmedia_audiodev.h @@ -0,0 +1,33 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_AUDIODEV_H__ +#define __PJMEDIA_AUDIODEV_H__ + +/** + * @file pjmedia_audiodev.h + * @brief PJMEDIA main header file. + */ + +#include <pjmedia-audiodev/audiodev.h> +#include <pjmedia-audiodev/audiodev_imp.h> +#include <pjmedia-audiodev/audiotest.h> + +#endif /* __PJMEDIA_AUDIODEV_H__ */ + |