summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2016-03-10 05:02:07 +0000
committerLiong Sauw Ming <ming@teluu.com>2016-03-10 05:02:07 +0000
commit70231deed2aa68e30657db5434cfdbcd320373c7 (patch)
tree09c1244d82cd75f834627e85fddc3cebedb3de36
parent3e3ec82e1a43ba8cafa4ccaea98f51f1f282063b (diff)
Fixed #1907: Remove pjmedia* circular dependency
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5255 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/build/Makefile20
-rw-r--r--pjmedia/include/pjmedia-audiodev/audiodev.h626
-rw-r--r--pjmedia/include/pjmedia-videodev/videodev.h725
-rw-r--r--pjmedia/include/pjmedia/audiodev.h728
-rw-r--r--pjmedia/include/pjmedia/endpoint.h63
-rw-r--r--pjmedia/include/pjmedia/sound.h17
-rw-r--r--pjmedia/include/pjmedia/videodev.h824
-rw-r--r--pjmedia/src/pjmedia-audiodev/audiodev.c703
-rw-r--r--pjmedia/src/pjmedia-videodev/videodev.c757
-rw-r--r--pjmedia/src/pjmedia/audiodev.c628
-rw-r--r--pjmedia/src/pjmedia/endpoint.c27
-rw-r--r--pjmedia/src/pjmedia/sound_legacy.c17
-rw-r--r--pjmedia/src/pjmedia/videodev.c699
13 files changed, 3070 insertions, 2764 deletions
diff --git a/pjmedia/build/Makefile b/pjmedia/build/Makefile
index 2a4af87d..53faa2dc 100644
--- a/pjmedia/build/Makefile
+++ b/pjmedia/build/Makefile
@@ -75,13 +75,11 @@ export PJMEDIA_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
types.o vid_codec.o vid_codec_util.o \
vid_port.o vid_stream.o vid_stream_info.o vid_tee.o \
wav_player.o wav_playlist.o wav_writer.o wave.o \
- wsola.o
+ wsola.o audiodev.o videodev.o
export PJMEDIA_CFLAGS += $(_CFLAGS)
export PJMEDIA_CXXFLAGS += $(_CXXFLAGS)
-export PJMEDIA_LDFLAGS += $(PJMEDIA_VIDEODEV_LDLIB) \
- $(PJMEDIA_AUDIODEV_LDLIB) \
- $(PJLIB_LDLIB) \
+export PJMEDIA_LDFLAGS += $(PJLIB_LDLIB) \
$(PJLIB_UTIL_LDLIB) \
$(PJNATH_LDLIB) \
$(_LDFLAGS)
@@ -97,7 +95,8 @@ export PJMEDIA_AUDIODEV_OBJS += audiodev.o audiotest.o errno.o \
android_jni_dev.o opensl_dev.o
export PJMEDIA_AUDIODEV_CFLAGS += $(_CFLAGS)
export PJMEDIA_AUDIODEV_CXXFLAGS += $(_CXXFLAGS)
-export PJMEDIA_AUDIODEV_LDFLAGS += $(PJLIB_LDLIB) \
+export PJMEDIA_AUDIODEV_LDFLAGS += $(PJMEDIA_LDLIB) \
+ $(PJLIB_LDLIB) \
$(_LDFLAGS)
@@ -105,12 +104,13 @@ export PJMEDIA_AUDIODEV_LDFLAGS += $(PJLIB_LDLIB) \
# Defines for building PJMEDIA-VIDEODEV library
#
export PJMEDIA_VIDEODEV_SRCDIR = ../src/pjmedia-videodev
-export PJMEDIA_VIDEODEV_OBJS += errno.o videodev.o avi_dev.o ffmpeg_dev.o \
+export PJMEDIA_VIDEODEV_OBJS += videodev.o errno.o avi_dev.o ffmpeg_dev.o \
colorbar_dev.o v4l2_dev.o opengl_dev.o \
util.o
export PJMEDIA_VIDEODEV_CFLAGS += $(_CFLAGS)
export PJMEDIA_VIDEODEV_CXXFLAGS += $(_CXXFLAGS)
-export PJMEDIA_VIDEODEV_LDFLAGS += $(PJLIB_LDLIB) \
+export PJMEDIA_VIDEODEV_LDFLAGS += $(PJMEDIA_LDLIB) \
+ $(PJLIB_LDLIB) \
$(_LDFLAGS)
@@ -211,7 +211,7 @@ distclean: realclean
pjmedia: $(PJMEDIA_LIB)
$(PJMEDIA_SONAME): $(PJMEDIA_LIB)
-$(PJMEDIA_LIB) $(PJMEDIA_SONAME): $(PJMEDIA_AUDIODEV_LIB) $(PJMEDIA_AUDIODEV_SONAME) $(PJMEDIA_VIDEODEV_LIB) $(PJMEDIA_VIDEODEV_SONAME)
+$(PJMEDIA_LIB) $(PJMEDIA_SONAME):
$(MAKE) -f $(RULES_MAK) APP=PJMEDIA app=pjmedia $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
pjmedia-codec: $(PJMEDIA_CODEC_LIB)
@@ -221,12 +221,12 @@ $(PJMEDIA_CODEC_LIB) $(PJMEDIA_CODEC_SONAME): $(PJMEDIA_LIB) $(PJMEDIA_SONAME)
pjmedia-videodev: $(PJMEDIA_VIDEODEV_LIB)
$(PJMEDIA_VIDEODEV_SONAME): $(PJMEDIA_VIDEODEV_LIB)
-$(PJMEDIA_VIDEODEV_LIB) $(PJMEDIA_VIDEODEV_SONAME):
+$(PJMEDIA_VIDEODEV_LIB) $(PJMEDIA_VIDEODEV_SONAME): $(PJMEDIA_LIB) $(PJMEDIA_SONAME)
$(MAKE) -f $(RULES_MAK) APP=PJMEDIA_VIDEODEV app=pjmedia-videodev $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
pjmedia-audiodev: $(PJMEDIA_AUDIODEV_LIB)
$(PJMEDIA_AUDIODEV_SONAME): $(PJMEDIA_AUDIODEV_LIB)
-$(PJMEDIA_AUDIODEV_LIB) $(PJMEDIA_AUDIODEV_SONAME):
+$(PJMEDIA_AUDIODEV_LIB) $(PJMEDIA_AUDIODEV_SONAME): $(PJMEDIA_LIB) $(PJMEDIA_SONAME)
$(MAKE) -f $(RULES_MAK) APP=PJMEDIA_AUDIODEV app=pjmedia-audiodev $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
pjsdp: $(PJSDP_LIB)
diff --git a/pjmedia/include/pjmedia-audiodev/audiodev.h b/pjmedia/include/pjmedia-audiodev/audiodev.h
index b5e144f2..106a0328 100644
--- a/pjmedia/include/pjmedia-audiodev/audiodev.h
+++ b/pjmedia/include/pjmedia-audiodev/audiodev.h
@@ -22,478 +22,21 @@
/**
* @file audiodev.h
- * @brief Audio device API.
+ * @brief Audio subsystem API.
*/
-#include <pjmedia-audiodev/config.h>
-#include <pjmedia-audiodev/errno.h>
-#include <pjmedia/format.h>
-#include <pjmedia/frame.h>
-#include <pjmedia/types.h>
#include <pj/pool.h>
+#include <pjmedia/audiodev.h>
PJ_BEGIN_DECL
/**
- * @defgroup s2_audio_device_reference Audio Device API Reference
- * @ingroup audio_device_api
+ * @defgroup s2_audio_device_reference Audio Subsystem API Reference
+ * @ingroup audio_subsystem_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, it is the default audio route of the audio framework
- * backend, as in opening audio device without specifying any route
- * setting or with specifying neutral route setting.
- */
- PJMEDIA_AUD_DEV_ROUTE_DEFAULT = 0,
-
- /** Route to loudspeaker */
- PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER = 1,
-
- /** Route to earpiece */
- PJMEDIA_AUD_DEV_ROUTE_EARPIECE = 2,
-
- /** Route to paired Bluetooth device */
- PJMEDIA_AUD_DEV_ROUTE_BLUETOOTH = 4
-
-} 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[PJMEDIA_AUD_DEV_INFO_NAME_LEN];
-
- /**
- * 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;
-
- /**
- * Enable/disable VAD. This setting is optional, and will only be used
- * if PJMEDIA_AUD_DEV_CAP_VAD is set in the flags.
- */
- pj_bool_t vad_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;
-
-/* typedef for factory creation function */
-typedef pjmedia_aud_dev_factory*
-(*pjmedia_aud_dev_factory_create_func_ptr)(pj_pool_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 pval 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 pval 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
@@ -558,167 +101,6 @@ pjmedia_aud_unregister_factory(pjmedia_aud_dev_factory_create_func_ptr adf);
/**
- * Refresh the list of sound devices installed in the system. This function
- * will only refresh the list of audio device so all active audio streams will
- * be unaffected. After refreshing the device list, application MUST make sure
- * to update all index references to audio devices (i.e. all variables of type
- * pjmedia_aud_dev_index) before calling any function that accepts audio device
- * index as its parameter.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_aud_dev_refresh(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);
-
-
-/**
* @}
*/
diff --git a/pjmedia/include/pjmedia-videodev/videodev.h b/pjmedia/include/pjmedia-videodev/videodev.h
index 21fba158..66407243 100644
--- a/pjmedia/include/pjmedia-videodev/videodev.h
+++ b/pjmedia/include/pjmedia-videodev/videodev.h
@@ -23,517 +23,18 @@
* @file videodev.h
* @brief Video device API.
*/
-#include <pjmedia-videodev/config.h>
-#include <pjmedia-videodev/errno.h>
-#include <pjmedia/event.h>
-#include <pjmedia/frame.h>
-#include <pjmedia/format.h>
-#include <pj/pool.h>
+#include <pjmedia/videodev.h>
PJ_BEGIN_DECL
/**
- * @defgroup video_device_reference Video Device API Reference
- * @ingroup video_device_api
+ * @defgroup video_device_reference Video Subsystem API Reference
+ * @ingroup video_subsystem_api
* @brief API Reference
* @{
*/
-/**
- * Type for device index.
- */
-typedef pj_int32_t pjmedia_vid_dev_index;
-
-/**
- * Enumeration of window handle type.
- */
-typedef enum pjmedia_vid_dev_hwnd_type
-{
- /**
- * Type none.
- */
- PJMEDIA_VID_DEV_HWND_TYPE_NONE,
-
- /**
- * Native window handle on Windows.
- */
- PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS,
-
- /**
- * Native view on iOS.
- */
- PJMEDIA_VID_DEV_HWND_TYPE_IOS,
-
- /**
- * Native window handle on Android.
- */
- PJMEDIA_VID_DEV_HWND_TYPE_ANDROID
-
-} pjmedia_vid_dev_hwnd_type;
-
-/**
- * Type for window handle.
- */
-typedef struct pjmedia_vid_dev_hwnd
-{
- /**
- * The window handle type.
- */
- pjmedia_vid_dev_hwnd_type type;
-
- /**
- * The window handle.
- */
- union
- {
- struct {
- void *hwnd; /**< HWND */
- } win;
- struct {
- void *window; /**< Window */
- void *display; /**< Display */
- } x11;
- struct {
- void *window; /**< Window */
- } cocoa;
- struct {
- void *window; /**< Window */
- } ios;
- struct {
- void *window; /**< Native window */
- } android;
- void *window;
- } info;
-
-} pjmedia_vid_dev_hwnd;
-
-/**
- * Parameter for switching device with PJMEDIA_VID_DEV_CAP_SWITCH capability.
- * Initialize this with pjmedia_vid_dev_switch_param_default()
- */
-typedef struct pjmedia_vid_dev_switch_param
-{
- /**
- * Target device ID to switch to. Once the switching is successful, the
- * video stream will use this device and the old device will be closed.
- */
- pjmedia_vid_dev_index target_id;
-
-} pjmedia_vid_dev_switch_param;
-
-
-/**
- * Enumeration of window flags.
- */
-typedef enum pjmedia_vid_dev_wnd_flag
-{
- /**
- * Window with border.
- */
- PJMEDIA_VID_DEV_WND_BORDER = 1,
-
- /**
- * Window can be resized.
- */
- PJMEDIA_VID_DEV_WND_RESIZABLE = 2
-
-} pjmedia_vid_dev_wnd_flag;
-
-
-/**
- * Device index constants.
- */
-enum pjmedia_vid_dev_std_index
-{
- /**
- * Constant to denote default capture device
- */
- PJMEDIA_VID_DEFAULT_CAPTURE_DEV = -1,
-
- /**
- * Constant to denote default render device
- */
- PJMEDIA_VID_DEFAULT_RENDER_DEV = -2,
-
- /**
- * Constant to denote invalid device index.
- */
- PJMEDIA_VID_INVALID_DEV = -3
-};
-
-
-/**
- * This enumeration identifies various video device capabilities. These video
- * capabilities indicates what features are supported by the underlying
- * video device implementation.
- *
- * Applications get these capabilities in the #pjmedia_vid_dev_info structure.
- *
- * Application can also set the specific features/capabilities when opening
- * the video stream by setting the \a flags member of #pjmedia_vid_dev_param
- * structure.
- *
- * Once video stream is running, application can also retrieve or set some
- * specific video capability, by using #pjmedia_vid_dev_stream_get_cap() and
- * #pjmedia_vid_dev_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_vid_dev_cap
-{
- /**
- * Support for video formats. The value of this capability
- * is represented by #pjmedia_format structure.
- */
- PJMEDIA_VID_DEV_CAP_FORMAT = 1,
-
- /**
- * Support for video input scaling
- */
- PJMEDIA_VID_DEV_CAP_INPUT_SCALE = 2,
-
- /**
- * Support for returning the native window handle of the video window.
- * For renderer, this means the window handle of the renderer window,
- * while for capture, this means the window handle of the native preview,
- * only if the device supports PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW
- * capability.
- *
- * The value of this capability is pointer to pjmedia_vid_dev_hwnd
- * structure.
- */
- PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW = 4,
-
- /**
- * Support for resizing video output. This capability SHOULD be
- * implemented by renderer, to alter the video output dimension on the fly.
- * Value is pjmedia_rect_size.
- */
- PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE = 8,
-
- /**
- * Support for setting the video window's position.
- * Value is pjmedia_coord specifying the window's new coordinate.
- */
- PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION = 16,
-
- /**
- * Support for setting the video output's visibility.
- * The value of this capability is a pj_bool_t containing boolean
- * PJ_TRUE or PJ_FALSE.
- */
- PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE = 32,
-
- /**
- * Support for native preview capability in capture devices. Value is
- * pj_bool_t. With native preview, capture device can be instructed to
- * show or hide a preview window showing video directly from the camera
- * by setting this capability to PJ_TRUE or PJ_FALSE. Once the preview
- * is started, application may use PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW
- * capability to query the video window.
- *
- * The value of this capability is a pj_bool_t containing boolean
- * PJ_TRUE or PJ_FALSE.
- */
- PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW = 64,
-
- /**
- * Support for changing video orientation. For a renderer device,
- * changing video orientation in will potentially affect the size of
- * render window, i.e: width and height swap. For a capture device,
- * the video will be rotated but the size of the video frame
- * will stay the same, so the video may be resized or stretched.
- *
- * The value of this capability is pjmedia_orient.
- */
- PJMEDIA_VID_DEV_CAP_ORIENTATION = 128,
-
- /**
- * Support for fast switching to another device. A video stream with this
- * capability allows replacing of its underlying device with another
- * device, saving the user from opening a new video stream and gets a much
- * faster and smoother switching action.
- *
- * Note that even when this capability is supported by a device, it may
- * not be able to switch to arbitrary device. Application must always
- * check the return value of the operation to verify that switching has
- * occurred.
- *
- * This capability is currently write-only (i.e. set-only).
- *
- * The value of this capability is pointer to pjmedia_vid_dev_switch_param
- * structure.
- */
- PJMEDIA_VID_DEV_CAP_SWITCH = 256,
-
- /**
- * Support for setting the output video window's flags.
- * The value of this capability is a bitmask combination of
- * #pjmedia_vid_dev_wnd_flag.
- */
- PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS = 512,
-
- /**
- * End of standard capability
- */
- PJMEDIA_VID_DEV_CAP_MAX = 16384
-
-} pjmedia_vid_dev_cap;
-
-/**
- * Device information structure returned by #pjmedia_vid_dev_get_info().
- */
-typedef struct pjmedia_vid_dev_info
-{
- /** The device ID */
- pjmedia_vid_dev_index id;
-
- /** The device name */
- char name[64];
-
- /** The underlying driver name */
- char driver[32];
-
- /**
- * The supported direction of the video device, i.e. whether it supports
- * capture only, render only, or both.
- */
- pjmedia_dir dir;
-
- /**
- * Specify whether the device supports callback. Devices that implement
- * "active interface" will actively call the callbacks to give or ask for
- * video frames. If the device doesn't support callback, application
- * must actively request or give video frames from/to the device by using
- * pjmedia_vid_dev_stream_get_frame()/pjmedia_vid_dev_stream_put_frame().
- */
- pj_bool_t has_callback;
-
- /** Device capabilities, as bitmask combination of #pjmedia_vid_dev_cap */
- unsigned caps;
-
- /** Number of video formats supported by this device */
- unsigned fmt_cnt;
-
- /**
- * Array of supported video formats. Some fields in each supported video
- * format may be set to zero or of "unknown" value, to indicate that the
- * value is unknown or should be ignored. When these value are not set
- * to zero, it indicates that the exact format combination is being used.
- */
- pjmedia_format fmt[PJMEDIA_VID_DEV_INFO_FMT_CNT];
-
-} pjmedia_vid_dev_info;
-
-
-/** Forward declaration for pjmedia_vid_dev_stream */
-typedef struct pjmedia_vid_dev_stream pjmedia_vid_dev_stream;
-
-typedef struct pjmedia_vid_dev_cb
-{
- /**
- * This callback is called by capturer stream when it has captured the
- * whole packet worth of video samples.
- *
- * @param stream The video stream.
- * @param user_data User data associated with the stream.
- * @param frame Captured frame.
- *
- * @return Returning non-PJ_SUCCESS will cause the video
- * stream to stop
- */
- pj_status_t (*capture_cb)(pjmedia_vid_dev_stream *stream,
- void *user_data,
- pjmedia_frame *frame);
-
- /**
- * This callback is called by renderer stream when it needs additional
- * data to be rendered by the device. Application must fill in the whole
- * of output buffer with video samples.
- *
- * The frame argument contains the following values:
- * - timestamp Rendering 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 stream The video stream.
- * @param user_data User data associated with the stream.
- * @param frame Video frame, which buffer is to be filled in by
- * the application.
- *
- * @return Returning non-PJ_SUCCESS will cause the video
- * stream to stop
- */
- pj_status_t (*render_cb)(pjmedia_vid_dev_stream *stream,
- void *user_data,
- pjmedia_frame *frame);
-
-} pjmedia_vid_dev_cb;
-
-
-/**
- * This structure specifies the parameters to open the video stream.
- */
-typedef struct pjmedia_vid_dev_param
-{
- /**
- * The video direction. This setting is mandatory.
- */
- pjmedia_dir dir;
-
- /**
- * The video capture device ID. This setting is mandatory if the video
- * direction includes input/capture direction.
- */
- pjmedia_vid_dev_index cap_id;
-
- /**
- * The video render device ID. This setting is mandatory if the video
- * direction includes output/render direction.
- */
- pjmedia_vid_dev_index rend_id;
-
- /**
- * Video clock rate. This setting is mandatory if the video
- * direction includes input/capture direction
- */
- unsigned clock_rate;
-
- /**
- * Video frame rate. This setting is mandatory if the video
- * direction includes input/capture direction
- */
-// pjmedia_ratio frame_rate;
-
- /**
- * This flags specifies which of the optional settings are valid in this
- * structure. The flags is bitmask combination of pjmedia_vid_dev_cap.
- */
- unsigned flags;
-
- /**
- * Set the video format. This setting is mandatory.
- */
- pjmedia_format fmt;
-
- /**
- * Window for the renderer to display the video. This setting is optional,
- * and will only be used if PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW is set in
- * the flags.
- */
- pjmedia_vid_dev_hwnd window;
-
- /**
- * Video display size. This setting is optional, and will only be used
- * if PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE is set in the flags.
- */
- pjmedia_rect_size disp_size;
-
- /**
- * Video window position. This setting is optional, and will only be used
- * if PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION is set in the flags.
- */
- pjmedia_coord window_pos;
-
- /**
- * Video window's visibility. This setting is optional, and will only be
- * used if PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE is set in the flags.
- */
- pj_bool_t window_hide;
-
- /**
- * Enable built-in preview. This setting is optional and is only used
- * if PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW capability is supported and
- * set in the flags.
- */
- pj_bool_t native_preview;
-
- /**
- * Video orientation. This setting is optional and is only used if
- * PJMEDIA_VID_DEV_CAP_ORIENTATION capability is supported and is
- * set in the flags.
- */
- pjmedia_orient orient;
-
- /**
- * Video window flags. This setting is optional, and will only be used
- * if PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS is set in the flags.
- */
- unsigned window_flags;
-
-} pjmedia_vid_dev_param;
-
-
-/** Forward declaration for video device factory */
-typedef struct pjmedia_vid_dev_factory pjmedia_vid_dev_factory;
-
-/* typedef for factory creation function */
-typedef pjmedia_vid_dev_factory*
-(*pjmedia_vid_dev_factory_create_func_ptr)(pj_pool_factory*);
-
-/**
- * Initialize pjmedia_vid_dev_switch_param.
- *
- * @param p Parameter to be initialized.
- */
-PJ_INLINE(void)
-pjmedia_vid_dev_switch_param_default(pjmedia_vid_dev_switch_param *p)
-{
- pj_bzero(p, sizeof(*p));
- p->target_id = PJMEDIA_VID_INVALID_DEV;
-}
-
-/**
- * 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_vid_dev_cap_name(pjmedia_vid_dev_cap cap,
- const char **p_desc);
-
-
-/**
- * Set a capability field value in #pjmedia_vid_dev_param structure. This will
- * also set the flags field for the specified capability in the structure.
- *
- * @param param The structure.
- * @param cap The video capability which value is to be set.
- * @param pval Pointer to value. Please see the type of value to
- * be supplied in the pjmedia_vid_dev_cap documentation.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t)
-pjmedia_vid_dev_param_set_cap(pjmedia_vid_dev_param *param,
- pjmedia_vid_dev_cap cap,
- const void *pval);
-
-
-/**
- * Get a capability field value from #pjmedia_vid_dev_param structure. This
- * function will return PJMEDIA_EVID_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 video capability which value is to be retrieved.
- * @param pval Pointer to value. Please see the type of value to
- * be supplied in the pjmedia_vid_dev_cap documentation.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t)
-pjmedia_vid_dev_param_get_cap(const pjmedia_vid_dev_param *param,
- pjmedia_vid_dev_cap cap,
- void *pval);
/**
* Initialize the video device subsystem. This will register all supported
@@ -610,226 +111,6 @@ pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr vdf,
/**
- * Refresh the list of video devices installed in the system. This function
- * will only refresh the list of videoo device so all active video streams will
- * be unaffected. After refreshing the device list, application MUST make sure
- * to update all index references to video devices (i.e. all variables of type
- * pjmedia_vid_dev_index) before calling any function that accepts video device
- * index as its parameter.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_refresh(void);
-
-
-/**
- * Get the number of video devices installed in the system.
- *
- * @return The number of video devices installed in the system.
- */
-PJ_DECL(unsigned) pjmedia_vid_dev_count(void);
-
-
-/**
- * Get device information.
- *
- * @param id The video 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_vid_dev_get_info(pjmedia_vid_dev_index id,
- pjmedia_vid_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_vid_dev_lookup(const char *drv_name,
- const char *dev_name,
- pjmedia_vid_dev_index *id);
-
-
-/**
- * Initialize the video device parameters with default values for the
- * specified device.
- *
- * @param id The video device ID.
- * @param param The video 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_vid_dev_default_param(pj_pool_t *pool,
- pjmedia_vid_dev_index id,
- pjmedia_vid_dev_param *param);
-
-
-/**
- * Open video stream object using the specified parameters. If stream is
- * created successfully, this function will return PJ_SUCCESS and the
- * stream pointer will be returned in the p_strm argument.
- *
- * The opened stream may have been opened with different size and fps
- * than the requested values in the \a param argument. Application should
- * check the actual size and fps that the stream was opened with by inspecting
- * the values in the \a param argument and see if they have changed. Also
- * if the device ID in the \a param specifies default device, it may be
- * replaced with the actual device ID upon return.
- *
- * @param param On input, it specifies the video device parameters
- * to be used for the stream. On output, this will be
- * set to the actual video device parameters used to
- * open the stream.
- * @param cb Pointer to structure containing video stream
- * callbacks.
- * @param user_data Arbitrary user data, which will be given back in the
- * callbacks.
- * @param p_strm Pointer to receive the video stream.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_create(
- pjmedia_vid_dev_param *param,
- const pjmedia_vid_dev_cb *cb,
- void *user_data,
- pjmedia_vid_dev_stream **p_strm);
-
-/**
- * Get the running parameters for the specified video stream.
- *
- * @param strm The video stream.
- * @param param Video 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_vid_dev_stream_get_param(
- pjmedia_vid_dev_stream *strm,
- pjmedia_vid_dev_param *param);
-
-/**
- * Get the value of a specific capability of the video stream.
- *
- * @param strm The video stream.
- * @param cap The video 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_vid_dev_cap
- * documentation.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_get_cap(
- pjmedia_vid_dev_stream *strm,
- pjmedia_vid_dev_cap cap,
- void *value);
-
-/**
- * Set the value of a specific capability of the video stream.
- *
- * @param strm The video stream.
- * @param cap The video capability which value is to be set.
- * @param value Pointer to value. Please see the type of value to
- * be supplied in the pjmedia_vid_dev_cap documentation.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_set_cap(
- pjmedia_vid_dev_stream *strm,
- pjmedia_vid_dev_cap cap,
- const void *value);
-
-/**
- * Start the stream.
- *
- * @param strm The video stream.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_start(
- pjmedia_vid_dev_stream *strm);
-
-/**
- * Query whether the stream has been started.
- *
- * @param strm The video stream
- *
- * @return PJ_TRUE if the video stream has been started.
- */
-PJ_DECL(pj_bool_t) pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm);
-
-
-/**
- * Request one frame from the stream. Application needs to call this function
- * periodically only if the stream doesn't support "active interface", i.e.
- * the pjmedia_vid_dev_info.has_callback member is PJ_FALSE.
- *
- * @param strm The video stream.
- * @param frame The video frame to be filled by the device.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_get_frame(
- pjmedia_vid_dev_stream *strm,
- pjmedia_frame *frame);
-
-/**
- * Put one frame to the stream. Application needs to call this function
- * periodically only if the stream doesn't support "active interface", i.e.
- * the pjmedia_vid_dev_info.has_callback member is PJ_FALSE.
- *
- * @param strm The video stream.
- * @param frame The video frame to put to the device.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_put_frame(
- pjmedia_vid_dev_stream *strm,
- const pjmedia_frame *frame);
-
-/**
- * Stop the stream.
- *
- * @param strm The video stream.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_stop(
- pjmedia_vid_dev_stream *strm);
-
-/**
- * Destroy the stream.
- *
- * @param strm The video stream.
- *
- * @return PJ_SUCCESS on successful operation or the appropriate
- * error code.
- */
-PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_destroy(
- pjmedia_vid_dev_stream *strm);
-
-
-/**
* @}
*/
diff --git a/pjmedia/include/pjmedia/audiodev.h b/pjmedia/include/pjmedia/audiodev.h
new file mode 100644
index 00000000..473c9fd1
--- /dev/null
+++ b/pjmedia/include/pjmedia/audiodev.h
@@ -0,0 +1,728 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 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_AUDIO_DEV_H__
+#define __PJMEDIA_AUDIO_DEV_H__
+
+/**
+ * @file audiodev.h
+ * @brief Audio device API.
+ */
+#include <pjmedia-audiodev/config.h>
+#include <pjmedia-audiodev/errno.h>
+#include <pjmedia/format.h>
+#include <pjmedia/frame.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
+};
+
+
+#define PJMEDIA_AUD_MAX_DRIVERS 16
+#define PJMEDIA_AUD_MAX_DEVS 64
+
+
+/** 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;
+
+/* typedef for factory creation function */
+typedef pjmedia_aud_dev_factory*
+(*pjmedia_aud_dev_factory_create_func_ptr)(pj_pool_factory*);
+
+
+/* Audio driver structure */
+typedef struct pjmedia_aud_driver
+{
+ pjmedia_aud_dev_factory_create_func_ptr create; /* Creation function */
+ pjmedia_aud_dev_factory *f; /* Factory instance */
+ char name[32]; /* Driver name */
+ unsigned dev_cnt; /* Number of devices */
+ unsigned start_idx; /* Start index in global list */
+ int rec_dev_idx; /* Default capture device. */
+ int play_dev_idx;/* Default playback device */
+ int dev_idx; /* Default device. */
+} pjmedia_aud_driver;
+
+
+/* Audio subsystem structure */
+typedef struct pjmedia_aud_subsys
+{
+ unsigned init_count; /* How many times init() is called */
+ pj_pool_factory *pf; /* The pool factory. */
+
+ unsigned drv_cnt; /* Number of drivers. */
+ pjmedia_aud_driver drv[PJMEDIA_AUD_MAX_DRIVERS];/* Array of drivers. */
+
+ unsigned dev_cnt; /* Total number of devices. */
+ pj_uint32_t dev_list[PJMEDIA_AUD_MAX_DEVS];/* Array of dev IDs. */
+
+} pjmedia_aud_subsys;
+
+
+/**
+ * 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, it is the default audio route of the audio framework
+ * backend, as in opening audio device without specifying any route
+ * setting or with specifying neutral route setting.
+ */
+ PJMEDIA_AUD_DEV_ROUTE_DEFAULT = 0,
+
+ /** Route to loudspeaker */
+ PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER = 1,
+
+ /** Route to earpiece */
+ PJMEDIA_AUD_DEV_ROUTE_EARPIECE = 2,
+
+ /** Route to paired Bluetooth device */
+ PJMEDIA_AUD_DEV_ROUTE_BLUETOOTH = 4
+
+} 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[PJMEDIA_AUD_DEV_INFO_NAME_LEN];
+
+ /**
+ * 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;
+
+ /**
+ * Enable/disable VAD. This setting is optional, and will only be used
+ * if PJMEDIA_AUD_DEV_CAP_VAD is set in the flags.
+ */
+ pj_bool_t vad_enabled;
+
+} pjmedia_aud_param;
+
+
+/**
+ * Get the audio subsystem.
+ *
+ * @return The audio subsystem.
+ */
+PJ_DECL(pjmedia_aud_subsys*) pjmedia_get_aud_subsys(void);
+
+/**
+ * Initialize the audio driver.
+ *
+ * @param drv_idx The index of the audio driver.
+ * @param refresh Specify non-zero to refresh the audio driver.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_aud_driver_init(unsigned drv_idx,
+ pj_bool_t refresh);
+
+/**
+ * Deinitialize the audio driver.
+ *
+ * @param drv_idx The index of the audio driver.
+ */
+PJ_DECL(void) pjmedia_aud_driver_deinit(unsigned drv_idx);
+
+
+/**
+ * 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 pval 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 pval 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);
+
+
+/**
+ * Refresh the list of sound devices installed in the system. This function
+ * will only refresh the list of audio device so all active audio streams will
+ * be unaffected. After refreshing the device list, application MUST make sure
+ * to update all index references to audio devices (i.e. all variables of type
+ * pjmedia_aud_dev_index) before calling any function that accepts audio device
+ * index as its parameter.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_aud_dev_refresh(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_AUDIO_DEV_H__ */
+
diff --git a/pjmedia/include/pjmedia/endpoint.h b/pjmedia/include/pjmedia/endpoint.h
index f300571b..42108c1e 100644
--- a/pjmedia/include/pjmedia/endpoint.h
+++ b/pjmedia/include/pjmedia/endpoint.h
@@ -40,6 +40,7 @@
#include <pjmedia/codec.h>
#include <pjmedia/sdp.h>
#include <pjmedia/transport.h>
+#include <pjmedia-audiodev/audiodev.h>
PJ_BEGIN_DECL
@@ -81,19 +82,77 @@ typedef void (*pjmedia_endpt_exit_callback)(pjmedia_endpt *endpt);
*
* @return PJ_SUCCESS on success.
*/
-PJ_DECL(pj_status_t) pjmedia_endpt_create( pj_pool_factory *pf,
+PJ_DECL(pj_status_t) pjmedia_endpt_create2(pj_pool_factory *pf,
pj_ioqueue_t *ioqueue,
unsigned worker_cnt,
pjmedia_endpt **p_endpt);
/**
+ * Create an instance of media endpoint and initialize audio subsystem.
+ *
+ * @param pf Pool factory, which will be used by the media endpoint
+ * throughout its lifetime.
+ * @param ioqueue Optional ioqueue instance to be registered to the
+ * endpoint. The ioqueue instance is used to poll all RTP
+ * and RTCP sockets. If this argument is NULL, the
+ * endpoint will create an internal ioqueue instance.
+ * @param worker_cnt Specify the number of worker threads to be created
+ * to poll the ioqueue.
+ * @param p_endpt Pointer to receive the endpoint instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_INLINE(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
+ pj_ioqueue_t *ioqueue,
+ unsigned worker_cnt,
+ pjmedia_endpt **p_endpt)
+{
+ /* This function is inlined to avoid build problem due to circular
+ * dependency, i.e: this function prevents pjmedia's dependency on
+ * pjmedia-audiodev.
+ */
+
+ pj_status_t status;
+
+ /* Sound */
+ status = pjmedia_aud_subsys_init(pf);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = pjmedia_endpt_create2(pf, ioqueue, worker_cnt, p_endpt);
+ if (status != PJ_SUCCESS) {
+ pjmedia_aud_subsys_shutdown();
+ }
+
+ return status;
+}
+
+/**
* Destroy media endpoint instance.
*
* @param endpt Media endpoint instance.
*
* @return PJ_SUCCESS on success.
*/
-PJ_DECL(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt);
+PJ_DECL(pj_status_t) pjmedia_endpt_destroy2(pjmedia_endpt *endpt);
+
+/**
+ * Destroy media endpoint instance and shutdown audio subsystem.
+ *
+ * @param endpt Media endpoint instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_INLINE(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt)
+{
+ /* This function is inlined to avoid build problem due to circular
+ * dependency, i.e: this function prevents pjmedia's dependency on
+ * pjmedia-audiodev.
+ */
+ pj_status_t status = pjmedia_endpt_destroy2(endpt);
+ pjmedia_aud_subsys_shutdown();
+ return status;
+}
/**
* Change the value of a flag.
diff --git a/pjmedia/include/pjmedia/sound.h b/pjmedia/include/pjmedia/sound.h
index 3bedb08f..73f379b6 100644
--- a/pjmedia/include/pjmedia/sound.h
+++ b/pjmedia/include/pjmedia/sound.h
@@ -140,8 +140,13 @@ typedef pj_status_t (*pjmedia_snd_rec_cb)(/* in */ void *user_data,
*
* @return Zero on success.
*/
-PJ_DECL(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory);
-
+PJ_INLINE(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)
+{
+ /* This function is inlined to avoid pjmedia's dependency on
+ * pjmedia-audiodev.
+ */
+ return pjmedia_aud_subsys_init(factory);
+}
/**
* Get the number of devices detected by the library.
@@ -323,7 +328,13 @@ PJ_DECL(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream);
*
* @return Zero on success.
*/
-PJ_DECL(pj_status_t) pjmedia_snd_deinit(void);
+PJ_INLINE(pj_status_t) pjmedia_snd_deinit(void)
+{
+ /* This function is inlined to avoid pjmedia's dependency on
+ * pjmedia-audiodev.
+ */
+ return pjmedia_aud_subsys_shutdown();
+}
diff --git a/pjmedia/include/pjmedia/videodev.h b/pjmedia/include/pjmedia/videodev.h
new file mode 100644
index 00000000..37447006
--- /dev/null
+++ b/pjmedia/include/pjmedia/videodev.h
@@ -0,0 +1,824 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 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_VIDEO_DEV_H__
+#define __PJMEDIA_VIDEO_DEV_H__
+
+/**
+ * @file videodev.h
+ * @brief Video device API.
+ */
+#include <pjmedia-videodev/config.h>
+#include <pjmedia-videodev/errno.h>
+#include <pjmedia/event.h>
+#include <pjmedia/frame.h>
+#include <pjmedia/format.h>
+#include <pj/pool.h>
+
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup video_device_reference Video Device API Reference
+ * @ingroup video_device_api
+ * @brief API Reference
+ * @{
+ */
+
+/**
+ * Type for device index.
+ */
+typedef pj_int32_t pjmedia_vid_dev_index;
+
+/**
+ * Enumeration of window handle type.
+ */
+typedef enum pjmedia_vid_dev_hwnd_type
+{
+ /**
+ * Type none.
+ */
+ PJMEDIA_VID_DEV_HWND_TYPE_NONE,
+
+ /**
+ * Native window handle on Windows.
+ */
+ PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS,
+
+ /**
+ * Native view on iOS.
+ */
+ PJMEDIA_VID_DEV_HWND_TYPE_IOS,
+
+ /**
+ * Native window handle on Android.
+ */
+ PJMEDIA_VID_DEV_HWND_TYPE_ANDROID
+
+} pjmedia_vid_dev_hwnd_type;
+
+/**
+ * Type for window handle.
+ */
+typedef struct pjmedia_vid_dev_hwnd
+{
+ /**
+ * The window handle type.
+ */
+ pjmedia_vid_dev_hwnd_type type;
+
+ /**
+ * The window handle.
+ */
+ union
+ {
+ struct {
+ void *hwnd; /**< HWND */
+ } win;
+ struct {
+ void *window; /**< Window */
+ void *display; /**< Display */
+ } x11;
+ struct {
+ void *window; /**< Window */
+ } cocoa;
+ struct {
+ void *window; /**< Window */
+ } ios;
+ struct {
+ void *window; /**< Native window */
+ } android;
+ void *window;
+ } info;
+
+} pjmedia_vid_dev_hwnd;
+
+/**
+ * Parameter for switching device with PJMEDIA_VID_DEV_CAP_SWITCH capability.
+ * Initialize this with pjmedia_vid_dev_switch_param_default()
+ */
+typedef struct pjmedia_vid_dev_switch_param
+{
+ /**
+ * Target device ID to switch to. Once the switching is successful, the
+ * video stream will use this device and the old device will be closed.
+ */
+ pjmedia_vid_dev_index target_id;
+
+} pjmedia_vid_dev_switch_param;
+
+
+/**
+ * Enumeration of window flags.
+ */
+typedef enum pjmedia_vid_dev_wnd_flag
+{
+ /**
+ * Window with border.
+ */
+ PJMEDIA_VID_DEV_WND_BORDER = 1,
+
+ /**
+ * Window can be resized.
+ */
+ PJMEDIA_VID_DEV_WND_RESIZABLE = 2
+
+} pjmedia_vid_dev_wnd_flag;
+
+
+/**
+ * Device index constants.
+ */
+enum pjmedia_vid_dev_std_index
+{
+ /**
+ * Constant to denote default capture device
+ */
+ PJMEDIA_VID_DEFAULT_CAPTURE_DEV = -1,
+
+ /**
+ * Constant to denote default render device
+ */
+ PJMEDIA_VID_DEFAULT_RENDER_DEV = -2,
+
+ /**
+ * Constant to denote invalid device index.
+ */
+ PJMEDIA_VID_INVALID_DEV = -3
+};
+
+
+/**
+ * This enumeration identifies various video device capabilities. These video
+ * capabilities indicates what features are supported by the underlying
+ * video device implementation.
+ *
+ * Applications get these capabilities in the #pjmedia_vid_dev_info structure.
+ *
+ * Application can also set the specific features/capabilities when opening
+ * the video stream by setting the \a flags member of #pjmedia_vid_dev_param
+ * structure.
+ *
+ * Once video stream is running, application can also retrieve or set some
+ * specific video capability, by using #pjmedia_vid_dev_stream_get_cap() and
+ * #pjmedia_vid_dev_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_vid_dev_cap
+{
+ /**
+ * Support for video formats. The value of this capability
+ * is represented by #pjmedia_format structure.
+ */
+ PJMEDIA_VID_DEV_CAP_FORMAT = 1,
+
+ /**
+ * Support for video input scaling
+ */
+ PJMEDIA_VID_DEV_CAP_INPUT_SCALE = 2,
+
+ /**
+ * Support for returning the native window handle of the video window.
+ * For renderer, this means the window handle of the renderer window,
+ * while for capture, this means the window handle of the native preview,
+ * only if the device supports PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW
+ * capability.
+ *
+ * The value of this capability is pointer to pjmedia_vid_dev_hwnd
+ * structure.
+ */
+ PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW = 4,
+
+ /**
+ * Support for resizing video output. This capability SHOULD be
+ * implemented by renderer, to alter the video output dimension on the fly.
+ * Value is pjmedia_rect_size.
+ */
+ PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE = 8,
+
+ /**
+ * Support for setting the video window's position.
+ * Value is pjmedia_coord specifying the window's new coordinate.
+ */
+ PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION = 16,
+
+ /**
+ * Support for setting the video output's visibility.
+ * The value of this capability is a pj_bool_t containing boolean
+ * PJ_TRUE or PJ_FALSE.
+ */
+ PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE = 32,
+
+ /**
+ * Support for native preview capability in capture devices. Value is
+ * pj_bool_t. With native preview, capture device can be instructed to
+ * show or hide a preview window showing video directly from the camera
+ * by setting this capability to PJ_TRUE or PJ_FALSE. Once the preview
+ * is started, application may use PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW
+ * capability to query the video window.
+ *
+ * The value of this capability is a pj_bool_t containing boolean
+ * PJ_TRUE or PJ_FALSE.
+ */
+ PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW = 64,
+
+ /**
+ * Support for changing video orientation. For a renderer device,
+ * changing video orientation in will potentially affect the size of
+ * render window, i.e: width and height swap. For a capture device,
+ * the video will be rotated but the size of the video frame
+ * will stay the same, so the video may be resized or stretched.
+ *
+ * The value of this capability is pjmedia_orient.
+ */
+ PJMEDIA_VID_DEV_CAP_ORIENTATION = 128,
+
+ /**
+ * Support for fast switching to another device. A video stream with this
+ * capability allows replacing of its underlying device with another
+ * device, saving the user from opening a new video stream and gets a much
+ * faster and smoother switching action.
+ *
+ * Note that even when this capability is supported by a device, it may
+ * not be able to switch to arbitrary device. Application must always
+ * check the return value of the operation to verify that switching has
+ * occurred.
+ *
+ * This capability is currently write-only (i.e. set-only).
+ *
+ * The value of this capability is pointer to pjmedia_vid_dev_switch_param
+ * structure.
+ */
+ PJMEDIA_VID_DEV_CAP_SWITCH = 256,
+
+ /**
+ * Support for setting the output video window's flags.
+ * The value of this capability is a bitmask combination of
+ * #pjmedia_vid_dev_wnd_flag.
+ */
+ PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS = 512,
+
+ /**
+ * End of standard capability
+ */
+ PJMEDIA_VID_DEV_CAP_MAX = 16384
+
+} pjmedia_vid_dev_cap;
+
+/**
+ * Device information structure returned by #pjmedia_vid_dev_get_info().
+ */
+typedef struct pjmedia_vid_dev_info
+{
+ /** The device ID */
+ pjmedia_vid_dev_index id;
+
+ /** The device name */
+ char name[64];
+
+ /** The underlying driver name */
+ char driver[32];
+
+ /**
+ * The supported direction of the video device, i.e. whether it supports
+ * capture only, render only, or both.
+ */
+ pjmedia_dir dir;
+
+ /**
+ * Specify whether the device supports callback. Devices that implement
+ * "active interface" will actively call the callbacks to give or ask for
+ * video frames. If the device doesn't support callback, application
+ * must actively request or give video frames from/to the device by using
+ * pjmedia_vid_dev_stream_get_frame()/pjmedia_vid_dev_stream_put_frame().
+ */
+ pj_bool_t has_callback;
+
+ /** Device capabilities, as bitmask combination of #pjmedia_vid_dev_cap */
+ unsigned caps;
+
+ /** Number of video formats supported by this device */
+ unsigned fmt_cnt;
+
+ /**
+ * Array of supported video formats. Some fields in each supported video
+ * format may be set to zero or of "unknown" value, to indicate that the
+ * value is unknown or should be ignored. When these value are not set
+ * to zero, it indicates that the exact format combination is being used.
+ */
+ pjmedia_format fmt[PJMEDIA_VID_DEV_INFO_FMT_CNT];
+
+} pjmedia_vid_dev_info;
+
+
+/** Forward declaration for pjmedia_vid_dev_stream */
+typedef struct pjmedia_vid_dev_stream pjmedia_vid_dev_stream;
+
+typedef struct pjmedia_vid_dev_cb
+{
+ /**
+ * This callback is called by capturer stream when it has captured the
+ * whole packet worth of video samples.
+ *
+ * @param stream The video stream.
+ * @param user_data User data associated with the stream.
+ * @param frame Captured frame.
+ *
+ * @return Returning non-PJ_SUCCESS will cause the video
+ * stream to stop
+ */
+ pj_status_t (*capture_cb)(pjmedia_vid_dev_stream *stream,
+ void *user_data,
+ pjmedia_frame *frame);
+
+ /**
+ * This callback is called by renderer stream when it needs additional
+ * data to be rendered by the device. Application must fill in the whole
+ * of output buffer with video samples.
+ *
+ * The frame argument contains the following values:
+ * - timestamp Rendering 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 stream The video stream.
+ * @param user_data User data associated with the stream.
+ * @param frame Video frame, which buffer is to be filled in by
+ * the application.
+ *
+ * @return Returning non-PJ_SUCCESS will cause the video
+ * stream to stop
+ */
+ pj_status_t (*render_cb)(pjmedia_vid_dev_stream *stream,
+ void *user_data,
+ pjmedia_frame *frame);
+
+} pjmedia_vid_dev_cb;
+
+
+/**
+ * This structure specifies the parameters to open the video stream.
+ */
+typedef struct pjmedia_vid_dev_param
+{
+ /**
+ * The video direction. This setting is mandatory.
+ */
+ pjmedia_dir dir;
+
+ /**
+ * The video capture device ID. This setting is mandatory if the video
+ * direction includes input/capture direction.
+ */
+ pjmedia_vid_dev_index cap_id;
+
+ /**
+ * The video render device ID. This setting is mandatory if the video
+ * direction includes output/render direction.
+ */
+ pjmedia_vid_dev_index rend_id;
+
+ /**
+ * Video clock rate. This setting is mandatory if the video
+ * direction includes input/capture direction
+ */
+ unsigned clock_rate;
+
+ /**
+ * Video frame rate. This setting is mandatory if the video
+ * direction includes input/capture direction
+ */
+// pjmedia_ratio frame_rate;
+
+ /**
+ * This flags specifies which of the optional settings are valid in this
+ * structure. The flags is bitmask combination of pjmedia_vid_dev_cap.
+ */
+ unsigned flags;
+
+ /**
+ * Set the video format. This setting is mandatory.
+ */
+ pjmedia_format fmt;
+
+ /**
+ * Window for the renderer to display the video. This setting is optional,
+ * and will only be used if PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW is set in
+ * the flags.
+ */
+ pjmedia_vid_dev_hwnd window;
+
+ /**
+ * Video display size. This setting is optional, and will only be used
+ * if PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE is set in the flags.
+ */
+ pjmedia_rect_size disp_size;
+
+ /**
+ * Video window position. This setting is optional, and will only be used
+ * if PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION is set in the flags.
+ */
+ pjmedia_coord window_pos;
+
+ /**
+ * Video window's visibility. This setting is optional, and will only be
+ * used if PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE is set in the flags.
+ */
+ pj_bool_t window_hide;
+
+ /**
+ * Enable built-in preview. This setting is optional and is only used
+ * if PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW capability is supported and
+ * set in the flags.
+ */
+ pj_bool_t native_preview;
+
+ /**
+ * Video orientation. This setting is optional and is only used if
+ * PJMEDIA_VID_DEV_CAP_ORIENTATION capability is supported and is
+ * set in the flags.
+ */
+ pjmedia_orient orient;
+
+ /**
+ * Video window flags. This setting is optional, and will only be used
+ * if PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS is set in the flags.
+ */
+ unsigned window_flags;
+
+} pjmedia_vid_dev_param;
+
+
+/** Forward declaration for video device factory */
+typedef struct pjmedia_vid_dev_factory pjmedia_vid_dev_factory;
+
+/* typedef for factory creation function */
+typedef pjmedia_vid_dev_factory*
+(*pjmedia_vid_dev_factory_create_func_ptr)(pj_pool_factory*);
+
+
+/* Video driver structure */
+typedef struct pjmedia_vid_driver
+{
+ pjmedia_vid_dev_factory_create_func_ptr create; /* Creation function */
+ pjmedia_vid_dev_factory *f; /* Factory instance */
+ char name[32]; /* Driver name */
+ unsigned dev_cnt; /* Number of devices */
+ unsigned start_idx; /* Start index in global list */
+ int cap_dev_idx; /* Default capture device. */
+ int rend_dev_idx; /* Default render device */
+} pjmedia_vid_driver;
+
+
+/* The video device subsystem */
+typedef struct pjmedia_vid_subsys
+{
+ unsigned init_count; /* How many times init() is called */
+ pj_pool_factory *pf; /* The pool factory. */
+
+ unsigned drv_cnt; /* Number of drivers. */
+ pjmedia_vid_driver drv[PJMEDIA_VID_DEV_MAX_DRIVERS];/* Array of drivers.*/
+
+ unsigned dev_cnt; /* Total number of devices. */
+ pj_uint32_t dev_list[PJMEDIA_VID_DEV_MAX_DEVS];/* Array of devIDs*/
+
+} pjmedia_vid_subsys;
+
+
+/**
+ * Get the video subsystem.
+ *
+ * @return The video subsystem.
+ */
+PJ_DECL(pjmedia_vid_subsys*) pjmedia_get_vid_subsys(void);
+
+
+/**
+ * Initialize the video driver.
+ *
+ * @param drv_idx The index of the video driver.
+ * @param refresh Specify non-zero to refresh the video driver.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_driver_init(unsigned drv_idx,
+ pj_bool_t refresh);
+
+
+/**
+ * Deinitialize the video driver.
+ *
+ * @param drv_idx The index of the video driver.
+ */
+PJ_DECL(void) pjmedia_vid_driver_deinit(unsigned drv_idx);
+
+
+/**
+ * Initialize pjmedia_vid_dev_switch_param.
+ *
+ * @param p Parameter to be initialized.
+ */
+PJ_INLINE(void)
+pjmedia_vid_dev_switch_param_default(pjmedia_vid_dev_switch_param *p)
+{
+ pj_bzero(p, sizeof(*p));
+ p->target_id = PJMEDIA_VID_INVALID_DEV;
+}
+
+/**
+ * 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_vid_dev_cap_name(pjmedia_vid_dev_cap cap,
+ const char **p_desc);
+
+
+/**
+ * Set a capability field value in #pjmedia_vid_dev_param structure. This will
+ * also set the flags field for the specified capability in the structure.
+ *
+ * @param param The structure.
+ * @param cap The video capability which value is to be set.
+ * @param pval Pointer to value. Please see the type of value to
+ * be supplied in the pjmedia_vid_dev_cap documentation.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_vid_dev_param_set_cap(pjmedia_vid_dev_param *param,
+ pjmedia_vid_dev_cap cap,
+ const void *pval);
+
+
+/**
+ * Get a capability field value from #pjmedia_vid_dev_param structure. This
+ * function will return PJMEDIA_EVID_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 video capability which value is to be retrieved.
+ * @param pval Pointer to value. Please see the type of value to
+ * be supplied in the pjmedia_vid_dev_cap documentation.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_vid_dev_param_get_cap(const pjmedia_vid_dev_param *param,
+ pjmedia_vid_dev_cap cap,
+ void *pval);
+
+
+/**
+ * Refresh the list of video devices installed in the system. This function
+ * will only refresh the list of videoo device so all active video streams will
+ * be unaffected. After refreshing the device list, application MUST make sure
+ * to update all index references to video devices (i.e. all variables of type
+ * pjmedia_vid_dev_index) before calling any function that accepts video device
+ * index as its parameter.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_refresh(void);
+
+
+/**
+ * Get the number of video devices installed in the system.
+ *
+ * @return The number of video devices installed in the system.
+ */
+PJ_DECL(unsigned) pjmedia_vid_dev_count(void);
+
+
+/**
+ * Get device information.
+ *
+ * @param id The video 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_vid_dev_get_info(pjmedia_vid_dev_index id,
+ pjmedia_vid_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_vid_dev_lookup(const char *drv_name,
+ const char *dev_name,
+ pjmedia_vid_dev_index *id);
+
+
+/**
+ * Initialize the video device parameters with default values for the
+ * specified device.
+ *
+ * @param id The video device ID.
+ * @param param The video 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_vid_dev_default_param(pj_pool_t *pool,
+ pjmedia_vid_dev_index id,
+ pjmedia_vid_dev_param *param);
+
+
+/**
+ * Open video stream object using the specified parameters. If stream is
+ * created successfully, this function will return PJ_SUCCESS and the
+ * stream pointer will be returned in the p_strm argument.
+ *
+ * The opened stream may have been opened with different size and fps
+ * than the requested values in the \a param argument. Application should
+ * check the actual size and fps that the stream was opened with by inspecting
+ * the values in the \a param argument and see if they have changed. Also
+ * if the device ID in the \a param specifies default device, it may be
+ * replaced with the actual device ID upon return.
+ *
+ * @param param On input, it specifies the video device parameters
+ * to be used for the stream. On output, this will be
+ * set to the actual video device parameters used to
+ * open the stream.
+ * @param cb Pointer to structure containing video stream
+ * callbacks.
+ * @param user_data Arbitrary user data, which will be given back in the
+ * callbacks.
+ * @param p_strm Pointer to receive the video stream.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_create(
+ pjmedia_vid_dev_param *param,
+ const pjmedia_vid_dev_cb *cb,
+ void *user_data,
+ pjmedia_vid_dev_stream **p_strm);
+
+/**
+ * Get the running parameters for the specified video stream.
+ *
+ * @param strm The video stream.
+ * @param param Video 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_vid_dev_stream_get_param(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_vid_dev_param *param);
+
+/**
+ * Get the value of a specific capability of the video stream.
+ *
+ * @param strm The video stream.
+ * @param cap The video 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_vid_dev_cap
+ * documentation.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_get_cap(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_vid_dev_cap cap,
+ void *value);
+
+/**
+ * Set the value of a specific capability of the video stream.
+ *
+ * @param strm The video stream.
+ * @param cap The video capability which value is to be set.
+ * @param value Pointer to value. Please see the type of value to
+ * be supplied in the pjmedia_vid_dev_cap documentation.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_set_cap(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_vid_dev_cap cap,
+ const void *value);
+
+/**
+ * Start the stream.
+ *
+ * @param strm The video stream.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_start(
+ pjmedia_vid_dev_stream *strm);
+
+/**
+ * Query whether the stream has been started.
+ *
+ * @param strm The video stream
+ *
+ * @return PJ_TRUE if the video stream has been started.
+ */
+PJ_DECL(pj_bool_t) pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm);
+
+
+/**
+ * Request one frame from the stream. Application needs to call this function
+ * periodically only if the stream doesn't support "active interface", i.e.
+ * the pjmedia_vid_dev_info.has_callback member is PJ_FALSE.
+ *
+ * @param strm The video stream.
+ * @param frame The video frame to be filled by the device.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_get_frame(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_frame *frame);
+
+/**
+ * Put one frame to the stream. Application needs to call this function
+ * periodically only if the stream doesn't support "active interface", i.e.
+ * the pjmedia_vid_dev_info.has_callback member is PJ_FALSE.
+ *
+ * @param strm The video stream.
+ * @param frame The video frame to put to the device.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_put_frame(
+ pjmedia_vid_dev_stream *strm,
+ const pjmedia_frame *frame);
+
+/**
+ * Stop the stream.
+ *
+ * @param strm The video stream.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_stop(
+ pjmedia_vid_dev_stream *strm);
+
+/**
+ * Destroy the stream.
+ *
+ * @param strm The video stream.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_destroy(
+ pjmedia_vid_dev_stream *strm);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJMEDIA_VIDEO_DEV_H__ */
diff --git a/pjmedia/src/pjmedia-audiodev/audiodev.c b/pjmedia/src/pjmedia-audiodev/audiodev.c
index f747373e..e28bf318 100644
--- a/pjmedia/src/pjmedia-audiodev/audiodev.c
+++ b/pjmedia/src/pjmedia-audiodev/audiodev.c
@@ -19,51 +19,9 @@
*/
#include <pjmedia-audiodev/audiodev_imp.h>
#include <pj/assert.h>
-#include <pj/errno.h>
-#include <pj/log.h>
-#include <pj/pool.h>
-#include <pj/string.h>
#define THIS_FILE "audiodev.c"
-#define DEFINE_CAP(name, info) {name, info}
-
-/* Capability names */
-static struct cap_info
-{
- const char *name;
- const char *info;
-} cap_infos[] =
-{
- DEFINE_CAP("ext-fmt", "Extended/non-PCM format"),
- DEFINE_CAP("latency-in", "Input latency/buffer size setting"),
- DEFINE_CAP("latency-out", "Output latency/buffer size setting"),
- DEFINE_CAP("vol-in", "Input volume setting"),
- DEFINE_CAP("vol-out", "Output volume setting"),
- DEFINE_CAP("meter-in", "Input meter"),
- DEFINE_CAP("meter-out", "Output meter"),
- DEFINE_CAP("route-in", "Input routing"),
- DEFINE_CAP("route-out", "Output routing"),
- DEFINE_CAP("aec", "Accoustic echo cancellation"),
- DEFINE_CAP("aec-tail", "Tail length setting for AEC"),
- DEFINE_CAP("vad", "Voice activity detection"),
- DEFINE_CAP("cng", "Comfort noise generation"),
- DEFINE_CAP("plg", "Packet loss concealment")
-};
-
-
-/*
- * The device index seen by application and driver is different.
- *
- * At application level, device index is index to global list of device.
- * At driver level, device index is index to device list on that particular
- * factory only.
- */
-#define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))
-#define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)
-#define GET_FID(dev_id) ((dev_id) >> 16)
-#define DEFAULT_DEV_ID 0
-
/* extern functions to create factories */
#if PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO
@@ -114,285 +72,18 @@ pjmedia_aud_dev_factory* pjmedia_symb_mda_factory(pj_pool_factory *pf);
pjmedia_aud_dev_factory* pjmedia_null_audio_factory(pj_pool_factory *pf);
#endif
-#define MAX_DRIVERS 16
-#define MAX_DEVS 64
-
-
-/* driver structure */
-struct driver
-{
- /* Creation function */
- pjmedia_aud_dev_factory_create_func_ptr create;
- /* Factory instance */
- pjmedia_aud_dev_factory *f;
- char name[32]; /* Driver name */
- unsigned dev_cnt; /* Number of devices */
- unsigned start_idx; /* Start index in global list */
- int rec_dev_idx;/* Default capture device. */
- int play_dev_idx;/* Default playback device */
- int dev_idx; /* Default device. */
-};
-
-/* The audio subsystem */
-static struct aud_subsys
-{
- unsigned init_count; /* How many times init() is called */
- pj_pool_factory *pf; /* The pool factory. */
-
- unsigned drv_cnt; /* Number of drivers. */
- struct driver drv[MAX_DRIVERS]; /* Array of drivers. */
-
- unsigned dev_cnt; /* Total number of devices. */
- pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */
-
-} aud_subsys;
-
-/* API: get capability name/info */
-PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap,
- const char **p_desc)
-{
- const char *desc;
- unsigned i;
-
- if (p_desc==NULL) p_desc = &desc;
-
- for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {
- if ((1 << i)==cap)
- break;
- }
-
- if (i==PJ_ARRAY_SIZE(cap_infos)) {
- *p_desc = "??";
- return "??";
- }
-
- *p_desc = cap_infos[i].info;
- return cap_infos[i].name;
-}
-
-static pj_status_t get_cap_pointer(const pjmedia_aud_param *param,
- pjmedia_aud_dev_cap cap,
- void **ptr,
- unsigned *size)
-{
-#define FIELD_INFO(name) *ptr = (void*)&param->name; \
- *size = sizeof(param->name)
-
- switch (cap) {
- case PJMEDIA_AUD_DEV_CAP_EXT_FORMAT:
- FIELD_INFO(ext_fmt);
- break;
- case PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY:
- FIELD_INFO(input_latency_ms);
- break;
- case PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY:
- FIELD_INFO(output_latency_ms);
- break;
- case PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING:
- FIELD_INFO(input_vol);
- break;
- case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING:
- FIELD_INFO(output_vol);
- break;
- case PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE:
- FIELD_INFO(input_route);
- break;
- case PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE:
- FIELD_INFO(output_route);
- break;
- case PJMEDIA_AUD_DEV_CAP_EC:
- FIELD_INFO(ec_enabled);
- break;
- case PJMEDIA_AUD_DEV_CAP_EC_TAIL:
- FIELD_INFO(ec_tail_ms);
- break;
- /* vad is no longer in "fmt" in 2.0.
- case PJMEDIA_AUD_DEV_CAP_VAD:
- FIELD_INFO(ext_fmt.vad);
- break;
- */
- case PJMEDIA_AUD_DEV_CAP_CNG:
- FIELD_INFO(cng_enabled);
- break;
- case PJMEDIA_AUD_DEV_CAP_PLC:
- FIELD_INFO(plc_enabled);
- break;
- default:
- return PJMEDIA_EAUD_INVCAP;
- }
-
-#undef FIELD_INFO
-
- return PJ_SUCCESS;
-}
-
-/* API: set cap value to param */
-PJ_DEF(pj_status_t) pjmedia_aud_param_set_cap( pjmedia_aud_param *param,
- pjmedia_aud_dev_cap cap,
- const void *pval)
-{
- void *cap_ptr;
- unsigned cap_size;
- pj_status_t status;
-
- status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
- if (status != PJ_SUCCESS)
- return status;
-
- pj_memcpy(cap_ptr, pval, cap_size);
- param->flags |= cap;
-
- return PJ_SUCCESS;
-}
-
-/* API: get cap value from param */
-PJ_DEF(pj_status_t) pjmedia_aud_param_get_cap( const pjmedia_aud_param *param,
- pjmedia_aud_dev_cap cap,
- void *pval)
-{
- void *cap_ptr;
- unsigned cap_size;
- pj_status_t status;
-
- status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
- if (status != PJ_SUCCESS)
- return status;
-
- if ((param->flags & cap) == 0) {
- pj_bzero(cap_ptr, cap_size);
- return PJMEDIA_EAUD_INVCAP;
- }
-
- pj_memcpy(pval, cap_ptr, cap_size);
- return PJ_SUCCESS;
-}
-
-/* Internal: init driver */
-static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh)
-{
- struct driver *drv = &aud_subsys.drv[drv_idx];
- pjmedia_aud_dev_factory *f;
- unsigned i, dev_cnt;
- pj_status_t status;
-
- if (!refresh && drv->create) {
- /* Create the factory */
- f = (*drv->create)(aud_subsys.pf);
- if (!f)
- return PJ_EUNKNOWN;
-
- /* Call factory->init() */
- status = f->op->init(f);
- if (status != PJ_SUCCESS) {
- f->op->destroy(f);
- return status;
- }
- } else {
- f = drv->f;
- }
-
- if (!f)
- return PJ_EUNKNOWN;
-
- /* Get number of devices */
- dev_cnt = f->op->get_dev_count(f);
- if (dev_cnt + aud_subsys.dev_cnt > MAX_DEVS) {
- PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"
- " there are too many devices",
- aud_subsys.dev_cnt + dev_cnt - MAX_DEVS));
- dev_cnt = MAX_DEVS - aud_subsys.dev_cnt;
- }
-
- /* enabling this will cause pjsua-lib initialization to fail when there
- * is no sound device installed in the system, even when pjsua has been
- * run with --null-audio
- *
- if (dev_cnt == 0) {
- f->op->destroy(f);
- return PJMEDIA_EAUD_NODEV;
- }
- */
-
- /* Fill in default devices */
- drv->play_dev_idx = drv->rec_dev_idx =
- drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;
- for (i=0; i<dev_cnt; ++i) {
- pjmedia_aud_dev_info info;
-
- status = f->op->get_dev_info(f, i, &info);
- if (status != PJ_SUCCESS) {
- f->op->destroy(f);
- return status;
- }
-
- if (drv->name[0]=='\0') {
- /* Set driver name */
- pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));
- drv->name[sizeof(drv->name)-1] = '\0';
- }
-
- if (drv->play_dev_idx < 0 && info.output_count) {
- /* Set default playback device */
- drv->play_dev_idx = i;
- }
- if (drv->rec_dev_idx < 0 && info.input_count) {
- /* Set default capture device */
- drv->rec_dev_idx = i;
- }
- if (drv->dev_idx < 0 && info.input_count &&
- info.output_count)
- {
- /* Set default capture and playback device */
- drv->dev_idx = i;
- }
-
- if (drv->play_dev_idx >= 0 && drv->rec_dev_idx >= 0 &&
- drv->dev_idx >= 0)
- {
- /* Done. */
- break;
- }
- }
-
- /* Register the factory */
- drv->f = f;
- drv->f->sys.drv_idx = drv_idx;
- drv->start_idx = aud_subsys.dev_cnt;
- drv->dev_cnt = dev_cnt;
-
- /* Register devices to global list */
- for (i=0; i<dev_cnt; ++i) {
- aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);
- }
-
- return PJ_SUCCESS;
-}
-
-/* Internal: deinit driver */
-static void deinit_driver(unsigned drv_idx)
-{
- struct driver *drv = &aud_subsys.drv[drv_idx];
-
- if (drv->f) {
- drv->f->op->destroy(drv->f);
- drv->f = NULL;
- }
-
- pj_bzero(drv, sizeof(*drv));
- drv->play_dev_idx = drv->rec_dev_idx =
- drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;
-}
/* API: Initialize the audio subsystem. */
PJ_DEF(pj_status_t) pjmedia_aud_subsys_init(pj_pool_factory *pf)
{
unsigned i;
pj_status_t status;
+ pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys();
/* Allow init() to be called multiple times as long as there is matching
* number of shutdown().
*/
- if (aud_subsys.init_count++ != 0) {
+ if (aud_subsys->init_count++ != 0) {
return PJ_SUCCESS;
}
@@ -403,58 +94,58 @@ PJ_DEF(pj_status_t) pjmedia_aud_subsys_init(pj_pool_factory *pf)
pj_assert(status == PJ_SUCCESS);
/* Init */
- aud_subsys.pf = pf;
- aud_subsys.drv_cnt = 0;
- aud_subsys.dev_cnt = 0;
+ aud_subsys->pf = pf;
+ aud_subsys->drv_cnt = 0;
+ aud_subsys->dev_cnt = 0;
/* Register creation functions */
#if PJMEDIA_AUDIO_DEV_HAS_OPENSL
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_opensl_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_opensl_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_android_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_android_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_BB10
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_bb10_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bb10_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_ALSA
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_alsa_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_alsa_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_COREAUDIO
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_coreaudio_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_coreaudio_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_pa_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_WMME
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_wmme_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_BDIMAD
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_bdimad_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bdimad_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_SYMB_VAS
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_vas_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_vas_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_SYMB_APS
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_aps_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_aps_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_mda_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_mda_factory;
#endif
#if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO
- aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory;
+ aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_null_audio_factory;
#endif
/* Initialize each factory and build the device ID list */
- for (i=0; i<aud_subsys.drv_cnt; ++i) {
- status = init_driver(i, PJ_FALSE);
+ for (i=0; i<aud_subsys->drv_cnt; ++i) {
+ status = pjmedia_aud_driver_init(i, PJ_FALSE);
if (status != PJ_SUCCESS) {
- deinit_driver(i);
+ pjmedia_aud_driver_deinit(i);
continue;
}
}
- return aud_subsys.dev_cnt ? PJ_SUCCESS : status;
+ return aud_subsys->dev_cnt ? PJ_SUCCESS : status;
}
/* API: register an audio device factory to the audio subsystem. */
@@ -462,16 +153,17 @@ PJ_DEF(pj_status_t)
pjmedia_aud_register_factory(pjmedia_aud_dev_factory_create_func_ptr adf)
{
pj_status_t status;
+ pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys();
- if (aud_subsys.init_count == 0)
+ if (aud_subsys->init_count == 0)
return PJMEDIA_EAUD_INIT;
- aud_subsys.drv[aud_subsys.drv_cnt].create = adf;
- status = init_driver(aud_subsys.drv_cnt, PJ_FALSE);
+ aud_subsys->drv[aud_subsys->drv_cnt].create = adf;
+ status = pjmedia_aud_driver_init(aud_subsys->drv_cnt, PJ_FALSE);
if (status == PJ_SUCCESS) {
- aud_subsys.drv_cnt++;
+ aud_subsys->drv_cnt++;
} else {
- deinit_driver(aud_subsys.drv_cnt);
+ pjmedia_aud_driver_deinit(aud_subsys->drv_cnt);
}
return status;
@@ -482,20 +174,21 @@ PJ_DEF(pj_status_t)
pjmedia_aud_unregister_factory(pjmedia_aud_dev_factory_create_func_ptr adf)
{
unsigned i, j;
+ pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys();
- if (aud_subsys.init_count == 0)
+ if (aud_subsys->init_count == 0)
return PJMEDIA_EAUD_INIT;
- for (i=0; i<aud_subsys.drv_cnt; ++i) {
- struct driver *drv = &aud_subsys.drv[i];
+ for (i=0; i<aud_subsys->drv_cnt; ++i) {
+ pjmedia_aud_driver *drv = &aud_subsys->drv[i];
if (drv->create == adf) {
for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++)
{
- aud_subsys.dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV;
+ aud_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV;
}
- deinit_driver(i);
+ pjmedia_aud_driver_deinit(i);
return PJ_SUCCESS;
}
}
@@ -506,342 +199,30 @@ pjmedia_aud_unregister_factory(pjmedia_aud_dev_factory_create_func_ptr adf)
/* API: get the pool factory registered to the audio subsystem. */
PJ_DEF(pj_pool_factory*) pjmedia_aud_subsys_get_pool_factory(void)
{
- return aud_subsys.pf;
+ pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys();
+ return aud_subsys->pf;
}
/* API: Shutdown the audio subsystem. */
PJ_DEF(pj_status_t) pjmedia_aud_subsys_shutdown(void)
{
unsigned i;
+ pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys();
/* Allow shutdown() to be called multiple times as long as there is matching
* number of init().
*/
- if (aud_subsys.init_count == 0) {
- return PJ_SUCCESS;
- }
- --aud_subsys.init_count;
-
- if (aud_subsys.init_count == 0) {
- for (i=0; i<aud_subsys.drv_cnt; ++i) {
- deinit_driver(i);
- }
-
- aud_subsys.pf = NULL;
- }
- return PJ_SUCCESS;
-}
-
-/* API: Refresh the list of sound devices installed in the system. */
-PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void)
-{
- unsigned i;
-
- aud_subsys.dev_cnt = 0;
- for (i=0; i<aud_subsys.drv_cnt; ++i) {
- struct driver *drv = &aud_subsys.drv[i];
-
- if (drv->f && drv->f->op->refresh) {
- pj_status_t status = drv->f->op->refresh(drv->f);
- if (status != PJ_SUCCESS) {
- PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "
- "list for %s", drv->name));
- }
- }
- init_driver(i, PJ_TRUE);
- }
- return PJ_SUCCESS;
-}
-
-/* API: Get the number of sound devices installed in the system. */
-PJ_DEF(unsigned) pjmedia_aud_dev_count(void)
-{
- return aud_subsys.dev_cnt;
-}
-
-/* Internal: convert local index to global device index */
-static pj_status_t make_global_index(unsigned drv_idx,
- pjmedia_aud_dev_index *id)
-{
- if (*id < 0) {
+ if (aud_subsys->init_count == 0) {
return PJ_SUCCESS;
}
+ --aud_subsys->init_count;
- /* Check that factory still exists */
- PJ_ASSERT_RETURN(aud_subsys.drv[drv_idx].f, PJ_EBUG);
-
- /* Check that device index is valid */
- PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[drv_idx].dev_cnt,
- PJ_EBUG);
-
- *id += aud_subsys.drv[drv_idx].start_idx;
- return PJ_SUCCESS;
-}
-
-/* Internal: lookup device id */
-static pj_status_t lookup_dev(pjmedia_aud_dev_index id,
- pjmedia_aud_dev_factory **p_f,
- unsigned *p_local_index)
-{
- int f_id, index;
-
- if (id < 0) {
- unsigned i;
-
- if (id == PJMEDIA_AUD_INVALID_DEV)
- return PJMEDIA_EAUD_INVDEV;
-
- for (i=0; i<aud_subsys.drv_cnt; ++i) {
- struct driver *drv = &aud_subsys.drv[i];
- if (drv->dev_idx >= 0) {
- id = drv->dev_idx;
- make_global_index(i, &id);
- break;
- } else if (id==PJMEDIA_AUD_DEFAULT_CAPTURE_DEV &&
- drv->rec_dev_idx >= 0)
- {
- id = drv->rec_dev_idx;
- make_global_index(i, &id);
- break;
- } else if (id==PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV &&
- drv->play_dev_idx >= 0)
- {
- id = drv->play_dev_idx;
- make_global_index(i, &id);
- break;
- }
- }
-
- if (id < 0) {
- return PJMEDIA_EAUD_NODEFDEV;
+ if (aud_subsys->init_count == 0) {
+ for (i=0; i<aud_subsys->drv_cnt; ++i) {
+ pjmedia_aud_driver_deinit(i);
}
- }
-
- f_id = GET_FID(aud_subsys.dev_list[id]);
- index = GET_INDEX(aud_subsys.dev_list[id]);
-
- if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt)
- return PJMEDIA_EAUD_INVDEV;
-
- if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt)
- return PJMEDIA_EAUD_INVDEV;
-
- *p_f = aud_subsys.drv[f_id].f;
- *p_local_index = (unsigned)index;
-
- return PJ_SUCCESS;
-
-}
-
-/* API: Get device information. */
-PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id,
- pjmedia_aud_dev_info *info)
-{
- pjmedia_aud_dev_factory *f;
- unsigned index;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(info && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);
- PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
-
- status = lookup_dev(id, &f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- return f->op->get_dev_info(f, index, info);
-}
-
-/* API: find device */
-PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name,
- const char *dev_name,
- pjmedia_aud_dev_index *id)
-{
- pjmedia_aud_dev_factory *f = NULL;
- unsigned drv_idx, dev_idx;
-
- PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);
- PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
-
- for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) {
- if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) {
- f = aud_subsys.drv[drv_idx].f;
- break;
- }
- }
-
- if (!f)
- return PJ_ENOTFOUND;
-
- for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) {
- pjmedia_aud_dev_info info;
- pj_status_t status;
-
- status = f->op->get_dev_info(f, dev_idx, &info);
- if (status != PJ_SUCCESS)
- return status;
-
- if (!pj_ansi_stricmp(dev_name, info.name))
- break;
- }
-
- if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt)
- return PJ_ENOTFOUND;
-
- *id = dev_idx;
- make_global_index(drv_idx, id);
-
- return PJ_SUCCESS;
-}
-
-/* API: Initialize the audio device parameters with default values for the
- * specified device.
- */
-PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id,
- pjmedia_aud_param *param)
-{
- pjmedia_aud_dev_factory *f;
- unsigned index;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(param && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);
- PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
-
- status = lookup_dev(id, &f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- status = f->op->default_param(f, index, param);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Normalize device IDs */
- make_global_index(f->sys.drv_idx, &param->rec_id);
- make_global_index(f->sys.drv_idx, &param->play_id);
-
- return PJ_SUCCESS;
-}
-
-/* API: Open audio stream object using the specified parameters. */
-PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm,
- 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 *rec_f=NULL, *play_f=NULL, *f=NULL;
- pjmedia_aud_param param;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL);
- PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
- PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||
- prm->dir==PJMEDIA_DIR_PLAYBACK ||
- prm->dir==PJMEDIA_DIR_CAPTURE_PLAYBACK,
- PJ_EINVAL);
-
- /* Must make copy of param because we're changing device ID */
- pj_memcpy(&param, prm, sizeof(param));
- /* Normalize rec_id */
- if (param.dir & PJMEDIA_DIR_CAPTURE) {
- unsigned index;
-
- if (param.rec_id < 0)
- param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV;
-
- status = lookup_dev(param.rec_id, &rec_f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- param.rec_id = index;
- f = rec_f;
+ aud_subsys->pf = NULL;
}
-
- /* Normalize play_id */
- if (param.dir & PJMEDIA_DIR_PLAYBACK) {
- unsigned index;
-
- if (param.play_id < 0)
- param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;
-
- status = lookup_dev(param.play_id, &play_f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- param.play_id = index;
- f = play_f;
- }
-
- PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);
-
- /* For now, rec_id and play_id must belong to the same factory */
- PJ_ASSERT_RETURN((param.dir != PJMEDIA_DIR_CAPTURE_PLAYBACK) ||
- (rec_f == play_f),
- PJMEDIA_EAUD_INVDEV);
-
- /* Create the stream */
- status = f->op->create_stream(f, &param, rec_cb, play_cb,
- user_data, p_aud_strm);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Assign factory id to the stream */
- (*p_aud_strm)->sys.drv_idx = f->sys.drv_idx;
return PJ_SUCCESS;
}
-
-/* API: Get the running parameters for the specified audio stream. */
-PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm,
- pjmedia_aud_param *param)
-{
- pj_status_t status;
-
- PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);
- PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
-
- status = strm->op->get_param(strm, param);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Normalize device id's */
- make_global_index(strm->sys.drv_idx, &param->rec_id);
- make_global_index(strm->sys.drv_idx, &param->play_id);
-
- return PJ_SUCCESS;
-}
-
-/* API: Get the value of a specific capability of the audio stream. */
-PJ_DEF(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm,
- pjmedia_aud_dev_cap cap,
- void *value)
-{
- return strm->op->get_cap(strm, cap, value);
-}
-
-/* API: Set the value of a specific capability of the audio stream. */
-PJ_DEF(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm,
- pjmedia_aud_dev_cap cap,
- const void *value)
-{
- return strm->op->set_cap(strm, cap, value);
-}
-
-/* API: Start the stream. */
-PJ_DEF(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm)
-{
- return strm->op->start(strm);
-}
-
-/* API: Stop the stream. */
-PJ_DEF(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm)
-{
- return strm->op->stop(strm);
-}
-
-/* API: Destroy the stream. */
-PJ_DEF(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm)
-{
- return strm->op->destroy(strm);
-}
-
-
diff --git a/pjmedia/src/pjmedia-videodev/videodev.c b/pjmedia/src/pjmedia-videodev/videodev.c
index 8558588d..1d560975 100644
--- a/pjmedia/src/pjmedia-videodev/videodev.c
+++ b/pjmedia/src/pjmedia-videodev/videodev.c
@@ -18,10 +18,6 @@
*/
#include <pjmedia-videodev/videodev_imp.h>
#include <pj/assert.h>
-#include <pj/errno.h>
-#include <pj/log.h>
-#include <pj/pool.h>
-#include <pj/string.h>
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
@@ -29,40 +25,6 @@
#define THIS_FILE "videodev.c"
-#define DEFINE_CAP(name, info) {name, info}
-
-/* Capability names */
-static struct cap_info
-{
- const char *name;
- const char *info;
-} cap_infos[] =
-{
- DEFINE_CAP("format", "Video format"),
- DEFINE_CAP("scale", "Input dimension"),
- DEFINE_CAP("window", "Window handle"),
- DEFINE_CAP("resize", "Renderer resize"),
- DEFINE_CAP("position", "Renderer position"),
- DEFINE_CAP("hide", "Renderer hide"),
- DEFINE_CAP("preview", "Input preview"),
- DEFINE_CAP("orientation", "Video orientation"),
- DEFINE_CAP("switch", "Switch device"),
- DEFINE_CAP("wndflags", "Window flags")
-};
-
-
-/*
- * The device index seen by application and driver is different.
- *
- * At application level, device index is index to global list of device.
- * At driver level, device index is index to device list on that particular
- * factory only.
- */
-#define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))
-#define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)
-#define GET_FID(dev_id) ((dev_id) >> 16)
-#define DEFAULT_DEV_ID 0
-
/* extern functions to create factories */
#if PJMEDIA_VIDEO_DEV_HAS_NULL_VIDEO
@@ -109,262 +71,17 @@ pjmedia_vid_dev_factory* pjmedia_and_factory(pj_pool_factory *pf);
#define MAX_DEVS PJMEDIA_VID_DEV_MAX_DEVS
-/* driver structure */
-struct driver
-{
- /* Creation function */
- pjmedia_vid_dev_factory_create_func_ptr create;
- /* Factory instance */
- pjmedia_vid_dev_factory *f;
- char name[32]; /* Driver name */
- unsigned dev_cnt; /* Number of devices */
- unsigned start_idx; /* Start index in global list */
- int cap_dev_idx; /* Default capture device. */
- int rend_dev_idx; /* Default render device */
-};
-
-/* The video device subsystem */
-static struct vid_subsys
-{
- unsigned init_count; /* How many times init() is called */
- pj_pool_factory *pf; /* The pool factory. */
-
- unsigned drv_cnt; /* Number of drivers. */
- struct driver drv[MAX_DRIVERS]; /* Array of drivers. */
-
- unsigned dev_cnt; /* Total number of devices. */
- pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */
-
-} vid_subsys;
-
-/* API: get capability name/info */
-PJ_DEF(const char*) pjmedia_vid_dev_cap_name(pjmedia_vid_dev_cap cap,
- const char **p_desc)
-{
- const char *desc;
- unsigned i;
-
- if (p_desc==NULL) p_desc = &desc;
-
- for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {
- if ((1 << i)==cap)
- break;
- }
-
- if (i==PJ_ARRAY_SIZE(cap_infos)) {
- *p_desc = "??";
- return "??";
- }
-
- *p_desc = cap_infos[i].info;
- return cap_infos[i].name;
-}
-
-static pj_status_t get_cap_pointer(const pjmedia_vid_dev_param *param,
- pjmedia_vid_dev_cap cap,
- void **ptr,
- unsigned *size)
-{
-#define FIELD_INFO(name) *ptr = (void*)&param->name; \
- *size = sizeof(param->name)
-
- switch (cap) {
- case PJMEDIA_VID_DEV_CAP_FORMAT:
- FIELD_INFO(fmt);
- break;
- case PJMEDIA_VID_DEV_CAP_INPUT_SCALE:
- FIELD_INFO(disp_size);
- break;
- case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW:
- FIELD_INFO(window);
- break;
- case PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE:
- FIELD_INFO(disp_size);
- break;
- case PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION:
- FIELD_INFO(window_pos);
- break;
- case PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE:
- FIELD_INFO(window_hide);
- break;
- case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW:
- FIELD_INFO(native_preview);
- break;
- case PJMEDIA_VID_DEV_CAP_ORIENTATION:
- FIELD_INFO(orient);
- break;
- /* The PJMEDIA_VID_DEV_CAP_SWITCH does not have an entry in the
- * param (it doesn't make sense to open a stream and tell it
- * to switch immediately).
- */
- case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS:
- FIELD_INFO(window_flags);
- break;
- default:
- return PJMEDIA_EVID_INVCAP;
- }
-
-#undef FIELD_INFO
-
- return PJ_SUCCESS;
-}
-
-/* API: set cap value to param */
-PJ_DEF(pj_status_t)
-pjmedia_vid_dev_param_set_cap( pjmedia_vid_dev_param *param,
- pjmedia_vid_dev_cap cap,
- const void *pval)
-{
- void *cap_ptr;
- unsigned cap_size;
- pj_status_t status;
-
- status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
- if (status != PJ_SUCCESS)
- return status;
-
- pj_memcpy(cap_ptr, pval, cap_size);
- param->flags |= cap;
-
- return PJ_SUCCESS;
-}
-
-/* API: get cap value from param */
-PJ_DEF(pj_status_t)
-pjmedia_vid_dev_param_get_cap( const pjmedia_vid_dev_param *param,
- pjmedia_vid_dev_cap cap,
- void *pval)
-{
- void *cap_ptr;
- unsigned cap_size;
- pj_status_t status;
-
- status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
- if (status != PJ_SUCCESS)
- return status;
-
- if ((param->flags & cap) == 0) {
- pj_bzero(cap_ptr, cap_size);
- return PJMEDIA_EVID_INVCAP;
- }
-
- pj_memcpy(pval, cap_ptr, cap_size);
- return PJ_SUCCESS;
-}
-
-/* Internal: init driver */
-static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh)
-{
- struct driver *drv = &vid_subsys.drv[drv_idx];
- pjmedia_vid_dev_factory *f;
- unsigned i, dev_cnt;
- pj_status_t status;
-
- if (!refresh) {
- /* Create the factory */
- f = (*drv->create)(vid_subsys.pf);
- if (!f)
- return PJ_EUNKNOWN;
-
- /* Call factory->init() */
- status = f->op->init(f);
- if (status != PJ_SUCCESS) {
- f->op->destroy(f);
- return status;
- }
- } else {
- f = drv->f;
- }
-
- /* Get number of devices */
- dev_cnt = f->op->get_dev_count(f);
- if (dev_cnt + vid_subsys.dev_cnt > MAX_DEVS) {
- PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"
- " there are too many devices",
- vid_subsys.dev_cnt + dev_cnt - MAX_DEVS));
- dev_cnt = MAX_DEVS - vid_subsys.dev_cnt;
- }
-
- /* enabling this will cause pjsua-lib initialization to fail when there
- * is no video device installed in the system, even when pjsua has been
- * run with --null-video
- *
- if (dev_cnt == 0) {
- f->op->destroy(f);
- return PJMEDIA_EVID_NODEV;
- }
- */
-
- /* Fill in default devices */
- drv->rend_dev_idx = drv->cap_dev_idx = -1;
- for (i=0; i<dev_cnt; ++i) {
- pjmedia_vid_dev_info info;
-
- status = f->op->get_dev_info(f, i, &info);
- if (status != PJ_SUCCESS) {
- f->op->destroy(f);
- return status;
- }
-
- if (drv->name[0]=='\0') {
- /* Set driver name */
- pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));
- drv->name[sizeof(drv->name)-1] = '\0';
- }
-
- if (drv->rend_dev_idx < 0 && (info.dir & PJMEDIA_DIR_RENDER)) {
- /* Set default render device */
- drv->rend_dev_idx = i;
- }
- if (drv->cap_dev_idx < 0 && (info.dir & PJMEDIA_DIR_CAPTURE)) {
- /* Set default capture device */
- drv->cap_dev_idx = i;
- }
-
- if (drv->rend_dev_idx >= 0 && drv->cap_dev_idx >= 0) {
- /* Done. */
- break;
- }
- }
-
- /* Register the factory */
- drv->f = f;
- drv->f->sys.drv_idx = drv_idx;
- drv->start_idx = vid_subsys.dev_cnt;
- drv->dev_cnt = dev_cnt;
-
- /* Register devices to global list */
- for (i=0; i<dev_cnt; ++i) {
- vid_subsys.dev_list[vid_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);
- }
-
- return PJ_SUCCESS;
-}
-
-/* Internal: deinit driver */
-static void deinit_driver(unsigned drv_idx)
-{
- struct driver *drv = &vid_subsys.drv[drv_idx];
-
- if (drv->f) {
- drv->f->op->destroy(drv->f);
- drv->f = NULL;
- }
-
- drv->dev_cnt = 0;
- drv->rend_dev_idx = drv->cap_dev_idx = -1;
-}
-
/* API: Initialize the video device subsystem. */
PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_init(pj_pool_factory *pf)
{
unsigned i;
pj_status_t status = PJ_SUCCESS;
+ pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
/* Allow init() to be called multiple times as long as there is matching
* number of shutdown().
*/
- if (vid_subsys.init_count++ != 0) {
+ if (vid_subsys->init_count++ != 0) {
return PJ_SUCCESS;
}
@@ -374,52 +91,52 @@ PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_init(pj_pool_factory *pf)
&pjmedia_videodev_strerror);
/* Init */
- vid_subsys.pf = pf;
- vid_subsys.drv_cnt = 0;
- vid_subsys.dev_cnt = 0;
+ vid_subsys->pf = pf;
+ vid_subsys->drv_cnt = 0;
+ vid_subsys->dev_cnt = 0;
/* Register creation functions */
#if PJMEDIA_VIDEO_DEV_HAS_V4L2
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_v4l2_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_v4l2_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_QT
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_qt_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_qt_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_OPENGL
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_opengl_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_opengl_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_IOS
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_ios_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ios_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_DSHOW
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_dshow_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_dshow_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_FFMPEG
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_ffmpeg_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ffmpeg_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_SDL
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_sdl_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_sdl_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_ANDROID
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_and_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_and_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC
/* Better put colorbar at the last, so the default capturer will be
* a real capturer, if any.
*/
- vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_cbar_factory;
+ vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_cbar_factory;
#endif
/* Initialize each factory and build the device ID list */
- for (i=0; i<vid_subsys.drv_cnt; ++i) {
- status = init_driver(i, PJ_FALSE);
+ for (i=0; i<vid_subsys->drv_cnt; ++i) {
+ status = pjmedia_vid_driver_init(i, PJ_FALSE);
if (status != PJ_SUCCESS) {
- deinit_driver(i);
+ pjmedia_vid_driver_deinit(i);
continue;
}
}
- return vid_subsys.dev_cnt ? PJ_SUCCESS : status;
+ return vid_subsys->dev_cnt ? PJ_SUCCESS : status;
}
/* API: register a video device factory to the video device subsystem. */
@@ -429,12 +146,13 @@ pjmedia_vid_register_factory(pjmedia_vid_dev_factory_create_func_ptr adf,
{
pj_bool_t refresh = PJ_FALSE;
pj_status_t status;
+ pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
- if (vid_subsys.init_count == 0)
+ if (vid_subsys->init_count == 0)
return PJMEDIA_EVID_INIT;
- vid_subsys.drv[vid_subsys.drv_cnt].create = adf;
- vid_subsys.drv[vid_subsys.drv_cnt].f = factory;
+ vid_subsys->drv[vid_subsys->drv_cnt].create = adf;
+ vid_subsys->drv[vid_subsys->drv_cnt].f = factory;
if (factory) {
/* Call factory->init() */
@@ -446,11 +164,11 @@ pjmedia_vid_register_factory(pjmedia_vid_dev_factory_create_func_ptr adf,
refresh = PJ_TRUE;
}
- status = init_driver(vid_subsys.drv_cnt, refresh);
+ status = pjmedia_vid_driver_init(vid_subsys->drv_cnt, refresh);
if (status == PJ_SUCCESS) {
- vid_subsys.drv_cnt++;
+ vid_subsys->drv_cnt++;
} else {
- deinit_driver(vid_subsys.drv_cnt);
+ pjmedia_vid_driver_deinit(vid_subsys->drv_cnt);
}
return status;
@@ -462,20 +180,21 @@ pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr adf,
pjmedia_vid_dev_factory *factory)
{
unsigned i, j;
+ pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
- if (vid_subsys.init_count == 0)
+ if (vid_subsys->init_count == 0)
return PJMEDIA_EVID_INIT;
- for (i=0; i<vid_subsys.drv_cnt; ++i) {
- struct driver *drv = &vid_subsys.drv[i];
+ for (i=0; i<vid_subsys->drv_cnt; ++i) {
+ pjmedia_vid_driver *drv = &vid_subsys->drv[i];
if ((factory && drv->f==factory) || (adf && drv->create == adf)) {
for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++)
{
- vid_subsys.dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV;
+ vid_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV;
}
- deinit_driver(i);
+ pjmedia_vid_driver_deinit(i);
pj_bzero(drv, sizeof(*drv));
return PJ_SUCCESS;
}
@@ -487,429 +206,33 @@ pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr adf,
/* API: get the pool factory registered to the video device subsystem. */
PJ_DEF(pj_pool_factory*) pjmedia_vid_dev_subsys_get_pool_factory(void)
{
- return vid_subsys.pf;
+ pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
+ return vid_subsys->pf;
}
/* API: Shutdown the video device subsystem. */
PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_shutdown(void)
{
unsigned i;
+ pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
/* Allow shutdown() to be called multiple times as long as there is
* matching number of init().
*/
- if (vid_subsys.init_count == 0) {
+ if (vid_subsys->init_count == 0) {
return PJ_SUCCESS;
}
- --vid_subsys.init_count;
+ --vid_subsys->init_count;
- if (vid_subsys.init_count == 0) {
- for (i=0; i<vid_subsys.drv_cnt; ++i) {
- deinit_driver(i);
+ if (vid_subsys->init_count == 0) {
+ for (i=0; i<vid_subsys->drv_cnt; ++i) {
+ pjmedia_vid_driver_deinit(i);
}
- vid_subsys.pf = NULL;
- }
- return PJ_SUCCESS;
-}
-
-/* API: Refresh the list of video devices installed in the system. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_refresh(void)
-{
- unsigned i;
-
- vid_subsys.dev_cnt = 0;
- for (i=0; i<vid_subsys.drv_cnt; ++i) {
- struct driver *drv = &vid_subsys.drv[i];
-
- if (drv->f && drv->f->op->refresh) {
- pj_status_t status = drv->f->op->refresh(drv->f);
- if (status != PJ_SUCCESS) {
- PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "
- "list for %s", drv->name));
- }
- }
- init_driver(i, PJ_TRUE);
- }
- return PJ_SUCCESS;
-}
-
-/* API: Get the number of video devices installed in the system. */
-PJ_DEF(unsigned) pjmedia_vid_dev_count(void)
-{
- return vid_subsys.dev_cnt;
-}
-
-/* Internal: convert local index to global device index */
-static pj_status_t make_global_index(unsigned drv_idx,
- pjmedia_vid_dev_index *id)
-{
- if (*id < 0) {
- return PJ_SUCCESS;
- }
-
- /* Check that factory still exists */
- PJ_ASSERT_RETURN(vid_subsys.drv[drv_idx].f, PJ_EBUG);
-
- /* Check that device index is valid */
- PJ_ASSERT_RETURN(*id>=0 && *id<(int)vid_subsys.drv[drv_idx].dev_cnt,
- PJ_EBUG);
-
- *id += vid_subsys.drv[drv_idx].start_idx;
- return PJ_SUCCESS;
-}
-
-/* Internal: lookup device id */
-static pj_status_t lookup_dev(pjmedia_vid_dev_index id,
- pjmedia_vid_dev_factory **p_f,
- unsigned *p_local_index)
-{
- int f_id, index;
-
- if (id < 0) {
- unsigned i;
-
- if (id <= PJMEDIA_VID_INVALID_DEV)
- return PJMEDIA_EVID_INVDEV;
-
- for (i=0; i<vid_subsys.drv_cnt; ++i) {
- struct driver *drv = &vid_subsys.drv[i];
- if (id==PJMEDIA_VID_DEFAULT_CAPTURE_DEV &&
- drv->cap_dev_idx >= 0)
- {
- id = drv->cap_dev_idx;
- make_global_index(i, &id);
- break;
- } else if (id==PJMEDIA_VID_DEFAULT_RENDER_DEV &&
- drv->rend_dev_idx >= 0)
- {
- id = drv->rend_dev_idx;
- make_global_index(i, &id);
- break;
- }
- }
-
- if (id < 0) {
- return PJMEDIA_EVID_NODEFDEV;
- }
- }
-
- f_id = GET_FID(vid_subsys.dev_list[id]);
- index = GET_INDEX(vid_subsys.dev_list[id]);
-
- if (f_id < 0 || f_id >= (int)vid_subsys.drv_cnt)
- return PJMEDIA_EVID_INVDEV;
-
- if (index < 0 || index >= (int)vid_subsys.drv[f_id].dev_cnt)
- return PJMEDIA_EVID_INVDEV;
-
- *p_f = vid_subsys.drv[f_id].f;
- *p_local_index = (unsigned)index;
-
- return PJ_SUCCESS;
-
-}
-
-/* API: lookup device id */
-PJ_DEF(pj_status_t)
-pjmedia_vid_dev_get_local_index(pjmedia_vid_dev_index id,
- pjmedia_vid_dev_factory **p_f,
- unsigned *p_local_index)
-{
- return lookup_dev(id, p_f, p_local_index);
-}
-
-/* API: from factory and local index, get global index */
-PJ_DEF(pj_status_t)
-pjmedia_vid_dev_get_global_index(const pjmedia_vid_dev_factory *f,
- unsigned local_idx,
- pjmedia_vid_dev_index *pid)
-{
- PJ_ASSERT_RETURN(f->sys.drv_idx >= 0 && f->sys.drv_idx < MAX_DRIVERS,
- PJ_EINVALIDOP);
- *pid = local_idx;
- return make_global_index(f->sys.drv_idx, pid);
-}
-
-/* API: Get device information. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_get_info(pjmedia_vid_dev_index id,
- pjmedia_vid_dev_info *info)
-{
- pjmedia_vid_dev_factory *f;
- unsigned index;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(info, PJ_EINVAL);
- PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
-
- if (id <= PJMEDIA_VID_INVALID_DEV)
- return PJMEDIA_EVID_INVDEV;
-
- status = lookup_dev(id, &f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- status = f->op->get_dev_info(f, index, info);
-
- /* Make sure device ID is the real ID (not PJMEDIA_VID_DEFAULT_*_DEV) */
- info->id = index;
- make_global_index(f->sys.drv_idx, &info->id);
-
- return status;
-}
-
-/* API: find device */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_lookup( const char *drv_name,
- const char *dev_name,
- pjmedia_vid_dev_index *id)
-{
- pjmedia_vid_dev_factory *f = NULL;
- unsigned drv_idx, dev_idx;
-
- PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);
- PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
-
- for (drv_idx=0; drv_idx<vid_subsys.drv_cnt; ++drv_idx) {
- if (!pj_ansi_stricmp(drv_name, vid_subsys.drv[drv_idx].name))
- {
- f = vid_subsys.drv[drv_idx].f;
- break;
- }
- }
-
- if (!f)
- return PJ_ENOTFOUND;
-
- for (dev_idx=0; dev_idx<vid_subsys.drv[drv_idx].dev_cnt; ++dev_idx)
- {
- pjmedia_vid_dev_info info;
- pj_status_t status;
-
- status = f->op->get_dev_info(f, dev_idx, &info);
- if (status != PJ_SUCCESS)
- return status;
-
- if (!pj_ansi_stricmp(dev_name, info.name))
- break;
- }
-
- if (dev_idx==vid_subsys.drv[drv_idx].dev_cnt)
- return PJ_ENOTFOUND;
-
- *id = dev_idx;
- make_global_index(drv_idx, id);
-
- return PJ_SUCCESS;
-}
-
-/* API: Initialize the video device parameters with default values for the
- * specified device.
- */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_default_param(pj_pool_t *pool,
- pjmedia_vid_dev_index id,
- pjmedia_vid_dev_param *param)
-{
- pjmedia_vid_dev_factory *f;
- unsigned index;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(param, PJ_EINVAL);
- PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
-
- if (id <= PJMEDIA_VID_INVALID_DEV)
- return PJMEDIA_EVID_INVDEV;
-
- status = lookup_dev(id, &f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- status = f->op->default_param(pool, f, index, param);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Normalize device IDs */
- make_global_index(f->sys.drv_idx, &param->cap_id);
- make_global_index(f->sys.drv_idx, &param->rend_id);
-
- return PJ_SUCCESS;
-}
-
-/* API: Open video stream object using the specified parameters. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_create(
- pjmedia_vid_dev_param *prm,
- const pjmedia_vid_dev_cb *cb,
- void *user_data,
- pjmedia_vid_dev_stream **p_vid_strm)
-{
- pjmedia_vid_dev_factory *cap_f=NULL, *rend_f=NULL, *f=NULL;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(prm && prm->dir && p_vid_strm, PJ_EINVAL);
- PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
- PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||
- prm->dir==PJMEDIA_DIR_RENDER ||
- prm->dir==PJMEDIA_DIR_CAPTURE_RENDER,
- PJ_EINVAL);
-
- /* Normalize cap_id */
- if (prm->dir & PJMEDIA_DIR_CAPTURE) {
- unsigned index;
-
- if (prm->cap_id < 0)
- prm->cap_id = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
-
- status = lookup_dev(prm->cap_id, &cap_f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- prm->cap_id = index;
- f = cap_f;
+ vid_subsys->pf = NULL;
}
-
- /* Normalize rend_id */
- if (prm->dir & PJMEDIA_DIR_RENDER) {
- unsigned index;
-
- if (prm->rend_id < 0)
- prm->rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV;
-
- status = lookup_dev(prm->rend_id, &rend_f, &index);
- if (status != PJ_SUCCESS)
- return status;
-
- prm->rend_id = index;
- f = rend_f;
- }
-
- PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);
-
- /* For now, cap_id and rend_id must belong to the same factory */
- PJ_ASSERT_RETURN((prm->dir != PJMEDIA_DIR_CAPTURE_RENDER) ||
- (cap_f == rend_f),
- PJMEDIA_EVID_INVDEV);
-
- /* Create the stream */
- status = f->op->create_stream(f, prm, cb,
- user_data, p_vid_strm);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Assign factory id to the stream */
- (*p_vid_strm)->sys.drv_idx = f->sys.drv_idx;
return PJ_SUCCESS;
}
-/* API: Get the running parameters for the specified video stream. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_param(
- pjmedia_vid_dev_stream *strm,
- pjmedia_vid_dev_param *param)
-{
- pj_status_t status;
-
- PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);
- PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
-
- status = strm->op->get_param(strm, param);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Normalize device id's */
- make_global_index(strm->sys.drv_idx, &param->cap_id);
- make_global_index(strm->sys.drv_idx, &param->rend_id);
-
- return PJ_SUCCESS;
-}
-
-/* API: Get the value of a specific capability of the video stream. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_cap(
- pjmedia_vid_dev_stream *strm,
- pjmedia_vid_dev_cap cap,
- void *value)
-{
- return strm->op->get_cap(strm, cap, value);
-}
-
-/* API: Set the value of a specific capability of the video stream. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_set_cap(
- pjmedia_vid_dev_stream *strm,
- pjmedia_vid_dev_cap cap,
- const void *value)
-{
- /* For fast switching, device global index needs to be converted to
- * local index before forwarding the request to the device stream.
- */
- if (cap == PJMEDIA_VID_DEV_CAP_SWITCH) {
- pjmedia_vid_dev_factory *f;
- unsigned local_idx;
- pj_status_t status;
- pjmedia_vid_dev_switch_param p = *(pjmedia_vid_dev_switch_param*)value;
-
- status = lookup_dev(p.target_id, &f, &local_idx);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Make sure that current & target devices share the same factory */
- if (f->sys.drv_idx != strm->sys.drv_idx)
- return PJMEDIA_EVID_INVDEV;
-
- p.target_id = local_idx;
- return strm->op->set_cap(strm, cap, &p);
- }
-
- return strm->op->set_cap(strm, cap, value);
-}
-
-/* API: Start the stream. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_start(pjmedia_vid_dev_stream *strm)
-{
- pj_status_t status;
-
- if (pjmedia_vid_dev_stream_is_running(strm))
- return PJ_SUCCESS;
-
- status = strm->op->start(strm);
- if (status == PJ_SUCCESS)
- strm->sys.is_running = PJ_TRUE;
- return status;
-}
-
-/* API: has it been started? */
-PJ_DEF(pj_bool_t)
-pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm)
-{
- return strm->sys.is_running;
-}
-
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_frame(
- pjmedia_vid_dev_stream *strm,
- pjmedia_frame *frame)
-{
- pj_assert(strm->op->get_frame);
- return strm->op->get_frame(strm, frame);
-}
-
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_put_frame(
- pjmedia_vid_dev_stream *strm,
- const pjmedia_frame *frame)
-{
- pj_assert(strm->op->put_frame);
- return strm->op->put_frame(strm, frame);
-}
-
-/* API: Stop the stream. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_stop(pjmedia_vid_dev_stream *strm)
-{
- strm->sys.is_running = PJ_FALSE;
- return strm->op->stop(strm);
-}
-
-/* API: Destroy the stream. */
-PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_destroy(
- pjmedia_vid_dev_stream *strm)
-{
- strm->sys.is_running = PJ_FALSE;
- return strm->op->destroy(strm);
-}
-
#endif /* PJMEDIA_HAS_VIDEO */
diff --git a/pjmedia/src/pjmedia/audiodev.c b/pjmedia/src/pjmedia/audiodev.c
new file mode 100644
index 00000000..398a4042
--- /dev/null
+++ b/pjmedia/src/pjmedia/audiodev.c
@@ -0,0 +1,628 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 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
+ */
+#include <pjmedia-audiodev/audiodev_imp.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+#define THIS_FILE "audiodev.c"
+
+#define DEFINE_CAP(name, info) {name, info}
+
+/* Capability names */
+static struct cap_info
+{
+ const char *name;
+ const char *info;
+} cap_infos[] =
+{
+ DEFINE_CAP("ext-fmt", "Extended/non-PCM format"),
+ DEFINE_CAP("latency-in", "Input latency/buffer size setting"),
+ DEFINE_CAP("latency-out", "Output latency/buffer size setting"),
+ DEFINE_CAP("vol-in", "Input volume setting"),
+ DEFINE_CAP("vol-out", "Output volume setting"),
+ DEFINE_CAP("meter-in", "Input meter"),
+ DEFINE_CAP("meter-out", "Output meter"),
+ DEFINE_CAP("route-in", "Input routing"),
+ DEFINE_CAP("route-out", "Output routing"),
+ DEFINE_CAP("aec", "Accoustic echo cancellation"),
+ DEFINE_CAP("aec-tail", "Tail length setting for AEC"),
+ DEFINE_CAP("vad", "Voice activity detection"),
+ DEFINE_CAP("cng", "Comfort noise generation"),
+ DEFINE_CAP("plg", "Packet loss concealment")
+};
+
+
+/*
+ * The device index seen by application and driver is different.
+ *
+ * At application level, device index is index to global list of device.
+ * At driver level, device index is index to device list on that particular
+ * factory only.
+ */
+#define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))
+#define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)
+#define GET_FID(dev_id) ((dev_id) >> 16)
+#define DEFAULT_DEV_ID 0
+
+
+/* The audio subsystem */
+static pjmedia_aud_subsys aud_subsys;
+
+/* API: get the audio subsystem. */
+PJ_DEF(pjmedia_aud_subsys*) pjmedia_get_aud_subsys(void)
+{
+ return &aud_subsys;
+}
+
+/* API: init driver */
+PJ_DEF(pj_status_t) pjmedia_aud_driver_init(unsigned drv_idx,
+ pj_bool_t refresh)
+{
+ pjmedia_aud_driver *drv = &aud_subsys.drv[drv_idx];
+ pjmedia_aud_dev_factory *f;
+ unsigned i, dev_cnt;
+ pj_status_t status;
+
+ if (!refresh && drv->create) {
+ /* Create the factory */
+ f = (*drv->create)(aud_subsys.pf);
+ if (!f)
+ return PJ_EUNKNOWN;
+
+ /* Call factory->init() */
+ status = f->op->init(f);
+ if (status != PJ_SUCCESS) {
+ f->op->destroy(f);
+ return status;
+ }
+ } else {
+ f = drv->f;
+ }
+
+ if (!f)
+ return PJ_EUNKNOWN;
+
+ /* Get number of devices */
+ dev_cnt = f->op->get_dev_count(f);
+ if (dev_cnt + aud_subsys.dev_cnt > PJMEDIA_AUD_MAX_DEVS) {
+ PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"
+ " there are too many devices",
+ aud_subsys.dev_cnt + dev_cnt -
+ PJMEDIA_AUD_MAX_DEVS));
+ dev_cnt = PJMEDIA_AUD_MAX_DEVS - aud_subsys.dev_cnt;
+ }
+
+ /* enabling this will cause pjsua-lib initialization to fail when there
+ * is no sound device installed in the system, even when pjsua has been
+ * run with --null-audio
+ *
+ if (dev_cnt == 0) {
+ f->op->destroy(f);
+ return PJMEDIA_EAUD_NODEV;
+ }
+ */
+
+ /* Fill in default devices */
+ drv->play_dev_idx = drv->rec_dev_idx =
+ drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;
+ for (i=0; i<dev_cnt; ++i) {
+ pjmedia_aud_dev_info info;
+
+ status = f->op->get_dev_info(f, i, &info);
+ if (status != PJ_SUCCESS) {
+ f->op->destroy(f);
+ return status;
+ }
+
+ if (drv->name[0]=='\0') {
+ /* Set driver name */
+ pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));
+ drv->name[sizeof(drv->name)-1] = '\0';
+ }
+
+ if (drv->play_dev_idx < 0 && info.output_count) {
+ /* Set default playback device */
+ drv->play_dev_idx = i;
+ }
+ if (drv->rec_dev_idx < 0 && info.input_count) {
+ /* Set default capture device */
+ drv->rec_dev_idx = i;
+ }
+ if (drv->dev_idx < 0 && info.input_count &&
+ info.output_count)
+ {
+ /* Set default capture and playback device */
+ drv->dev_idx = i;
+ }
+
+ if (drv->play_dev_idx >= 0 && drv->rec_dev_idx >= 0 &&
+ drv->dev_idx >= 0)
+ {
+ /* Done. */
+ break;
+ }
+ }
+
+ /* Register the factory */
+ drv->f = f;
+ drv->f->sys.drv_idx = drv_idx;
+ drv->start_idx = aud_subsys.dev_cnt;
+ drv->dev_cnt = dev_cnt;
+
+ /* Register devices to global list */
+ for (i=0; i<dev_cnt; ++i) {
+ aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);
+ }
+
+ return PJ_SUCCESS;
+}
+
+/* API: deinit driver */
+PJ_DEF(void) pjmedia_aud_driver_deinit(unsigned drv_idx)
+{
+ pjmedia_aud_driver *drv = &aud_subsys.drv[drv_idx];
+
+ if (drv->f) {
+ drv->f->op->destroy(drv->f);
+ drv->f = NULL;
+ }
+
+ pj_bzero(drv, sizeof(*drv));
+ drv->play_dev_idx = drv->rec_dev_idx =
+ drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;
+}
+
+/* API: get capability name/info */
+PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap,
+ const char **p_desc)
+{
+ const char *desc;
+ unsigned i;
+
+ if (p_desc==NULL) p_desc = &desc;
+
+ for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {
+ if ((1 << i)==cap)
+ break;
+ }
+
+ if (i==PJ_ARRAY_SIZE(cap_infos)) {
+ *p_desc = "??";
+ return "??";
+ }
+
+ *p_desc = cap_infos[i].info;
+ return cap_infos[i].name;
+}
+
+static pj_status_t get_cap_pointer(const pjmedia_aud_param *param,
+ pjmedia_aud_dev_cap cap,
+ void **ptr,
+ unsigned *size)
+{
+#define FIELD_INFO(name) *ptr = (void*)&param->name; \
+ *size = sizeof(param->name)
+
+ switch (cap) {
+ case PJMEDIA_AUD_DEV_CAP_EXT_FORMAT:
+ FIELD_INFO(ext_fmt);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY:
+ FIELD_INFO(input_latency_ms);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY:
+ FIELD_INFO(output_latency_ms);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING:
+ FIELD_INFO(input_vol);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING:
+ FIELD_INFO(output_vol);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE:
+ FIELD_INFO(input_route);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE:
+ FIELD_INFO(output_route);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_EC:
+ FIELD_INFO(ec_enabled);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_EC_TAIL:
+ FIELD_INFO(ec_tail_ms);
+ break;
+ /* vad is no longer in "fmt" in 2.0.
+ case PJMEDIA_AUD_DEV_CAP_VAD:
+ FIELD_INFO(ext_fmt.vad);
+ break;
+ */
+ case PJMEDIA_AUD_DEV_CAP_CNG:
+ FIELD_INFO(cng_enabled);
+ break;
+ case PJMEDIA_AUD_DEV_CAP_PLC:
+ FIELD_INFO(plc_enabled);
+ break;
+ default:
+ return PJMEDIA_EAUD_INVCAP;
+ }
+
+#undef FIELD_INFO
+
+ return PJ_SUCCESS;
+}
+
+/* API: set cap value to param */
+PJ_DEF(pj_status_t) pjmedia_aud_param_set_cap( pjmedia_aud_param *param,
+ pjmedia_aud_dev_cap cap,
+ const void *pval)
+{
+ void *cap_ptr;
+ unsigned cap_size;
+ pj_status_t status;
+
+ status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ pj_memcpy(cap_ptr, pval, cap_size);
+ param->flags |= cap;
+
+ return PJ_SUCCESS;
+}
+
+/* API: get cap value from param */
+PJ_DEF(pj_status_t) pjmedia_aud_param_get_cap( const pjmedia_aud_param *param,
+ pjmedia_aud_dev_cap cap,
+ void *pval)
+{
+ void *cap_ptr;
+ unsigned cap_size;
+ pj_status_t status;
+
+ status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ if ((param->flags & cap) == 0) {
+ pj_bzero(cap_ptr, cap_size);
+ return PJMEDIA_EAUD_INVCAP;
+ }
+
+ pj_memcpy(pval, cap_ptr, cap_size);
+ return PJ_SUCCESS;
+}
+
+
+/* API: Refresh the list of sound devices installed in the system. */
+PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void)
+{
+ unsigned i;
+
+ aud_subsys.dev_cnt = 0;
+ for (i=0; i<aud_subsys.drv_cnt; ++i) {
+ pjmedia_aud_driver *drv = &aud_subsys.drv[i];
+
+ if (drv->f && drv->f->op->refresh) {
+ pj_status_t status = drv->f->op->refresh(drv->f);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "
+ "list for %s", drv->name));
+ }
+ }
+ pjmedia_aud_driver_init(i, PJ_TRUE);
+ }
+ return PJ_SUCCESS;
+}
+
+/* API: Get the number of sound devices installed in the system. */
+PJ_DEF(unsigned) pjmedia_aud_dev_count(void)
+{
+ return aud_subsys.dev_cnt;
+}
+
+/* Internal: convert local index to global device index */
+static pj_status_t make_global_index(unsigned drv_idx,
+ pjmedia_aud_dev_index *id)
+{
+ if (*id < 0) {
+ return PJ_SUCCESS;
+ }
+
+ /* Check that factory still exists */
+ PJ_ASSERT_RETURN(aud_subsys.drv[drv_idx].f, PJ_EBUG);
+
+ /* Check that device index is valid */
+ PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[drv_idx].dev_cnt,
+ PJ_EBUG);
+
+ *id += aud_subsys.drv[drv_idx].start_idx;
+ return PJ_SUCCESS;
+}
+
+/* Internal: lookup device id */
+static pj_status_t lookup_dev(pjmedia_aud_dev_index id,
+ pjmedia_aud_dev_factory **p_f,
+ unsigned *p_local_index)
+{
+ int f_id, index;
+
+ if (id < 0) {
+ unsigned i;
+
+ if (id == PJMEDIA_AUD_INVALID_DEV)
+ return PJMEDIA_EAUD_INVDEV;
+
+ for (i=0; i<aud_subsys.drv_cnt; ++i) {
+ pjmedia_aud_driver *drv = &aud_subsys.drv[i];
+ if (drv->dev_idx >= 0) {
+ id = drv->dev_idx;
+ make_global_index(i, &id);
+ break;
+ } else if (id==PJMEDIA_AUD_DEFAULT_CAPTURE_DEV &&
+ drv->rec_dev_idx >= 0)
+ {
+ id = drv->rec_dev_idx;
+ make_global_index(i, &id);
+ break;
+ } else if (id==PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV &&
+ drv->play_dev_idx >= 0)
+ {
+ id = drv->play_dev_idx;
+ make_global_index(i, &id);
+ break;
+ }
+ }
+
+ if (id < 0) {
+ return PJMEDIA_EAUD_NODEFDEV;
+ }
+ }
+
+ f_id = GET_FID(aud_subsys.dev_list[id]);
+ index = GET_INDEX(aud_subsys.dev_list[id]);
+
+ if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt)
+ return PJMEDIA_EAUD_INVDEV;
+
+ if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt)
+ return PJMEDIA_EAUD_INVDEV;
+
+ *p_f = aud_subsys.drv[f_id].f;
+ *p_local_index = (unsigned)index;
+
+ return PJ_SUCCESS;
+
+}
+
+/* API: Get device information. */
+PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id,
+ pjmedia_aud_dev_info *info)
+{
+ pjmedia_aud_dev_factory *f;
+ unsigned index;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(info && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);
+ PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
+
+ status = lookup_dev(id, &f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ return f->op->get_dev_info(f, index, info);
+}
+
+/* API: find device */
+PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name,
+ const char *dev_name,
+ pjmedia_aud_dev_index *id)
+{
+ pjmedia_aud_dev_factory *f = NULL;
+ unsigned drv_idx, dev_idx;
+
+ PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);
+ PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
+
+ for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) {
+ if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) {
+ f = aud_subsys.drv[drv_idx].f;
+ break;
+ }
+ }
+
+ if (!f)
+ return PJ_ENOTFOUND;
+
+ for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) {
+ pjmedia_aud_dev_info info;
+ pj_status_t status;
+
+ status = f->op->get_dev_info(f, dev_idx, &info);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ if (!pj_ansi_stricmp(dev_name, info.name))
+ break;
+ }
+
+ if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt)
+ return PJ_ENOTFOUND;
+
+ *id = dev_idx;
+ make_global_index(drv_idx, id);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Initialize the audio device parameters with default values for the
+ * specified device.
+ */
+PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id,
+ pjmedia_aud_param *param)
+{
+ pjmedia_aud_dev_factory *f;
+ unsigned index;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(param && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);
+ PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
+
+ status = lookup_dev(id, &f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = f->op->default_param(f, index, param);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Normalize device IDs */
+ make_global_index(f->sys.drv_idx, &param->rec_id);
+ make_global_index(f->sys.drv_idx, &param->play_id);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Open audio stream object using the specified parameters. */
+PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm,
+ 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 *rec_f=NULL, *play_f=NULL, *f=NULL;
+ pjmedia_aud_param param;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL);
+ PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
+ PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||
+ prm->dir==PJMEDIA_DIR_PLAYBACK ||
+ prm->dir==PJMEDIA_DIR_CAPTURE_PLAYBACK,
+ PJ_EINVAL);
+
+ /* Must make copy of param because we're changing device ID */
+ pj_memcpy(&param, prm, sizeof(param));
+
+ /* Normalize rec_id */
+ if (param.dir & PJMEDIA_DIR_CAPTURE) {
+ unsigned index;
+
+ if (param.rec_id < 0)
+ param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV;
+
+ status = lookup_dev(param.rec_id, &rec_f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ param.rec_id = index;
+ f = rec_f;
+ }
+
+ /* Normalize play_id */
+ if (param.dir & PJMEDIA_DIR_PLAYBACK) {
+ unsigned index;
+
+ if (param.play_id < 0)
+ param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;
+
+ status = lookup_dev(param.play_id, &play_f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ param.play_id = index;
+ f = play_f;
+ }
+
+ PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);
+
+ /* For now, rec_id and play_id must belong to the same factory */
+ PJ_ASSERT_RETURN((param.dir != PJMEDIA_DIR_CAPTURE_PLAYBACK) ||
+ (rec_f == play_f),
+ PJMEDIA_EAUD_INVDEV);
+
+ /* Create the stream */
+ status = f->op->create_stream(f, &param, rec_cb, play_cb,
+ user_data, p_aud_strm);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Assign factory id to the stream */
+ (*p_aud_strm)->sys.drv_idx = f->sys.drv_idx;
+ return PJ_SUCCESS;
+}
+
+/* API: Get the running parameters for the specified audio stream. */
+PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm,
+ pjmedia_aud_param *param)
+{
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);
+ PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);
+
+ status = strm->op->get_param(strm, param);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Normalize device id's */
+ make_global_index(strm->sys.drv_idx, &param->rec_id);
+ make_global_index(strm->sys.drv_idx, &param->play_id);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Get the value of a specific capability of the audio stream. */
+PJ_DEF(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm,
+ pjmedia_aud_dev_cap cap,
+ void *value)
+{
+ return strm->op->get_cap(strm, cap, value);
+}
+
+/* API: Set the value of a specific capability of the audio stream. */
+PJ_DEF(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm,
+ pjmedia_aud_dev_cap cap,
+ const void *value)
+{
+ return strm->op->set_cap(strm, cap, value);
+}
+
+/* API: Start the stream. */
+PJ_DEF(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm)
+{
+ return strm->op->start(strm);
+}
+
+/* API: Stop the stream. */
+PJ_DEF(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm)
+{
+ return strm->op->stop(strm);
+}
+
+/* API: Destroy the stream. */
+PJ_DEF(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm)
+{
+ return strm->op->destroy(strm);
+}
+
+
diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c
index 650c71d8..82d7d568 100644
--- a/pjmedia/src/pjmedia/endpoint.c
+++ b/pjmedia/src/pjmedia/endpoint.c
@@ -105,10 +105,10 @@ struct pjmedia_endpt
/**
* Initialize and get the instance of media endpoint.
*/
-PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
- pj_ioqueue_t *ioqueue,
- unsigned worker_cnt,
- pjmedia_endpt **p_endpt)
+PJ_DEF(pj_status_t) pjmedia_endpt_create2(pj_pool_factory *pf,
+ pj_ioqueue_t *ioqueue,
+ unsigned worker_cnt,
+ pjmedia_endpt **p_endpt)
{
pj_pool_t *pool;
pjmedia_endpt *endpt;
@@ -133,10 +133,15 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
endpt->thread_cnt = worker_cnt;
endpt->has_telephone_event = PJ_TRUE;
- /* Sound */
- status = pjmedia_aud_subsys_init(pf);
- if (status != PJ_SUCCESS)
- goto on_error;
+ /* Initialize audio subsystem.
+ * To avoid pjmedia's dependendy on pjmedia-audiodev, the initialization
+ * (and shutdown) of audio subsystem will be done in the application
+ * level instead, when it calls inline functions pjmedia_endpt_create()
+ * and pjmedia_endpt_destroy().
+ */
+ //status = pjmedia_aud_subsys_init(pf);
+ //if (status != PJ_SUCCESS)
+ // goto on_error;
/* Init codec manager. */
status = pjmedia_codec_mgr_init(&endpt->codec_mgr, endpt->pf);
@@ -188,7 +193,7 @@ on_error:
pj_ioqueue_destroy(endpt->ioqueue);
pjmedia_codec_mgr_destroy(&endpt->codec_mgr);
- pjmedia_aud_subsys_shutdown();
+ //pjmedia_aud_subsys_shutdown();
pj_pool_release(pool);
return status;
}
@@ -204,7 +209,7 @@ PJ_DEF(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt)
/**
* Deinitialize media endpoint.
*/
-PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
+PJ_DEF(pj_status_t) pjmedia_endpt_destroy2 (pjmedia_endpt *endpt)
{
exit_cb *ecb;
@@ -219,7 +224,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
endpt->pf = NULL;
pjmedia_codec_mgr_destroy(&endpt->codec_mgr);
- pjmedia_aud_subsys_shutdown();
+ //pjmedia_aud_subsys_shutdown();
/* Call all registered exit callbacks */
ecb = endpt->exit_cb_list.next;
diff --git a/pjmedia/src/pjmedia/sound_legacy.c b/pjmedia/src/pjmedia/sound_legacy.c
index d5bcf3dc..ee9dd027 100644
--- a/pjmedia/src/pjmedia/sound_legacy.c
+++ b/pjmedia/src/pjmedia/sound_legacy.c
@@ -27,7 +27,6 @@
*/
#include <pjmedia/sound.h>
-#include <pjmedia-audiodev/errno.h>
#include <pj/assert.h>
#if PJMEDIA_HAS_LEGACY_SOUND_API
@@ -49,20 +48,6 @@ struct pjmedia_snd_stream
void *user_user_data;
};
-PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)
-{
- return pjmedia_aud_subsys_init(factory);
-}
-
-PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)
-{
- return pjmedia_aud_subsys_shutdown();
-}
-
-PJ_DEF(int) pjmedia_snd_get_dev_count(void)
-{
- return pjmedia_aud_dev_count();
-}
PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
{
@@ -158,7 +143,7 @@ static pj_status_t open_stream( pjmedia_dir dir,
}
/* Create sound wrapper */
- pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(),
+ pool = pj_pool_create(pjmedia_get_aud_subsys()->pf,
"legacy-snd", 512, 512, NULL);
snd_strm = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_stream);
snd_strm->pool = pool;
diff --git a/pjmedia/src/pjmedia/videodev.c b/pjmedia/src/pjmedia/videodev.c
new file mode 100644
index 00000000..84d26069
--- /dev/null
+++ b/pjmedia/src/pjmedia/videodev.c
@@ -0,0 +1,699 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 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
+ */
+#include <pjmedia-videodev/videodev_imp.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+
+
+#define THIS_FILE "videodev.c"
+
+#define DEFINE_CAP(name, info) {name, info}
+
+/* Capability names */
+static struct cap_info
+{
+ const char *name;
+ const char *info;
+} cap_infos[] =
+{
+ DEFINE_CAP("format", "Video format"),
+ DEFINE_CAP("scale", "Input dimension"),
+ DEFINE_CAP("window", "Window handle"),
+ DEFINE_CAP("resize", "Renderer resize"),
+ DEFINE_CAP("position", "Renderer position"),
+ DEFINE_CAP("hide", "Renderer hide"),
+ DEFINE_CAP("preview", "Input preview"),
+ DEFINE_CAP("orientation", "Video orientation"),
+ DEFINE_CAP("switch", "Switch device"),
+ DEFINE_CAP("wndflags", "Window flags")
+};
+
+
+/*
+ * The device index seen by application and driver is different.
+ *
+ * At application level, device index is index to global list of device.
+ * At driver level, device index is index to device list on that particular
+ * factory only.
+ */
+#define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))
+#define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)
+#define GET_FID(dev_id) ((dev_id) >> 16)
+#define DEFAULT_DEV_ID 0
+
+
+#define MAX_DRIVERS PJMEDIA_VID_DEV_MAX_DRIVERS
+#define MAX_DEVS PJMEDIA_VID_DEV_MAX_DEVS
+
+static pjmedia_vid_subsys vid_subsys;
+
+
+/* API: get the video subsystem. */
+PJ_DEF(pjmedia_vid_subsys*) pjmedia_get_vid_subsys(void)
+{
+ return &vid_subsys;
+}
+
+
+/* API: get capability name/info */
+PJ_DEF(const char*) pjmedia_vid_dev_cap_name(pjmedia_vid_dev_cap cap,
+ const char **p_desc)
+{
+ const char *desc;
+ unsigned i;
+
+ if (p_desc==NULL) p_desc = &desc;
+
+ for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {
+ if ((1 << i)==cap)
+ break;
+ }
+
+ if (i==PJ_ARRAY_SIZE(cap_infos)) {
+ *p_desc = "??";
+ return "??";
+ }
+
+ *p_desc = cap_infos[i].info;
+ return cap_infos[i].name;
+}
+
+static pj_status_t get_cap_pointer(const pjmedia_vid_dev_param *param,
+ pjmedia_vid_dev_cap cap,
+ void **ptr,
+ unsigned *size)
+{
+#define FIELD_INFO(name) *ptr = (void*)&param->name; \
+ *size = sizeof(param->name)
+
+ switch (cap) {
+ case PJMEDIA_VID_DEV_CAP_FORMAT:
+ FIELD_INFO(fmt);
+ break;
+ case PJMEDIA_VID_DEV_CAP_INPUT_SCALE:
+ FIELD_INFO(disp_size);
+ break;
+ case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW:
+ FIELD_INFO(window);
+ break;
+ case PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE:
+ FIELD_INFO(disp_size);
+ break;
+ case PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION:
+ FIELD_INFO(window_pos);
+ break;
+ case PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE:
+ FIELD_INFO(window_hide);
+ break;
+ case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW:
+ FIELD_INFO(native_preview);
+ break;
+ case PJMEDIA_VID_DEV_CAP_ORIENTATION:
+ FIELD_INFO(orient);
+ break;
+ /* The PJMEDIA_VID_DEV_CAP_SWITCH does not have an entry in the
+ * param (it doesn't make sense to open a stream and tell it
+ * to switch immediately).
+ */
+ case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS:
+ FIELD_INFO(window_flags);
+ break;
+ default:
+ return PJMEDIA_EVID_INVCAP;
+ }
+
+#undef FIELD_INFO
+
+ return PJ_SUCCESS;
+}
+
+/* API: set cap value to param */
+PJ_DEF(pj_status_t)
+pjmedia_vid_dev_param_set_cap( pjmedia_vid_dev_param *param,
+ pjmedia_vid_dev_cap cap,
+ const void *pval)
+{
+ void *cap_ptr;
+ unsigned cap_size;
+ pj_status_t status;
+
+ status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ pj_memcpy(cap_ptr, pval, cap_size);
+ param->flags |= cap;
+
+ return PJ_SUCCESS;
+}
+
+/* API: get cap value from param */
+PJ_DEF(pj_status_t)
+pjmedia_vid_dev_param_get_cap( const pjmedia_vid_dev_param *param,
+ pjmedia_vid_dev_cap cap,
+ void *pval)
+{
+ void *cap_ptr;
+ unsigned cap_size;
+ pj_status_t status;
+
+ status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ if ((param->flags & cap) == 0) {
+ pj_bzero(cap_ptr, cap_size);
+ return PJMEDIA_EVID_INVCAP;
+ }
+
+ pj_memcpy(pval, cap_ptr, cap_size);
+ return PJ_SUCCESS;
+}
+
+/* API: init driver */
+PJ_DEF(pj_status_t) pjmedia_vid_driver_init(unsigned drv_idx,
+ pj_bool_t refresh)
+{
+ pjmedia_vid_driver *drv = &vid_subsys.drv[drv_idx];
+ pjmedia_vid_dev_factory *f;
+ unsigned i, dev_cnt;
+ pj_status_t status;
+
+ if (!refresh) {
+ /* Create the factory */
+ f = (*drv->create)(vid_subsys.pf);
+ if (!f)
+ return PJ_EUNKNOWN;
+
+ /* Call factory->init() */
+ status = f->op->init(f);
+ if (status != PJ_SUCCESS) {
+ f->op->destroy(f);
+ return status;
+ }
+ } else {
+ f = drv->f;
+ }
+
+ /* Get number of devices */
+ dev_cnt = f->op->get_dev_count(f);
+ if (dev_cnt + vid_subsys.dev_cnt > MAX_DEVS) {
+ PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"
+ " there are too many devices",
+ vid_subsys.dev_cnt + dev_cnt - MAX_DEVS));
+ dev_cnt = MAX_DEVS - vid_subsys.dev_cnt;
+ }
+
+ /* enabling this will cause pjsua-lib initialization to fail when there
+ * is no video device installed in the system, even when pjsua has been
+ * run with --null-video
+ *
+ if (dev_cnt == 0) {
+ f->op->destroy(f);
+ return PJMEDIA_EVID_NODEV;
+ }
+ */
+
+ /* Fill in default devices */
+ drv->rend_dev_idx = drv->cap_dev_idx = -1;
+ for (i=0; i<dev_cnt; ++i) {
+ pjmedia_vid_dev_info info;
+
+ status = f->op->get_dev_info(f, i, &info);
+ if (status != PJ_SUCCESS) {
+ f->op->destroy(f);
+ return status;
+ }
+
+ if (drv->name[0]=='\0') {
+ /* Set driver name */
+ pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));
+ drv->name[sizeof(drv->name)-1] = '\0';
+ }
+
+ if (drv->rend_dev_idx < 0 && (info.dir & PJMEDIA_DIR_RENDER)) {
+ /* Set default render device */
+ drv->rend_dev_idx = i;
+ }
+ if (drv->cap_dev_idx < 0 && (info.dir & PJMEDIA_DIR_CAPTURE)) {
+ /* Set default capture device */
+ drv->cap_dev_idx = i;
+ }
+
+ if (drv->rend_dev_idx >= 0 && drv->cap_dev_idx >= 0) {
+ /* Done. */
+ break;
+ }
+ }
+
+ /* Register the factory */
+ drv->f = f;
+ drv->f->sys.drv_idx = drv_idx;
+ drv->start_idx = vid_subsys.dev_cnt;
+ drv->dev_cnt = dev_cnt;
+
+ /* Register devices to global list */
+ for (i=0; i<dev_cnt; ++i) {
+ vid_subsys.dev_list[vid_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);
+ }
+
+ return PJ_SUCCESS;
+}
+
+/* API: deinit driver */
+PJ_DEF(void) pjmedia_vid_driver_deinit(unsigned drv_idx)
+{
+ pjmedia_vid_driver *drv = &vid_subsys.drv[drv_idx];
+
+ if (drv->f) {
+ drv->f->op->destroy(drv->f);
+ drv->f = NULL;
+ }
+
+ drv->dev_cnt = 0;
+ drv->rend_dev_idx = drv->cap_dev_idx = -1;
+}
+
+
+/* API: Refresh the list of video devices installed in the system. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_refresh(void)
+{
+ unsigned i;
+
+ vid_subsys.dev_cnt = 0;
+ for (i=0; i<vid_subsys.drv_cnt; ++i) {
+ pjmedia_vid_driver *drv = &vid_subsys.drv[i];
+
+ if (drv->f && drv->f->op->refresh) {
+ pj_status_t status = drv->f->op->refresh(drv->f);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "
+ "list for %s", drv->name));
+ }
+ }
+ pjmedia_vid_driver_init(i, PJ_TRUE);
+ }
+ return PJ_SUCCESS;
+}
+
+/* API: Get the number of video devices installed in the system. */
+PJ_DEF(unsigned) pjmedia_vid_dev_count(void)
+{
+ return vid_subsys.dev_cnt;
+}
+
+/* Internal: convert local index to global device index */
+static pj_status_t make_global_index(unsigned drv_idx,
+ pjmedia_vid_dev_index *id)
+{
+ if (*id < 0) {
+ return PJ_SUCCESS;
+ }
+
+ /* Check that factory still exists */
+ PJ_ASSERT_RETURN(vid_subsys.drv[drv_idx].f, PJ_EBUG);
+
+ /* Check that device index is valid */
+ PJ_ASSERT_RETURN(*id>=0 && *id<(int)vid_subsys.drv[drv_idx].dev_cnt,
+ PJ_EBUG);
+
+ *id += vid_subsys.drv[drv_idx].start_idx;
+ return PJ_SUCCESS;
+}
+
+/* Internal: lookup device id */
+static pj_status_t lookup_dev(pjmedia_vid_dev_index id,
+ pjmedia_vid_dev_factory **p_f,
+ unsigned *p_local_index)
+{
+ int f_id, index;
+
+ if (id < 0) {
+ unsigned i;
+
+ if (id <= PJMEDIA_VID_INVALID_DEV)
+ return PJMEDIA_EVID_INVDEV;
+
+ for (i=0; i<vid_subsys.drv_cnt; ++i) {
+ pjmedia_vid_driver *drv = &vid_subsys.drv[i];
+ if (id==PJMEDIA_VID_DEFAULT_CAPTURE_DEV &&
+ drv->cap_dev_idx >= 0)
+ {
+ id = drv->cap_dev_idx;
+ make_global_index(i, &id);
+ break;
+ } else if (id==PJMEDIA_VID_DEFAULT_RENDER_DEV &&
+ drv->rend_dev_idx >= 0)
+ {
+ id = drv->rend_dev_idx;
+ make_global_index(i, &id);
+ break;
+ }
+ }
+
+ if (id < 0) {
+ return PJMEDIA_EVID_NODEFDEV;
+ }
+ }
+
+ f_id = GET_FID(vid_subsys.dev_list[id]);
+ index = GET_INDEX(vid_subsys.dev_list[id]);
+
+ if (f_id < 0 || f_id >= (int)vid_subsys.drv_cnt)
+ return PJMEDIA_EVID_INVDEV;
+
+ if (index < 0 || index >= (int)vid_subsys.drv[f_id].dev_cnt)
+ return PJMEDIA_EVID_INVDEV;
+
+ *p_f = vid_subsys.drv[f_id].f;
+ *p_local_index = (unsigned)index;
+
+ return PJ_SUCCESS;
+
+}
+
+/* API: lookup device id */
+PJ_DEF(pj_status_t)
+pjmedia_vid_dev_get_local_index(pjmedia_vid_dev_index id,
+ pjmedia_vid_dev_factory **p_f,
+ unsigned *p_local_index)
+{
+ return lookup_dev(id, p_f, p_local_index);
+}
+
+/* API: from factory and local index, get global index */
+PJ_DEF(pj_status_t)
+pjmedia_vid_dev_get_global_index(const pjmedia_vid_dev_factory *f,
+ unsigned local_idx,
+ pjmedia_vid_dev_index *pid)
+{
+ PJ_ASSERT_RETURN(f->sys.drv_idx >= 0 && f->sys.drv_idx < MAX_DRIVERS,
+ PJ_EINVALIDOP);
+ *pid = local_idx;
+ return make_global_index(f->sys.drv_idx, pid);
+}
+
+/* API: Get device information. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_get_info(pjmedia_vid_dev_index id,
+ pjmedia_vid_dev_info *info)
+{
+ pjmedia_vid_dev_factory *f;
+ unsigned index;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(info, PJ_EINVAL);
+ PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
+
+ if (id <= PJMEDIA_VID_INVALID_DEV)
+ return PJMEDIA_EVID_INVDEV;
+
+ status = lookup_dev(id, &f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = f->op->get_dev_info(f, index, info);
+
+ /* Make sure device ID is the real ID (not PJMEDIA_VID_DEFAULT_*_DEV) */
+ info->id = index;
+ make_global_index(f->sys.drv_idx, &info->id);
+
+ return status;
+}
+
+/* API: find device */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_lookup( const char *drv_name,
+ const char *dev_name,
+ pjmedia_vid_dev_index *id)
+{
+ pjmedia_vid_dev_factory *f = NULL;
+ unsigned drv_idx, dev_idx;
+
+ PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);
+ PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
+
+ for (drv_idx=0; drv_idx<vid_subsys.drv_cnt; ++drv_idx) {
+ if (!pj_ansi_stricmp(drv_name, vid_subsys.drv[drv_idx].name))
+ {
+ f = vid_subsys.drv[drv_idx].f;
+ break;
+ }
+ }
+
+ if (!f)
+ return PJ_ENOTFOUND;
+
+ for (dev_idx=0; dev_idx<vid_subsys.drv[drv_idx].dev_cnt; ++dev_idx)
+ {
+ pjmedia_vid_dev_info info;
+ pj_status_t status;
+
+ status = f->op->get_dev_info(f, dev_idx, &info);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ if (!pj_ansi_stricmp(dev_name, info.name))
+ break;
+ }
+
+ if (dev_idx==vid_subsys.drv[drv_idx].dev_cnt)
+ return PJ_ENOTFOUND;
+
+ *id = dev_idx;
+ make_global_index(drv_idx, id);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Initialize the video device parameters with default values for the
+ * specified device.
+ */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_default_param(pj_pool_t *pool,
+ pjmedia_vid_dev_index id,
+ pjmedia_vid_dev_param *param)
+{
+ pjmedia_vid_dev_factory *f;
+ unsigned index;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(param, PJ_EINVAL);
+ PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
+
+ if (id <= PJMEDIA_VID_INVALID_DEV)
+ return PJMEDIA_EVID_INVDEV;
+
+ status = lookup_dev(id, &f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = f->op->default_param(pool, f, index, param);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Normalize device IDs */
+ make_global_index(f->sys.drv_idx, &param->cap_id);
+ make_global_index(f->sys.drv_idx, &param->rend_id);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Open video stream object using the specified parameters. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_create(
+ pjmedia_vid_dev_param *prm,
+ const pjmedia_vid_dev_cb *cb,
+ void *user_data,
+ pjmedia_vid_dev_stream **p_vid_strm)
+{
+ pjmedia_vid_dev_factory *cap_f=NULL, *rend_f=NULL, *f=NULL;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(prm && prm->dir && p_vid_strm, PJ_EINVAL);
+ PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
+ PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||
+ prm->dir==PJMEDIA_DIR_RENDER ||
+ prm->dir==PJMEDIA_DIR_CAPTURE_RENDER,
+ PJ_EINVAL);
+
+ /* Normalize cap_id */
+ if (prm->dir & PJMEDIA_DIR_CAPTURE) {
+ unsigned index;
+
+ if (prm->cap_id < 0)
+ prm->cap_id = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
+
+ status = lookup_dev(prm->cap_id, &cap_f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ prm->cap_id = index;
+ f = cap_f;
+ }
+
+ /* Normalize rend_id */
+ if (prm->dir & PJMEDIA_DIR_RENDER) {
+ unsigned index;
+
+ if (prm->rend_id < 0)
+ prm->rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV;
+
+ status = lookup_dev(prm->rend_id, &rend_f, &index);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ prm->rend_id = index;
+ f = rend_f;
+ }
+
+ PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);
+
+ /* For now, cap_id and rend_id must belong to the same factory */
+ PJ_ASSERT_RETURN((prm->dir != PJMEDIA_DIR_CAPTURE_RENDER) ||
+ (cap_f == rend_f),
+ PJMEDIA_EVID_INVDEV);
+
+ /* Create the stream */
+ status = f->op->create_stream(f, prm, cb,
+ user_data, p_vid_strm);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Assign factory id to the stream */
+ (*p_vid_strm)->sys.drv_idx = f->sys.drv_idx;
+ return PJ_SUCCESS;
+}
+
+/* API: Get the running parameters for the specified video stream. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_param(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_vid_dev_param *param)
+{
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);
+ PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);
+
+ status = strm->op->get_param(strm, param);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Normalize device id's */
+ make_global_index(strm->sys.drv_idx, &param->cap_id);
+ make_global_index(strm->sys.drv_idx, &param->rend_id);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Get the value of a specific capability of the video stream. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_cap(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_vid_dev_cap cap,
+ void *value)
+{
+ return strm->op->get_cap(strm, cap, value);
+}
+
+/* API: Set the value of a specific capability of the video stream. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_set_cap(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_vid_dev_cap cap,
+ const void *value)
+{
+ /* For fast switching, device global index needs to be converted to
+ * local index before forwarding the request to the device stream.
+ */
+ if (cap == PJMEDIA_VID_DEV_CAP_SWITCH) {
+ pjmedia_vid_dev_factory *f;
+ unsigned local_idx;
+ pj_status_t status;
+ pjmedia_vid_dev_switch_param p = *(pjmedia_vid_dev_switch_param*)value;
+
+ status = lookup_dev(p.target_id, &f, &local_idx);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Make sure that current & target devices share the same factory */
+ if (f->sys.drv_idx != strm->sys.drv_idx)
+ return PJMEDIA_EVID_INVDEV;
+
+ p.target_id = local_idx;
+ return strm->op->set_cap(strm, cap, &p);
+ }
+
+ return strm->op->set_cap(strm, cap, value);
+}
+
+/* API: Start the stream. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_start(pjmedia_vid_dev_stream *strm)
+{
+ pj_status_t status;
+
+ if (pjmedia_vid_dev_stream_is_running(strm))
+ return PJ_SUCCESS;
+
+ status = strm->op->start(strm);
+ if (status == PJ_SUCCESS)
+ strm->sys.is_running = PJ_TRUE;
+ return status;
+}
+
+/* API: has it been started? */
+PJ_DEF(pj_bool_t)
+pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm)
+{
+ return strm->sys.is_running;
+}
+
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_frame(
+ pjmedia_vid_dev_stream *strm,
+ pjmedia_frame *frame)
+{
+ pj_assert(strm->op->get_frame);
+ return strm->op->get_frame(strm, frame);
+}
+
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_put_frame(
+ pjmedia_vid_dev_stream *strm,
+ const pjmedia_frame *frame)
+{
+ pj_assert(strm->op->put_frame);
+ return strm->op->put_frame(strm, frame);
+}
+
+/* API: Stop the stream. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_stop(pjmedia_vid_dev_stream *strm)
+{
+ strm->sys.is_running = PJ_FALSE;
+ return strm->op->stop(strm);
+}
+
+/* API: Destroy the stream. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_destroy(
+ pjmedia_vid_dev_stream *strm)
+{
+ strm->sys.is_running = PJ_FALSE;
+ return strm->op->destroy(strm);
+}
+
+
+#endif /* PJMEDIA_HAS_VIDEO */