Fixed #1907: Remove pjmedia* circular dependency
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5255 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
0b33ce5ea5
commit
b1f406ce4f
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
@ -557,167 +100,6 @@ PJ_DECL(pj_status_t)
|
|||
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);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
@ -609,226 +110,6 @@ pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr vdf,
|
|||
pjmedia_vid_dev_factory *factory);
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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__ */
|
||||
|
|
@ -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,11 +82,51 @@ 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.
|
||||
*
|
||||
|
@ -93,7 +134,25 @@ PJ_DECL(pj_status_t) pjmedia_endpt_create( pj_pool_factory *pf,
|
|||
*
|
||||
* @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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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__ */
|
|
@ -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*)¶m->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) {
|
||||
if (aud_subsys->init_count == 0) {
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
--aud_subsys.init_count;
|
||||
--aud_subsys->init_count;
|
||||
|
||||
if (aud_subsys.init_count == 0) {
|
||||
for (i=0; i<aud_subsys.drv_cnt; ++i) {
|
||||
deinit_driver(i);
|
||||
if (aud_subsys->init_count == 0) {
|
||||
for (i=0; i<aud_subsys->drv_cnt; ++i) {
|
||||
pjmedia_aud_driver_deinit(i);
|
||||
}
|
||||
|
||||
aud_subsys.pf = NULL;
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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, ¶m->rec_id);
|
||||
make_global_index(f->sys.drv_idx, ¶m->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(¶m, 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, ¶m, 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, ¶m->rec_id);
|
||||
make_global_index(strm->sys.drv_idx, ¶m->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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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*)¶m->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;
|
||||
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, ¶m->cap_id);
|
||||
make_global_index(f->sys.drv_idx, ¶m->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, ¶m->cap_id);
|
||||
make_global_index(strm->sys.drv_idx, ¶m->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 */
|
||||
|
|
|
@ -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*)¶m->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, ¶m->rec_id);
|
||||
make_global_index(f->sys.drv_idx, ¶m->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(¶m, 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, ¶m, 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, ¶m->rec_id);
|
||||
make_global_index(strm->sys.drv_idx, ¶m->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);
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*)¶m->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, ¶m->cap_id);
|
||||
make_global_index(f->sys.drv_idx, ¶m->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, ¶m->cap_id);
|
||||
make_global_index(strm->sys.drv_idx, ¶m->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 */
|
Loading…
Reference in New Issue