- Timestamp:
- Mar 10, 2016 5:02:07 AM (9 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 4 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/Makefile
r5239 r5255 76 76 vid_port.o vid_stream.o vid_stream_info.o vid_tee.o \ 77 77 wav_player.o wav_playlist.o wav_writer.o wave.o \ 78 wsola.o 78 wsola.o audiodev.o videodev.o 79 79 80 80 export PJMEDIA_CFLAGS += $(_CFLAGS) 81 81 export PJMEDIA_CXXFLAGS += $(_CXXFLAGS) 82 export PJMEDIA_LDFLAGS += $(PJMEDIA_VIDEODEV_LDLIB) \ 83 $(PJMEDIA_AUDIODEV_LDLIB) \ 84 $(PJLIB_LDLIB) \ 82 export PJMEDIA_LDFLAGS += $(PJLIB_LDLIB) \ 85 83 $(PJLIB_UTIL_LDLIB) \ 86 84 $(PJNATH_LDLIB) \ … … 98 96 export PJMEDIA_AUDIODEV_CFLAGS += $(_CFLAGS) 99 97 export PJMEDIA_AUDIODEV_CXXFLAGS += $(_CXXFLAGS) 100 export PJMEDIA_AUDIODEV_LDFLAGS += $(PJLIB_LDLIB) \ 98 export PJMEDIA_AUDIODEV_LDFLAGS += $(PJMEDIA_LDLIB) \ 99 $(PJLIB_LDLIB) \ 101 100 $(_LDFLAGS) 102 101 … … 106 105 # 107 106 export PJMEDIA_VIDEODEV_SRCDIR = ../src/pjmedia-videodev 108 export PJMEDIA_VIDEODEV_OBJS += errno.o videodev.o avi_dev.o ffmpeg_dev.o \107 export PJMEDIA_VIDEODEV_OBJS += videodev.o errno.o avi_dev.o ffmpeg_dev.o \ 109 108 colorbar_dev.o v4l2_dev.o opengl_dev.o \ 110 109 util.o 111 110 export PJMEDIA_VIDEODEV_CFLAGS += $(_CFLAGS) 112 111 export PJMEDIA_VIDEODEV_CXXFLAGS += $(_CXXFLAGS) 113 export PJMEDIA_VIDEODEV_LDFLAGS += $(PJLIB_LDLIB) \ 112 export PJMEDIA_VIDEODEV_LDFLAGS += $(PJMEDIA_LDLIB) \ 113 $(PJLIB_LDLIB) \ 114 114 $(_LDFLAGS) 115 115 … … 212 212 pjmedia: $(PJMEDIA_LIB) 213 213 $(PJMEDIA_SONAME): $(PJMEDIA_LIB) 214 $(PJMEDIA_LIB) $(PJMEDIA_SONAME): $(PJMEDIA_AUDIODEV_LIB) $(PJMEDIA_AUDIODEV_SONAME) $(PJMEDIA_VIDEODEV_LIB) $(PJMEDIA_VIDEODEV_SONAME)214 $(PJMEDIA_LIB) $(PJMEDIA_SONAME): 215 215 $(MAKE) -f $(RULES_MAK) APP=PJMEDIA app=pjmedia $(subst /,$(HOST_PSEP),$(LIBDIR)/$@) 216 216 … … 222 222 pjmedia-videodev: $(PJMEDIA_VIDEODEV_LIB) 223 223 $(PJMEDIA_VIDEODEV_SONAME): $(PJMEDIA_VIDEODEV_LIB) 224 $(PJMEDIA_VIDEODEV_LIB) $(PJMEDIA_VIDEODEV_SONAME): 224 $(PJMEDIA_VIDEODEV_LIB) $(PJMEDIA_VIDEODEV_SONAME): $(PJMEDIA_LIB) $(PJMEDIA_SONAME) 225 225 $(MAKE) -f $(RULES_MAK) APP=PJMEDIA_VIDEODEV app=pjmedia-videodev $(subst /,$(HOST_PSEP),$(LIBDIR)/$@) 226 226 227 227 pjmedia-audiodev: $(PJMEDIA_AUDIODEV_LIB) 228 228 $(PJMEDIA_AUDIODEV_SONAME): $(PJMEDIA_AUDIODEV_LIB) 229 $(PJMEDIA_AUDIODEV_LIB) $(PJMEDIA_AUDIODEV_SONAME): 229 $(PJMEDIA_AUDIODEV_LIB) $(PJMEDIA_AUDIODEV_SONAME): $(PJMEDIA_LIB) $(PJMEDIA_SONAME) 230 230 $(MAKE) -f $(RULES_MAK) APP=PJMEDIA_AUDIODEV app=pjmedia-audiodev $(subst /,$(HOST_PSEP),$(LIBDIR)/$@) 231 231 -
pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev.h
r5201 r5255 23 23 /** 24 24 * @file audiodev.h 25 * @brief Audio deviceAPI.25 * @brief Audio subsystem API. 26 26 */ 27 #include <pjmedia-audiodev/config.h>28 #include <pjmedia-audiodev/errno.h>29 #include <pjmedia/format.h>30 #include <pjmedia/frame.h>31 #include <pjmedia/types.h>32 27 #include <pj/pool.h> 28 #include <pjmedia/audiodev.h> 33 29 34 30 … … 36 32 37 33 /** 38 * @defgroup s2_audio_device_reference Audio DeviceAPI Reference39 * @ingroup audio_ device_api34 * @defgroup s2_audio_device_reference Audio Subsystem API Reference 35 * @ingroup audio_subsystem_api 40 36 * @brief API Reference 41 37 * @{ 42 38 */ 43 39 44 /**45 * Type for device index.46 */47 typedef pj_int32_t pjmedia_aud_dev_index;48 49 /**50 * Device index constants.51 */52 enum53 {54 /**55 * Constant to denote default capture device56 */57 PJMEDIA_AUD_DEFAULT_CAPTURE_DEV = -1,58 59 /**60 * Constant to denote default playback device61 */62 PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV = -2,63 64 /**65 * Constant to denote invalid device index.66 */67 PJMEDIA_AUD_INVALID_DEV = -368 };69 70 71 /**72 * This enumeration identifies various audio device capabilities. These audio73 * capabilities indicates what features are supported by the underlying74 * audio device implementation.75 *76 * Applications get these capabilities in the #pjmedia_aud_dev_info structure.77 *78 * Application can also set the specific features/capabilities when opening79 * the audio stream by setting the \a flags member of #pjmedia_aud_param80 * structure.81 *82 * Once audio stream is running, application can also retrieve or set some83 * specific audio capability, by using #pjmedia_aud_stream_get_cap() and84 * #pjmedia_aud_stream_set_cap() and specifying the desired capability. The85 * value of the capability is specified as pointer, and application needs to86 * supply the pointer with the correct value, according to the documentation87 * of each of the capability.88 */89 typedef enum pjmedia_aud_dev_cap90 {91 /**92 * Support for audio formats other than PCM. The value of this capability93 * is represented by #pjmedia_format structure.94 */95 PJMEDIA_AUD_DEV_CAP_EXT_FORMAT = 1,96 97 /**98 * Support for audio input latency control or query. The value of this99 * capability is an unsigned integer containing milliseconds value of100 * the latency.101 */102 PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY = 2,103 104 /**105 * Support for audio output latency control or query. The value of this106 * capability is an unsigned integer containing milliseconds value of107 * the latency.108 */109 PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY = 4,110 111 /**112 * Support for setting/retrieving the audio input device volume level.113 * The value of this capability is an unsigned integer representing114 * the input audio volume setting in percent.115 */116 PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING = 8,117 118 /**119 * Support for setting/retrieving the audio output device volume level.120 * The value of this capability is an unsigned integer representing121 * the output audio volume setting in percent.122 */123 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING = 16,124 125 /**126 * Support for monitoring the current audio input signal volume.127 * The value of this capability is an unsigned integer representing128 * the audio volume in percent.129 */130 PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER = 32,131 132 /**133 * Support for monitoring the current audio output signal volume.134 * The value of this capability is an unsigned integer representing135 * the audio volume in percent.136 */137 PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER = 64,138 139 /**140 * Support for audio input routing. The value of this capability is an141 * integer containing #pjmedia_aud_dev_route enumeration.142 */143 PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE = 128,144 145 /**146 * Support for audio output routing (e.g. loudspeaker vs earpiece). The147 * value of this capability is an integer containing #pjmedia_aud_dev_route148 * enumeration.149 */150 PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE = 256,151 152 /**153 * The audio device has echo cancellation feature. The value of this154 * capability is a pj_bool_t containing boolean PJ_TRUE or PJ_FALSE.155 */156 PJMEDIA_AUD_DEV_CAP_EC = 512,157 158 /**159 * The audio device supports setting echo cancellation fail length. The160 * value of this capability is an unsigned integer representing the161 * echo tail in milliseconds.162 */163 PJMEDIA_AUD_DEV_CAP_EC_TAIL = 1024,164 165 /**166 * The audio device has voice activity detection feature. The value167 * of this capability is a pj_bool_t containing boolean PJ_TRUE or168 * PJ_FALSE.169 */170 PJMEDIA_AUD_DEV_CAP_VAD = 2048,171 172 /**173 * The audio device has comfort noise generation feature. The value174 * of this capability is a pj_bool_t containing boolean PJ_TRUE or175 * PJ_FALSE.176 */177 PJMEDIA_AUD_DEV_CAP_CNG = 4096,178 179 /**180 * The audio device has packet loss concealment feature. The value181 * of this capability is a pj_bool_t containing boolean PJ_TRUE or182 * PJ_FALSE.183 */184 PJMEDIA_AUD_DEV_CAP_PLC = 8192,185 186 /**187 * End of capability188 */189 PJMEDIA_AUD_DEV_CAP_MAX = 16384190 191 } pjmedia_aud_dev_cap;192 193 194 /**195 * This enumeration describes audio routing setting.196 */197 typedef enum pjmedia_aud_dev_route198 {199 /**200 * Default route, it is the default audio route of the audio framework201 * backend, as in opening audio device without specifying any route202 * setting or with specifying neutral route setting.203 */204 PJMEDIA_AUD_DEV_ROUTE_DEFAULT = 0,205 206 /** Route to loudspeaker */207 PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER = 1,208 209 /** Route to earpiece */210 PJMEDIA_AUD_DEV_ROUTE_EARPIECE = 2,211 212 /** Route to paired Bluetooth device */213 PJMEDIA_AUD_DEV_ROUTE_BLUETOOTH = 4214 215 } pjmedia_aud_dev_route;216 217 218 /**219 * Device information structure returned by #pjmedia_aud_dev_get_info().220 */221 typedef struct pjmedia_aud_dev_info222 {223 /**224 * The device name225 */226 char name[PJMEDIA_AUD_DEV_INFO_NAME_LEN];227 228 /**229 * Maximum number of input channels supported by this device. If the230 * value is zero, the device does not support input operation (i.e.231 * it is a playback only device).232 */233 unsigned input_count;234 235 /**236 * Maximum number of output channels supported by this device. If the237 * value is zero, the device does not support output operation (i.e.238 * it is an input only device).239 */240 unsigned output_count;241 242 /**243 * Default sampling rate.244 */245 unsigned default_samples_per_sec;246 247 /**248 * The underlying driver name249 */250 char driver[32];251 252 /**253 * Device capabilities, as bitmask combination of #pjmedia_aud_dev_cap.254 */255 unsigned caps;256 257 /**258 * Supported audio device routes, as bitmask combination of259 * #pjmedia_aud_dev_route. The value may be zero if the device260 * does not support audio routing.261 */262 unsigned routes;263 264 /**265 * Number of audio formats supported by this device. The value may be266 * zero if the device does not support non-PCM format.267 */268 unsigned ext_fmt_cnt;269 270 /**271 * Array of supported extended audio formats272 */273 pjmedia_format ext_fmt[8];274 275 276 } pjmedia_aud_dev_info;277 278 279 /**280 * This callback is called by player stream when it needs additional data281 * to be played by the device. Application must fill in the whole of output282 * buffer with audio samples.283 *284 * The frame argument contains the following values:285 * - timestamp Playback timestamp, in samples.286 * - buf Buffer to be filled out by application.287 * - size The size requested in bytes, which will be equal to288 * the size of one whole packet.289 *290 * @param user_data User data associated with the stream.291 * @param frame Audio frame, which buffer is to be filled in by292 * the application.293 *294 * @return Returning non-PJ_SUCCESS will cause the audio stream295 * to stop296 */297 typedef pj_status_t (*pjmedia_aud_play_cb)(void *user_data,298 pjmedia_frame *frame);299 300 /**301 * This callback is called by recorder stream when it has captured the whole302 * packet worth of audio samples.303 *304 * @param user_data User data associated with the stream.305 * @param frame Captured frame.306 *307 * @return Returning non-PJ_SUCCESS will cause the audio stream308 * to stop309 */310 typedef pj_status_t (*pjmedia_aud_rec_cb)(void *user_data,311 pjmedia_frame *frame);312 313 /**314 * This structure specifies the parameters to open the audio stream.315 */316 typedef struct pjmedia_aud_param317 {318 /**319 * The audio direction. This setting is mandatory.320 */321 pjmedia_dir dir;322 323 /**324 * The audio recorder device ID. This setting is mandatory if the audio325 * direction includes input/capture direction.326 */327 pjmedia_aud_dev_index rec_id;328 329 /**330 * The audio playback device ID. This setting is mandatory if the audio331 * direction includes output/playback direction.332 */333 pjmedia_aud_dev_index play_id;334 335 /**336 * Clock rate/sampling rate. This setting is mandatory.337 */338 unsigned clock_rate;339 340 /**341 * Number of channels. This setting is mandatory.342 */343 unsigned channel_count;344 345 /**346 * Number of samples per frame. This setting is mandatory.347 */348 unsigned samples_per_frame;349 350 /**351 * Number of bits per sample. This setting is mandatory.352 */353 unsigned bits_per_sample;354 355 /**356 * This flags specifies which of the optional settings are valid in this357 * structure. The flags is bitmask combination of pjmedia_aud_dev_cap.358 */359 unsigned flags;360 361 /**362 * Set the audio format. This setting is optional, and will only be used363 * if PJMEDIA_AUD_DEV_CAP_EXT_FORMAT is set in the flags.364 */365 pjmedia_format ext_fmt;366 367 /**368 * Input latency, in milliseconds. This setting is optional, and will369 * only be used if PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY is set in the flags.370 */371 unsigned input_latency_ms;372 373 /**374 * Input latency, in milliseconds. This setting is optional, and will375 * only be used if PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY is set in the flags.376 */377 unsigned output_latency_ms;378 379 /**380 * Input volume setting, in percent. This setting is optional, and will381 * only be used if PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING is set in382 * the flags.383 */384 unsigned input_vol;385 386 /**387 * Output volume setting, in percent. This setting is optional, and will388 * only be used if PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING is set in389 * the flags.390 */391 unsigned output_vol;392 393 /**394 * Set the audio input route. This setting is optional, and will only be395 * used if PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE is set in the flags.396 */397 pjmedia_aud_dev_route input_route;398 399 /**400 * Set the audio output route. This setting is optional, and will only be401 * used if PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE is set in the flags.402 */403 pjmedia_aud_dev_route output_route;404 405 /**406 * Enable/disable echo canceller, if the device supports it. This setting407 * is optional, and will only be used if PJMEDIA_AUD_DEV_CAP_EC is set in408 * the flags.409 */410 pj_bool_t ec_enabled;411 412 /**413 * Set echo canceller tail length in milliseconds, if the device supports414 * it. This setting is optional, and will only be used if415 * PJMEDIA_AUD_DEV_CAP_EC_TAIL is set in the flags.416 */417 unsigned ec_tail_ms;418 419 /**420 * Enable/disable PLC. This setting is optional, and will only be used421 * if PJMEDIA_AUD_DEV_CAP_PLC is set in the flags.422 */423 pj_bool_t plc_enabled;424 425 /**426 * Enable/disable CNG. This setting is optional, and will only be used427 * if PJMEDIA_AUD_DEV_CAP_CNG is set in the flags.428 */429 pj_bool_t cng_enabled;430 431 /**432 * Enable/disable VAD. This setting is optional, and will only be used433 * if PJMEDIA_AUD_DEV_CAP_VAD is set in the flags.434 */435 pj_bool_t vad_enabled;436 437 } pjmedia_aud_param;438 439 440 /** Forward declaration for pjmedia_aud_stream */441 typedef struct pjmedia_aud_stream pjmedia_aud_stream;442 443 /** Forward declaration for audio device factory */444 typedef struct pjmedia_aud_dev_factory pjmedia_aud_dev_factory;445 446 /* typedef for factory creation function */447 typedef pjmedia_aud_dev_factory*448 (*pjmedia_aud_dev_factory_create_func_ptr)(pj_pool_factory*);449 450 451 /**452 * Get string info for the specified capability.453 *454 * @param cap The capability ID.455 * @param p_desc Optional pointer which will be filled with longer456 * description about the capability.457 *458 * @return Capability name.459 */460 PJ_DECL(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap,461 const char **p_desc);462 463 464 /**465 * Set a capability field value in #pjmedia_aud_param structure. This will466 * also set the flags field for the specified capability in the structure.467 *468 * @param param The structure.469 * @param cap The audio capability which value is to be set.470 * @param pval Pointer to value. Please see the type of value to471 * be supplied in the pjmedia_aud_dev_cap documentation.472 *473 * @return PJ_SUCCESS on successful operation or the appropriate474 * error code.475 */476 PJ_DECL(pj_status_t) pjmedia_aud_param_set_cap(pjmedia_aud_param *param,477 pjmedia_aud_dev_cap cap,478 const void *pval);479 480 481 /**482 * Get a capability field value from #pjmedia_aud_param structure. This483 * function will return PJMEDIA_EAUD_INVCAP error if the flag for that484 * capability is not set in the flags field in the structure.485 *486 * @param param The structure.487 * @param cap The audio capability which value is to be retrieved.488 * @param pval Pointer to value. Please see the type of value to489 * be supplied in the pjmedia_aud_dev_cap documentation.490 *491 * @return PJ_SUCCESS on successful operation or the appropriate492 * error code.493 */494 PJ_DECL(pj_status_t) pjmedia_aud_param_get_cap(const pjmedia_aud_param *param,495 pjmedia_aud_dev_cap cap,496 void *pval);497 40 498 41 /** … … 559 102 560 103 /** 561 * Refresh the list of sound devices installed in the system. This function562 * will only refresh the list of audio device so all active audio streams will563 * be unaffected. After refreshing the device list, application MUST make sure564 * to update all index references to audio devices (i.e. all variables of type565 * pjmedia_aud_dev_index) before calling any function that accepts audio device566 * index as its parameter.567 *568 * @return PJ_SUCCESS on successful operation or the appropriate569 * error code.570 */571 PJ_DECL(pj_status_t) pjmedia_aud_dev_refresh(void);572 573 574 /**575 * Get the number of sound devices installed in the system.576 *577 * @return The number of sound devices installed in the system.578 */579 PJ_DECL(unsigned) pjmedia_aud_dev_count(void);580 581 582 /**583 * Get device information.584 *585 * @param id The audio device ID.586 * @param info The device information which will be filled in by this587 * function once it returns successfully.588 *589 * @return PJ_SUCCESS on successful operation or the appropriate590 * error code.591 */592 PJ_DECL(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id,593 pjmedia_aud_dev_info *info);594 595 596 /**597 * Lookup device index based on the driver and device name.598 *599 * @param drv_name The driver name.600 * @param dev_name The device name.601 * @param id Pointer to store the returned device ID.602 *603 * @return PJ_SUCCESS if the device can be found.604 */605 PJ_DECL(pj_status_t) pjmedia_aud_dev_lookup(const char *drv_name,606 const char *dev_name,607 pjmedia_aud_dev_index *id);608 609 610 /**611 * Initialize the audio device parameters with default values for the612 * specified device.613 *614 * @param id The audio device ID.615 * @param param The audio device parameters which will be initialized616 * by this function once it returns successfully.617 *618 * @return PJ_SUCCESS on successful operation or the appropriate619 * error code.620 */621 PJ_DECL(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id,622 pjmedia_aud_param *param);623 624 625 /**626 * Open audio stream object using the specified parameters.627 *628 * @param param Sound device parameters to be used for the stream.629 * @param rec_cb Callback to be called on every input frame captured.630 * @param play_cb Callback to be called everytime the sound device needs631 * audio frames to be played back.632 * @param user_data Arbitrary user data, which will be given back in the633 * callbacks.634 * @param p_strm Pointer to receive the audio stream.635 *636 * @return PJ_SUCCESS on successful operation or the appropriate637 * error code.638 */639 PJ_DECL(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *param,640 pjmedia_aud_rec_cb rec_cb,641 pjmedia_aud_play_cb play_cb,642 void *user_data,643 pjmedia_aud_stream **p_strm);644 645 /**646 * Get the running parameters for the specified audio stream.647 *648 * @param strm The audio stream.649 * @param param Audio stream parameters to be filled in by this650 * function once it returns successfully.651 *652 * @return PJ_SUCCESS on successful operation or the appropriate653 * error code.654 */655 PJ_DECL(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm,656 pjmedia_aud_param *param);657 658 /**659 * Get the value of a specific capability of the audio stream.660 *661 * @param strm The audio stream.662 * @param cap The audio capability which value is to be retrieved.663 * @param value Pointer to value to be filled in by this function664 * once it returns successfully. Please see the type665 * of value to be supplied in the pjmedia_aud_dev_cap666 * documentation.667 *668 * @return PJ_SUCCESS on successful operation or the appropriate669 * error code.670 */671 PJ_DECL(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm,672 pjmedia_aud_dev_cap cap,673 void *value);674 675 /**676 * Set the value of a specific capability of the audio stream.677 *678 * @param strm The audio stream.679 * @param cap The audio capability which value is to be set.680 * @param value Pointer to value. Please see the type of value to681 * be supplied in the pjmedia_aud_dev_cap documentation.682 *683 * @return PJ_SUCCESS on successful operation or the appropriate684 * error code.685 */686 PJ_DECL(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm,687 pjmedia_aud_dev_cap cap,688 const void *value);689 690 /**691 * Start the stream.692 *693 * @param strm The audio stream.694 *695 * @return PJ_SUCCESS on successful operation or the appropriate696 * error code.697 */698 PJ_DECL(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm);699 700 /**701 * Stop the stream.702 *703 * @param strm The audio stream.704 *705 * @return PJ_SUCCESS on successful operation or the appropriate706 * error code.707 */708 PJ_DECL(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm);709 710 /**711 * Destroy the stream.712 *713 * @param strm The audio stream.714 *715 * @return PJ_SUCCESS on successful operation or the appropriate716 * error code.717 */718 PJ_DECL(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm);719 720 721 /**722 104 * @} 723 105 */ -
pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev.h
r5125 r5255 24 24 * @brief Video device API. 25 25 */ 26 #include <pjmedia-videodev/config.h> 27 #include <pjmedia-videodev/errno.h> 28 #include <pjmedia/event.h> 29 #include <pjmedia/frame.h> 30 #include <pjmedia/format.h> 31 #include <pj/pool.h> 26 #include <pjmedia/videodev.h> 32 27 33 28 … … 35 30 36 31 /** 37 * @defgroup video_device_reference Video DeviceAPI Reference38 * @ingroup video_ device_api32 * @defgroup video_device_reference Video Subsystem API Reference 33 * @ingroup video_subsystem_api 39 34 * @brief API Reference 40 35 * @{ 41 36 */ 42 37 43 /**44 * Type for device index.45 */46 typedef pj_int32_t pjmedia_vid_dev_index;47 48 /**49 * Enumeration of window handle type.50 */51 typedef enum pjmedia_vid_dev_hwnd_type52 {53 /**54 * Type none.55 */56 PJMEDIA_VID_DEV_HWND_TYPE_NONE,57 58 /**59 * Native window handle on Windows.60 */61 PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS,62 63 /**64 * Native view on iOS.65 */66 PJMEDIA_VID_DEV_HWND_TYPE_IOS,67 68 /**69 * Native window handle on Android.70 */71 PJMEDIA_VID_DEV_HWND_TYPE_ANDROID72 73 } pjmedia_vid_dev_hwnd_type;74 75 /**76 * Type for window handle.77 */78 typedef struct pjmedia_vid_dev_hwnd79 {80 /**81 * The window handle type.82 */83 pjmedia_vid_dev_hwnd_type type;84 85 /**86 * The window handle.87 */88 union89 {90 struct {91 void *hwnd; /**< HWND */92 } win;93 struct {94 void *window; /**< Window */95 void *display; /**< Display */96 } x11;97 struct {98 void *window; /**< Window */99 } cocoa;100 struct {101 void *window; /**< Window */102 } ios;103 struct {104 void *window; /**< Native window */105 } android;106 void *window;107 } info;108 109 } pjmedia_vid_dev_hwnd;110 111 /**112 * Parameter for switching device with PJMEDIA_VID_DEV_CAP_SWITCH capability.113 * Initialize this with pjmedia_vid_dev_switch_param_default()114 */115 typedef struct pjmedia_vid_dev_switch_param116 {117 /**118 * Target device ID to switch to. Once the switching is successful, the119 * video stream will use this device and the old device will be closed.120 */121 pjmedia_vid_dev_index target_id;122 123 } pjmedia_vid_dev_switch_param;124 125 126 /**127 * Enumeration of window flags.128 */129 typedef enum pjmedia_vid_dev_wnd_flag130 {131 /**132 * Window with border.133 */134 PJMEDIA_VID_DEV_WND_BORDER = 1,135 136 /**137 * Window can be resized.138 */139 PJMEDIA_VID_DEV_WND_RESIZABLE = 2140 141 } pjmedia_vid_dev_wnd_flag;142 143 144 /**145 * Device index constants.146 */147 enum pjmedia_vid_dev_std_index148 {149 /**150 * Constant to denote default capture device151 */152 PJMEDIA_VID_DEFAULT_CAPTURE_DEV = -1,153 154 /**155 * Constant to denote default render device156 */157 PJMEDIA_VID_DEFAULT_RENDER_DEV = -2,158 159 /**160 * Constant to denote invalid device index.161 */162 PJMEDIA_VID_INVALID_DEV = -3163 };164 165 166 /**167 * This enumeration identifies various video device capabilities. These video168 * capabilities indicates what features are supported by the underlying169 * video device implementation.170 *171 * Applications get these capabilities in the #pjmedia_vid_dev_info structure.172 *173 * Application can also set the specific features/capabilities when opening174 * the video stream by setting the \a flags member of #pjmedia_vid_dev_param175 * structure.176 *177 * Once video stream is running, application can also retrieve or set some178 * specific video capability, by using #pjmedia_vid_dev_stream_get_cap() and179 * #pjmedia_vid_dev_stream_set_cap() and specifying the desired capability. The180 * value of the capability is specified as pointer, and application needs to181 * supply the pointer with the correct value, according to the documentation182 * of each of the capability.183 */184 typedef enum pjmedia_vid_dev_cap185 {186 /**187 * Support for video formats. The value of this capability188 * is represented by #pjmedia_format structure.189 */190 PJMEDIA_VID_DEV_CAP_FORMAT = 1,191 192 /**193 * Support for video input scaling194 */195 PJMEDIA_VID_DEV_CAP_INPUT_SCALE = 2,196 197 /**198 * Support for returning the native window handle of the video window.199 * For renderer, this means the window handle of the renderer window,200 * while for capture, this means the window handle of the native preview,201 * only if the device supports PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW202 * capability.203 *204 * The value of this capability is pointer to pjmedia_vid_dev_hwnd205 * structure.206 */207 PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW = 4,208 209 /**210 * Support for resizing video output. This capability SHOULD be211 * implemented by renderer, to alter the video output dimension on the fly.212 * Value is pjmedia_rect_size.213 */214 PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE = 8,215 216 /**217 * Support for setting the video window's position.218 * Value is pjmedia_coord specifying the window's new coordinate.219 */220 PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION = 16,221 222 /**223 * Support for setting the video output's visibility.224 * The value of this capability is a pj_bool_t containing boolean225 * PJ_TRUE or PJ_FALSE.226 */227 PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE = 32,228 229 /**230 * Support for native preview capability in capture devices. Value is231 * pj_bool_t. With native preview, capture device can be instructed to232 * show or hide a preview window showing video directly from the camera233 * by setting this capability to PJ_TRUE or PJ_FALSE. Once the preview234 * is started, application may use PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW235 * capability to query the video window.236 *237 * The value of this capability is a pj_bool_t containing boolean238 * PJ_TRUE or PJ_FALSE.239 */240 PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW = 64,241 242 /**243 * Support for changing video orientation. For a renderer device,244 * changing video orientation in will potentially affect the size of245 * render window, i.e: width and height swap. For a capture device,246 * the video will be rotated but the size of the video frame247 * will stay the same, so the video may be resized or stretched.248 *249 * The value of this capability is pjmedia_orient.250 */251 PJMEDIA_VID_DEV_CAP_ORIENTATION = 128,252 253 /**254 * Support for fast switching to another device. A video stream with this255 * capability allows replacing of its underlying device with another256 * device, saving the user from opening a new video stream and gets a much257 * faster and smoother switching action.258 *259 * Note that even when this capability is supported by a device, it may260 * not be able to switch to arbitrary device. Application must always261 * check the return value of the operation to verify that switching has262 * occurred.263 *264 * This capability is currently write-only (i.e. set-only).265 *266 * The value of this capability is pointer to pjmedia_vid_dev_switch_param267 * structure.268 */269 PJMEDIA_VID_DEV_CAP_SWITCH = 256,270 271 /**272 * Support for setting the output video window's flags.273 * The value of this capability is a bitmask combination of274 * #pjmedia_vid_dev_wnd_flag.275 */276 PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS = 512,277 278 /**279 * End of standard capability280 */281 PJMEDIA_VID_DEV_CAP_MAX = 16384282 283 } pjmedia_vid_dev_cap;284 285 /**286 * Device information structure returned by #pjmedia_vid_dev_get_info().287 */288 typedef struct pjmedia_vid_dev_info289 {290 /** The device ID */291 pjmedia_vid_dev_index id;292 293 /** The device name */294 char name[64];295 296 /** The underlying driver name */297 char driver[32];298 299 /**300 * The supported direction of the video device, i.e. whether it supports301 * capture only, render only, or both.302 */303 pjmedia_dir dir;304 305 /**306 * Specify whether the device supports callback. Devices that implement307 * "active interface" will actively call the callbacks to give or ask for308 * video frames. If the device doesn't support callback, application309 * must actively request or give video frames from/to the device by using310 * pjmedia_vid_dev_stream_get_frame()/pjmedia_vid_dev_stream_put_frame().311 */312 pj_bool_t has_callback;313 314 /** Device capabilities, as bitmask combination of #pjmedia_vid_dev_cap */315 unsigned caps;316 317 /** Number of video formats supported by this device */318 unsigned fmt_cnt;319 320 /**321 * Array of supported video formats. Some fields in each supported video322 * format may be set to zero or of "unknown" value, to indicate that the323 * value is unknown or should be ignored. When these value are not set324 * to zero, it indicates that the exact format combination is being used.325 */326 pjmedia_format fmt[PJMEDIA_VID_DEV_INFO_FMT_CNT];327 328 } pjmedia_vid_dev_info;329 330 331 /** Forward declaration for pjmedia_vid_dev_stream */332 typedef struct pjmedia_vid_dev_stream pjmedia_vid_dev_stream;333 334 typedef struct pjmedia_vid_dev_cb335 {336 /**337 * This callback is called by capturer stream when it has captured the338 * whole packet worth of video samples.339 *340 * @param stream The video stream.341 * @param user_data User data associated with the stream.342 * @param frame Captured frame.343 *344 * @return Returning non-PJ_SUCCESS will cause the video345 * stream to stop346 */347 pj_status_t (*capture_cb)(pjmedia_vid_dev_stream *stream,348 void *user_data,349 pjmedia_frame *frame);350 351 /**352 * This callback is called by renderer stream when it needs additional353 * data to be rendered by the device. Application must fill in the whole354 * of output buffer with video samples.355 *356 * The frame argument contains the following values:357 * - timestamp Rendering timestamp, in samples.358 * - buf Buffer to be filled out by application.359 * - size The size requested in bytes, which will be equal360 * to the size of one whole packet.361 *362 * @param stream The video stream.363 * @param user_data User data associated with the stream.364 * @param frame Video frame, which buffer is to be filled in by365 * the application.366 *367 * @return Returning non-PJ_SUCCESS will cause the video368 * stream to stop369 */370 pj_status_t (*render_cb)(pjmedia_vid_dev_stream *stream,371 void *user_data,372 pjmedia_frame *frame);373 374 } pjmedia_vid_dev_cb;375 376 377 /**378 * This structure specifies the parameters to open the video stream.379 */380 typedef struct pjmedia_vid_dev_param381 {382 /**383 * The video direction. This setting is mandatory.384 */385 pjmedia_dir dir;386 387 /**388 * The video capture device ID. This setting is mandatory if the video389 * direction includes input/capture direction.390 */391 pjmedia_vid_dev_index cap_id;392 393 /**394 * The video render device ID. This setting is mandatory if the video395 * direction includes output/render direction.396 */397 pjmedia_vid_dev_index rend_id;398 399 /**400 * Video clock rate. This setting is mandatory if the video401 * direction includes input/capture direction402 */403 unsigned clock_rate;404 405 /**406 * Video frame rate. This setting is mandatory if the video407 * direction includes input/capture direction408 */409 // pjmedia_ratio frame_rate;410 411 /**412 * This flags specifies which of the optional settings are valid in this413 * structure. The flags is bitmask combination of pjmedia_vid_dev_cap.414 */415 unsigned flags;416 417 /**418 * Set the video format. This setting is mandatory.419 */420 pjmedia_format fmt;421 422 /**423 * Window for the renderer to display the video. This setting is optional,424 * and will only be used if PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW is set in425 * the flags.426 */427 pjmedia_vid_dev_hwnd window;428 429 /**430 * Video display size. This setting is optional, and will only be used431 * if PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE is set in the flags.432 */433 pjmedia_rect_size disp_size;434 435 /**436 * Video window position. This setting is optional, and will only be used437 * if PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION is set in the flags.438 */439 pjmedia_coord window_pos;440 441 /**442 * Video window's visibility. This setting is optional, and will only be443 * used if PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE is set in the flags.444 */445 pj_bool_t window_hide;446 447 /**448 * Enable built-in preview. This setting is optional and is only used449 * if PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW capability is supported and450 * set in the flags.451 */452 pj_bool_t native_preview;453 454 /**455 * Video orientation. This setting is optional and is only used if456 * PJMEDIA_VID_DEV_CAP_ORIENTATION capability is supported and is457 * set in the flags.458 */459 pjmedia_orient orient;460 461 /**462 * Video window flags. This setting is optional, and will only be used463 * if PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS is set in the flags.464 */465 unsigned window_flags;466 467 } pjmedia_vid_dev_param;468 469 470 /** Forward declaration for video device factory */471 typedef struct pjmedia_vid_dev_factory pjmedia_vid_dev_factory;472 473 /* typedef for factory creation function */474 typedef pjmedia_vid_dev_factory*475 (*pjmedia_vid_dev_factory_create_func_ptr)(pj_pool_factory*);476 477 /**478 * Initialize pjmedia_vid_dev_switch_param.479 *480 * @param p Parameter to be initialized.481 */482 PJ_INLINE(void)483 pjmedia_vid_dev_switch_param_default(pjmedia_vid_dev_switch_param *p)484 {485 pj_bzero(p, sizeof(*p));486 p->target_id = PJMEDIA_VID_INVALID_DEV;487 }488 489 /**490 * Get string info for the specified capability.491 *492 * @param cap The capability ID.493 * @param p_desc Optional pointer which will be filled with longer494 * description about the capability.495 *496 * @return Capability name.497 */498 PJ_DECL(const char*) pjmedia_vid_dev_cap_name(pjmedia_vid_dev_cap cap,499 const char **p_desc);500 501 502 /**503 * Set a capability field value in #pjmedia_vid_dev_param structure. This will504 * also set the flags field for the specified capability in the structure.505 *506 * @param param The structure.507 * @param cap The video capability which value is to be set.508 * @param pval Pointer to value. Please see the type of value to509 * be supplied in the pjmedia_vid_dev_cap documentation.510 *511 * @return PJ_SUCCESS on successful operation or the appropriate512 * error code.513 */514 PJ_DECL(pj_status_t)515 pjmedia_vid_dev_param_set_cap(pjmedia_vid_dev_param *param,516 pjmedia_vid_dev_cap cap,517 const void *pval);518 519 520 /**521 * Get a capability field value from #pjmedia_vid_dev_param structure. This522 * function will return PJMEDIA_EVID_INVCAP error if the flag for that523 * capability is not set in the flags field in the structure.524 *525 * @param param The structure.526 * @param cap The video capability which value is to be retrieved.527 * @param pval Pointer to value. Please see the type of value to528 * be supplied in the pjmedia_vid_dev_cap documentation.529 *530 * @return PJ_SUCCESS on successful operation or the appropriate531 * error code.532 */533 PJ_DECL(pj_status_t)534 pjmedia_vid_dev_param_get_cap(const pjmedia_vid_dev_param *param,535 pjmedia_vid_dev_cap cap,536 void *pval);537 38 538 39 /** … … 611 112 612 113 /** 613 * Refresh the list of video devices installed in the system. This function614 * will only refresh the list of videoo device so all active video streams will615 * be unaffected. After refreshing the device list, application MUST make sure616 * to update all index references to video devices (i.e. all variables of type617 * pjmedia_vid_dev_index) before calling any function that accepts video device618 * index as its parameter.619 *620 * @return PJ_SUCCESS on successful operation or the appropriate621 * error code.622 */623 PJ_DECL(pj_status_t) pjmedia_vid_dev_refresh(void);624 625 626 /**627 * Get the number of video devices installed in the system.628 *629 * @return The number of video devices installed in the system.630 */631 PJ_DECL(unsigned) pjmedia_vid_dev_count(void);632 633 634 /**635 * Get device information.636 *637 * @param id The video device ID.638 * @param info The device information which will be filled in by this639 * function once it returns successfully.640 *641 * @return PJ_SUCCESS on successful operation or the appropriate642 * error code.643 */644 PJ_DECL(pj_status_t) pjmedia_vid_dev_get_info(pjmedia_vid_dev_index id,645 pjmedia_vid_dev_info *info);646 647 648 /**649 * Lookup device index based on the driver and device name.650 *651 * @param drv_name The driver name.652 * @param dev_name The device name.653 * @param id Pointer to store the returned device ID.654 *655 * @return PJ_SUCCESS if the device can be found.656 */657 PJ_DECL(pj_status_t) pjmedia_vid_dev_lookup(const char *drv_name,658 const char *dev_name,659 pjmedia_vid_dev_index *id);660 661 662 /**663 * Initialize the video device parameters with default values for the664 * specified device.665 *666 * @param id The video device ID.667 * @param param The video device parameters which will be initialized668 * by this function once it returns successfully.669 *670 * @return PJ_SUCCESS on successful operation or the appropriate671 * error code.672 */673 PJ_DECL(pj_status_t)674 pjmedia_vid_dev_default_param(pj_pool_t *pool,675 pjmedia_vid_dev_index id,676 pjmedia_vid_dev_param *param);677 678 679 /**680 * Open video stream object using the specified parameters. If stream is681 * created successfully, this function will return PJ_SUCCESS and the682 * stream pointer will be returned in the p_strm argument.683 *684 * The opened stream may have been opened with different size and fps685 * than the requested values in the \a param argument. Application should686 * check the actual size and fps that the stream was opened with by inspecting687 * the values in the \a param argument and see if they have changed. Also688 * if the device ID in the \a param specifies default device, it may be689 * replaced with the actual device ID upon return.690 *691 * @param param On input, it specifies the video device parameters692 * to be used for the stream. On output, this will be693 * set to the actual video device parameters used to694 * open the stream.695 * @param cb Pointer to structure containing video stream696 * callbacks.697 * @param user_data Arbitrary user data, which will be given back in the698 * callbacks.699 * @param p_strm Pointer to receive the video stream.700 *701 * @return PJ_SUCCESS on successful operation or the appropriate702 * error code.703 */704 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_create(705 pjmedia_vid_dev_param *param,706 const pjmedia_vid_dev_cb *cb,707 void *user_data,708 pjmedia_vid_dev_stream **p_strm);709 710 /**711 * Get the running parameters for the specified video stream.712 *713 * @param strm The video stream.714 * @param param Video stream parameters to be filled in by this715 * function once it returns successfully.716 *717 * @return PJ_SUCCESS on successful operation or the appropriate718 * error code.719 */720 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_get_param(721 pjmedia_vid_dev_stream *strm,722 pjmedia_vid_dev_param *param);723 724 /**725 * Get the value of a specific capability of the video stream.726 *727 * @param strm The video stream.728 * @param cap The video capability which value is to be retrieved.729 * @param value Pointer to value to be filled in by this function730 * once it returns successfully. Please see the type731 * of value to be supplied in the pjmedia_vid_dev_cap732 * documentation.733 *734 * @return PJ_SUCCESS on successful operation or the appropriate735 * error code.736 */737 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_get_cap(738 pjmedia_vid_dev_stream *strm,739 pjmedia_vid_dev_cap cap,740 void *value);741 742 /**743 * Set the value of a specific capability of the video stream.744 *745 * @param strm The video stream.746 * @param cap The video capability which value is to be set.747 * @param value Pointer to value. Please see the type of value to748 * be supplied in the pjmedia_vid_dev_cap documentation.749 *750 * @return PJ_SUCCESS on successful operation or the appropriate751 * error code.752 */753 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_set_cap(754 pjmedia_vid_dev_stream *strm,755 pjmedia_vid_dev_cap cap,756 const void *value);757 758 /**759 * Start the stream.760 *761 * @param strm The video stream.762 *763 * @return PJ_SUCCESS on successful operation or the appropriate764 * error code.765 */766 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_start(767 pjmedia_vid_dev_stream *strm);768 769 /**770 * Query whether the stream has been started.771 *772 * @param strm The video stream773 *774 * @return PJ_TRUE if the video stream has been started.775 */776 PJ_DECL(pj_bool_t) pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm);777 778 779 /**780 * Request one frame from the stream. Application needs to call this function781 * periodically only if the stream doesn't support "active interface", i.e.782 * the pjmedia_vid_dev_info.has_callback member is PJ_FALSE.783 *784 * @param strm The video stream.785 * @param frame The video frame to be filled by the device.786 *787 * @return PJ_SUCCESS on successful operation or the appropriate788 * error code.789 */790 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_get_frame(791 pjmedia_vid_dev_stream *strm,792 pjmedia_frame *frame);793 794 /**795 * Put one frame to the stream. Application needs to call this function796 * periodically only if the stream doesn't support "active interface", i.e.797 * the pjmedia_vid_dev_info.has_callback member is PJ_FALSE.798 *799 * @param strm The video stream.800 * @param frame The video frame to put to the device.801 *802 * @return PJ_SUCCESS on successful operation or the appropriate803 * error code.804 */805 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_put_frame(806 pjmedia_vid_dev_stream *strm,807 const pjmedia_frame *frame);808 809 /**810 * Stop the stream.811 *812 * @param strm The video stream.813 *814 * @return PJ_SUCCESS on successful operation or the appropriate815 * error code.816 */817 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_stop(818 pjmedia_vid_dev_stream *strm);819 820 /**821 * Destroy the stream.822 *823 * @param strm The video stream.824 *825 * @return PJ_SUCCESS on successful operation or the appropriate826 * error code.827 */828 PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_destroy(829 pjmedia_vid_dev_stream *strm);830 831 832 /**833 114 * @} 834 115 */ -
pjproject/trunk/pjmedia/include/pjmedia/endpoint.h
r4474 r5255 41 41 #include <pjmedia/sdp.h> 42 42 #include <pjmedia/transport.h> 43 #include <pjmedia-audiodev/audiodev.h> 43 44 44 45 … … 82 83 * @return PJ_SUCCESS on success. 83 84 */ 84 PJ_DECL(pj_status_t) pjmedia_endpt_create (pj_pool_factory *pf,85 PJ_DECL(pj_status_t) pjmedia_endpt_create2(pj_pool_factory *pf, 85 86 pj_ioqueue_t *ioqueue, 86 87 unsigned worker_cnt, … … 88 89 89 90 /** 91 * Create an instance of media endpoint and initialize audio subsystem. 92 * 93 * @param pf Pool factory, which will be used by the media endpoint 94 * throughout its lifetime. 95 * @param ioqueue Optional ioqueue instance to be registered to the 96 * endpoint. The ioqueue instance is used to poll all RTP 97 * and RTCP sockets. If this argument is NULL, the 98 * endpoint will create an internal ioqueue instance. 99 * @param worker_cnt Specify the number of worker threads to be created 100 * to poll the ioqueue. 101 * @param p_endpt Pointer to receive the endpoint instance. 102 * 103 * @return PJ_SUCCESS on success. 104 */ 105 PJ_INLINE(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf, 106 pj_ioqueue_t *ioqueue, 107 unsigned worker_cnt, 108 pjmedia_endpt **p_endpt) 109 { 110 /* This function is inlined to avoid build problem due to circular 111 * dependency, i.e: this function prevents pjmedia's dependency on 112 * pjmedia-audiodev. 113 */ 114 115 pj_status_t status; 116 117 /* Sound */ 118 status = pjmedia_aud_subsys_init(pf); 119 if (status != PJ_SUCCESS) 120 return status; 121 122 status = pjmedia_endpt_create2(pf, ioqueue, worker_cnt, p_endpt); 123 if (status != PJ_SUCCESS) { 124 pjmedia_aud_subsys_shutdown(); 125 } 126 127 return status; 128 } 129 130 /** 90 131 * Destroy media endpoint instance. 91 132 * … … 94 135 * @return PJ_SUCCESS on success. 95 136 */ 96 PJ_DECL(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt); 137 PJ_DECL(pj_status_t) pjmedia_endpt_destroy2(pjmedia_endpt *endpt); 138 139 /** 140 * Destroy media endpoint instance and shutdown audio subsystem. 141 * 142 * @param endpt Media endpoint instance. 143 * 144 * @return PJ_SUCCESS on success. 145 */ 146 PJ_INLINE(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt) 147 { 148 /* This function is inlined to avoid build problem due to circular 149 * dependency, i.e: this function prevents pjmedia's dependency on 150 * pjmedia-audiodev. 151 */ 152 pj_status_t status = pjmedia_endpt_destroy2(endpt); 153 pjmedia_aud_subsys_shutdown(); 154 return status; 155 } 97 156 98 157 /** -
pjproject/trunk/pjmedia/include/pjmedia/sound.h
r5201 r5255 141 141 * @return Zero on success. 142 142 */ 143 PJ_DECL(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory); 144 143 PJ_INLINE(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory) 144 { 145 /* This function is inlined to avoid pjmedia's dependency on 146 * pjmedia-audiodev. 147 */ 148 return pjmedia_aud_subsys_init(factory); 149 } 145 150 146 151 /** … … 324 329 * @return Zero on success. 325 330 */ 326 PJ_DECL(pj_status_t) pjmedia_snd_deinit(void); 331 PJ_INLINE(pj_status_t) pjmedia_snd_deinit(void) 332 { 333 /* This function is inlined to avoid pjmedia's dependency on 334 * pjmedia-audiodev. 335 */ 336 return pjmedia_aud_subsys_shutdown(); 337 } 327 338 328 339 -
pjproject/trunk/pjmedia/src/pjmedia-audiodev/audiodev.c
r4879 r5255 20 20 #include <pjmedia-audiodev/audiodev_imp.h> 21 21 #include <pj/assert.h> 22 #include <pj/errno.h>23 #include <pj/log.h>24 #include <pj/pool.h>25 #include <pj/string.h>26 22 27 23 #define THIS_FILE "audiodev.c" 28 29 #define DEFINE_CAP(name, info) {name, info}30 31 /* Capability names */32 static struct cap_info33 {34 const char *name;35 const char *info;36 } cap_infos[] =37 {38 DEFINE_CAP("ext-fmt", "Extended/non-PCM format"),39 DEFINE_CAP("latency-in", "Input latency/buffer size setting"),40 DEFINE_CAP("latency-out", "Output latency/buffer size setting"),41 DEFINE_CAP("vol-in", "Input volume setting"),42 DEFINE_CAP("vol-out", "Output volume setting"),43 DEFINE_CAP("meter-in", "Input meter"),44 DEFINE_CAP("meter-out", "Output meter"),45 DEFINE_CAP("route-in", "Input routing"),46 DEFINE_CAP("route-out", "Output routing"),47 DEFINE_CAP("aec", "Accoustic echo cancellation"),48 DEFINE_CAP("aec-tail", "Tail length setting for AEC"),49 DEFINE_CAP("vad", "Voice activity detection"),50 DEFINE_CAP("cng", "Comfort noise generation"),51 DEFINE_CAP("plg", "Packet loss concealment")52 };53 54 55 /*56 * The device index seen by application and driver is different.57 *58 * At application level, device index is index to global list of device.59 * At driver level, device index is index to device list on that particular60 * factory only.61 */62 #define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))63 #define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)64 #define GET_FID(dev_id) ((dev_id) >> 16)65 #define DEFAULT_DEV_ID 066 24 67 25 … … 115 73 #endif 116 74 117 #define MAX_DRIVERS 16118 #define MAX_DEVS 64119 120 121 /* driver structure */122 struct driver123 {124 /* Creation function */125 pjmedia_aud_dev_factory_create_func_ptr create;126 /* Factory instance */127 pjmedia_aud_dev_factory *f;128 char name[32]; /* Driver name */129 unsigned dev_cnt; /* Number of devices */130 unsigned start_idx; /* Start index in global list */131 int rec_dev_idx;/* Default capture device. */132 int play_dev_idx;/* Default playback device */133 int dev_idx; /* Default device. */134 };135 136 /* The audio subsystem */137 static struct aud_subsys138 {139 unsigned init_count; /* How many times init() is called */140 pj_pool_factory *pf; /* The pool factory. */141 142 unsigned drv_cnt; /* Number of drivers. */143 struct driver drv[MAX_DRIVERS]; /* Array of drivers. */144 145 unsigned dev_cnt; /* Total number of devices. */146 pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */147 148 } aud_subsys;149 150 /* API: get capability name/info */151 PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap,152 const char **p_desc)153 {154 const char *desc;155 unsigned i;156 157 if (p_desc==NULL) p_desc = &desc;158 159 for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {160 if ((1 << i)==cap)161 break;162 }163 164 if (i==PJ_ARRAY_SIZE(cap_infos)) {165 *p_desc = "??";166 return "??";167 }168 169 *p_desc = cap_infos[i].info;170 return cap_infos[i].name;171 }172 173 static pj_status_t get_cap_pointer(const pjmedia_aud_param *param,174 pjmedia_aud_dev_cap cap,175 void **ptr,176 unsigned *size)177 {178 #define FIELD_INFO(name) *ptr = (void*)¶m->name; \179 *size = sizeof(param->name)180 181 switch (cap) {182 case PJMEDIA_AUD_DEV_CAP_EXT_FORMAT:183 FIELD_INFO(ext_fmt);184 break;185 case PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY:186 FIELD_INFO(input_latency_ms);187 break;188 case PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY:189 FIELD_INFO(output_latency_ms);190 break;191 case PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING:192 FIELD_INFO(input_vol);193 break;194 case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING:195 FIELD_INFO(output_vol);196 break;197 case PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE:198 FIELD_INFO(input_route);199 break;200 case PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE:201 FIELD_INFO(output_route);202 break;203 case PJMEDIA_AUD_DEV_CAP_EC:204 FIELD_INFO(ec_enabled);205 break;206 case PJMEDIA_AUD_DEV_CAP_EC_TAIL:207 FIELD_INFO(ec_tail_ms);208 break;209 /* vad is no longer in "fmt" in 2.0.210 case PJMEDIA_AUD_DEV_CAP_VAD:211 FIELD_INFO(ext_fmt.vad);212 break;213 */214 case PJMEDIA_AUD_DEV_CAP_CNG:215 FIELD_INFO(cng_enabled);216 break;217 case PJMEDIA_AUD_DEV_CAP_PLC:218 FIELD_INFO(plc_enabled);219 break;220 default:221 return PJMEDIA_EAUD_INVCAP;222 }223 224 #undef FIELD_INFO225 226 return PJ_SUCCESS;227 }228 229 /* API: set cap value to param */230 PJ_DEF(pj_status_t) pjmedia_aud_param_set_cap( pjmedia_aud_param *param,231 pjmedia_aud_dev_cap cap,232 const void *pval)233 {234 void *cap_ptr;235 unsigned cap_size;236 pj_status_t status;237 238 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);239 if (status != PJ_SUCCESS)240 return status;241 242 pj_memcpy(cap_ptr, pval, cap_size);243 param->flags |= cap;244 245 return PJ_SUCCESS;246 }247 248 /* API: get cap value from param */249 PJ_DEF(pj_status_t) pjmedia_aud_param_get_cap( const pjmedia_aud_param *param,250 pjmedia_aud_dev_cap cap,251 void *pval)252 {253 void *cap_ptr;254 unsigned cap_size;255 pj_status_t status;256 257 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);258 if (status != PJ_SUCCESS)259 return status;260 261 if ((param->flags & cap) == 0) {262 pj_bzero(cap_ptr, cap_size);263 return PJMEDIA_EAUD_INVCAP;264 }265 266 pj_memcpy(pval, cap_ptr, cap_size);267 return PJ_SUCCESS;268 }269 270 /* Internal: init driver */271 static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh)272 {273 struct driver *drv = &aud_subsys.drv[drv_idx];274 pjmedia_aud_dev_factory *f;275 unsigned i, dev_cnt;276 pj_status_t status;277 278 if (!refresh && drv->create) {279 /* Create the factory */280 f = (*drv->create)(aud_subsys.pf);281 if (!f)282 return PJ_EUNKNOWN;283 284 /* Call factory->init() */285 status = f->op->init(f);286 if (status != PJ_SUCCESS) {287 f->op->destroy(f);288 return status;289 }290 } else {291 f = drv->f;292 }293 294 if (!f)295 return PJ_EUNKNOWN;296 297 /* Get number of devices */298 dev_cnt = f->op->get_dev_count(f);299 if (dev_cnt + aud_subsys.dev_cnt > MAX_DEVS) {300 PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"301 " there are too many devices",302 aud_subsys.dev_cnt + dev_cnt - MAX_DEVS));303 dev_cnt = MAX_DEVS - aud_subsys.dev_cnt;304 }305 306 /* enabling this will cause pjsua-lib initialization to fail when there307 * is no sound device installed in the system, even when pjsua has been308 * run with --null-audio309 *310 if (dev_cnt == 0) {311 f->op->destroy(f);312 return PJMEDIA_EAUD_NODEV;313 }314 */315 316 /* Fill in default devices */317 drv->play_dev_idx = drv->rec_dev_idx =318 drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;319 for (i=0; i<dev_cnt; ++i) {320 pjmedia_aud_dev_info info;321 322 status = f->op->get_dev_info(f, i, &info);323 if (status != PJ_SUCCESS) {324 f->op->destroy(f);325 return status;326 }327 328 if (drv->name[0]=='\0') {329 /* Set driver name */330 pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));331 drv->name[sizeof(drv->name)-1] = '\0';332 }333 334 if (drv->play_dev_idx < 0 && info.output_count) {335 /* Set default playback device */336 drv->play_dev_idx = i;337 }338 if (drv->rec_dev_idx < 0 && info.input_count) {339 /* Set default capture device */340 drv->rec_dev_idx = i;341 }342 if (drv->dev_idx < 0 && info.input_count &&343 info.output_count)344 {345 /* Set default capture and playback device */346 drv->dev_idx = i;347 }348 349 if (drv->play_dev_idx >= 0 && drv->rec_dev_idx >= 0 &&350 drv->dev_idx >= 0)351 {352 /* Done. */353 break;354 }355 }356 357 /* Register the factory */358 drv->f = f;359 drv->f->sys.drv_idx = drv_idx;360 drv->start_idx = aud_subsys.dev_cnt;361 drv->dev_cnt = dev_cnt;362 363 /* Register devices to global list */364 for (i=0; i<dev_cnt; ++i) {365 aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);366 }367 368 return PJ_SUCCESS;369 }370 371 /* Internal: deinit driver */372 static void deinit_driver(unsigned drv_idx)373 {374 struct driver *drv = &aud_subsys.drv[drv_idx];375 376 if (drv->f) {377 drv->f->op->destroy(drv->f);378 drv->f = NULL;379 }380 381 pj_bzero(drv, sizeof(*drv));382 drv->play_dev_idx = drv->rec_dev_idx =383 drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;384 }385 75 386 76 /* API: Initialize the audio subsystem. */ … … 389 79 unsigned i; 390 80 pj_status_t status; 81 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 391 82 392 83 /* Allow init() to be called multiple times as long as there is matching 393 84 * number of shutdown(). 394 85 */ 395 if (aud_subsys .init_count++ != 0) {86 if (aud_subsys->init_count++ != 0) { 396 87 return PJ_SUCCESS; 397 88 } … … 404 95 405 96 /* Init */ 406 aud_subsys .pf = pf;407 aud_subsys .drv_cnt = 0;408 aud_subsys .dev_cnt = 0;97 aud_subsys->pf = pf; 98 aud_subsys->drv_cnt = 0; 99 aud_subsys->dev_cnt = 0; 409 100 410 101 /* Register creation functions */ 411 102 #if PJMEDIA_AUDIO_DEV_HAS_OPENSL 412 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_opensl_factory;103 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_opensl_factory; 413 104 #endif 414 105 #if PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI 415 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_android_factory;106 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_android_factory; 416 107 #endif 417 108 #if PJMEDIA_AUDIO_DEV_HAS_BB10 418 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_bb10_factory;109 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bb10_factory; 419 110 #endif 420 111 #if PJMEDIA_AUDIO_DEV_HAS_ALSA 421 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_alsa_factory;112 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_alsa_factory; 422 113 #endif 423 114 #if PJMEDIA_AUDIO_DEV_HAS_COREAUDIO 424 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_coreaudio_factory;115 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_coreaudio_factory; 425 116 #endif 426 117 #if PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 427 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory;118 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_pa_factory; 428 119 #endif 429 120 #if PJMEDIA_AUDIO_DEV_HAS_WMME 430 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory;121 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_wmme_factory; 431 122 #endif 432 123 #if PJMEDIA_AUDIO_DEV_HAS_BDIMAD 433 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_bdimad_factory;124 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bdimad_factory; 434 125 #endif 435 126 #if PJMEDIA_AUDIO_DEV_HAS_SYMB_VAS 436 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_vas_factory;127 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_vas_factory; 437 128 #endif 438 129 #if PJMEDIA_AUDIO_DEV_HAS_SYMB_APS 439 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_aps_factory;130 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_aps_factory; 440 131 #endif 441 132 #if PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA 442 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_mda_factory;133 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_mda_factory; 443 134 #endif 444 135 #if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO 445 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory;136 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_null_audio_factory; 446 137 #endif 447 138 448 139 /* Initialize each factory and build the device ID list */ 449 for (i=0; i<aud_subsys .drv_cnt; ++i) {450 status = init_driver(i, PJ_FALSE);140 for (i=0; i<aud_subsys->drv_cnt; ++i) { 141 status = pjmedia_aud_driver_init(i, PJ_FALSE); 451 142 if (status != PJ_SUCCESS) { 452 deinit_driver(i);143 pjmedia_aud_driver_deinit(i); 453 144 continue; 454 145 } 455 146 } 456 147 457 return aud_subsys .dev_cnt ? PJ_SUCCESS : status;148 return aud_subsys->dev_cnt ? PJ_SUCCESS : status; 458 149 } 459 150 … … 463 154 { 464 155 pj_status_t status; 465 466 if (aud_subsys.init_count == 0) 156 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 157 158 if (aud_subsys->init_count == 0) 467 159 return PJMEDIA_EAUD_INIT; 468 160 469 aud_subsys .drv[aud_subsys.drv_cnt].create = adf;470 status = init_driver(aud_subsys.drv_cnt, PJ_FALSE);161 aud_subsys->drv[aud_subsys->drv_cnt].create = adf; 162 status = pjmedia_aud_driver_init(aud_subsys->drv_cnt, PJ_FALSE); 471 163 if (status == PJ_SUCCESS) { 472 aud_subsys .drv_cnt++;164 aud_subsys->drv_cnt++; 473 165 } else { 474 deinit_driver(aud_subsys.drv_cnt);166 pjmedia_aud_driver_deinit(aud_subsys->drv_cnt); 475 167 } 476 168 … … 483 175 { 484 176 unsigned i, j; 485 486 if (aud_subsys.init_count == 0) 177 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 178 179 if (aud_subsys->init_count == 0) 487 180 return PJMEDIA_EAUD_INIT; 488 181 489 for (i=0; i<aud_subsys .drv_cnt; ++i) {490 struct driver *drv = &aud_subsys.drv[i];182 for (i=0; i<aud_subsys->drv_cnt; ++i) { 183 pjmedia_aud_driver *drv = &aud_subsys->drv[i]; 491 184 492 185 if (drv->create == adf) { 493 186 for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 494 187 { 495 aud_subsys .dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV;188 aud_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV; 496 189 } 497 190 498 deinit_driver(i);191 pjmedia_aud_driver_deinit(i); 499 192 return PJ_SUCCESS; 500 193 } … … 507 200 PJ_DEF(pj_pool_factory*) pjmedia_aud_subsys_get_pool_factory(void) 508 201 { 509 return aud_subsys.pf; 202 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 203 return aud_subsys->pf; 510 204 } 511 205 … … 514 208 { 515 209 unsigned i; 210 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 516 211 517 212 /* Allow shutdown() to be called multiple times as long as there is matching 518 213 * number of init(). 519 214 */ 520 if (aud_subsys .init_count == 0) {215 if (aud_subsys->init_count == 0) { 521 216 return PJ_SUCCESS; 522 217 } 523 --aud_subsys .init_count;524 525 if (aud_subsys .init_count == 0) {526 for (i=0; i<aud_subsys .drv_cnt; ++i) {527 deinit_driver(i);218 --aud_subsys->init_count; 219 220 if (aud_subsys->init_count == 0) { 221 for (i=0; i<aud_subsys->drv_cnt; ++i) { 222 pjmedia_aud_driver_deinit(i); 528 223 } 529 224 530 aud_subsys .pf = NULL;225 aud_subsys->pf = NULL; 531 226 } 532 227 return PJ_SUCCESS; 533 228 } 534 535 /* API: Refresh the list of sound devices installed in the system. */536 PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void)537 {538 unsigned i;539 540 aud_subsys.dev_cnt = 0;541 for (i=0; i<aud_subsys.drv_cnt; ++i) {542 struct driver *drv = &aud_subsys.drv[i];543 544 if (drv->f && drv->f->op->refresh) {545 pj_status_t status = drv->f->op->refresh(drv->f);546 if (status != PJ_SUCCESS) {547 PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "548 "list for %s", drv->name));549 }550 }551 init_driver(i, PJ_TRUE);552 }553 return PJ_SUCCESS;554 }555 556 /* API: Get the number of sound devices installed in the system. */557 PJ_DEF(unsigned) pjmedia_aud_dev_count(void)558 {559 return aud_subsys.dev_cnt;560 }561 562 /* Internal: convert local index to global device index */563 static pj_status_t make_global_index(unsigned drv_idx,564 pjmedia_aud_dev_index *id)565 {566 if (*id < 0) {567 return PJ_SUCCESS;568 }569 570 /* Check that factory still exists */571 PJ_ASSERT_RETURN(aud_subsys.drv[drv_idx].f, PJ_EBUG);572 573 /* Check that device index is valid */574 PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[drv_idx].dev_cnt,575 PJ_EBUG);576 577 *id += aud_subsys.drv[drv_idx].start_idx;578 return PJ_SUCCESS;579 }580 581 /* Internal: lookup device id */582 static pj_status_t lookup_dev(pjmedia_aud_dev_index id,583 pjmedia_aud_dev_factory **p_f,584 unsigned *p_local_index)585 {586 int f_id, index;587 588 if (id < 0) {589 unsigned i;590 591 if (id == PJMEDIA_AUD_INVALID_DEV)592 return PJMEDIA_EAUD_INVDEV;593 594 for (i=0; i<aud_subsys.drv_cnt; ++i) {595 struct driver *drv = &aud_subsys.drv[i];596 if (drv->dev_idx >= 0) {597 id = drv->dev_idx;598 make_global_index(i, &id);599 break;600 } else if (id==PJMEDIA_AUD_DEFAULT_CAPTURE_DEV &&601 drv->rec_dev_idx >= 0)602 {603 id = drv->rec_dev_idx;604 make_global_index(i, &id);605 break;606 } else if (id==PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV &&607 drv->play_dev_idx >= 0)608 {609 id = drv->play_dev_idx;610 make_global_index(i, &id);611 break;612 }613 }614 615 if (id < 0) {616 return PJMEDIA_EAUD_NODEFDEV;617 }618 }619 620 f_id = GET_FID(aud_subsys.dev_list[id]);621 index = GET_INDEX(aud_subsys.dev_list[id]);622 623 if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt)624 return PJMEDIA_EAUD_INVDEV;625 626 if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt)627 return PJMEDIA_EAUD_INVDEV;628 629 *p_f = aud_subsys.drv[f_id].f;630 *p_local_index = (unsigned)index;631 632 return PJ_SUCCESS;633 634 }635 636 /* API: Get device information. */637 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id,638 pjmedia_aud_dev_info *info)639 {640 pjmedia_aud_dev_factory *f;641 unsigned index;642 pj_status_t status;643 644 PJ_ASSERT_RETURN(info && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);645 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);646 647 status = lookup_dev(id, &f, &index);648 if (status != PJ_SUCCESS)649 return status;650 651 return f->op->get_dev_info(f, index, info);652 }653 654 /* API: find device */655 PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name,656 const char *dev_name,657 pjmedia_aud_dev_index *id)658 {659 pjmedia_aud_dev_factory *f = NULL;660 unsigned drv_idx, dev_idx;661 662 PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);663 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);664 665 for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) {666 if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) {667 f = aud_subsys.drv[drv_idx].f;668 break;669 }670 }671 672 if (!f)673 return PJ_ENOTFOUND;674 675 for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) {676 pjmedia_aud_dev_info info;677 pj_status_t status;678 679 status = f->op->get_dev_info(f, dev_idx, &info);680 if (status != PJ_SUCCESS)681 return status;682 683 if (!pj_ansi_stricmp(dev_name, info.name))684 break;685 }686 687 if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt)688 return PJ_ENOTFOUND;689 690 *id = dev_idx;691 make_global_index(drv_idx, id);692 693 return PJ_SUCCESS;694 }695 696 /* API: Initialize the audio device parameters with default values for the697 * specified device.698 */699 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id,700 pjmedia_aud_param *param)701 {702 pjmedia_aud_dev_factory *f;703 unsigned index;704 pj_status_t status;705 706 PJ_ASSERT_RETURN(param && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);707 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);708 709 status = lookup_dev(id, &f, &index);710 if (status != PJ_SUCCESS)711 return status;712 713 status = f->op->default_param(f, index, param);714 if (status != PJ_SUCCESS)715 return status;716 717 /* Normalize device IDs */718 make_global_index(f->sys.drv_idx, ¶m->rec_id);719 make_global_index(f->sys.drv_idx, ¶m->play_id);720 721 return PJ_SUCCESS;722 }723 724 /* API: Open audio stream object using the specified parameters. */725 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm,726 pjmedia_aud_rec_cb rec_cb,727 pjmedia_aud_play_cb play_cb,728 void *user_data,729 pjmedia_aud_stream **p_aud_strm)730 {731 pjmedia_aud_dev_factory *rec_f=NULL, *play_f=NULL, *f=NULL;732 pjmedia_aud_param param;733 pj_status_t status;734 735 PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL);736 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);737 PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||738 prm->dir==PJMEDIA_DIR_PLAYBACK ||739 prm->dir==PJMEDIA_DIR_CAPTURE_PLAYBACK,740 PJ_EINVAL);741 742 /* Must make copy of param because we're changing device ID */743 pj_memcpy(¶m, prm, sizeof(param));744 745 /* Normalize rec_id */746 if (param.dir & PJMEDIA_DIR_CAPTURE) {747 unsigned index;748 749 if (param.rec_id < 0)750 param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV;751 752 status = lookup_dev(param.rec_id, &rec_f, &index);753 if (status != PJ_SUCCESS)754 return status;755 756 param.rec_id = index;757 f = rec_f;758 }759 760 /* Normalize play_id */761 if (param.dir & PJMEDIA_DIR_PLAYBACK) {762 unsigned index;763 764 if (param.play_id < 0)765 param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;766 767 status = lookup_dev(param.play_id, &play_f, &index);768 if (status != PJ_SUCCESS)769 return status;770 771 param.play_id = index;772 f = play_f;773 }774 775 PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);776 777 /* For now, rec_id and play_id must belong to the same factory */778 PJ_ASSERT_RETURN((param.dir != PJMEDIA_DIR_CAPTURE_PLAYBACK) ||779 (rec_f == play_f),780 PJMEDIA_EAUD_INVDEV);781 782 /* Create the stream */783 status = f->op->create_stream(f, ¶m, rec_cb, play_cb,784 user_data, p_aud_strm);785 if (status != PJ_SUCCESS)786 return status;787 788 /* Assign factory id to the stream */789 (*p_aud_strm)->sys.drv_idx = f->sys.drv_idx;790 return PJ_SUCCESS;791 }792 793 /* API: Get the running parameters for the specified audio stream. */794 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm,795 pjmedia_aud_param *param)796 {797 pj_status_t status;798 799 PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);800 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);801 802 status = strm->op->get_param(strm, param);803 if (status != PJ_SUCCESS)804 return status;805 806 /* Normalize device id's */807 make_global_index(strm->sys.drv_idx, ¶m->rec_id);808 make_global_index(strm->sys.drv_idx, ¶m->play_id);809 810 return PJ_SUCCESS;811 }812 813 /* API: Get the value of a specific capability of the audio stream. */814 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm,815 pjmedia_aud_dev_cap cap,816 void *value)817 {818 return strm->op->get_cap(strm, cap, value);819 }820 821 /* API: Set the value of a specific capability of the audio stream. */822 PJ_DEF(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm,823 pjmedia_aud_dev_cap cap,824 const void *value)825 {826 return strm->op->set_cap(strm, cap, value);827 }828 829 /* API: Start the stream. */830 PJ_DEF(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm)831 {832 return strm->op->start(strm);833 }834 835 /* API: Stop the stream. */836 PJ_DEF(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm)837 {838 return strm->op->stop(strm);839 }840 841 /* API: Destroy the stream. */842 PJ_DEF(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm)843 {844 return strm->op->destroy(strm);845 }846 847 -
pjproject/trunk/pjmedia/src/pjmedia-videodev/videodev.c
r5125 r5255 19 19 #include <pjmedia-videodev/videodev_imp.h> 20 20 #include <pj/assert.h> 21 #include <pj/errno.h>22 #include <pj/log.h>23 #include <pj/pool.h>24 #include <pj/string.h>25 21 26 22 … … 29 25 30 26 #define THIS_FILE "videodev.c" 31 32 #define DEFINE_CAP(name, info) {name, info}33 34 /* Capability names */35 static struct cap_info36 {37 const char *name;38 const char *info;39 } cap_infos[] =40 {41 DEFINE_CAP("format", "Video format"),42 DEFINE_CAP("scale", "Input dimension"),43 DEFINE_CAP("window", "Window handle"),44 DEFINE_CAP("resize", "Renderer resize"),45 DEFINE_CAP("position", "Renderer position"),46 DEFINE_CAP("hide", "Renderer hide"),47 DEFINE_CAP("preview", "Input preview"),48 DEFINE_CAP("orientation", "Video orientation"),49 DEFINE_CAP("switch", "Switch device"),50 DEFINE_CAP("wndflags", "Window flags")51 };52 53 54 /*55 * The device index seen by application and driver is different.56 *57 * At application level, device index is index to global list of device.58 * At driver level, device index is index to device list on that particular59 * factory only.60 */61 #define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))62 #define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)63 #define GET_FID(dev_id) ((dev_id) >> 16)64 #define DEFAULT_DEV_ID 065 27 66 28 … … 110 72 111 73 112 /* driver structure */113 struct driver114 {115 /* Creation function */116 pjmedia_vid_dev_factory_create_func_ptr create;117 /* Factory instance */118 pjmedia_vid_dev_factory *f;119 char name[32]; /* Driver name */120 unsigned dev_cnt; /* Number of devices */121 unsigned start_idx; /* Start index in global list */122 int cap_dev_idx; /* Default capture device. */123 int rend_dev_idx; /* Default render device */124 };125 126 /* The video device subsystem */127 static struct vid_subsys128 {129 unsigned init_count; /* How many times init() is called */130 pj_pool_factory *pf; /* The pool factory. */131 132 unsigned drv_cnt; /* Number of drivers. */133 struct driver drv[MAX_DRIVERS]; /* Array of drivers. */134 135 unsigned dev_cnt; /* Total number of devices. */136 pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */137 138 } vid_subsys;139 140 /* API: get capability name/info */141 PJ_DEF(const char*) pjmedia_vid_dev_cap_name(pjmedia_vid_dev_cap cap,142 const char **p_desc)143 {144 const char *desc;145 unsigned i;146 147 if (p_desc==NULL) p_desc = &desc;148 149 for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {150 if ((1 << i)==cap)151 break;152 }153 154 if (i==PJ_ARRAY_SIZE(cap_infos)) {155 *p_desc = "??";156 return "??";157 }158 159 *p_desc = cap_infos[i].info;160 return cap_infos[i].name;161 }162 163 static pj_status_t get_cap_pointer(const pjmedia_vid_dev_param *param,164 pjmedia_vid_dev_cap cap,165 void **ptr,166 unsigned *size)167 {168 #define FIELD_INFO(name) *ptr = (void*)¶m->name; \169 *size = sizeof(param->name)170 171 switch (cap) {172 case PJMEDIA_VID_DEV_CAP_FORMAT:173 FIELD_INFO(fmt);174 break;175 case PJMEDIA_VID_DEV_CAP_INPUT_SCALE:176 FIELD_INFO(disp_size);177 break;178 case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW:179 FIELD_INFO(window);180 break;181 case PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE:182 FIELD_INFO(disp_size);183 break;184 case PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION:185 FIELD_INFO(window_pos);186 break;187 case PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE:188 FIELD_INFO(window_hide);189 break;190 case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW:191 FIELD_INFO(native_preview);192 break;193 case PJMEDIA_VID_DEV_CAP_ORIENTATION:194 FIELD_INFO(orient);195 break;196 /* The PJMEDIA_VID_DEV_CAP_SWITCH does not have an entry in the197 * param (it doesn't make sense to open a stream and tell it198 * to switch immediately).199 */200 case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS:201 FIELD_INFO(window_flags);202 break;203 default:204 return PJMEDIA_EVID_INVCAP;205 }206 207 #undef FIELD_INFO208 209 return PJ_SUCCESS;210 }211 212 /* API: set cap value to param */213 PJ_DEF(pj_status_t)214 pjmedia_vid_dev_param_set_cap( pjmedia_vid_dev_param *param,215 pjmedia_vid_dev_cap cap,216 const void *pval)217 {218 void *cap_ptr;219 unsigned cap_size;220 pj_status_t status;221 222 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);223 if (status != PJ_SUCCESS)224 return status;225 226 pj_memcpy(cap_ptr, pval, cap_size);227 param->flags |= cap;228 229 return PJ_SUCCESS;230 }231 232 /* API: get cap value from param */233 PJ_DEF(pj_status_t)234 pjmedia_vid_dev_param_get_cap( const pjmedia_vid_dev_param *param,235 pjmedia_vid_dev_cap cap,236 void *pval)237 {238 void *cap_ptr;239 unsigned cap_size;240 pj_status_t status;241 242 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);243 if (status != PJ_SUCCESS)244 return status;245 246 if ((param->flags & cap) == 0) {247 pj_bzero(cap_ptr, cap_size);248 return PJMEDIA_EVID_INVCAP;249 }250 251 pj_memcpy(pval, cap_ptr, cap_size);252 return PJ_SUCCESS;253 }254 255 /* Internal: init driver */256 static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh)257 {258 struct driver *drv = &vid_subsys.drv[drv_idx];259 pjmedia_vid_dev_factory *f;260 unsigned i, dev_cnt;261 pj_status_t status;262 263 if (!refresh) {264 /* Create the factory */265 f = (*drv->create)(vid_subsys.pf);266 if (!f)267 return PJ_EUNKNOWN;268 269 /* Call factory->init() */270 status = f->op->init(f);271 if (status != PJ_SUCCESS) {272 f->op->destroy(f);273 return status;274 }275 } else {276 f = drv->f;277 }278 279 /* Get number of devices */280 dev_cnt = f->op->get_dev_count(f);281 if (dev_cnt + vid_subsys.dev_cnt > MAX_DEVS) {282 PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"283 " there are too many devices",284 vid_subsys.dev_cnt + dev_cnt - MAX_DEVS));285 dev_cnt = MAX_DEVS - vid_subsys.dev_cnt;286 }287 288 /* enabling this will cause pjsua-lib initialization to fail when there289 * is no video device installed in the system, even when pjsua has been290 * run with --null-video291 *292 if (dev_cnt == 0) {293 f->op->destroy(f);294 return PJMEDIA_EVID_NODEV;295 }296 */297 298 /* Fill in default devices */299 drv->rend_dev_idx = drv->cap_dev_idx = -1;300 for (i=0; i<dev_cnt; ++i) {301 pjmedia_vid_dev_info info;302 303 status = f->op->get_dev_info(f, i, &info);304 if (status != PJ_SUCCESS) {305 f->op->destroy(f);306 return status;307 }308 309 if (drv->name[0]=='\0') {310 /* Set driver name */311 pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));312 drv->name[sizeof(drv->name)-1] = '\0';313 }314 315 if (drv->rend_dev_idx < 0 && (info.dir & PJMEDIA_DIR_RENDER)) {316 /* Set default render device */317 drv->rend_dev_idx = i;318 }319 if (drv->cap_dev_idx < 0 && (info.dir & PJMEDIA_DIR_CAPTURE)) {320 /* Set default capture device */321 drv->cap_dev_idx = i;322 }323 324 if (drv->rend_dev_idx >= 0 && drv->cap_dev_idx >= 0) {325 /* Done. */326 break;327 }328 }329 330 /* Register the factory */331 drv->f = f;332 drv->f->sys.drv_idx = drv_idx;333 drv->start_idx = vid_subsys.dev_cnt;334 drv->dev_cnt = dev_cnt;335 336 /* Register devices to global list */337 for (i=0; i<dev_cnt; ++i) {338 vid_subsys.dev_list[vid_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);339 }340 341 return PJ_SUCCESS;342 }343 344 /* Internal: deinit driver */345 static void deinit_driver(unsigned drv_idx)346 {347 struct driver *drv = &vid_subsys.drv[drv_idx];348 349 if (drv->f) {350 drv->f->op->destroy(drv->f);351 drv->f = NULL;352 }353 354 drv->dev_cnt = 0;355 drv->rend_dev_idx = drv->cap_dev_idx = -1;356 }357 358 74 /* API: Initialize the video device subsystem. */ 359 75 PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_init(pj_pool_factory *pf) … … 361 77 unsigned i; 362 78 pj_status_t status = PJ_SUCCESS; 79 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 363 80 364 81 /* Allow init() to be called multiple times as long as there is matching 365 82 * number of shutdown(). 366 83 */ 367 if (vid_subsys .init_count++ != 0) {84 if (vid_subsys->init_count++ != 0) { 368 85 return PJ_SUCCESS; 369 86 } … … 375 92 376 93 /* Init */ 377 vid_subsys .pf = pf;378 vid_subsys .drv_cnt = 0;379 vid_subsys .dev_cnt = 0;94 vid_subsys->pf = pf; 95 vid_subsys->drv_cnt = 0; 96 vid_subsys->dev_cnt = 0; 380 97 381 98 /* Register creation functions */ 382 99 #if PJMEDIA_VIDEO_DEV_HAS_V4L2 383 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_v4l2_factory;100 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_v4l2_factory; 384 101 #endif 385 102 #if PJMEDIA_VIDEO_DEV_HAS_QT 386 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_qt_factory;103 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_qt_factory; 387 104 #endif 388 105 #if PJMEDIA_VIDEO_DEV_HAS_OPENGL 389 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_opengl_factory;106 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_opengl_factory; 390 107 #endif 391 108 #if PJMEDIA_VIDEO_DEV_HAS_IOS 392 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_ios_factory;109 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ios_factory; 393 110 #endif 394 111 #if PJMEDIA_VIDEO_DEV_HAS_DSHOW 395 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_dshow_factory;112 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_dshow_factory; 396 113 #endif 397 114 #if PJMEDIA_VIDEO_DEV_HAS_FFMPEG 398 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_ffmpeg_factory;115 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ffmpeg_factory; 399 116 #endif 400 117 #if PJMEDIA_VIDEO_DEV_HAS_SDL 401 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_sdl_factory;118 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_sdl_factory; 402 119 #endif 403 120 #if PJMEDIA_VIDEO_DEV_HAS_ANDROID 404 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_and_factory;121 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_and_factory; 405 122 #endif 406 123 #if PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC … … 408 125 * a real capturer, if any. 409 126 */ 410 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_cbar_factory;127 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_cbar_factory; 411 128 #endif 412 129 413 130 /* Initialize each factory and build the device ID list */ 414 for (i=0; i<vid_subsys .drv_cnt; ++i) {415 status = init_driver(i, PJ_FALSE);131 for (i=0; i<vid_subsys->drv_cnt; ++i) { 132 status = pjmedia_vid_driver_init(i, PJ_FALSE); 416 133 if (status != PJ_SUCCESS) { 417 deinit_driver(i);134 pjmedia_vid_driver_deinit(i); 418 135 continue; 419 136 } 420 137 } 421 138 422 return vid_subsys .dev_cnt ? PJ_SUCCESS : status;139 return vid_subsys->dev_cnt ? PJ_SUCCESS : status; 423 140 } 424 141 … … 430 147 pj_bool_t refresh = PJ_FALSE; 431 148 pj_status_t status; 432 433 if (vid_subsys.init_count == 0) 149 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 150 151 if (vid_subsys->init_count == 0) 434 152 return PJMEDIA_EVID_INIT; 435 153 436 vid_subsys .drv[vid_subsys.drv_cnt].create = adf;437 vid_subsys .drv[vid_subsys.drv_cnt].f = factory;154 vid_subsys->drv[vid_subsys->drv_cnt].create = adf; 155 vid_subsys->drv[vid_subsys->drv_cnt].f = factory; 438 156 439 157 if (factory) { … … 447 165 } 448 166 449 status = init_driver(vid_subsys.drv_cnt, refresh);167 status = pjmedia_vid_driver_init(vid_subsys->drv_cnt, refresh); 450 168 if (status == PJ_SUCCESS) { 451 vid_subsys .drv_cnt++;169 vid_subsys->drv_cnt++; 452 170 } else { 453 deinit_driver(vid_subsys.drv_cnt);171 pjmedia_vid_driver_deinit(vid_subsys->drv_cnt); 454 172 } 455 173 … … 463 181 { 464 182 unsigned i, j; 465 466 if (vid_subsys.init_count == 0) 183 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 184 185 if (vid_subsys->init_count == 0) 467 186 return PJMEDIA_EVID_INIT; 468 187 469 for (i=0; i<vid_subsys .drv_cnt; ++i) {470 struct driver *drv = &vid_subsys.drv[i];188 for (i=0; i<vid_subsys->drv_cnt; ++i) { 189 pjmedia_vid_driver *drv = &vid_subsys->drv[i]; 471 190 472 191 if ((factory && drv->f==factory) || (adf && drv->create == adf)) { 473 192 for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 474 193 { 475 vid_subsys .dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV;194 vid_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV; 476 195 } 477 196 478 deinit_driver(i);197 pjmedia_vid_driver_deinit(i); 479 198 pj_bzero(drv, sizeof(*drv)); 480 199 return PJ_SUCCESS; … … 488 207 PJ_DEF(pj_pool_factory*) pjmedia_vid_dev_subsys_get_pool_factory(void) 489 208 { 490 return vid_subsys.pf; 209 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 210 return vid_subsys->pf; 491 211 } 492 212 … … 495 215 { 496 216 unsigned i; 217 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 497 218 498 219 /* Allow shutdown() to be called multiple times as long as there is 499 220 * matching number of init(). 500 221 */ 501 if (vid_subsys .init_count == 0) {222 if (vid_subsys->init_count == 0) { 502 223 return PJ_SUCCESS; 503 224 } 504 --vid_subsys .init_count;505 506 if (vid_subsys .init_count == 0) {507 for (i=0; i<vid_subsys .drv_cnt; ++i) {508 deinit_driver(i);225 --vid_subsys->init_count; 226 227 if (vid_subsys->init_count == 0) { 228 for (i=0; i<vid_subsys->drv_cnt; ++i) { 229 pjmedia_vid_driver_deinit(i); 509 230 } 510 231 511 vid_subsys .pf = NULL;232 vid_subsys->pf = NULL; 512 233 } 513 234 return PJ_SUCCESS; 514 235 } 515 236 516 /* API: Refresh the list of video devices installed in the system. */517 PJ_DEF(pj_status_t) pjmedia_vid_dev_refresh(void)518 {519 unsigned i;520 521 vid_subsys.dev_cnt = 0;522 for (i=0; i<vid_subsys.drv_cnt; ++i) {523 struct driver *drv = &vid_subsys.drv[i];524 525 if (drv->f && drv->f->op->refresh) {526 pj_status_t status = drv->f->op->refresh(drv->f);527 if (status != PJ_SUCCESS) {528 PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "529 "list for %s", drv->name));530 }531 }532 init_driver(i, PJ_TRUE);533 }534 return PJ_SUCCESS;535 }536 537 /* API: Get the number of video devices installed in the system. */538 PJ_DEF(unsigned) pjmedia_vid_dev_count(void)539 {540 return vid_subsys.dev_cnt;541 }542 543 /* Internal: convert local index to global device index */544 static pj_status_t make_global_index(unsigned drv_idx,545 pjmedia_vid_dev_index *id)546 {547 if (*id < 0) {548 return PJ_SUCCESS;549 }550 551 /* Check that factory still exists */552 PJ_ASSERT_RETURN(vid_subsys.drv[drv_idx].f, PJ_EBUG);553 554 /* Check that device index is valid */555 PJ_ASSERT_RETURN(*id>=0 && *id<(int)vid_subsys.drv[drv_idx].dev_cnt,556 PJ_EBUG);557 558 *id += vid_subsys.drv[drv_idx].start_idx;559 return PJ_SUCCESS;560 }561 562 /* Internal: lookup device id */563 static pj_status_t lookup_dev(pjmedia_vid_dev_index id,564 pjmedia_vid_dev_factory **p_f,565 unsigned *p_local_index)566 {567 int f_id, index;568 569 if (id < 0) {570 unsigned i;571 572 if (id <= PJMEDIA_VID_INVALID_DEV)573 return PJMEDIA_EVID_INVDEV;574 575 for (i=0; i<vid_subsys.drv_cnt; ++i) {576 struct driver *drv = &vid_subsys.drv[i];577 if (id==PJMEDIA_VID_DEFAULT_CAPTURE_DEV &&578 drv->cap_dev_idx >= 0)579 {580 id = drv->cap_dev_idx;581 make_global_index(i, &id);582 break;583 } else if (id==PJMEDIA_VID_DEFAULT_RENDER_DEV &&584 drv->rend_dev_idx >= 0)585 {586 id = drv->rend_dev_idx;587 make_global_index(i, &id);588 break;589 }590 }591 592 if (id < 0) {593 return PJMEDIA_EVID_NODEFDEV;594 }595 }596 597 f_id = GET_FID(vid_subsys.dev_list[id]);598 index = GET_INDEX(vid_subsys.dev_list[id]);599 600 if (f_id < 0 || f_id >= (int)vid_subsys.drv_cnt)601 return PJMEDIA_EVID_INVDEV;602 603 if (index < 0 || index >= (int)vid_subsys.drv[f_id].dev_cnt)604 return PJMEDIA_EVID_INVDEV;605 606 *p_f = vid_subsys.drv[f_id].f;607 *p_local_index = (unsigned)index;608 609 return PJ_SUCCESS;610 611 }612 613 /* API: lookup device id */614 PJ_DEF(pj_status_t)615 pjmedia_vid_dev_get_local_index(pjmedia_vid_dev_index id,616 pjmedia_vid_dev_factory **p_f,617 unsigned *p_local_index)618 {619 return lookup_dev(id, p_f, p_local_index);620 }621 622 /* API: from factory and local index, get global index */623 PJ_DEF(pj_status_t)624 pjmedia_vid_dev_get_global_index(const pjmedia_vid_dev_factory *f,625 unsigned local_idx,626 pjmedia_vid_dev_index *pid)627 {628 PJ_ASSERT_RETURN(f->sys.drv_idx >= 0 && f->sys.drv_idx < MAX_DRIVERS,629 PJ_EINVALIDOP);630 *pid = local_idx;631 return make_global_index(f->sys.drv_idx, pid);632 }633 634 /* API: Get device information. */635 PJ_DEF(pj_status_t) pjmedia_vid_dev_get_info(pjmedia_vid_dev_index id,636 pjmedia_vid_dev_info *info)637 {638 pjmedia_vid_dev_factory *f;639 unsigned index;640 pj_status_t status;641 642 PJ_ASSERT_RETURN(info, PJ_EINVAL);643 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);644 645 if (id <= PJMEDIA_VID_INVALID_DEV)646 return PJMEDIA_EVID_INVDEV;647 648 status = lookup_dev(id, &f, &index);649 if (status != PJ_SUCCESS)650 return status;651 652 status = f->op->get_dev_info(f, index, info);653 654 /* Make sure device ID is the real ID (not PJMEDIA_VID_DEFAULT_*_DEV) */655 info->id = index;656 make_global_index(f->sys.drv_idx, &info->id);657 658 return status;659 }660 661 /* API: find device */662 PJ_DEF(pj_status_t) pjmedia_vid_dev_lookup( const char *drv_name,663 const char *dev_name,664 pjmedia_vid_dev_index *id)665 {666 pjmedia_vid_dev_factory *f = NULL;667 unsigned drv_idx, dev_idx;668 669 PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);670 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);671 672 for (drv_idx=0; drv_idx<vid_subsys.drv_cnt; ++drv_idx) {673 if (!pj_ansi_stricmp(drv_name, vid_subsys.drv[drv_idx].name))674 {675 f = vid_subsys.drv[drv_idx].f;676 break;677 }678 }679 680 if (!f)681 return PJ_ENOTFOUND;682 683 for (dev_idx=0; dev_idx<vid_subsys.drv[drv_idx].dev_cnt; ++dev_idx)684 {685 pjmedia_vid_dev_info info;686 pj_status_t status;687 688 status = f->op->get_dev_info(f, dev_idx, &info);689 if (status != PJ_SUCCESS)690 return status;691 692 if (!pj_ansi_stricmp(dev_name, info.name))693 break;694 }695 696 if (dev_idx==vid_subsys.drv[drv_idx].dev_cnt)697 return PJ_ENOTFOUND;698 699 *id = dev_idx;700 make_global_index(drv_idx, id);701 702 return PJ_SUCCESS;703 }704 705 /* API: Initialize the video device parameters with default values for the706 * specified device.707 */708 PJ_DEF(pj_status_t) pjmedia_vid_dev_default_param(pj_pool_t *pool,709 pjmedia_vid_dev_index id,710 pjmedia_vid_dev_param *param)711 {712 pjmedia_vid_dev_factory *f;713 unsigned index;714 pj_status_t status;715 716 PJ_ASSERT_RETURN(param, PJ_EINVAL);717 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);718 719 if (id <= PJMEDIA_VID_INVALID_DEV)720 return PJMEDIA_EVID_INVDEV;721 722 status = lookup_dev(id, &f, &index);723 if (status != PJ_SUCCESS)724 return status;725 726 status = f->op->default_param(pool, f, index, param);727 if (status != PJ_SUCCESS)728 return status;729 730 /* Normalize device IDs */731 make_global_index(f->sys.drv_idx, ¶m->cap_id);732 make_global_index(f->sys.drv_idx, ¶m->rend_id);733 734 return PJ_SUCCESS;735 }736 737 /* API: Open video stream object using the specified parameters. */738 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_create(739 pjmedia_vid_dev_param *prm,740 const pjmedia_vid_dev_cb *cb,741 void *user_data,742 pjmedia_vid_dev_stream **p_vid_strm)743 {744 pjmedia_vid_dev_factory *cap_f=NULL, *rend_f=NULL, *f=NULL;745 pj_status_t status;746 747 PJ_ASSERT_RETURN(prm && prm->dir && p_vid_strm, PJ_EINVAL);748 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);749 PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||750 prm->dir==PJMEDIA_DIR_RENDER ||751 prm->dir==PJMEDIA_DIR_CAPTURE_RENDER,752 PJ_EINVAL);753 754 /* Normalize cap_id */755 if (prm->dir & PJMEDIA_DIR_CAPTURE) {756 unsigned index;757 758 if (prm->cap_id < 0)759 prm->cap_id = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;760 761 status = lookup_dev(prm->cap_id, &cap_f, &index);762 if (status != PJ_SUCCESS)763 return status;764 765 prm->cap_id = index;766 f = cap_f;767 }768 769 /* Normalize rend_id */770 if (prm->dir & PJMEDIA_DIR_RENDER) {771 unsigned index;772 773 if (prm->rend_id < 0)774 prm->rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV;775 776 status = lookup_dev(prm->rend_id, &rend_f, &index);777 if (status != PJ_SUCCESS)778 return status;779 780 prm->rend_id = index;781 f = rend_f;782 }783 784 PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);785 786 /* For now, cap_id and rend_id must belong to the same factory */787 PJ_ASSERT_RETURN((prm->dir != PJMEDIA_DIR_CAPTURE_RENDER) ||788 (cap_f == rend_f),789 PJMEDIA_EVID_INVDEV);790 791 /* Create the stream */792 status = f->op->create_stream(f, prm, cb,793 user_data, p_vid_strm);794 if (status != PJ_SUCCESS)795 return status;796 797 /* Assign factory id to the stream */798 (*p_vid_strm)->sys.drv_idx = f->sys.drv_idx;799 return PJ_SUCCESS;800 }801 802 /* API: Get the running parameters for the specified video stream. */803 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_param(804 pjmedia_vid_dev_stream *strm,805 pjmedia_vid_dev_param *param)806 {807 pj_status_t status;808 809 PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);810 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);811 812 status = strm->op->get_param(strm, param);813 if (status != PJ_SUCCESS)814 return status;815 816 /* Normalize device id's */817 make_global_index(strm->sys.drv_idx, ¶m->cap_id);818 make_global_index(strm->sys.drv_idx, ¶m->rend_id);819 820 return PJ_SUCCESS;821 }822 823 /* API: Get the value of a specific capability of the video stream. */824 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_cap(825 pjmedia_vid_dev_stream *strm,826 pjmedia_vid_dev_cap cap,827 void *value)828 {829 return strm->op->get_cap(strm, cap, value);830 }831 832 /* API: Set the value of a specific capability of the video stream. */833 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_set_cap(834 pjmedia_vid_dev_stream *strm,835 pjmedia_vid_dev_cap cap,836 const void *value)837 {838 /* For fast switching, device global index needs to be converted to839 * local index before forwarding the request to the device stream.840 */841 if (cap == PJMEDIA_VID_DEV_CAP_SWITCH) {842 pjmedia_vid_dev_factory *f;843 unsigned local_idx;844 pj_status_t status;845 pjmedia_vid_dev_switch_param p = *(pjmedia_vid_dev_switch_param*)value;846 847 status = lookup_dev(p.target_id, &f, &local_idx);848 if (status != PJ_SUCCESS)849 return status;850 851 /* Make sure that current & target devices share the same factory */852 if (f->sys.drv_idx != strm->sys.drv_idx)853 return PJMEDIA_EVID_INVDEV;854 855 p.target_id = local_idx;856 return strm->op->set_cap(strm, cap, &p);857 }858 859 return strm->op->set_cap(strm, cap, value);860 }861 862 /* API: Start the stream. */863 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_start(pjmedia_vid_dev_stream *strm)864 {865 pj_status_t status;866 867 if (pjmedia_vid_dev_stream_is_running(strm))868 return PJ_SUCCESS;869 870 status = strm->op->start(strm);871 if (status == PJ_SUCCESS)872 strm->sys.is_running = PJ_TRUE;873 return status;874 }875 876 /* API: has it been started? */877 PJ_DEF(pj_bool_t)878 pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm)879 {880 return strm->sys.is_running;881 }882 883 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_frame(884 pjmedia_vid_dev_stream *strm,885 pjmedia_frame *frame)886 {887 pj_assert(strm->op->get_frame);888 return strm->op->get_frame(strm, frame);889 }890 891 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_put_frame(892 pjmedia_vid_dev_stream *strm,893 const pjmedia_frame *frame)894 {895 pj_assert(strm->op->put_frame);896 return strm->op->put_frame(strm, frame);897 }898 899 /* API: Stop the stream. */900 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_stop(pjmedia_vid_dev_stream *strm)901 {902 strm->sys.is_running = PJ_FALSE;903 return strm->op->stop(strm);904 }905 906 /* API: Destroy the stream. */907 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_destroy(908 pjmedia_vid_dev_stream *strm)909 {910 strm->sys.is_running = PJ_FALSE;911 return strm->op->destroy(strm);912 }913 914 237 915 238 #endif /* PJMEDIA_HAS_VIDEO */ -
pjproject/trunk/pjmedia/src/pjmedia/endpoint.c
r5242 r5255 106 106 * Initialize and get the instance of media endpoint. 107 107 */ 108 PJ_DEF(pj_status_t) pjmedia_endpt_create (pj_pool_factory *pf,109 pj_ioqueue_t *ioqueue,110 unsigned worker_cnt,111 pjmedia_endpt **p_endpt)108 PJ_DEF(pj_status_t) pjmedia_endpt_create2(pj_pool_factory *pf, 109 pj_ioqueue_t *ioqueue, 110 unsigned worker_cnt, 111 pjmedia_endpt **p_endpt) 112 112 { 113 113 pj_pool_t *pool; … … 134 134 endpt->has_telephone_event = PJ_TRUE; 135 135 136 /* Sound */ 137 status = pjmedia_aud_subsys_init(pf); 138 if (status != PJ_SUCCESS) 139 goto on_error; 136 /* Initialize audio subsystem. 137 * To avoid pjmedia's dependendy on pjmedia-audiodev, the initialization 138 * (and shutdown) of audio subsystem will be done in the application 139 * level instead, when it calls inline functions pjmedia_endpt_create() 140 * and pjmedia_endpt_destroy(). 141 */ 142 //status = pjmedia_aud_subsys_init(pf); 143 //if (status != PJ_SUCCESS) 144 // goto on_error; 140 145 141 146 /* Init codec manager. */ … … 189 194 190 195 pjmedia_codec_mgr_destroy(&endpt->codec_mgr); 191 pjmedia_aud_subsys_shutdown();196 //pjmedia_aud_subsys_shutdown(); 192 197 pj_pool_release(pool); 193 198 return status; … … 205 210 * Deinitialize media endpoint. 206 211 */ 207 PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)212 PJ_DEF(pj_status_t) pjmedia_endpt_destroy2 (pjmedia_endpt *endpt) 208 213 { 209 214 exit_cb *ecb; … … 220 225 221 226 pjmedia_codec_mgr_destroy(&endpt->codec_mgr); 222 pjmedia_aud_subsys_shutdown();227 //pjmedia_aud_subsys_shutdown(); 223 228 224 229 /* Call all registered exit callbacks */ -
pjproject/trunk/pjmedia/src/pjmedia/sound_legacy.c
r5140 r5255 28 28 29 29 #include <pjmedia/sound.h> 30 #include <pjmedia-audiodev/errno.h>31 30 #include <pj/assert.h> 32 31 … … 50 49 }; 51 50 52 PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)53 {54 return pjmedia_aud_subsys_init(factory);55 }56 57 PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)58 {59 return pjmedia_aud_subsys_shutdown();60 }61 62 PJ_DEF(int) pjmedia_snd_get_dev_count(void)63 {64 return pjmedia_aud_dev_count();65 }66 51 67 52 PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index) … … 159 144 160 145 /* Create sound wrapper */ 161 pool = pj_pool_create(pjmedia_ aud_subsys_get_pool_factory(),146 pool = pj_pool_create(pjmedia_get_aud_subsys()->pf, 162 147 "legacy-snd", 512, 512, NULL); 163 148 snd_strm = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_stream);
Note: See TracChangeset
for help on using the changeset viewer.