- Timestamp:
- Feb 21, 2009 2:21:59 PM (16 years ago)
- Location:
- pjproject/branches/projects/aps-direct
- Files:
-
- 2 deleted
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/aps-direct/pjmedia/build/pjmedia.dsp
r2458 r2468 122 122 # Begin Source File 123 123 124 SOURCE=..\src\pjmedia\dsound.c125 # End Source File126 # Begin Source File127 128 124 SOURCE=..\src\pjmedia\echo_common.c 129 125 # End Source File … … 178 174 # Begin Source File 179 175 180 SOURCE=..\src\pjmedia\nullsound.c181 # End Source File182 # Begin Source File183 184 SOURCE=..\src\pjmedia\pasound.c185 # End Source File186 # Begin Source File187 188 176 SOURCE=..\src\pjmedia\plc_common.c 189 177 # End Source File … … 295 283 296 284 SOURCE=..\src\pjmedia\wave.c 297 # End Source File298 # Begin Source File299 300 SOURCE=..\src\pjmedia\wmme_sound.c301 285 # End Source File 302 286 # Begin Source File -
pjproject/branches/projects/aps-direct/pjmedia/build/pjmedia_audiodev.dsp
r2463 r2468 102 102 # Begin Source File 103 103 104 SOURCE="..\src\pjmedia-audiodev\symb_aps_dev.cpp" 105 # PROP Exclude_From_Build 1 106 # End Source File 107 # Begin Source File 108 109 SOURCE="..\src\pjmedia-audiodev\symb_mda_dev.cpp" 110 # PROP Exclude_From_Build 1 111 # End Source File 112 # Begin Source File 113 104 114 SOURCE="..\src\pjmedia-audiodev\wmme_dev.c" 105 115 # End Source File -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiodev.h
r2466 r2468 18 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 #ifndef __ AUDIODEV_H__21 #define __ AUDIODEV_H__20 #ifndef __PJMEDIA_AUDIODEV_AUDIODEV_H__ 21 #define __PJMEDIA_AUDIODEV_AUDIODEV_H__ 22 22 23 23 /** … … 52 52 */ 53 53 54 /** Device identifier */ 55 typedef pj_int32_t pjmedia_aud_dev_id; 56 57 /** Constant to denote default ID */ 58 #define PJMEDIA_AUD_DEV_DEFAULT_ID (-1) 54 /** 55 * Type for device index. 56 */ 57 typedef pj_int32_t pjmedia_aud_dev_index; 58 59 /** 60 * Constant to denote default device 61 */ 62 #define PJMEDIA_AUD_DEV_DEFAULT (-1) 63 64 /** 65 * Type for device unique identifier. The unique device ID can be used to save 66 * a reference to a particular device across software reboots. 67 */ 68 typedef pj_uint32_t pjmedia_aud_dev_uid; 59 69 60 70 … … 67 77 * 68 78 * Application can also set the specific features/capabilities when opening 69 * the audio stream by setting the \a flags member of #pjmedia_aud_ dev_param79 * the audio stream by setting the \a flags member of #pjmedia_aud_param 70 80 * structure. 71 81 * … … 118 128 * the audio volume in percent. 119 129 */ 120 PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_ VOLUME= 32,130 PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER = 32, 121 131 122 132 /** … … 125 135 * the audio volume in percent. 126 136 */ 127 PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_ VOLUME= 64,137 PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER = 64, 128 138 129 139 /** … … 142 152 /** 143 153 * The audio device has echo cancellation feature. The value of this 144 * capability is a n integercontaining boolean PJ_TRUE or PJ_FALSE.154 * capability is a pj_bool_t containing boolean PJ_TRUE or PJ_FALSE. 145 155 */ 146 156 PJMEDIA_AUD_DEV_CAP_EC = 512, … … 155 165 /** 156 166 * The audio device has voice activity detection feature. The value 157 * of this capability is a n integercontaining boolean PJ_TRUE or167 * of this capability is a pj_bool_t containing boolean PJ_TRUE or 158 168 * PJ_FALSE. 159 169 */ … … 162 172 /** 163 173 * The audio device has comfort noise generation feature. The value 164 * of this capability is a n integercontaining boolean PJ_TRUE or174 * of this capability is a pj_bool_t containing boolean PJ_TRUE or 165 175 * PJ_FALSE. 166 176 */ … … 169 179 /** 170 180 * The audio device has packet loss concealment feature. The value 171 * of this capability is a n integercontaining boolean PJ_TRUE or181 * of this capability is a pj_bool_t containing boolean PJ_TRUE or 172 182 * PJ_FALSE. 173 183 */ … … 226 236 * The underlying driver name 227 237 */ 228 char driver[ 128];238 char driver[32]; 229 239 230 240 /** … … 290 300 291 301 /** 292 * This structure specifies the parameters to open the audio devicestream.293 */ 294 typedef struct pjmedia_aud_ dev_param302 * This structure specifies the parameters to open the audio stream. 303 */ 304 typedef struct pjmedia_aud_param 295 305 { 296 306 /** … … 303 313 * direction includes input/capture direction. 304 314 */ 305 pjmedia_aud_dev_i drec_id;315 pjmedia_aud_dev_index rec_id; 306 316 307 317 /** … … 309 319 * direction includes output/playback direction. 310 320 */ 311 pjmedia_aud_dev_i dplay_id;321 pjmedia_aud_dev_index play_id; 312 322 313 323 /** … … 387 397 pj_bool_t cng_enabled; 388 398 389 } pjmedia_aud_ dev_param;399 } pjmedia_aud_param; 390 400 391 401 … … 432 442 433 443 /** 444 * Get string info for the specified capability. 445 * 446 * @param cap The capability ID. 447 * @param p_desc Optional pointer which will be filled with longer 448 * description about the capability. 449 * 450 * @return Capability name. 451 */ 452 PJ_DECL(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, 453 const char **p_desc); 454 455 456 /** 434 457 * Get the number of sound devices installed in the system. 435 458 * … … 438 461 PJ_DECL(unsigned) pjmedia_aud_dev_count(void); 439 462 440 441 /**442 * Enumerate device ID's.443 *444 * @param max_count Maximum number of device id's to retrieve.445 * @param ids Array to receive the device id's.446 *447 * @return The actual number of device id's filled in.448 */449 PJ_DECL(unsigned) pjmedia_aud_dev_enum(unsigned max_count,450 pjmedia_aud_dev_id ids[]);451 463 452 464 /** … … 460 472 * error code. 461 473 */ 462 PJ_DECL(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_i did,474 PJ_DECL(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, 463 475 pjmedia_aud_dev_info *info); 476 477 478 /** 479 * Lookup device index based on the driver and device name. 480 * 481 * @param drv_name The driver name. 482 * @param dev_name The device name. 483 * 484 * @return PJ_SUCCESS if the device can be found. 485 */ 486 PJ_DECL(pj_status_t) pjmedia_aud_dev_lookup(const char *drv_name, 487 const char *dev_name, 488 pjmedia_aud_dev_index *id); 464 489 465 490 … … 475 500 * error code. 476 501 */ 477 PJ_DECL(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_i did,478 pjmedia_aud_ dev_param *param);502 PJ_DECL(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, 503 pjmedia_aud_param *param); 479 504 480 505 … … 493 518 * error code. 494 519 */ 495 PJ_DECL(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_ dev_param *param,520 PJ_DECL(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *param, 496 521 pjmedia_aud_rec_cb rec_cb, 497 522 pjmedia_aud_play_cb play_cb, 498 523 void *user_data, 499 pjmedia_aud_stream **p_ aud_strm);524 pjmedia_aud_stream **p_strm); 500 525 501 526 /** … … 510 535 */ 511 536 PJ_DECL(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, 512 pjmedia_aud_ dev_param *param);537 pjmedia_aud_param *param); 513 538 514 539 /** … … 581 606 #define PJMEDIA_EAUD_NOTREADY -1 582 607 608 /* Invalid audio capability or audio capability not supported */ 609 #define PJMEDIA_EAUD_INVCAP -1 610 583 611 /* Unknown system error */ 584 612 #define PJMEDIA_EAUD_SYSERR -1 … … 592 620 593 621 594 #endif /* __ AUDIODEV_H__ */595 622 #endif /* __PJMEDIA_AUDIODEV_AUDIODEV_H__ */ 623 -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiodev_imp.h
r2459 r2468 80 80 pj_status_t (*default_param)(pjmedia_aud_dev_factory *f, 81 81 unsigned index, 82 pjmedia_aud_ dev_param *param);82 pjmedia_aud_param *param); 83 83 84 84 /** … … 87 87 */ 88 88 pj_status_t (*create_stream)(pjmedia_aud_dev_factory *f, 89 const pjmedia_aud_ dev_param *param,89 const pjmedia_aud_param *param, 90 90 pjmedia_aud_rec_cb rec_cb, 91 91 pjmedia_aud_play_cb play_cb, … … 120 120 */ 121 121 pj_status_t (*get_param)(pjmedia_aud_stream *strm, 122 pjmedia_aud_ dev_param *param);122 pjmedia_aud_param *param); 123 123 124 124 /** … … 159 159 struct pjmedia_aud_stream 160 160 { 161 /** Factory */162 pjmedia_aud_dev_factory *factory;161 /** Factory id (internal) */ 162 unsigned factory_id; 163 163 164 164 /** Operations */ -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiotest.h
r2463 r2468 18 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 #ifndef __ AUDIOTEST_H__21 #define __ AUDIOTEST_H__20 #ifndef __PJMEDIA_AUDIODEV_AUDIOTEST_H__ 21 #define __PJMEDIA_AUDIODEV_AUDIOTEST_H__ 22 22 23 23 /** … … 92 92 * Perform audio device testing. 93 93 */ 94 PJ_DECL(pj_status_t) pjmedia_aud_test(const pjmedia_aud_ dev_param *param,94 PJ_DECL(pj_status_t) pjmedia_aud_test(const pjmedia_aud_param *param, 95 95 pjmedia_aud_test_results *result); 96 96 … … 102 102 103 103 104 #endif /* __ AUDIOTEST_H__ */104 #endif /* __PJMEDIA_AUDIODEV_AUDIOTEST_H__ */ 105 105 106 106 -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia.h
r2394 r2468 53 53 #include <pjmedia/session.h> 54 54 #include <pjmedia/silencedet.h> 55 /* This sound API is deprecated. Please see: 56 http://trac.pjsip.org/repos/wiki/Audio_Dev_API 55 57 #include <pjmedia/sound.h> 58 */ 56 59 #include <pjmedia/sound_port.h> 57 60 #include <pjmedia/splitcomb.h> -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/config.h
r2452 r2468 65 65 */ 66 66 67 /** Constant for NULL sound backend. */ 68 #define PJMEDIA_SOUND_NULL_SOUND 0 69 70 /** Constant for PortAudio sound backend. */ 71 #define PJMEDIA_SOUND_PORTAUDIO_SOUND 1 72 73 /** Constant for Win32 DirectSound sound backend. */ 74 #define PJMEDIA_SOUND_WIN32_DIRECT_SOUND 2 75 76 /** Constant for Win32 MME sound backend. */ 77 #define PJMEDIA_SOUND_WIN32_MME_SOUND 3 78 79 /** Constant for Symbian Multimedia Audio Stream backend. */ 80 #define PJMEDIA_SOUND_SYMB_MDA_SOUND 4 81 82 /** Constant for Symbian APS backend. */ 83 #define PJMEDIA_SOUND_SYMB_APS_SOUND 5 84 85 /** Constant for Symbian VAS backend. */ 86 #define PJMEDIA_SOUND_SYMB_VAS_SOUND 6 87 88 89 /** When this is set, pjmedia will not provide any sound device backend. 90 * Application will have to provide its own sound device backend 91 * and link the application with it. 92 */ 93 #define PJMEDIA_SOUND_EXTERNAL 255 94 95 96 /** 97 * Unless specified otherwise, sound device uses PortAudio implementation 98 * by default. 99 */ 100 #ifndef PJMEDIA_SOUND_IMPLEMENTATION 101 # if defined(PJ_WIN32) && PJ_WIN32!=0 102 /*# define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_WIN32_DIRECT_SOUND*/ 103 /*# define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_WIN32_MME_SOUND*/ 104 # define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_PORTAUDIO_SOUND 105 # else 106 # define PJMEDIA_SOUND_IMPLEMENTATION PJMEDIA_SOUND_PORTAUDIO_SOUND 107 # endif 108 #endif 109 110 /** 111 * Specify if the sound device implementation supports handling encoded 112 * frames. Setting this to zero will activate some emulation in the 113 * sound port. 114 */ 115 #if PJMEDIA_SOUND_IMPLEMENTATION==PJMEDIA_SOUND_SYMB_APS_SOUND || \ 116 PJMEDIA_SOUND_IMPLEMENTATION==PJMEDIA_SOUND_SYMB_VAS_SOUND 117 # define PJMEDIA_SND_SUPPORT_OPEN2 1 118 #else 119 # define PJMEDIA_SND_SUPPORT_OPEN2 0 120 #endif 121 122 /** 123 * Specify whether we prefer to use DirectSound on Windows. 124 * 125 * Default: 0 126 */ 127 #ifndef PJMEDIA_PREFER_DIRECT_SOUND 128 # define PJMEDIA_PREFER_DIRECT_SOUND 0 129 #endif 130 131 132 /** 133 * Specify sound device latency default, in milisecond. 67 /** 68 * This macro has been deprecated in releasee 1.1. Please see 69 * http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more information. 70 */ 71 #if defined(PJMEDIA_SOUND_IMPLEMENTATION) 72 # error PJMEDIA_SOUND_IMPLEMENTATION has been deprecated 73 #endif 74 75 /** 76 * This macro has been deprecated in releasee 1.1. Please see 77 * http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more information. 78 */ 79 #if defined(PJMEDIA_PREFER_DIRECT_SOUND) 80 # error PJMEDIA_PREFER_DIRECT_SOUND has been deprecated 81 #endif 82 83 /** 84 * Setting PJMEDIA_AUDIO_API to this value will completely deprecate the use 85 * of old API, and inclusion of <pjmedia/sound.h> in the code will raise 86 * compilation error. 87 */ 88 #define PJMEDIA_AUDIO_API_NEW_ONLY 1 89 90 /** 91 * Setting PJMEDIA_AUDIO_API to this value enables application to use the old 92 * sound device API to access audio devices provided by the new audio device 93 * API. 94 */ 95 #define PJMEDIA_AUDIO_API_HAS_OLD_API 2 96 97 /** 98 * Setting PJMEDIA_AUDIO_API to this value enables old sound device 99 * implementation to be accessed via both old and new API's. 100 */ 101 #define PJMEDIA_AUDIO_API_HAS_OLD_DEVICE 3 102 103 /** 104 * Specify how the audio API should handle compatibility with old sound API. 105 * Valid values are: PJMEDIA_AUDIO_API_HAS_OLD_API (default, 106 * PJMEDIA_AUDIO_API_NEW_ONLY, or PJMEDIA_AUDIO_API_HAS_OLD_DEVICE. Please 107 * see http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more info. 108 */ 109 #ifndef PJMEDIA_AUDIO_API 110 # define PJMEDIA_AUDIO_API PJMEDIA_AUDIO_API_NEW_ONLY 111 #endif 112 113 114 /** 115 * Specify default sound device latency, in milisecond. 134 116 */ 135 117 #ifndef PJMEDIA_SND_DEFAULT_REC_LATENCY … … 137 119 #endif 138 120 121 /** 122 * Specify default sound device latency, in milisecond. 123 */ 139 124 #ifndef PJMEDIA_SND_DEFAULT_PLAY_LATENCY 140 125 # define PJMEDIA_SND_DEFAULT_PLAY_LATENCY 100 141 #endif142 143 144 /**145 * Specify whether delay buffer is used for sound device.146 * When delay buffer is enabled, the sound device callback147 * will be called one after another evenly.148 * The delay buffer also performs the best delay calculation149 * for the sound device, and will try to limit the delay caused150 * by uneven callback calls to this delay.151 *152 * When this setting is enabled, the PJMEDIA_SOUND_BUFFER_COUNT153 * macro will specify the maximum size of the delay buffer.154 */155 #ifndef PJMEDIA_SOUND_USE_DELAYBUF156 # define PJMEDIA_SOUND_USE_DELAYBUF 0157 126 #endif 158 127 -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/endpoint.h
r2394 r2468 38 38 */ 39 39 40 #include <pjmedia/sound.h>41 40 #include <pjmedia/codec.h> 42 41 #include <pjmedia/sdp.h> -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/sound.h
r2460 r2468 20 20 #ifndef __PJMEDIA_SOUND_H__ 21 21 #define __PJMEDIA_SOUND_H__ 22 23 24 /* This is legacy sound device code, which has been superseded by the 25 * new pjmedia-audiodev framework. Please see the documentation on how 26 * to use this legacy API. 27 */ 28 #if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 29 # error "The sound device API is deprecated. Please see doc for details." 30 #endif 22 31 23 32 -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/sound_port.h
r2438 r2468 25 25 * @brief Media port connection abstraction to sound device. 26 26 */ 27 #include <pjmedia /sound.h>27 #include <pjmedia-audiodev/audiodev.h> 28 28 #include <pjmedia/port.h> 29 29 … … 163 163 164 164 /** 165 * Create unidirectional or bidirectional sound port. This also allows 166 * creating sound port with extended settings, e.g: audio format, see 167 * #pjmedia_snd_setting. 168 * 169 * @param pool Pool to allocate sound port structure. 170 * @param dir Sound device direction. 171 * @param rec_id Device index for recorder/capture stream, or 172 * -1 to use the first capable device. 173 * @param play_id Device index for playback stream, or -1 to use 174 * the first capable device. 175 * @param clock_rate Sound device's clock rate to set. 176 * @param channel_count Set number of channels, 1 for mono, or 2 for 177 * stereo. The channel count determines the format 178 * of the frame. 179 * @param samples_per_frame Number of samples per frame. 180 * @param bits_per_sample Set the number of bits per sample. The normal 181 * value for this parameter is 16 bits per sample. 182 * @param setting Sound device extended settings, see 183 * #pjmedia_snd_setting. 165 * Create sound device port according to the specified parameters. 166 * 167 * @param pool Pool to allocate sound port structure. 168 * @param prm Sound device settings. 184 169 * @param p_port Pointer to receive the sound device port instance. 185 170 * … … 188 173 */ 189 174 PJ_DECL(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 190 pjmedia_dir dir, 191 int rec_id, 192 int play_id, 193 unsigned clock_rate, 194 unsigned channel_count, 195 unsigned samples_per_frame, 196 unsigned bits_per_sample, 197 const pjmedia_snd_setting *setting, 175 const pjmedia_aud_param *prm, 198 176 pjmedia_snd_port **p_port); 199 177 … … 217 195 * @return The sound stream instance. 218 196 */ 219 PJ_DECL(pjmedia_ snd_stream*) pjmedia_snd_port_get_snd_stream(197 PJ_DECL(pjmedia_aud_stream*) pjmedia_snd_port_get_snd_stream( 220 198 pjmedia_snd_port *snd_port); 221 199 222 200 223 201 /** 224 * Configure the echo cancellation tail length. By default, echo canceller 225 * is enabled in the sound device with the default tail length. After the 226 * sound port is created, application can query the current echo canceller 227 * tail length by calling #pjmedia_snd_port_get_ec_tail. 228 * 229 * Note that you should only change the EC settings when the sound port 230 * is not connected to any downstream ports, otherwise race condition may 231 * occur. 202 * Change the echo cancellation settings. The echo cancellation settings 203 * should have been specified when this sound port was created, by setting 204 * the appropriate fields in the pjmedia_aud_param, because not all sound 205 * device implementation supports changing the EC setting once the device 206 * has been opened. 207 * 208 * The behavior of this function depends on whether device or software AEC 209 * is being used. If the device supports AEC, this function will forward 210 * the change request to the device and it will be up to the device whether 211 * to support the request. If software AEC is being used (the software EC 212 * will be used if the device does not support AEC), this function will 213 * change the software EC settings. 232 214 * 233 215 * @param snd_port The sound device port. … … 237 219 * be disabled. 238 220 * @param options The options to be passed to #pjmedia_echo_create(). 221 * This is only used if software EC is being used. 239 222 * 240 223 * @return PJ_SUCCESS on success. -
pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/stream.h
r2394 r2468 27 27 */ 28 28 29 #include <pjmedia/sound.h>30 29 #include <pjmedia/codec.h> 31 30 #include <pjmedia/endpoint.h> -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/audiodev.c
r2464 r2468 20 20 #include <pjmedia-audiodev/audiodev_imp.h> 21 21 #include <pj/errno.h> 22 #include <pj/log.h> 23 #include <pj/string.h> 24 25 #define THIS_FILE "audiodev.c" 26 27 /* Capability names */ 28 static struct cap_info 29 { 30 const char *name; 31 const char *info; 32 } cap_infos[] = 33 { 34 {"ext-fmt", "Extended/non-PCM format"}, 35 {"latency-in", "Input latency/buffer size setting"}, 36 {"latency-out", "Output latency/buffer size setting"}, 37 {"vol-in", "Input volume setting"}, 38 {"vol-out", "Output volume setting"}, 39 {"meter-in", "Input meter"}, 40 {"meter-out", "Output meter"}, 41 {"route-in", "Input routing"}, 42 {"route-out", "Output routing"}, 43 {"aec", "Accoustic echo cancellation"}, 44 {"aec-tail", "Tail length setting for AEC"}, 45 {"vad", "Voice activity detection"}, 46 {"cng", "Comfort noise generation"}, 47 {"plg", "Packet loss concealment"} 48 }; 49 22 50 23 51 /* 24 * The Device IDseen by application and driver is different.52 * The device index seen by application and driver is different. 25 53 * 26 * At application level, device ID is a 32bit value. The high 16bit contains 27 * the factory ID, and the low 16bit contains the device index in the 28 * specified factory. The device ID may also be -1 to denote default device. 29 * 30 * At driver level, device ID is a 16bit unsigned integer index. 54 * At application level, device index is index to global list of device. 55 * At driver level, device index is index to device list on that particular 56 * factory only. 31 57 */ 32 58 #define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF)) … … 41 67 42 68 #define MAX_DRIVERS 16 69 #define MAX_DEVS 64 70 71 /* typedef for factory creation function */ 72 typedef pjmedia_aud_dev_factory* (*create_func_ptr)(pj_pool_factory*); 73 74 /* driver structure */ 75 struct driver 76 { 77 create_func_ptr create; /* Creation function. */ 78 pjmedia_aud_dev_factory *f; /* Factory instance. */ 79 char name[32]; /* Driver name */ 80 unsigned dev_cnt; /* Number of devices */ 81 unsigned start_idx; /* Start index in global list */ 82 }; 43 83 44 84 /* The audio subsystem */ 45 85 static struct aud_subsys 46 86 { 47 unsigned init_count; 48 pj_pool_factory *pf; 49 unsigned factory_cnt; 50 51 struct factory 52 { 53 pjmedia_aud_dev_factory* (*create)(pj_pool_factory*); 54 pjmedia_aud_dev_factory *f; 55 56 } factories[MAX_DRIVERS]; 87 unsigned init_count; /* How many times init() is called */ 88 pj_pool_factory *pf; /* The pool factory. */ 89 90 unsigned drv_cnt; /* Number of drivers. */ 91 struct driver drv[MAX_DRIVERS]; /* Array of drivers. */ 92 93 unsigned dev_cnt; /* Total number of devices. */ 94 pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */ 57 95 58 96 } aud_subsys; … … 74 112 75 113 aud_subsys.pf = pf; 76 aud_subsys.factory_cnt = 0; 77 78 aud_subsys.factories[aud_subsys.factory_cnt++].create = &pjmedia_pa_factory; 79 aud_subsys.factories[aud_subsys.factory_cnt++].create = &pjmedia_wmme_factory; 80 81 for (i=0; i<aud_subsys.factory_cnt; ++i) { 114 aud_subsys.drv_cnt = 0; 115 aud_subsys.dev_cnt = 0; 116 117 /* Register creation functions */ 118 aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory; 119 aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory; 120 121 /* Initialize each factory and build the device ID list */ 122 for (i=0; i<aud_subsys.drv_cnt; ++i) { 82 123 pjmedia_aud_dev_factory *f; 83 84 f = (*aud_subsys.factories[i].create)(pf); 124 pjmedia_aud_dev_info info; 125 unsigned j, dev_cnt; 126 127 /* Create the factory */ 128 f = (*aud_subsys.drv[i].create)(pf); 85 129 if (!f) 86 130 continue; 87 131 132 /* Call factory->init() */ 88 133 status = f->op->init(f); 89 134 if (status != PJ_SUCCESS) { … … 92 137 } 93 138 94 aud_subsys.factories[i].f = f; 95 aud_subsys.factories[i].f->internal.id = i; 96 } 97 98 return aud_subsys.factory_cnt ? PJ_SUCCESS : status; 139 /* Build device list */ 140 dev_cnt = f->op->get_dev_count(f); 141 if (dev_cnt == 0) { 142 f->op->destroy(f); 143 continue; 144 } 145 146 /* Get one device info */ 147 status = f->op->get_dev_info(f, 0, &info); 148 if (status != PJ_SUCCESS) { 149 f->op->destroy(f); 150 continue; 151 } 152 153 /* Register the factory */ 154 aud_subsys.drv[i].f = f; 155 aud_subsys.drv[i].f->internal.id = i; 156 aud_subsys.drv[i].start_idx = aud_subsys.dev_cnt; 157 pj_ansi_strncpy(aud_subsys.drv[i].name, info.driver, 158 sizeof(aud_subsys.drv[i].name)); 159 aud_subsys.drv[i].name[sizeof(aud_subsys.drv[i].name)-1] = '\0'; 160 161 /* Register devices */ 162 if (aud_subsys.dev_cnt + dev_cnt > MAX_DEVS) { 163 PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because" 164 " there are too many sound devices", 165 aud_subsys.dev_cnt + dev_cnt - MAX_DEVS)); 166 dev_cnt = MAX_DEVS - aud_subsys.dev_cnt; 167 } 168 for (j=0; j<dev_cnt; ++j) { 169 aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(i, j); 170 } 171 172 } 173 174 return aud_subsys.drv_cnt ? PJ_SUCCESS : status; 99 175 } 100 176 … … 118 194 --aud_subsys.init_count; 119 195 120 for (i=0; i<aud_subsys. factory_cnt; ++i) {121 pjmedia_aud_dev_factory *f = aud_subsys. factories[i].f;196 for (i=0; i<aud_subsys.drv_cnt; ++i) { 197 pjmedia_aud_dev_factory *f = aud_subsys.drv[i].f; 122 198 123 199 if (!f) … … 125 201 126 202 f->op->destroy(f); 127 aud_subsys.factories[i].f = NULL; 128 } 129 130 return PJ_SUCCESS; 203 aud_subsys.drv[i].f = NULL; 204 } 205 206 return PJ_SUCCESS; 207 } 208 209 /* API: get capability name/info */ 210 PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, 211 const char **p_desc) 212 { 213 char *desc; 214 unsigned i; 215 216 if (p_desc==NULL) p_desc = &desc; 217 218 for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) { 219 if ((1 << i)==cap) 220 break; 221 } 222 223 if (i==32) { 224 *p_desc = "??"; 225 return "??"; 226 } 227 228 *p_desc = cap_infos[i].info; 229 return cap_infos[i].name; 131 230 } 132 231 … … 134 233 PJ_DEF(unsigned) pjmedia_aud_dev_count(void) 135 234 { 136 unsigned i, count = 0; 137 138 for (i=0; i<aud_subsys.factory_cnt; ++i) { 139 pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f; 140 141 if (!f) 142 continue; 143 144 count += f->op->get_dev_count(f); 145 } 146 147 return count; 148 } 149 150 /* API: Enumerate device ID's. */ 151 PJ_DEF(unsigned) pjmedia_aud_dev_enum(unsigned max_count, 152 pjmedia_aud_dev_id ids[]) 153 { 154 unsigned i, count = 0; 155 156 for (i=0; i<aud_subsys.factory_cnt && count < max_count; ++i) { 157 pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f; 158 unsigned j, fcount; 159 160 if (!f) 161 continue; 162 163 fcount = f->op->get_dev_count(f); 164 for (j=0; j<fcount && count<max_count; ++j) { 165 ids[count++] = MAKE_DEV_ID(i, j); 166 } 167 } 168 169 return count; 170 } 171 235 return aud_subsys.dev_cnt; 236 } 237 238 /* Internal: lookup device id */ 239 static pj_status_t lookup_dev(pjmedia_aud_dev_index id, 240 pjmedia_aud_dev_factory **p_f, 241 unsigned *p_local_index) 242 { 243 int f_id, index; 244 245 if (id == PJMEDIA_AUD_DEV_DEFAULT) 246 id = DEFAULT_DEV_ID; 247 248 PJ_ASSERT_RETURN(id>=0 && id<(int)aud_subsys.dev_cnt, 249 PJMEDIA_EAUD_INVDEV); 250 251 f_id = GET_FID(aud_subsys.dev_list[id]); 252 index = GET_INDEX(aud_subsys.dev_list[id]); 253 254 if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt) 255 return PJMEDIA_EAUD_INVDEV; 256 257 if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt) 258 return PJMEDIA_EAUD_INVDEV; 259 260 *p_f = aud_subsys.drv[f_id].f; 261 *p_local_index = (unsigned)index; 262 263 return PJ_SUCCESS; 264 265 } 266 267 /* Internal: convert local index to global device index */ 268 static pj_status_t make_global_index(pjmedia_aud_dev_factory *f, 269 pjmedia_aud_dev_index *id) 270 { 271 unsigned f_id = f->internal.id; 272 273 if (*id == PJMEDIA_AUD_DEV_DEFAULT) 274 return PJ_SUCCESS; 275 276 /* Check that factory still exists */ 277 PJ_ASSERT_RETURN(f, PJ_EBUG); 278 279 /* Check that device index is valid */ 280 PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[f_id].dev_cnt, PJ_EBUG); 281 282 *id += aud_subsys.drv[f_id].start_idx; 283 return PJ_SUCCESS; 284 } 172 285 173 286 /* API: Get device information. */ 174 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_i did,287 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, 175 288 pjmedia_aud_dev_info *info) 176 289 { 177 290 pjmedia_aud_dev_factory *f; 178 int f_id, index; 179 180 if (id == PJMEDIA_AUD_DEV_DEFAULT_ID) 181 id = DEFAULT_DEV_ID; 182 183 f_id = GET_FID(id); 184 index = GET_INDEX(id); 185 186 if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 187 return PJMEDIA_EAUD_INVDEV; 188 189 f = aud_subsys.factories[f_id].f; 190 if (f == NULL) 191 return PJMEDIA_EAUD_INVDEV; 291 unsigned index; 292 pj_status_t status; 293 294 PJ_ASSERT_RETURN(info, PJ_EINVAL); 295 296 status = lookup_dev(id, &f, &index); 297 if (status != PJ_SUCCESS) 298 return status; 192 299 193 300 return f->op->get_dev_info(f, index, info); 301 } 302 303 /* API: find device */ 304 PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name, 305 const char *dev_name, 306 pjmedia_aud_dev_index *id) 307 { 308 pjmedia_aud_dev_factory *f = NULL; 309 unsigned i, j; 310 311 PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); 312 313 for (i=0; i<aud_subsys.drv_cnt; ++i) { 314 if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[i].name)) { 315 f = aud_subsys.drv[i].f; 316 break; 317 } 318 } 319 320 if (!f) 321 return PJ_ENOTFOUND; 322 323 for (j=0; j<aud_subsys.drv[i].dev_cnt; ++j) { 324 pjmedia_aud_dev_info info; 325 pj_status_t status; 326 327 status = f->op->get_dev_info(f, j, &info); 328 if (status != PJ_SUCCESS) 329 return status; 330 331 if (!pj_ansi_stricmp(dev_name, info.name)) 332 break; 333 } 334 335 if (j==aud_subsys.drv[i].dev_cnt) 336 return PJ_ENOTFOUND; 337 338 *id = j; 339 make_global_index(f, id); 340 341 return PJ_SUCCESS; 194 342 } 195 343 … … 197 345 * specified device. 198 346 */ 199 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_i did,200 pjmedia_aud_ dev_param *param)347 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, 348 pjmedia_aud_param *param) 201 349 { 202 350 pjmedia_aud_dev_factory *f; 203 int f_id,index;351 unsigned index; 204 352 pj_status_t status; 205 353 206 if (id == PJMEDIA_AUD_DEV_DEFAULT_ID) 207 id = DEFAULT_DEV_ID; 208 209 f_id = GET_FID(id); 210 index = GET_INDEX(id); 211 212 if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 213 return PJMEDIA_EAUD_INVDEV; 214 215 f = aud_subsys.factories[f_id].f; 216 if (f == NULL) 217 return PJMEDIA_EAUD_INVDEV; 354 PJ_ASSERT_RETURN(param, PJ_EINVAL); 355 356 status = lookup_dev(id, &f, &index); 357 if (status != PJ_SUCCESS) 358 return status; 218 359 219 360 status = f->op->default_param(f, index, param); … … 222 363 223 364 /* Normalize device IDs */ 224 if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 225 param->rec_id = MAKE_DEV_ID(f_id, param->rec_id); 226 if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 227 param->play_id = MAKE_DEV_ID(f_id, param->play_id); 365 make_global_index(f, ¶m->rec_id); 366 make_global_index(f, ¶m->play_id); 228 367 229 368 return PJ_SUCCESS; … … 231 370 232 371 /* API: Open audio stream object using the specified parameters. */ 233 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_ dev_param *p,372 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm, 234 373 pjmedia_aud_rec_cb rec_cb, 235 374 pjmedia_aud_play_cb play_cb, … … 237 376 pjmedia_aud_stream **p_aud_strm) 238 377 { 239 pjmedia_aud_dev_factory *f; 240 pjmedia_aud_dev_param param; 241 int f_id; 378 pjmedia_aud_dev_factory *rec_f=NULL, *play_f=NULL, *f=NULL; 379 pjmedia_aud_param param; 242 380 pj_status_t status; 243 381 382 PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL); 383 244 384 /* Must make copy of param because we're changing device ID */ 245 pj_memcpy(¶m, p, sizeof(param)); 246 247 /* Set default device */ 248 if (param.rec_id == PJMEDIA_AUD_DEV_DEFAULT_ID) 249 param.rec_id = DEFAULT_DEV_ID; 250 if (param.play_id == PJMEDIA_AUD_DEV_DEFAULT_ID) 251 param.play_id = DEFAULT_DEV_ID; 385 pj_memcpy(¶m, prm, sizeof(param)); 386 387 /* Normalize rec_id */ 388 if (param.dir & PJMEDIA_DIR_CAPTURE) { 389 unsigned index; 390 391 status = lookup_dev(param.rec_id, &rec_f, &index); 392 if (status != PJ_SUCCESS) 393 return status; 394 395 param.rec_id = index; 396 f = rec_f; 397 } 398 399 /* Normalize play_id */ 400 if (param.dir & PJMEDIA_DIR_PLAYBACK) { 401 unsigned index; 402 403 status = lookup_dev(param.play_id, &play_f, &index); 404 if (status != PJ_SUCCESS) 405 return status; 406 407 param.play_id = index; 408 f = play_f; 409 410 /* For now, rec_id and play_id must belong to the same factory */ 411 PJ_ASSERT_RETURN(rec_f == play_f, PJ_EINVAL); 412 } 413 252 414 253 if (param.dir & PJMEDIA_DIR_CAPTURE) 254 f_id = GET_FID(param.rec_id); 255 else 256 f_id = GET_FID(param.play_id); 257 258 if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 259 return PJMEDIA_EAUD_INVDEV; 260 261 /* Normalize device id's */ 262 param.rec_id = GET_INDEX(param.rec_id); 263 param.play_id = GET_INDEX(param.play_id); 264 265 f = aud_subsys.factories[f_id].f; 266 if (f == NULL) 267 return PJMEDIA_EAUD_INVDEV; 268 415 /* Create the stream */ 269 416 status = f->op->create_stream(f, ¶m, rec_cb, play_cb, 270 417 user_data, p_aud_strm); … … 272 419 return status; 273 420 274 (*p_aud_strm)->factory = f; 421 /* Assign factory id to the stream */ 422 (*p_aud_strm)->factory_id = f->internal.id; 275 423 return PJ_SUCCESS; 276 424 } … … 278 426 /* API: Get the running parameters for the specified audio stream. */ 279 427 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, 280 pjmedia_aud_ dev_param *param)428 pjmedia_aud_param *param) 281 429 { 282 430 pj_status_t status; … … 287 435 288 436 /* Normalize device id's */ 289 if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 290 param->rec_id = MAKE_DEV_ID(strm->factory->internal.id, param->rec_id); 291 if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 292 param->play_id = MAKE_DEV_ID(strm->factory->internal.id, param->play_id); 437 make_global_index(aud_subsys.drv[strm->factory_id].f, ¶m->rec_id); 438 make_global_index(aud_subsys.drv[strm->factory_id].f, ¶m->play_id); 293 439 294 440 return PJ_SUCCESS; -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/audiotest.c
r2463 r2468 52 52 { 53 53 pj_pool_t *pool; 54 const pjmedia_aud_ dev_param *param;54 const pjmedia_aud_param *param; 55 55 pjmedia_aud_test_results *result; 56 56 pj_bool_t running; … … 182 182 183 183 184 PJ_DEF(pj_status_t) pjmedia_aud_test( const pjmedia_aud_ dev_param *param,184 PJ_DEF(pj_status_t) pjmedia_aud_test( const pjmedia_aud_param *param, 185 185 pjmedia_aud_test_results *result) 186 186 { -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/pa_dev.c
r2464 r2468 106 106 static pj_status_t pa_default_param(pjmedia_aud_dev_factory *f, 107 107 unsigned index, 108 pjmedia_aud_ dev_param *param);108 pjmedia_aud_param *param); 109 109 static pj_status_t pa_create_stream(pjmedia_aud_dev_factory *f, 110 const pjmedia_aud_ dev_param *param,110 const pjmedia_aud_param *param, 111 111 pjmedia_aud_rec_cb rec_cb, 112 112 pjmedia_aud_play_cb play_cb, … … 116 116 /* Stream prototypes */ 117 117 static pj_status_t strm_get_param(pjmedia_aud_stream *strm, 118 pjmedia_aud_ dev_param *param);118 pjmedia_aud_param *param); 119 119 static pj_status_t strm_get_cap(pjmedia_aud_stream *strm, 120 120 pjmedia_aud_dev_cap cap, … … 515 515 static pj_status_t pa_default_param(pjmedia_aud_dev_factory *f, 516 516 unsigned index, 517 pjmedia_aud_ dev_param *param)517 pjmedia_aud_param *param) 518 518 { 519 519 pjmedia_aud_dev_info adi; … … 534 534 param->dir = PJMEDIA_DIR_CAPTURE; 535 535 param->rec_id = index; 536 param->play_id = PJMEDIA_AUD_DEV_DEFAULT _ID;536 param->play_id = PJMEDIA_AUD_DEV_DEFAULT; 537 537 } else if (adi.output_count) { 538 538 param->dir = PJMEDIA_DIR_PLAYBACK; 539 539 param->play_id = index; 540 param->rec_id = PJMEDIA_AUD_DEV_DEFAULT _ID;540 param->rec_id = PJMEDIA_AUD_DEV_DEFAULT; 541 541 } else { 542 542 return PJMEDIA_EAUD_INVDEV; … … 670 670 /* Internal: create capture/recorder stream */ 671 671 static pj_status_t create_rec_stream( struct pa_aud_factory *pa, 672 const pjmedia_aud_ dev_param *param,672 const pjmedia_aud_param *param, 673 673 pjmedia_aud_rec_cb rec_cb, 674 674 void *user_data, … … 676 676 { 677 677 pj_pool_t *pool; 678 pjmedia_aud_dev_i drec_id;678 pjmedia_aud_dev_index rec_id; 679 679 struct pa_aud_stream *stream; 680 680 PaStreamParameters inputParam; … … 775 775 /* Internal: create playback stream */ 776 776 static pj_status_t create_play_stream(struct pa_aud_factory *pa, 777 const pjmedia_aud_ dev_param *param,777 const pjmedia_aud_param *param, 778 778 pjmedia_aud_play_cb play_cb, 779 779 void *user_data, … … 781 781 { 782 782 pj_pool_t *pool; 783 pjmedia_aud_dev_i dplay_id;783 pjmedia_aud_dev_index play_id; 784 784 struct pa_aud_stream *stream; 785 785 PaStreamParameters outputParam; … … 882 882 /* Internal: Create both player and recorder stream */ 883 883 static pj_status_t create_bidir_stream(struct pa_aud_factory *pa, 884 const pjmedia_aud_ dev_param *param,884 const pjmedia_aud_param *param, 885 885 pjmedia_aud_rec_cb rec_cb, 886 886 pjmedia_aud_play_cb play_cb, … … 889 889 { 890 890 pj_pool_t *pool; 891 pjmedia_aud_dev_i drec_id, play_id;891 pjmedia_aud_dev_index rec_id, play_id; 892 892 struct pa_aud_stream *stream; 893 893 PaStream *paStream = NULL; … … 1061 1061 /* API: create stream */ 1062 1062 static pj_status_t pa_create_stream(pjmedia_aud_dev_factory *f, 1063 const pjmedia_aud_ dev_param *param,1063 const pjmedia_aud_param *param, 1064 1064 pjmedia_aud_rec_cb rec_cb, 1065 1065 pjmedia_aud_play_cb play_cb, … … 1092 1092 /* API: Get stream parameters */ 1093 1093 static pj_status_t strm_get_param(pjmedia_aud_stream *s, 1094 pjmedia_aud_ dev_param *pi)1094 pjmedia_aud_param *pi) 1095 1095 { 1096 1096 struct pa_aud_stream *strm = (struct pa_aud_stream*)s; -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp
r2466 r2468 72 72 73 73 // Common settings. 74 pjmedia_aud_ dev_param param; /**< Stream param. */74 pjmedia_aud_param param; /**< Stream param. */ 75 75 pjmedia_aud_rec_cb rec_cb; /**< Record callback. */ 76 76 pjmedia_aud_play_cb play_cb; /**< Playback callback. */ … … 101 101 static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 102 102 unsigned index, 103 pjmedia_aud_ dev_param *param);103 pjmedia_aud_param *param); 104 104 static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 105 const pjmedia_aud_ dev_param *param,105 const pjmedia_aud_param *param, 106 106 pjmedia_aud_rec_cb rec_cb, 107 107 pjmedia_aud_play_cb play_cb, … … 110 110 111 111 static pj_status_t stream_get_param(pjmedia_aud_stream *strm, 112 pjmedia_aud_ dev_param *param);112 pjmedia_aud_param *param); 113 113 static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, 114 114 pjmedia_aud_dev_cap cap, … … 1176 1176 static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 1177 1177 unsigned index, 1178 pjmedia_aud_ dev_param *param)1178 pjmedia_aud_param *param) 1179 1179 { 1180 1180 struct aps_factory *af = (struct aps_factory*)f; … … 1200 1200 /* API: create stream */ 1201 1201 static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 1202 const pjmedia_aud_ dev_param *param,1202 const pjmedia_aud_param *param, 1203 1203 pjmedia_aud_rec_cb rec_cb, 1204 1204 pjmedia_aud_play_cb play_cb, … … 1333 1333 /* API: Get stream info. */ 1334 1334 static pj_status_t stream_get_param(pjmedia_aud_stream *s, 1335 pjmedia_aud_ dev_param *pi)1335 pjmedia_aud_param *pi) 1336 1336 { 1337 1337 struct aps_stream *strm = (struct aps_stream*)s; -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp
r2467 r2468 73 73 74 74 // Common settings. 75 pjmedia_aud_ dev_param param; /**< Stream param. */75 pjmedia_aud_param param; /**< Stream param. */ 76 76 77 77 // Audio engine … … 90 90 static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 91 91 unsigned index, 92 pjmedia_aud_ dev_param *param);92 pjmedia_aud_param *param); 93 93 static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 94 const pjmedia_aud_ dev_param *param,94 const pjmedia_aud_param *param, 95 95 pjmedia_aud_rec_cb rec_cb, 96 96 pjmedia_aud_play_cb play_cb, … … 99 99 100 100 static pj_status_t stream_get_param(pjmedia_aud_stream *strm, 101 pjmedia_aud_ dev_param *param);101 pjmedia_aud_param *param); 102 102 static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, 103 103 pjmedia_aud_dev_cap cap, … … 845 845 static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 846 846 unsigned index, 847 pjmedia_aud_ dev_param *param)847 pjmedia_aud_param *param) 848 848 { 849 849 struct mda_factory *af = (struct mda_factory*)f; … … 867 867 /* API: create stream */ 868 868 static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 869 const pjmedia_aud_ dev_param *param,869 const pjmedia_aud_param *param, 870 870 pjmedia_aud_rec_cb rec_cb, 871 871 pjmedia_aud_play_cb play_cb, … … 922 922 /* API: Get stream info. */ 923 923 static pj_status_t stream_get_param(pjmedia_aud_stream *s, 924 pjmedia_aud_ dev_param *pi)924 pjmedia_aud_param *pi) 925 925 { 926 926 struct mda_stream *strm = (struct mda_stream*)s; -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/wmme_dev.c
r2459 r2468 121 121 static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 122 122 unsigned index, 123 pjmedia_aud_ dev_param *param);123 pjmedia_aud_param *param); 124 124 static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 125 const pjmedia_aud_ dev_param *param,125 const pjmedia_aud_param *param, 126 126 pjmedia_aud_rec_cb rec_cb, 127 127 pjmedia_aud_play_cb play_cb, … … 130 130 131 131 static pj_status_t stream_get_param(pjmedia_aud_stream *strm, 132 pjmedia_aud_ dev_param *param);132 pjmedia_aud_param *param); 133 133 static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, 134 134 pjmedia_aud_dev_cap cap, … … 399 399 static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 400 400 unsigned index, 401 pjmedia_aud_ dev_param *param)401 pjmedia_aud_param *param) 402 402 { 403 403 struct wmme_factory *wf = (struct wmme_factory*)f; … … 414 414 param->dir = PJMEDIA_DIR_CAPTURE; 415 415 param->rec_id = index; 416 param->play_id = PJMEDIA_AUD_DEV_DEFAULT _ID;416 param->play_id = PJMEDIA_AUD_DEV_DEFAULT; 417 417 } else if (di->info.output_count) { 418 418 param->dir = PJMEDIA_DIR_PLAYBACK; 419 419 param->play_id = index; 420 param->rec_id = PJMEDIA_AUD_DEV_DEFAULT _ID;420 param->rec_id = PJMEDIA_AUD_DEV_DEFAULT; 421 421 } else { 422 422 return PJMEDIA_EAUD_INVDEV; … … 816 816 /* API: create stream */ 817 817 static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 818 const pjmedia_aud_ dev_param *param,818 const pjmedia_aud_param *param, 819 819 pjmedia_aud_rec_cb rec_cb, 820 820 pjmedia_aud_play_cb play_cb, … … 930 930 /* API: Get stream info. */ 931 931 static pj_status_t stream_get_param(pjmedia_aud_stream *s, 932 pjmedia_aud_ dev_param *pi)932 pjmedia_aud_param *pi) 933 933 { 934 934 struct wmme_stream *strm = (struct wmme_stream*)s; -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conf_switch.c
r2460 r2468 114 114 unsigned port_cnt; /**< Current number of ports. */ 115 115 unsigned connect_cnt; /**< Total number of connections */ 116 pjmedia_snd_port *snd_dev_port; /**< Sound device port. */117 116 pjmedia_port *master_port; /**< Port zero's port. */ 118 117 char master_name_buf[80]; /**< Port0 name buffer. */ … … 188 187 pj_status_t status; 189 188 190 191 189 status = create_conf_port(pool, conf, conf->master_port, &name, &conf_port); 192 190 if (status != PJ_SUCCESS) 193 191 return status; 194 195 196 /* Create sound device port: */197 198 if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) {199 pjmedia_snd_stream *strm;200 pjmedia_snd_stream_info si;201 pjmedia_port_info *master_port_info = (pjmedia_port_info*)202 &conf->master_port->info;203 204 /*205 * If capture is disabled then create player only port.206 * Otherwise create bidirectional sound device port.207 */208 if (conf->options & PJMEDIA_CONF_NO_MIC) {209 status = pjmedia_snd_port_create_player(210 pool, -1,211 master_port_info->clock_rate,212 master_port_info->channel_count,213 master_port_info->samples_per_frame,214 master_port_info->bits_per_sample,215 0, /* options */216 &conf->snd_dev_port);217 218 } else {219 status = pjmedia_snd_port_create(220 pool, -1, -1,221 master_port_info->clock_rate,222 master_port_info->channel_count,223 master_port_info->samples_per_frame,224 master_port_info->bits_per_sample,225 0, /* Options */226 &conf->snd_dev_port);227 }228 229 if (status != PJ_SUCCESS)230 return status;231 232 strm = pjmedia_snd_port_get_snd_stream(conf->snd_dev_port);233 status = pjmedia_snd_stream_get_info(strm, &si);234 if (status == PJ_SUCCESS) {235 const pjmedia_snd_dev_info *snd_dev_info;236 if (conf->options & PJMEDIA_CONF_NO_MIC)237 snd_dev_info = pjmedia_snd_get_dev_info(si.play_id);238 else239 snd_dev_info = pjmedia_snd_get_dev_info(si.rec_id);240 pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info->name);241 }242 }243 244 192 245 193 /* Add the port to the bridge */ … … 247 195 conf->ports[0] = conf_port; 248 196 conf->port_cnt++; 249 250 197 251 198 PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0")); … … 312 259 return status; 313 260 314 /* If sound device was created, connect sound device to the315 * master port.316 */317 if (conf->snd_dev_port) {318 status = pjmedia_snd_port_connect( conf->snd_dev_port,319 conf->master_port );320 if (status != PJ_SUCCESS) {321 pjmedia_conf_destroy(conf);322 return status;323 }324 }325 326 261 /* Done */ 327 262 … … 359 294 { 360 295 PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL); 361 362 /* Destroy sound device port. */363 if (conf->snd_dev_port) {364 pjmedia_snd_port_destroy(conf->snd_dev_port);365 conf->snd_dev_port = NULL;366 }367 296 368 297 /* Destroy mutex */ -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conference.c
r2460 r2468 466 466 467 467 if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) { 468 pjmedia_ snd_stream *strm;469 pjmedia_ snd_stream_info si;468 pjmedia_aud_stream *strm; 469 pjmedia_aud_param param; 470 470 471 471 /* … … 495 495 496 496 strm = pjmedia_snd_port_get_snd_stream(conf->snd_dev_port); 497 status = pjmedia_ snd_stream_get_info(strm, &si);497 status = pjmedia_aud_stream_get_param(strm, ¶m); 498 498 if (status == PJ_SUCCESS) { 499 const pjmedia_snd_dev_info *snd_dev_info;499 pjmedia_aud_dev_info snd_dev_info; 500 500 if (conf->options & PJMEDIA_CONF_NO_MIC) 501 snd_dev_info = pjmedia_snd_get_dev_info(si.play_id);501 pjmedia_aud_dev_get_info(param.play_id, &snd_dev_info); 502 502 else 503 snd_dev_info = pjmedia_snd_get_dev_info(si.rec_id);504 pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info ->name);503 pjmedia_aud_dev_get_info(param.rec_id, &snd_dev_info); 504 pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info.name); 505 505 } 506 506 } -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/endpoint.c
r2394 r2468 21 21 #include <pjmedia/errno.h> 22 22 #include <pjmedia/sdp.h> 23 #include <pjmedia-audiodev/audiodev.h> 23 24 #include <pj/assert.h> 24 25 #include <pj/ioqueue.h> … … 122 123 123 124 /* Sound */ 124 status = pjmedia_ snd_init(pf);125 status = pjmedia_aud_subsys_init(pf); 125 126 if (status != PJ_SUCCESS) 126 127 goto on_error; … … 172 173 pj_ioqueue_destroy(endpt->ioqueue); 173 174 174 pjmedia_ snd_deinit();175 pjmedia_aud_subsys_shutdown(); 175 176 pj_pool_release(pool); 176 177 return status; … … 213 214 endpt->pf = NULL; 214 215 215 pjmedia_ snd_deinit();216 pjmedia_aud_subsys_shutdown(); 216 217 pj_pool_release (endpt->pool); 217 218 -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/sound_port.c
r2460 r2468 23 23 #include <pjmedia/echo.h> 24 24 #include <pjmedia/errno.h> 25 #include <pjmedia/plc.h>26 25 #include <pj/assert.h> 27 26 #include <pj/log.h> … … 29 28 #include <pj/string.h> /* pj_memset() */ 30 29 31 //#define SIMULATE_LOST_PCT 2032 30 #define AEC_TAIL 128 /* default AEC length in ms */ 33 31 #define AEC_SUSPEND_LIMIT 5 /* seconds of no activity */ … … 41 39 int rec_id; 42 40 int play_id; 43 pjmedia_snd_stream *snd_stream; 41 pj_uint32_t aud_caps; 42 pjmedia_aud_param aud_param; 43 pjmedia_aud_stream *aud_stream; 44 44 pjmedia_dir dir; 45 45 pjmedia_port *port; 46 47 pjmedia_echo_state *ec_state;48 unsigned aec_tail_len;49 50 pj_bool_t ec_suspended;51 unsigned ec_suspend_count;52 unsigned ec_suspend_limit;53 54 pjmedia_plc *plc;55 46 56 47 unsigned clock_rate; … … 58 49 unsigned samples_per_frame; 59 50 unsigned bits_per_sample; 60 pjmedia_snd_setting setting; 61 62 #if PJMEDIA_SOUND_USE_DELAYBUF 63 pjmedia_delay_buf *delay_buf; 64 #endif 65 66 /* Encoded sound emulation */ 67 #if !defined(PJMEDIA_SND_SUPPORT_OPEN2) || !PJMEDIA_SND_SUPPORT_OPEN2 68 unsigned frm_buf_size; 69 pj_uint8_t *put_frm_buf; 70 pj_uint8_t *get_frm_buf; 71 #endif 51 52 /* software ec */ 53 pjmedia_echo_state *ec_state; 54 unsigned ec_options; 55 unsigned ec_tail_len; 56 pj_bool_t ec_suspended; 57 unsigned ec_suspend_count; 58 unsigned ec_suspend_limit; 72 59 }; 73 60 … … 76 63 * played. 77 64 */ 78 static pj_status_t play_cb(/* in */ void *user_data, 79 /* in */ pj_uint32_t timestamp, 80 /* out */ void *output, 81 /* out */ unsigned size) 65 static pj_status_t play_cb(void *user_data, pjmedia_frame *frame) 82 66 { 83 67 pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 84 68 pjmedia_port *port; 85 pjmedia_frame frame;69 unsigned required_size = frame->size; 86 70 pj_status_t status; 87 71 … … 90 74 goto no_frame; 91 75 92 frame.buf = output; 93 frame.size = size; 94 frame.timestamp.u32.hi = 0; 95 frame.timestamp.u32.lo = timestamp; 96 97 #if PJMEDIA_SOUND_USE_DELAYBUF 98 if (snd_port->delay_buf) { 99 status = pjmedia_delay_buf_get(snd_port->delay_buf, (pj_int16_t*)output); 100 if (status != PJ_SUCCESS) 101 pj_bzero(output, size); 102 103 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 104 pjmedia_port_put_frame(port, &frame); 105 106 #ifdef TEST_OVERFLOW_UNDERFLOW 107 { 108 static int count = 1; 109 if (++count % 10 == 0) { 110 status = pjmedia_delay_buf_get(snd_port->delay_buf, 111 (pj_int16_t*)output); 112 if (status != PJ_SUCCESS) 113 pj_bzero(output, size); 114 115 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 116 pjmedia_port_put_frame(port, &frame); 117 } 118 } 119 #endif 120 121 } 122 #endif 123 124 status = pjmedia_port_get_frame(port, &frame); 76 status = pjmedia_port_get_frame(port, frame); 125 77 if (status != PJ_SUCCESS) 126 78 goto no_frame; 127 79 128 if (frame .type != PJMEDIA_FRAME_TYPE_AUDIO)80 if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO) 129 81 goto no_frame; 130 82 131 83 /* Must supply the required samples */ 132 pj_assert(frame.size == size); 133 134 #ifdef SIMULATE_LOST_PCT 135 /* Simulate packet lost */ 136 if (pj_rand() % 100 < SIMULATE_LOST_PCT) { 137 PJ_LOG(4,(THIS_FILE, "Frame dropped")); 138 goto no_frame; 139 } 140 #endif 141 142 if (snd_port->plc) 143 pjmedia_plc_save(snd_port->plc, (pj_int16_t*) output); 84 PJ_UNUSED_ARG(required_size); 85 pj_assert(frame->size == required_size); 144 86 145 87 if (snd_port->ec_state) { … … 150 92 } 151 93 snd_port->ec_suspend_count = 0; 152 pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*) output);94 pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*)frame->buf); 153 95 } 154 96 … … 166 108 if (snd_port->ec_state) { 167 109 /* To maintain correct delay in EC */ 168 pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*)output); 169 } 170 } 171 172 /* Apply PLC */ 173 if (snd_port->plc) { 174 175 pjmedia_plc_generate(snd_port->plc, (pj_int16_t*) output); 176 #ifdef SIMULATE_LOST_PCT 177 PJ_LOG(4,(THIS_FILE, "Lost frame generated")); 178 #endif 179 } else { 180 pj_bzero(output, size); 181 } 182 110 pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*)frame->buf); 111 } 112 } 183 113 184 114 return PJ_SUCCESS; … … 190 120 * frame. 191 121 */ 192 static pj_status_t rec_cb(/* in */ void *user_data, 193 /* in */ pj_uint32_t timestamp, 194 /* in */ void *input, 195 /* in*/ unsigned size) 122 static pj_status_t rec_cb(void *user_data, pjmedia_frame *frame) 196 123 { 197 124 pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 198 125 pjmedia_port *port; 199 pjmedia_frame frame;200 126 201 127 port = snd_port->port; … … 205 131 /* Cancel echo */ 206 132 if (snd_port->ec_state && !snd_port->ec_suspended) { 207 pjmedia_echo_capture(snd_port->ec_state, (pj_int16_t*) input, 0); 208 } 209 210 #if PJMEDIA_SOUND_USE_DELAYBUF 211 if (snd_port->delay_buf) { 212 pjmedia_delay_buf_put(snd_port->delay_buf, (pj_int16_t*)input); 213 } else { 214 frame.buf = (void*)input; 215 frame.size = size; 216 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 217 frame.timestamp.u32.lo = timestamp; 218 219 pjmedia_port_put_frame(port, &frame); 220 } 221 #else 222 frame.buf = (void*)input; 223 frame.size = size; 224 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 225 frame.timestamp.u32.lo = timestamp; 226 227 pjmedia_port_put_frame(port, &frame); 228 #endif 133 pjmedia_echo_capture(snd_port->ec_state, (pj_int16_t*) frame->buf, 0); 134 } 135 136 pjmedia_port_put_frame(port, frame); 229 137 230 138 return PJ_SUCCESS; … … 235 143 * played. This version is for non-PCM data. 236 144 */ 237 static pj_status_t play_cb_ext(/* in */ void *user_data, 238 /* in */ pj_uint32_t timestamp, 239 /* out */ void *output, 240 /* out */ unsigned size) 241 { 242 #if defined(PJMEDIA_SND_SUPPORT_OPEN2) && PJMEDIA_SND_SUPPORT_OPEN2!=0 243 /* This is the version to use when the sound device supports 244 * open2(). 245 */ 145 static pj_status_t play_cb_ext(void *user_data, pjmedia_frame *frame) 146 { 246 147 pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 247 pjmedia_port *port; 248 pjmedia_frame *frame = (pjmedia_frame*) output; 249 pj_status_t status; 250 251 PJ_UNUSED_ARG(size); 252 PJ_UNUSED_ARG(timestamp); 253 254 port = snd_port->port; 148 pjmedia_port *port = snd_port->port; 149 255 150 if (port == NULL) { 256 151 frame->type = PJMEDIA_FRAME_TYPE_NONE; … … 258 153 } 259 154 260 status = pjmedia_port_get_frame(port, frame); 261 262 return status; 263 #else 264 /* This is the emulation version */ 265 pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 266 pjmedia_port *port = snd_port->port; 267 pjmedia_frame_ext *fx = (pjmedia_frame_ext*) snd_port->get_frm_buf; 268 pj_status_t status; 269 270 if (port==NULL) { 271 goto no_frame; 272 } 273 274 pj_bzero(fx, sizeof(*fx)); 275 fx->base.type = PJMEDIA_FRAME_TYPE_NONE; 276 fx->base.buf = ((pj_uint8_t*)fx) + sizeof(*fx); 277 fx->base.size = snd_port->frm_buf_size - sizeof(*fx); 278 fx->base.timestamp.u32.hi = 0; 279 fx->base.timestamp.u32.lo = timestamp; 280 281 status = pjmedia_port_get_frame(port, &fx->base); 282 if (status != PJ_SUCCESS) 283 goto no_frame; 284 285 if (fx->base.type == PJMEDIA_FRAME_TYPE_AUDIO) { 286 pj_assert(fx->base.size == size); 287 pj_memcpy(output, fx->base.buf, size); 288 } else if (fx->base.type == PJMEDIA_FRAME_TYPE_EXTENDED) { 289 void (*decoder)(pj_int16_t*, const pj_uint8_t*, pj_size_t) = NULL; 290 unsigned i, size_decoded; 291 292 switch (snd_port->setting.format.id) { 293 case PJMEDIA_FORMAT_PCMA: 294 decoder = &pjmedia_alaw_decode; 295 break; 296 case PJMEDIA_FORMAT_PCMU: 297 decoder = &pjmedia_ulaw_decode; 298 break; 299 default: 300 PJ_LOG(1,(THIS_FILE, "Unsupported format %d", 301 snd_port->setting.format.id)); 302 goto no_frame; 303 } 304 305 if (fx->samples_cnt > size>>1) { 306 PJ_LOG(4,(THIS_FILE, "Frame too large by %d samples", 307 fx->samples_cnt - (size>>1))); 308 } else if (fx->samples_cnt < size>>1) { 309 PJ_LOG(4,(THIS_FILE, "Not enough frame by %d samples", 310 (size>>1) - fx->samples_cnt)); 311 } 312 313 for (i=0, size_decoded=0; 314 i<fx->subframe_cnt && size_decoded<size; 315 ++i) 316 { 317 pjmedia_frame_ext_subframe *subfrm; 318 319 subfrm = pjmedia_frame_ext_get_subframe(fx, i); 320 321 if (!subfrm || subfrm->bitlen==0) 322 continue; 323 324 if ((subfrm->bitlen>>3) > (int)(size-size_decoded)) { 325 subfrm->bitlen = (pj_uint16_t)((size-size_decoded) << 3); 326 } 327 328 (*decoder)((short*)((pj_uint8_t*)output + size_decoded), 329 subfrm->data, subfrm->bitlen>>3); 330 331 size_decoded += (subfrm->bitlen>>3) << 1; 332 } 333 334 if (size_decoded < size) { 335 pj_bzero((pj_uint8_t*)output + size_decoded, size-size_decoded); 336 } 337 338 } else { 339 goto no_frame; 340 } 341 342 return PJ_SUCCESS; 343 344 no_frame: 345 pj_bzero(output, size); 346 return PJ_SUCCESS; 347 348 #endif /* PJMEDIA_SND_SUPPORT_OPEN2 */ 155 pjmedia_port_get_frame(port, frame); 156 157 return PJ_SUCCESS; 349 158 } 350 159 … … 354 163 * frame. This version is for non-PCM data. 355 164 */ 356 static pj_status_t rec_cb_ext(/* in */ void *user_data, 357 /* in */ pj_uint32_t timestamp, 358 /* in */ void *input, 359 /* in*/ unsigned size) 360 { 361 #if defined(PJMEDIA_SND_SUPPORT_OPEN2) && PJMEDIA_SND_SUPPORT_OPEN2!=0 362 /* This is the version to use when the sound device supports 363 * open2(). 364 */ 165 static pj_status_t rec_cb_ext(void *user_data, pjmedia_frame *frame) 166 { 365 167 pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 366 168 pjmedia_port *port; 367 pjmedia_frame *frame = (pjmedia_frame*)input;368 369 PJ_UNUSED_ARG(size);370 PJ_UNUSED_ARG(timestamp);371 169 372 170 port = snd_port->port; … … 377 175 378 176 return PJ_SUCCESS; 379 #else380 pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data;381 pjmedia_port *port = snd_port->port;382 pjmedia_frame_ext *fx = (pjmedia_frame_ext*) snd_port->put_frm_buf;383 void (*encoder)(pj_uint8_t*, const pj_int16_t*, pj_size_t) = NULL;384 385 if (port==NULL)386 return PJ_SUCCESS;387 388 pj_bzero(fx, sizeof(*fx));389 fx->base.buf = NULL;390 fx->base.size = snd_port->frm_buf_size - sizeof(*fx);391 fx->base.type = PJMEDIA_FRAME_TYPE_EXTENDED;392 fx->base.timestamp.u32.lo = timestamp;393 394 switch (snd_port->setting.format.id) {395 case PJMEDIA_FORMAT_PCMA:396 encoder = &pjmedia_alaw_encode;397 break;398 case PJMEDIA_FORMAT_PCMU:399 encoder = &pjmedia_ulaw_encode;400 break;401 default:402 PJ_LOG(1,(THIS_FILE, "Unsupported format %d",403 snd_port->setting.format.id));404 return PJ_SUCCESS;405 }406 407 (*encoder)((pj_uint8_t*)input, (pj_int16_t*)input, size >> 1);408 409 pjmedia_frame_ext_append_subframe(fx, input, (size >> 1) << 3,410 size >> 1);411 pjmedia_port_put_frame(port, &fx->base);412 413 return PJ_SUCCESS;414 #endif415 177 } 416 178 … … 422 184 pjmedia_snd_port *snd_port ) 423 185 { 424 pjmedia_snd_rec_cb snd_rec_cb; 425 pjmedia_snd_play_cb snd_play_cb; 186 pjmedia_aud_rec_cb snd_rec_cb; 187 pjmedia_aud_play_cb snd_play_cb; 188 pjmedia_aud_param param_copy; 426 189 pj_status_t status; 427 190 428 191 /* Check if sound has been started. */ 429 if (snd_port-> snd_stream != NULL)192 if (snd_port->aud_stream != NULL) 430 193 return PJ_SUCCESS; 431 194 … … 435 198 PJ_EBUG); 436 199 437 if (snd_port->setting.format.id == PJMEDIA_FORMAT_L16) { 200 /* Get device caps */ 201 if (snd_port->aud_param.dir & PJMEDIA_DIR_CAPTURE) { 202 pjmedia_aud_dev_info dev_info; 203 204 status = pjmedia_aud_dev_get_info(snd_port->aud_param.rec_id, 205 &dev_info); 206 if (status != PJ_SUCCESS) 207 return status; 208 209 snd_port->aud_caps = dev_info.caps; 210 } else { 211 snd_port->aud_caps = 0; 212 } 213 214 /* Process EC settings */ 215 pj_memcpy(¶m_copy, &snd_port->aud_param, sizeof(param_copy)); 216 if (param_copy.flags & PJMEDIA_AUD_DEV_CAP_EC) { 217 /* EC is wanted */ 218 if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) { 219 /* Device supports EC */ 220 /* Nothing to do */ 221 } else { 222 /* Device doesn't support EC, remove EC settings from 223 * device parameters 224 */ 225 param_copy.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | 226 PJMEDIA_AUD_DEV_CAP_EC_TAIL); 227 } 228 } 229 230 /* Use different callback if format is not PCM */ 231 if (snd_port->aud_param.ext_fmt.id == PJMEDIA_FORMAT_L16) { 438 232 snd_rec_cb = &rec_cb; 439 233 snd_play_cb = &play_cb; … … 443 237 } 444 238 445 #if defined(PJMEDIA_SND_SUPPORT_OPEN2) && PJMEDIA_SND_SUPPORT_OPEN2!=0 446 status = pjmedia_snd_open2( snd_port->dir, 447 snd_port->rec_id, 448 snd_port->play_id, 449 snd_port->clock_rate, 450 snd_port->channel_count, 451 snd_port->samples_per_frame, 452 snd_port->bits_per_sample, 453 snd_rec_cb, 454 snd_play_cb, 455 snd_port, 456 &snd_port->setting, 457 &snd_port->snd_stream); 458 #else 459 status = pjmedia_snd_open( snd_port->rec_id, 460 snd_port->play_id, 461 snd_port->clock_rate, 462 snd_port->channel_count, 463 snd_port->samples_per_frame, 464 snd_port->bits_per_sample, 465 snd_rec_cb, 466 snd_play_cb, 467 snd_port, 468 &snd_port->snd_stream); 469 #endif 239 /* Open the device */ 240 status = pjmedia_aud_stream_create(¶m_copy, 241 snd_rec_cb, 242 snd_play_cb, 243 snd_port, 244 &snd_port->aud_stream); 470 245 471 246 if (status != PJ_SUCCESS) 472 247 return status; 473 474 475 #ifdef SIMULATE_LOST_PCT476 snd_port->setting.plc = PJ_TRUE;477 #endif478 479 /* If we have player components, allocate buffer to save the last480 * frame played to the speaker. The last frame is used for packet481 * lost concealment (PLC) algorithm.482 */483 if ((snd_port->dir & PJMEDIA_DIR_PLAYBACK) &&484 (snd_port->setting.plc))485 {486 status = pjmedia_plc_create(pool, snd_port->clock_rate,487 snd_port->samples_per_frame *488 snd_port->channel_count,489 0, &snd_port->plc);490 if (status != PJ_SUCCESS) {491 PJ_LOG(4,(THIS_FILE, "Unable to create PLC"));492 snd_port->plc = NULL;493 }494 }495 248 496 249 /* Inactivity limit before EC is suspended. */ … … 499 252 snd_port->samples_per_frame); 500 253 254 /* Create software EC if parameter specifies EC but device 255 * doesn't support EC 256 */ 257 if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC) && 258 (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)==0) 259 { 260 if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC_TAIL)==0) { 261 snd_port->aud_param.flags |= PJMEDIA_AUD_DEV_CAP_EC_TAIL; 262 snd_port->aud_param.ec_tail_ms = AEC_TAIL; 263 PJ_LOG(4,(THIS_FILE, "AEC tail is set to default %u ms", 264 snd_port->aud_param.ec_tail_ms)); 265 } 266 267 status = pjmedia_snd_port_set_ec(snd_port, pool, 268 snd_port->aud_param.ec_tail_ms, 0); 269 if (status != PJ_SUCCESS) { 270 pjmedia_aud_stream_destroy(snd_port->aud_stream); 271 snd_port->aud_stream = NULL; 272 return status; 273 } 274 } 275 501 276 /* Start sound stream. */ 502 status = pjmedia_ snd_stream_start(snd_port->snd_stream);277 status = pjmedia_aud_stream_start(snd_port->aud_stream); 503 278 if (status != PJ_SUCCESS) { 504 pjmedia_ snd_stream_close(snd_port->snd_stream);505 snd_port-> snd_stream = NULL;279 pjmedia_aud_stream_destroy(snd_port->aud_stream); 280 snd_port->aud_stream = NULL; 506 281 return status; 507 282 } … … 518 293 { 519 294 /* Check if we have sound stream device. */ 520 if (snd_port-> snd_stream) {521 pjmedia_ snd_stream_stop(snd_port->snd_stream);522 pjmedia_ snd_stream_close(snd_port->snd_stream);523 snd_port-> snd_stream = NULL;295 if (snd_port->aud_stream) { 296 pjmedia_aud_stream_stop(snd_port->aud_stream); 297 pjmedia_aud_stream_destroy(snd_port->aud_stream); 298 snd_port->aud_stream = NULL; 524 299 } 525 300 … … 547 322 pjmedia_snd_port **p_port) 548 323 { 549 pjmedia_snd_port *snd_port; 324 pjmedia_aud_param param; 325 pj_status_t status; 550 326 551 327 PJ_UNUSED_ARG(options); 552 328 553 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 554 555 snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 556 PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 557 558 snd_port->rec_id = rec_id; 559 snd_port->play_id = play_id; 560 snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 561 snd_port->clock_rate = clock_rate; 562 snd_port->channel_count = channel_count; 563 snd_port->samples_per_frame = samples_per_frame; 564 snd_port->bits_per_sample = bits_per_sample; 565 566 #if PJMEDIA_SOUND_USE_DELAYBUF 567 do { 568 pj_status_t status; 569 unsigned ptime; 570 571 ptime = samples_per_frame * 1000 / (clock_rate * channel_count); 572 573 status = pjmedia_delay_buf_create(pool, "snd_buff", 574 clock_rate, samples_per_frame, 575 channel_count, 576 PJMEDIA_SOUND_BUFFER_COUNT * ptime, 577 0, &snd_port->delay_buf); 578 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 579 } while (0); 580 #endif 581 582 *p_port = snd_port; 583 584 585 /* Start sound device immediately. 586 * If there's no port connected, the sound callback will return 587 * empty signal. 588 */ 589 return start_sound_device( pool, snd_port ); 590 329 status = pjmedia_aud_dev_default_param(rec_id, ¶m); 330 if (status != PJ_SUCCESS) 331 return status; 332 333 param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 334 param.rec_id = rec_id; 335 param.play_id = play_id; 336 param.clock_rate = clock_rate; 337 param.channel_count = channel_count; 338 param.samples_per_frame = samples_per_frame; 339 param.bits_per_sample = bits_per_sample; 340 341 return pjmedia_snd_port_create2(pool, ¶m, p_port); 591 342 } 592 343 … … 603 354 pjmedia_snd_port **p_port) 604 355 { 605 pjmedia_snd_port *snd_port; 356 pjmedia_aud_param param; 357 pj_status_t status; 606 358 607 359 PJ_UNUSED_ARG(options); 608 360 609 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 610 611 snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 612 PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 613 614 snd_port->rec_id = dev_id; 615 snd_port->dir = PJMEDIA_DIR_CAPTURE; 616 snd_port->clock_rate = clock_rate; 617 snd_port->channel_count = channel_count; 618 snd_port->samples_per_frame = samples_per_frame; 619 snd_port->bits_per_sample = bits_per_sample; 620 621 *p_port = snd_port; 622 623 /* Start sound device immediately. 624 * If there's no port connected, the sound callback will return 625 * empty signal. 626 */ 627 return start_sound_device( pool, snd_port ); 361 status = pjmedia_aud_dev_default_param(dev_id, ¶m); 362 if (status != PJ_SUCCESS) 363 return status; 364 365 param.dir = PJMEDIA_DIR_CAPTURE; 366 param.rec_id = dev_id; 367 param.clock_rate = clock_rate; 368 param.channel_count = channel_count; 369 param.samples_per_frame = samples_per_frame; 370 param.bits_per_sample = bits_per_sample; 371 372 return pjmedia_snd_port_create2(pool, ¶m, p_port); 628 373 } 629 374 … … 641 386 pjmedia_snd_port **p_port) 642 387 { 388 pjmedia_aud_param param; 389 pj_status_t status; 390 391 PJ_UNUSED_ARG(options); 392 393 status = pjmedia_aud_dev_default_param(dev_id, ¶m); 394 if (status != PJ_SUCCESS) 395 return status; 396 397 param.dir = PJMEDIA_DIR_PLAYBACK; 398 param.play_id = dev_id; 399 param.clock_rate = clock_rate; 400 param.channel_count = channel_count; 401 param.samples_per_frame = samples_per_frame; 402 param.bits_per_sample = bits_per_sample; 403 404 return pjmedia_snd_port_create2(pool, ¶m, p_port); 405 } 406 407 408 /* 409 * Create sound port. 410 */ 411 PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 412 const pjmedia_aud_param *prm, 413 pjmedia_snd_port **p_port) 414 { 643 415 pjmedia_snd_port *snd_port; 644 416 645 PJ_UNUSED_ARG(options); 646 647 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 417 PJ_ASSERT_RETURN(pool && prm && p_port, PJ_EINVAL); 648 418 649 419 snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 650 420 PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 651 421 652 snd_port->play_id = dev_id; 653 snd_port->dir = PJMEDIA_DIR_PLAYBACK; 654 snd_port->clock_rate = clock_rate; 655 snd_port->channel_count = channel_count; 656 snd_port->samples_per_frame = samples_per_frame; 657 snd_port->bits_per_sample = bits_per_sample; 658 422 snd_port->dir = prm->dir; 423 snd_port->rec_id = prm->rec_id; 424 snd_port->play_id = prm->play_id; 425 snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 426 snd_port->clock_rate = prm->clock_rate; 427 snd_port->channel_count = prm->channel_count; 428 snd_port->samples_per_frame = prm->samples_per_frame; 429 snd_port->bits_per_sample = prm->bits_per_sample; 430 pj_memcpy(&snd_port->aud_param, prm, sizeof(*prm)); 431 659 432 *p_port = snd_port; 433 660 434 661 435 /* Start sound device immediately. … … 664 438 */ 665 439 return start_sound_device( pool, snd_port ); 666 }667 668 669 /*670 * Create bidirectional port.671 */672 PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool,673 pjmedia_dir dir,674 int rec_id,675 int play_id,676 unsigned clock_rate,677 unsigned channel_count,678 unsigned samples_per_frame,679 unsigned bits_per_sample,680 const pjmedia_snd_setting *setting,681 pjmedia_snd_port **p_port)682 {683 pjmedia_snd_port *snd_port;684 685 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);686 687 snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port);688 PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);689 690 snd_port->dir = dir;691 snd_port->rec_id = rec_id;692 snd_port->play_id = play_id;693 snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;694 snd_port->clock_rate = clock_rate;695 snd_port->channel_count = channel_count;696 snd_port->samples_per_frame = samples_per_frame;697 snd_port->bits_per_sample = bits_per_sample;698 pj_memcpy(&snd_port->setting, setting, sizeof(*setting));699 700 #if PJMEDIA_SOUND_USE_DELAYBUF701 if (snd_port->setting.format.u32 == PJMEDIA_FORMAT_L16) {702 pj_status_t status;703 unsigned ptime;704 705 ptime = samples_per_frame * 1000 / (clock_rate * channel_count);706 707 status = pjmedia_delay_buf_create(pool, "snd_buff",708 clock_rate, samples_per_frame,709 channel_count,710 PJMEDIA_SOUND_BUFFER_COUNT * ptime,711 0, &snd_port->delay_buf);712 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);713 }714 #endif715 716 #if !defined(PJMEDIA_SND_SUPPORT_OPEN2) || PJMEDIA_SND_SUPPORT_OPEN2==0717 /* For devices that doesn't support open2(), enable simulation */718 if (snd_port->setting.format.id != PJMEDIA_FORMAT_L16) {719 snd_port->frm_buf_size = sizeof(pjmedia_frame_ext) +720 (samples_per_frame << 1) +721 16 * sizeof(pjmedia_frame_ext_subframe);722 snd_port->put_frm_buf = (pj_uint8_t*)723 pj_pool_alloc(pool, snd_port->frm_buf_size);724 snd_port->get_frm_buf = (pj_uint8_t*)725 pj_pool_alloc(pool, snd_port->frm_buf_size);726 }727 #endif728 729 *p_port = snd_port;730 731 732 /* Start sound device immediately.733 * If there's no port connected, the sound callback will return734 * empty signal.735 */736 return start_sound_device( pool, snd_port );737 440 738 441 } … … 753 456 * Retrieve the sound stream associated by this sound device port. 754 457 */ 755 PJ_DEF(pjmedia_ snd_stream*) pjmedia_snd_port_get_snd_stream(458 PJ_DEF(pjmedia_aud_stream*) pjmedia_snd_port_get_snd_stream( 756 459 pjmedia_snd_port *snd_port) 757 460 { 758 461 PJ_ASSERT_RETURN(snd_port, NULL); 759 return snd_port-> snd_stream;760 } 761 762 763 /* 764 * Enable AEC462 return snd_port->aud_stream; 463 } 464 465 466 /* 467 * Change EC settings. 765 468 */ 766 469 PJ_DEF(pj_status_t) pjmedia_snd_port_set_ec( pjmedia_snd_port *snd_port, … … 769 472 unsigned options) 770 473 { 771 pjmedia_ snd_stream_info si;474 pjmedia_aud_param prm; 772 475 pj_status_t status; 773 476 … … 777 480 PJ_EINVALIDOP); 778 481 779 /* Sound port must have 16bits per sample */ 780 PJ_ASSERT_RETURN(snd_port->bits_per_sample == 16, 781 PJ_EINVALIDOP); 782 783 /* Destroy AEC */ 784 if (snd_port->ec_state) { 785 pjmedia_echo_destroy(snd_port->ec_state); 786 snd_port->ec_state = NULL; 787 } 788 789 snd_port->aec_tail_len = tail_ms; 790 791 if (tail_ms != 0) { 792 unsigned delay_ms; 793 794 status = pjmedia_snd_stream_get_info(snd_port->snd_stream, &si); 482 /* Determine whether we use device or software EC */ 483 if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) { 484 /* We use device EC */ 485 pj_bool_t ec_enabled; 486 487 /* Query EC status */ 488 status = pjmedia_aud_stream_get_cap(snd_port->aud_stream, 489 PJMEDIA_AUD_DEV_CAP_EC, 490 &ec_enabled); 795 491 if (status != PJ_SUCCESS) 796 si.rec_latency = si.play_latency = 0; 797 798 //No need to add input latency in the latency calculation, 799 //since actual input latency should be zero. 800 //delay_ms = (si.rec_latency + si.play_latency) * 1000 / 801 // snd_port->clock_rate; 802 delay_ms = si.play_latency * 1000 / snd_port->clock_rate; 803 status = pjmedia_echo_create2(pool, snd_port->clock_rate, 804 snd_port->channel_count, 805 snd_port->samples_per_frame, 806 tail_ms, delay_ms, 807 options, &snd_port->ec_state); 808 if (status != PJ_SUCCESS) 492 return status; 493 494 if (tail_ms != 0) { 495 /* Change EC setting */ 496 497 if (!ec_enabled) { 498 /* Enable EC first */ 499 pj_bool_t value = PJ_TRUE; 500 status = pjmedia_aud_stream_set_cap(snd_port->aud_stream, 501 PJMEDIA_AUD_DEV_CAP_EC, 502 &value); 503 if (status != PJ_SUCCESS) 504 return status; 505 } 506 507 if ((snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC_TAIL)==0) { 508 /* Device does not support setting EC tail */ 509 return PJMEDIA_EAUD_INVCAP; 510 } 511 512 return pjmedia_aud_stream_set_cap(snd_port->aud_stream, 513 PJMEDIA_AUD_DEV_CAP_EC_TAIL, 514 &tail_ms); 515 516 } else if (ec_enabled) { 517 /* Disable EC */ 518 pj_bool_t value = PJ_FALSE; 519 return pjmedia_aud_stream_set_cap(snd_port->aud_stream, 520 PJMEDIA_AUD_DEV_CAP_EC, 521 &value); 522 } else { 523 /* Request to disable EC but EC has been disabled */ 524 /* Do nothing */ 525 return PJ_SUCCESS; 526 } 527 528 } else { 529 /* We use software EC */ 530 /* Sound port must have 16bits per sample */ 531 PJ_ASSERT_RETURN(snd_port->bits_per_sample == 16, 532 PJ_EINVALIDOP); 533 534 /* Check if there is change in parameters */ 535 if (tail_ms==snd_port->ec_tail_len && options==snd_port->ec_options) { 536 PJ_LOG(5,(THIS_FILE, "pjmedia_snd_port_set_ec() ignored, no " 537 "change in settings")); 538 return PJ_SUCCESS; 539 } 540 541 /* Destroy AEC */ 542 if (snd_port->ec_state) { 543 pjmedia_echo_destroy(snd_port->ec_state); 809 544 snd_port->ec_state = NULL; 810 else 811 snd_port->ec_suspended = PJ_FALSE; 812 } else { 813 PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the " 814 "sound port")); 815 status = PJ_SUCCESS; 545 } 546 547 snd_port->ec_options = options; 548 snd_port->ec_tail_len = tail_ms; 549 550 if (tail_ms != 0) { 551 unsigned delay_ms; 552 553 status = pjmedia_aud_stream_get_param(snd_port->aud_stream, &prm); 554 if (status != PJ_SUCCESS) 555 prm.input_latency_ms = prm.output_latency_ms = 0; 556 557 //No need to add input latency in the latency calculation, 558 //since actual input latency should be zero. 559 //delay_ms = (si.rec_latency + si.play_latency) * 1000 / 560 // snd_port->clock_rate; 561 delay_ms = prm.output_latency_ms; 562 status = pjmedia_echo_create2(pool, snd_port->clock_rate, 563 snd_port->channel_count, 564 snd_port->samples_per_frame, 565 tail_ms, delay_ms, 566 options, &snd_port->ec_state); 567 if (status != PJ_SUCCESS) 568 snd_port->ec_state = NULL; 569 else 570 snd_port->ec_suspended = PJ_FALSE; 571 } else { 572 PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the " 573 "sound port")); 574 status = PJ_SUCCESS; 575 } 816 576 } 817 577 … … 825 585 { 826 586 PJ_ASSERT_RETURN(snd_port && p_length, PJ_EINVAL); 827 *p_length = snd_port->ec_state ? snd_port->aec_tail_len : 0; 828 return PJ_SUCCESS; 829 } 830 587 588 /* Determine whether we use device or software EC */ 589 if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) { 590 /* We use device EC */ 591 pj_bool_t ec_enabled; 592 pj_status_t status; 593 594 /* Query EC status */ 595 status = pjmedia_aud_stream_get_cap(snd_port->aud_stream, 596 PJMEDIA_AUD_DEV_CAP_EC, 597 &ec_enabled); 598 if (status != PJ_SUCCESS) 599 return status; 600 601 if (!ec_enabled) { 602 *p_length = 0; 603 } else if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC_TAIL) { 604 /* Get device EC tail */ 605 status = pjmedia_aud_stream_get_cap(snd_port->aud_stream, 606 PJMEDIA_AUD_DEV_CAP_EC_TAIL, 607 p_length); 608 if (status != PJ_SUCCESS) 609 return status; 610 } else { 611 /* Just use default */ 612 *p_length = AEC_TAIL; 613 } 614 615 } else { 616 /* We use software EC */ 617 *p_length = snd_port->ec_state ? snd_port->ec_tail_len : 0; 618 } 619 return PJ_SUCCESS; 620 } 831 621 832 622 -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/transport_ice.c
r2394 r2468 22 22 #include <pj/assert.h> 23 23 #include <pj/log.h> 24 #include <pj/pool.h> 24 25 #include <pj/rand.h> 25 26 -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/transport_loop.c
r2394 r2468 23 23 #include <pj/ioqueue.h> 24 24 #include <pj/log.h> 25 #include <pj/pool.h> 25 26 #include <pj/rand.h> 26 27 #include <pj/string.h> -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/transport_udp.c
r2394 r2468 24 24 #include <pj/ioqueue.h> 25 25 #include <pj/log.h> 26 #include <pj/pool.h> 26 27 #include <pj/rand.h> 27 28 #include <pj/string.h> -
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/wmme_sound.c
r2366 r2468 1 #include <pjmedia/sound.h>2 #include <pjmedia/errno.h>3 #include <pj/assert.h>4 #include <pj/log.h>5 #include <pj/os.h>6 #include <pj/string.h>7 8 #if PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_WIN32_MME_SOUND9 10 #ifdef _MSC_VER11 # pragma warning(push, 3)12 #endif13 14 #include <windows.h>15 #include <mmsystem.h>16 17 #ifdef _MSC_VER18 # pragma warning(pop)19 #endif20 21 #if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=022 # pragma comment(lib, "Coredll.lib")23 #elif defined(_MSC_VER)24 # pragma comment(lib, "winmm.lib")25 #endif26 27 28 #define THIS_FILE "wmme_sound.c"29 #define BITS_PER_SAMPLE 1630 #define BYTES_PER_SAMPLE (BITS_PER_SAMPLE/8)31 32 #define MAX_PACKET_BUFFER_COUNT 3233 #define MAX_HARDWARE 1634 35 struct wmme_dev_info36 {37 pjmedia_snd_dev_info info;38 unsigned deviceId;39 };40 41 static unsigned dev_count;42 static struct wmme_dev_info dev_info[MAX_HARDWARE];43 static pj_bool_t snd_initialized = PJ_FALSE;44 45 /* Latency settings */46 static unsigned snd_input_latency = PJMEDIA_SND_DEFAULT_REC_LATENCY;47 static unsigned snd_output_latency = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;48 49 50 /* Individual WMME capture/playback stream descriptor */51 struct wmme_stream52 {53 union54 {55 HWAVEIN In;56 HWAVEOUT Out;57 } hWave;58 59 WAVEHDR *WaveHdr;60 HANDLE hEvent;61 DWORD dwBufIdx;62 DWORD dwMaxBufIdx;63 pj_timestamp timestamp;64 };65 66 67 /* Sound stream. */68 struct pjmedia_snd_stream69 {70 pjmedia_dir dir; /**< Sound direction. */71 int play_id; /**< Playback dev id. */72 int rec_id; /**< Recording dev id. */73 pj_pool_t *pool; /**< Memory pool. */74 75 pjmedia_snd_rec_cb rec_cb; /**< Capture callback. */76 pjmedia_snd_play_cb play_cb; /**< Playback callback. */77 void *user_data; /**< Application data. */78 79 struct wmme_stream play_strm; /**< Playback stream. */80 struct wmme_stream rec_strm; /**< Capture stream. */81 82 void *buffer; /**< Temp. frame buffer. */83 unsigned clock_rate; /**< Clock rate. */84 unsigned samples_per_frame; /**< Samples per frame. */85 unsigned bits_per_sample; /**< Bits per sample. */86 unsigned channel_count; /**< Channel count. */87 88 pj_thread_t *thread; /**< Thread handle. */89 HANDLE thread_quit_event; /**< Quit signal to thread */90 };91 92 93 static pj_pool_factory *pool_factory;94 95 static void init_waveformatex (LPWAVEFORMATEX pcmwf,96 unsigned clock_rate,97 unsigned channel_count)98 {99 pj_bzero(pcmwf, sizeof(PCMWAVEFORMAT));100 pcmwf->wFormatTag = WAVE_FORMAT_PCM;101 pcmwf->nChannels = (pj_uint16_t)channel_count;102 pcmwf->nSamplesPerSec = clock_rate;103 pcmwf->nBlockAlign = (pj_uint16_t)(channel_count * BYTES_PER_SAMPLE);104 pcmwf->nAvgBytesPerSec = clock_rate * channel_count * BYTES_PER_SAMPLE;105 pcmwf->wBitsPerSample = BITS_PER_SAMPLE;106 }107 108 109 /*110 * Initialize WMME player device.111 */112 static pj_status_t init_player_stream( pj_pool_t *pool,113 struct wmme_stream *wmme_strm,114 int dev_id,115 unsigned clock_rate,116 unsigned channel_count,117 unsigned samples_per_frame,118 unsigned buffer_count)119 {120 MMRESULT mr;121 WAVEFORMATEX pcmwf;122 unsigned bytes_per_frame;123 unsigned i;124 125 PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL);126 127 /* Check device ID */128 if (dev_id == -1)129 dev_id = 0;130 131 PJ_ASSERT_RETURN(dev_id >= 0 && dev_id < (int)dev_count, PJ_EINVAL);132 133 /*134 * Create a wait event.135 */136 wmme_strm->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);137 if (NULL == wmme_strm->hEvent)138 return pj_get_os_error();139 140 /*141 * Set up wave format structure for opening the device.142 */143 init_waveformatex(&pcmwf, clock_rate, channel_count);144 bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE;145 146 /*147 * Open wave device.148 */149 mr = waveOutOpen(&wmme_strm->hWave.Out, dev_info[dev_id].deviceId, &pcmwf,150 (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT);151 if (mr != MMSYSERR_NOERROR)152 /* TODO: This is for HRESULT/GetLastError() */153 PJ_RETURN_OS_ERROR(mr);154 155 /* Pause the wave out device */156 mr = waveOutPause(wmme_strm->hWave.Out);157 if (mr != MMSYSERR_NOERROR)158 /* TODO: This is for HRESULT/GetLastError() */159 PJ_RETURN_OS_ERROR(mr);160 161 /*162 * Create the buffers.163 */164 wmme_strm->WaveHdr = pj_pool_zalloc(pool, sizeof(WAVEHDR) * buffer_count);165 for (i = 0; i < buffer_count; ++i)166 {167 wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, bytes_per_frame);168 wmme_strm->WaveHdr[i].dwBufferLength = bytes_per_frame;169 mr = waveOutPrepareHeader(wmme_strm->hWave.Out,170 &(wmme_strm->WaveHdr[i]),171 sizeof(WAVEHDR));172 if (mr != MMSYSERR_NOERROR)173 /* TODO: This is for HRESULT/GetLastError() */174 PJ_RETURN_OS_ERROR(mr);175 mr = waveOutWrite(wmme_strm->hWave.Out, &(wmme_strm->WaveHdr[i]),176 sizeof(WAVEHDR));177 if (mr != MMSYSERR_NOERROR)178 /* TODO: This is for HRESULT/GetLastError() */179 PJ_RETURN_OS_ERROR(mr);180 }181 182 wmme_strm->dwBufIdx = 0;183 wmme_strm->dwMaxBufIdx = buffer_count;184 wmme_strm->timestamp.u64 = 0;185 186 /* Done setting up play device. */187 PJ_LOG(5, (THIS_FILE,188 " WaveAPI Sound player \"%s\" initialized (clock_rate=%d, "189 "channel_count=%d, samples_per_frame=%d (%dms))",190 dev_info[dev_id].info.name,191 clock_rate, channel_count, samples_per_frame,192 samples_per_frame * 1000 / clock_rate));193 194 return PJ_SUCCESS;195 }196 197 198 /*199 * Initialize Windows Multimedia recorder device200 */201 static pj_status_t init_capture_stream( pj_pool_t *pool,202 struct wmme_stream *wmme_strm,203 int dev_id,204 unsigned clock_rate,205 unsigned channel_count,206 unsigned samples_per_frame,207 unsigned buffer_count)208 {209 MMRESULT mr;210 WAVEFORMATEX pcmwf;211 unsigned bytes_per_frame;212 unsigned i;213 214 PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL);215 216 /* Check device ID */217 if (dev_id == -1)218 dev_id = 0;219 220 PJ_ASSERT_RETURN(dev_id >= 0 && dev_id < (int)dev_count, PJ_EINVAL);221 222 /*223 * Create a wait event.224 */225 wmme_strm->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);226 if (NULL == wmme_strm->hEvent)227 return pj_get_os_error();228 229 /*230 * Set up wave format structure for opening the device.231 */232 init_waveformatex(&pcmwf, clock_rate, channel_count);233 bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE;234 235 /*236 * Open wave device.237 */238 mr = waveInOpen(&wmme_strm->hWave.In, dev_info[dev_id].deviceId, &pcmwf,239 (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT);240 if (mr != MMSYSERR_NOERROR)241 /* TODO: This is for HRESULT/GetLastError() */242 PJ_RETURN_OS_ERROR(mr);243 244 /*245 * Create the buffers.246 */247 wmme_strm->WaveHdr = pj_pool_zalloc(pool, sizeof(WAVEHDR) * buffer_count);248 for (i = 0; i < buffer_count; ++i)249 {250 wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, bytes_per_frame);251 wmme_strm->WaveHdr[i].dwBufferLength = bytes_per_frame;252 mr = waveInPrepareHeader(wmme_strm->hWave.In, &(wmme_strm->WaveHdr[i]),253 sizeof(WAVEHDR));254 if (mr != MMSYSERR_NOERROR)255 /* TODO: This is for HRESULT/GetLastError() */256 PJ_RETURN_OS_ERROR(mr);257 mr = waveInAddBuffer(wmme_strm->hWave.In, &(wmme_strm->WaveHdr[i]),258 sizeof(WAVEHDR));259 if (mr != MMSYSERR_NOERROR)260 /* TODO: This is for HRESULT/GetLastError() */261 PJ_RETURN_OS_ERROR(mr);262 }263 264 wmme_strm->dwBufIdx = 0;265 wmme_strm->dwMaxBufIdx = buffer_count;266 wmme_strm->timestamp.u64 = 0;267 268 /* Done setting up play device. */269 PJ_LOG(5,(THIS_FILE,270 " WaveAPI Sound recorder \"%s\" initialized (clock_rate=%d, "271 "channel_count=%d, samples_per_frame=%d (%dms))",272 dev_info[dev_id].info.name,273 clock_rate, channel_count, samples_per_frame,274 samples_per_frame * 1000 / clock_rate));275 276 return PJ_SUCCESS;277 }278 279 280 281 /*282 * WMME capture and playback thread.283 */284 static int PJ_THREAD_FUNC wmme_dev_thread(void *arg)285 {286 pjmedia_snd_stream *strm = arg;287 HANDLE events[3];288 unsigned eventCount;289 unsigned bytes_per_frame;290 pj_status_t status = PJ_SUCCESS;291 292 293 eventCount = 0;294 events[eventCount++] = strm->thread_quit_event;295 if (strm->dir & PJMEDIA_DIR_PLAYBACK)296 events[eventCount++] = strm->play_strm.hEvent;297 if (strm->dir & PJMEDIA_DIR_CAPTURE)298 events[eventCount++] = strm->rec_strm.hEvent;299 300 301 /* Raise self priority. We don't want the audio to be distorted by302 * system activity.303 */304 #if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE != 0305 if (strm->dir & PJMEDIA_DIR_PLAYBACK)306 CeSetThreadPriority(GetCurrentThread(), 153);307 else308 CeSetThreadPriority(GetCurrentThread(), 247);309 #else310 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);311 #endif312 313 /* Calculate bytes per frame */314 bytes_per_frame = strm->samples_per_frame * BYTES_PER_SAMPLE;315 316 /*317 * Loop while not signalled to quit, wait for event objects to be318 * signalled by WMME capture and play buffer.319 */320 while (status == PJ_SUCCESS)321 {322 323 DWORD rc;324 pjmedia_dir signalled_dir;325 326 rc = WaitForMultipleObjects(eventCount, events, FALSE, INFINITE);327 if (rc < WAIT_OBJECT_0 || rc >= WAIT_OBJECT_0 + eventCount)328 continue;329 330 if (rc == WAIT_OBJECT_0)331 break;332 333 if (rc == (WAIT_OBJECT_0 + 1))334 {335 if (events[1] == strm->play_strm.hEvent)336 signalled_dir = PJMEDIA_DIR_PLAYBACK;337 else338 signalled_dir = PJMEDIA_DIR_CAPTURE;339 }340 else341 {342 if (events[2] == strm->play_strm.hEvent)343 signalled_dir = PJMEDIA_DIR_PLAYBACK;344 else345 signalled_dir = PJMEDIA_DIR_CAPTURE;346 }347 348 349 if (signalled_dir == PJMEDIA_DIR_PLAYBACK)350 {351 struct wmme_stream *wmme_strm = &strm->play_strm;352 MMRESULT mr = MMSYSERR_NOERROR;353 status = PJ_SUCCESS;354 355 /*356 * Windows Multimedia has requested us to feed some frames to357 * playback buffer.358 */359 360 while (wmme_strm->WaveHdr[wmme_strm->dwBufIdx].dwFlags & WHDR_DONE)361 {362 void* buffer = wmme_strm->WaveHdr[wmme_strm->dwBufIdx].lpData;363 364 PJ_LOG(5,(THIS_FILE, "Finished writing buffer %d",365 wmme_strm->dwBufIdx));366 367 /* Get frame from application. */368 status = (*strm->play_cb)(strm->user_data,369 wmme_strm->timestamp.u32.lo,370 buffer,371 bytes_per_frame);372 373 if (status != PJ_SUCCESS)374 break;375 376 /* Write to the device. */377 mr = waveOutWrite(wmme_strm->hWave.Out,378 &(wmme_strm->WaveHdr[wmme_strm->dwBufIdx]),379 sizeof(WAVEHDR));380 if (mr != MMSYSERR_NOERROR)381 {382 status = PJ_STATUS_FROM_OS(mr);383 break;384 }385 386 /* Increment position. */387 if (++wmme_strm->dwBufIdx >= wmme_strm->dwMaxBufIdx)388 wmme_strm->dwBufIdx = 0;389 wmme_strm->timestamp.u64 += strm->samples_per_frame /390 strm->channel_count;391 }392 }393 else394 {395 struct wmme_stream *wmme_strm = &strm->rec_strm;396 MMRESULT mr = MMSYSERR_NOERROR;397 status = PJ_SUCCESS;398 399 /*400 * Windows Multimedia has indicated that it has some frames ready401 * in the capture buffer. Get as much frames as possible to402 * prevent overflows.403 */404 #if 0405 {406 static DWORD tc = 0;407 DWORD now = GetTickCount();408 DWORD i = 0;409 DWORD bits = 0;410 411 if (tc == 0) tc = now;412 413 for (i = 0; i < wmme_strm->dwMaxBufIdx; ++i)414 {415 bits = bits << 4;416 bits |= wmme_strm->WaveHdr[i].dwFlags & WHDR_DONE;417 }418 PJ_LOG(5,(THIS_FILE, "Record Signal> Index: %d, Delta: %4.4d, "419 "Flags: %6.6x\n",420 wmme_strm->dwBufIdx,421 now - tc,422 bits));423 tc = now;424 }425 #endif426 427 while (wmme_strm->WaveHdr[wmme_strm->dwBufIdx].dwFlags & WHDR_DONE)428 {429 char* buffer = (char*)430 wmme_strm->WaveHdr[wmme_strm->dwBufIdx].lpData;431 unsigned cap_len =432 wmme_strm->WaveHdr[wmme_strm->dwBufIdx].dwBytesRecorded;433 434 /*435 PJ_LOG(5,(THIS_FILE, "Read %d bytes from buffer %d", cap_len,436 wmme_strm->dwBufIdx));437 */438 439 if (cap_len < bytes_per_frame)440 pj_bzero(buffer + cap_len, bytes_per_frame - cap_len);441 442 /* Copy the audio data out of the wave buffer. */443 pj_memcpy(strm->buffer, buffer, bytes_per_frame);444 445 /* Re-add the buffer to the device. */446 mr = waveInAddBuffer(wmme_strm->hWave.In,447 &(wmme_strm->WaveHdr[wmme_strm->dwBufIdx]),448 sizeof(WAVEHDR));449 if (mr != MMSYSERR_NOERROR) {450 status = PJ_STATUS_FROM_OS(mr);451 break;452 }453 454 /* Call callback */455 status = (*strm->rec_cb)(strm->user_data,456 wmme_strm->timestamp.u32.lo,457 strm->buffer,458 bytes_per_frame);459 460 if (status != PJ_SUCCESS)461 break;462 463 /* Increment position. */464 if (++wmme_strm->dwBufIdx >= wmme_strm->dwMaxBufIdx)465 wmme_strm->dwBufIdx = 0;466 wmme_strm->timestamp.u64 += strm->samples_per_frame /467 strm->channel_count;468 }469 }470 }471 472 PJ_LOG(5,(THIS_FILE, "WMME: thread stopping.."));473 return 0;474 }475 476 477 /*478 * Init sound library.479 */480 PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)481 {482 unsigned c;483 int i;484 int inputDeviceCount, outputDeviceCount, maximumPossibleDeviceCount;485 486 if (snd_initialized)487 return PJ_SUCCESS;488 489 pj_bzero(&dev_info, sizeof(dev_info));490 491 dev_count = 0;492 pool_factory = factory;493 494 /* Enumerate sound playback devices */495 maximumPossibleDeviceCount = 0;496 497 inputDeviceCount = waveInGetNumDevs();498 if (inputDeviceCount > 0)499 /* assume there is a WAVE_MAPPER */500 maximumPossibleDeviceCount += inputDeviceCount + 1;501 502 outputDeviceCount = waveOutGetNumDevs();503 if (outputDeviceCount > 0)504 /* assume there is a WAVE_MAPPER */505 maximumPossibleDeviceCount += outputDeviceCount + 1;506 507 if (maximumPossibleDeviceCount >= MAX_HARDWARE)508 {509 pj_assert(!"Too many hardware found");510 PJ_LOG(3,(THIS_FILE, "Too many hardware found, "511 "some devices will not be listed"));512 }513 514 if (inputDeviceCount > 0)515 {516 /* -1 is the WAVE_MAPPER */517 for (i = -1; i < inputDeviceCount && dev_count < MAX_HARDWARE; ++i)518 {519 UINT uDeviceID = (UINT)((i==-1) ? WAVE_MAPPER : i);520 WAVEINCAPS wic;521 MMRESULT mr;522 523 pj_bzero(&wic, sizeof(WAVEINCAPS));524 525 mr = waveInGetDevCaps(uDeviceID, &wic, sizeof(WAVEINCAPS));526 527 if (mr == MMSYSERR_NOMEM)528 return PJ_ENOMEM;529 530 if (mr != MMSYSERR_NOERROR)531 continue;532 533 #ifdef UNICODE534 WideCharToMultiByte(CP_ACP, 0, wic.szPname, wcslen(wic.szPname),535 dev_info[dev_count].info.name, 64, NULL, NULL);536 #else537 strncpy(dev_info[dev_count].info.name, wic.szPname, MAXPNAMELEN);538 #endif539 if (uDeviceID == WAVE_MAPPER)540 strcat(dev_info[dev_count].info.name, " - Input");541 542 dev_info[dev_count].info.input_count = wic.wChannels;543 dev_info[dev_count].info.output_count = 0;544 dev_info[dev_count].info.default_samples_per_sec = 44100;545 dev_info[dev_count].deviceId = uDeviceID;546 547 /* Sometimes a device can return a rediculously large number of548 * channels. This happened with an SBLive card on a Windows ME box.549 * It also happens on Win XP!550 */551 if ((dev_info[dev_count].info.input_count < 1) ||552 (dev_info[dev_count].info.input_count > 256))553 dev_info[dev_count].info.input_count = 2;554 555 ++dev_count;556 }557 }558 559 if( outputDeviceCount > 0 )560 {561 /* -1 is the WAVE_MAPPER */562 for (i = -1; i < outputDeviceCount && dev_count < MAX_HARDWARE; ++i)563 {564 UINT uDeviceID = (UINT)((i==-1) ? WAVE_MAPPER : i);565 WAVEOUTCAPS woc;566 MMRESULT mr;567 568 pj_bzero(&woc, sizeof(WAVEOUTCAPS));569 570 mr = waveOutGetDevCaps(uDeviceID, &woc, sizeof(WAVEOUTCAPS));571 572 if (mr == MMSYSERR_NOMEM)573 return PJ_ENOMEM;574 575 if (mr != MMSYSERR_NOERROR)576 continue;577 578 #ifdef UNICODE579 WideCharToMultiByte(CP_ACP, 0, woc.szPname, wcslen(woc.szPname),580 dev_info[dev_count].info.name, 64, NULL, NULL);581 #else582 strncpy(dev_info[dev_count].info.name, woc.szPname, MAXPNAMELEN);583 #endif584 if (uDeviceID == WAVE_MAPPER)585 strcat(dev_info[dev_count].info.name, " - Output");586 587 dev_info[dev_count].info.output_count = woc.wChannels;588 dev_info[dev_count].info.input_count = 0;589 dev_info[dev_count].deviceId = uDeviceID;590 /* TODO: Perform a search! */591 dev_info[dev_count].info.default_samples_per_sec = 44100;592 593 /* Sometimes a device can return a rediculously large number of channels.594 * This happened with an SBLive card on a Windows ME box.595 * It also happens on Win XP!596 */597 if ((dev_info[dev_count].info.output_count < 1) ||598 (dev_info[dev_count].info.output_count > 256))599 dev_info[dev_count].info.output_count = 2;600 601 ++dev_count;602 }603 }604 605 PJ_LOG(4, (THIS_FILE, "WMME initialized, found %d devices:", dev_count));606 for (c = 0; c < dev_count; ++c)607 {608 PJ_LOG(4, (THIS_FILE, " dev_id %d: %s (in=%d, out=%d)",609 c,610 dev_info[c].info.name,611 dev_info[c].info.input_count,612 dev_info[c].info.output_count));613 }614 return PJ_SUCCESS;615 }616 617 /*618 * Deinitialize sound library.619 */620 PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)621 {622 snd_initialized = PJ_FALSE;623 return PJ_SUCCESS;624 }625 626 /*627 * Get device count.628 */629 PJ_DEF(int) pjmedia_snd_get_dev_count(void)630 {631 return dev_count;632 }633 634 /*635 * Get device info.636 */637 PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)638 {639 if (index == (unsigned)-1)640 index = 0;641 642 PJ_ASSERT_RETURN(index < dev_count, NULL);643 644 return &dev_info[index].info;645 }646 647 648 /*649 * Open stream.650 */651 static pj_status_t open_stream(pjmedia_dir dir,652 int rec_id,653 int play_id,654 unsigned clock_rate,655 unsigned channel_count,656 unsigned samples_per_frame,657 unsigned bits_per_sample,658 pjmedia_snd_rec_cb rec_cb,659 pjmedia_snd_play_cb play_cb,660 void *user_data,661 pjmedia_snd_stream **p_snd_strm)662 {663 pj_pool_t *pool;664 pjmedia_snd_stream *strm;665 pj_status_t status;666 667 668 /* Make sure sound subsystem has been initialized with669 * pjmedia_snd_init()670 */671 PJ_ASSERT_RETURN(pool_factory != NULL, PJ_EINVALIDOP);672 673 674 /* Can only support 16bits per sample */675 PJ_ASSERT_RETURN(bits_per_sample == BITS_PER_SAMPLE, PJ_EINVAL);676 677 /* Create and Initialize stream descriptor */678 pool = pj_pool_create(pool_factory, "wmme-dev", 1000, 1000, NULL);679 PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);680 681 strm = pj_pool_zalloc(pool, sizeof(pjmedia_snd_stream));682 strm->dir = dir;683 strm->play_id = play_id;684 strm->rec_id = rec_id;685 strm->pool = pool;686 strm->rec_cb = rec_cb;687 strm->play_cb = play_cb;688 strm->user_data = user_data;689 strm->clock_rate = clock_rate;690 strm->samples_per_frame = samples_per_frame;691 strm->bits_per_sample = bits_per_sample;692 strm->channel_count = channel_count;693 strm->buffer = pj_pool_alloc(pool, samples_per_frame * BYTES_PER_SAMPLE);694 if (!strm->buffer)695 {696 pj_pool_release(pool);697 return PJ_ENOMEM;698 }699 700 /* Create player stream */701 if (dir & PJMEDIA_DIR_PLAYBACK)702 {703 unsigned buf_count;704 705 buf_count = snd_output_latency * clock_rate * channel_count /706 samples_per_frame / 1000;707 708 status = init_player_stream(strm->pool,709 &strm->play_strm,710 play_id,711 clock_rate,712 channel_count,713 samples_per_frame,714 buf_count);715 716 if (status != PJ_SUCCESS)717 {718 pjmedia_snd_stream_close(strm);719 return status;720 }721 }722 723 /* Create capture stream */724 if (dir & PJMEDIA_DIR_CAPTURE)725 {726 unsigned buf_count;727 728 buf_count = snd_input_latency * clock_rate * channel_count /729 samples_per_frame / 1000;730 731 status = init_capture_stream(strm->pool,732 &strm->rec_strm,733 rec_id,734 clock_rate,735 channel_count,736 samples_per_frame,737 buf_count);738 739 if (status != PJ_SUCCESS)740 {741 pjmedia_snd_stream_close(strm);742 return status;743 }744 }745 746 /* Create the stop event */747 strm->thread_quit_event = CreateEvent(NULL, FALSE, FALSE, NULL);748 if (strm->thread_quit_event == NULL)749 return pj_get_os_error();750 751 /* Create and start the thread */752 status = pj_thread_create(pool, "wmme", &wmme_dev_thread, strm, 0, 0,753 &strm->thread);754 if (status != PJ_SUCCESS)755 {756 pjmedia_snd_stream_close(strm);757 return status;758 }759 760 *p_snd_strm = strm;761 762 return PJ_SUCCESS;763 }764 765 /*766 * Open stream.767 */768 PJ_DEF(pj_status_t) pjmedia_snd_open_rec(int index,769 unsigned clock_rate,770 unsigned channel_count,771 unsigned samples_per_frame,772 unsigned bits_per_sample,773 pjmedia_snd_rec_cb rec_cb,774 void *user_data,775 pjmedia_snd_stream **p_snd_strm)776 {777 PJ_ASSERT_RETURN(rec_cb && p_snd_strm, PJ_EINVAL);778 779 return open_stream( PJMEDIA_DIR_CAPTURE,780 index,781 -1,782 clock_rate,783 channel_count,784 samples_per_frame,785 bits_per_sample,786 rec_cb,787 NULL,788 user_data,789 p_snd_strm);790 }791 792 PJ_DEF(pj_status_t) pjmedia_snd_open_player(int index,793 unsigned clock_rate,794 unsigned channel_count,795 unsigned samples_per_frame,796 unsigned bits_per_sample,797 pjmedia_snd_play_cb play_cb,798 void *user_data,799 pjmedia_snd_stream **p_snd_strm)800 {801 PJ_ASSERT_RETURN(play_cb && p_snd_strm, PJ_EINVAL);802 803 return open_stream( PJMEDIA_DIR_PLAYBACK,804 -1,805 index,806 clock_rate,807 channel_count,808 samples_per_frame,809 bits_per_sample,810 NULL,811 play_cb,812 user_data,813 p_snd_strm);814 }815 816 /*817 * Open both player and recorder.818 */819 PJ_DEF(pj_status_t) pjmedia_snd_open(int rec_id,820 int play_id,821 unsigned clock_rate,822 unsigned channel_count,823 unsigned samples_per_frame,824 unsigned bits_per_sample,825 pjmedia_snd_rec_cb rec_cb,826 pjmedia_snd_play_cb play_cb,827 void *user_data,828 pjmedia_snd_stream **p_snd_strm)829 {830 PJ_ASSERT_RETURN(rec_cb && play_cb && p_snd_strm, PJ_EINVAL);831 832 return open_stream( PJMEDIA_DIR_CAPTURE_PLAYBACK,833 rec_id,834 play_id,835 clock_rate,836 channel_count,837 samples_per_frame,838 bits_per_sample,839 rec_cb,840 play_cb,841 user_data,842 p_snd_strm);843 }844 845 /*846 * Get stream info.847 */848 PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,849 pjmedia_snd_stream_info *pi)850 {851 PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);852 853 pj_bzero(pi, sizeof(*pi));854 pi->dir = strm->dir;855 pi->play_id = strm->play_id;856 pi->rec_id = strm->rec_id;857 pi->clock_rate = strm->clock_rate;858 pi->channel_count = strm->channel_count;859 pi->samples_per_frame = strm->samples_per_frame;860 pi->bits_per_sample = strm->bits_per_sample;861 pi->rec_latency = snd_input_latency * strm->clock_rate *862 strm->channel_count / 1000;863 pi->play_latency = snd_output_latency * strm->clock_rate *864 strm->channel_count / 1000;865 866 return PJ_SUCCESS;867 }868 869 870 /*871 * Start stream.872 */873 PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)874 {875 MMRESULT mr;876 877 PJ_UNUSED_ARG(stream);878 879 if (stream->play_strm.hWave.Out != NULL)880 {881 mr = waveOutRestart(stream->play_strm.hWave.Out);882 if (mr != MMSYSERR_NOERROR)883 /* TODO: This macro is supposed to be used for HRESULT, fix. */884 PJ_RETURN_OS_ERROR(mr);885 PJ_LOG(5,(THIS_FILE, "WMME playback stream started"));886 }887 888 if (stream->rec_strm.hWave.In != NULL)889 {890 mr = waveInStart(stream->rec_strm.hWave.In);891 if (mr != MMSYSERR_NOERROR)892 /* TODO: This macro is supposed to be used for HRESULT, fix. */893 PJ_RETURN_OS_ERROR(mr);894 PJ_LOG(5,(THIS_FILE, "WMME capture stream started"));895 }896 897 return PJ_SUCCESS;898 }899 900 /*901 * Stop stream.902 */903 PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream)904 {905 MMRESULT mr;906 907 PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);908 909 if (stream->play_strm.hWave.Out != NULL)910 {911 mr = waveOutPause(stream->play_strm.hWave.Out);912 if (mr != MMSYSERR_NOERROR)913 /* TODO: This macro is supposed to be used for HRESULT, fix. */914 PJ_RETURN_OS_ERROR(mr);915 PJ_LOG(5,(THIS_FILE, "Stopped WMME playback stream"));916 }917 918 if (stream->rec_strm.hWave.In != NULL)919 {920 mr = waveInStop(stream->rec_strm.hWave.In);921 if (mr != MMSYSERR_NOERROR)922 /* TODO: This macro is supposed to be used for HRESULT, fix. */923 PJ_RETURN_OS_ERROR(mr);924 PJ_LOG(5,(THIS_FILE, "Stopped WMME capture stream"));925 }926 927 return PJ_SUCCESS;928 }929 930 931 /*932 * Destroy stream.933 */934 PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream)935 {936 unsigned i;937 938 PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);939 940 pjmedia_snd_stream_stop(stream);941 942 if (stream->thread)943 {944 SetEvent(stream->thread_quit_event);945 pj_thread_join(stream->thread);946 pj_thread_destroy(stream->thread);947 stream->thread = NULL;948 }949 950 /* Unprepare the headers and close the play device */951 if (stream->play_strm.hWave.Out)952 {953 waveOutReset(stream->play_strm.hWave.Out);954 for (i = 0; i < stream->play_strm.dwMaxBufIdx; ++i)955 waveOutUnprepareHeader(stream->play_strm.hWave.Out,956 &(stream->play_strm.WaveHdr[i]),957 sizeof(WAVEHDR));958 waveOutClose(stream->play_strm.hWave.Out);959 stream->play_strm.hWave.Out = NULL;960 }961 962 /* Close the play event */963 if (stream->play_strm.hEvent)964 {965 CloseHandle(stream->play_strm.hEvent);966 stream->play_strm.hEvent = NULL;967 }968 969 /* Unprepare the headers and close the record device */970 if (stream->rec_strm.hWave.In)971 {972 waveInReset(stream->rec_strm.hWave.In);973 for (i = 0; i < stream->play_strm.dwMaxBufIdx; ++i)974 waveInUnprepareHeader(stream->rec_strm.hWave.In,975 &(stream->rec_strm.WaveHdr[i]),976 sizeof(WAVEHDR));977 waveInClose(stream->rec_strm.hWave.In);978 stream->rec_strm.hWave.In = NULL;979 }980 981 /* Close the record event */982 if (stream->rec_strm.hEvent)983 {984 CloseHandle(stream->rec_strm.hEvent);985 stream->rec_strm.hEvent = NULL;986 }987 988 pj_pool_release(stream->pool);989 990 return PJ_SUCCESS;991 }992 993 /*994 * Set sound latency.995 */996 PJ_DEF(pj_status_t) pjmedia_snd_set_latency(unsigned input_latency,997 unsigned output_latency)998 {999 snd_input_latency = (input_latency == 0)?1000 PJMEDIA_SND_DEFAULT_REC_LATENCY : input_latency;1001 snd_output_latency = (output_latency == 0)?1002 PJMEDIA_SND_DEFAULT_PLAY_LATENCY : output_latency;1003 1004 return PJ_SUCCESS;1005 }1006 1007 #endif /* PJMEDIA_SOUND_IMPLEMENTATION */1008 -
pjproject/branches/projects/aps-direct/pjproject.dsw
r2463 r2468 234 234 Project_Dep_Name pjnath 235 235 End Project Dependency 236 Begin Project Dependency 237 Project_Dep_Name pjmedia_audiodev 238 End Project Dependency 236 239 }}} 237 240 … … 363 366 Project_Dep_Name libsrtp 364 367 End Project Dependency 368 Begin Project Dependency 369 Project_Dep_Name pjmedia_audiodev 370 End Project Dependency 365 371 }}} 366 372 … … 451 457 End Project Dependency 452 458 Begin Project Dependency 459 Project_Dep_Name libgsmcodec 460 End Project Dependency 461 Begin Project Dependency 462 Project_Dep_Name libilbccodec 463 End Project Dependency 464 Begin Project Dependency 465 Project_Dep_Name libportaudio 466 End Project Dependency 467 Begin Project Dependency 468 Project_Dep_Name libresample 469 End Project Dependency 470 Begin Project Dependency 471 Project_Dep_Name libspeex 472 End Project Dependency 473 Begin Project Dependency 474 Project_Dep_Name pjnath 475 End Project Dependency 476 Begin Project Dependency 477 Project_Dep_Name libsrtp 478 End Project Dependency 479 Begin Project Dependency 480 Project_Dep_Name pjmedia_audiodev 481 End Project Dependency 482 }}} 483 484 ############################################################################### 485 486 Project: "samples"=".\pjsip-apps\build\samples.dsp" - Package Owner=<4> 487 488 Package=<5> 489 {{{ 490 }}} 491 492 Package=<4> 493 {{{ 494 Begin Project Dependency 495 Project_Dep_Name pjlib 496 End Project Dependency 497 Begin Project Dependency 498 Project_Dep_Name pjlib_util 499 End Project Dependency 500 Begin Project Dependency 501 Project_Dep_Name pjmedia 502 End Project Dependency 503 Begin Project Dependency 504 Project_Dep_Name pjmedia_codec 505 End Project Dependency 506 Begin Project Dependency 507 Project_Dep_Name pjsip_core 508 End Project Dependency 509 Begin Project Dependency 510 Project_Dep_Name pjsip_simple 511 End Project Dependency 512 Begin Project Dependency 513 Project_Dep_Name pjsip_ua 514 End Project Dependency 515 Begin Project Dependency 453 516 Project_Dep_Name pjsua_lib 454 517 End Project Dependency … … 481 544 ############################################################################### 482 545 483 Project: " samples"=".\pjsip-apps\build\samples.dsp" - Package Owner=<4>546 Project: "test_pjsip"=".\pjsip\build\test_pjsip.dsp" - Package Owner=<4> 484 547 485 548 Package=<5> … … 513 576 Project_Dep_Name pjsua_lib 514 577 End Project Dependency 515 Begin Project Dependency516 Project_Dep_Name libgsmcodec517 End Project Dependency518 Begin Project Dependency519 Project_Dep_Name libilbccodec520 End Project Dependency521 Begin Project Dependency522 Project_Dep_Name libportaudio523 End Project Dependency524 Begin Project Dependency525 Project_Dep_Name libresample526 End Project Dependency527 Begin Project Dependency528 Project_Dep_Name libspeex529 End Project Dependency530 Begin Project Dependency531 Project_Dep_Name pjnath532 End Project Dependency533 Begin Project Dependency534 Project_Dep_Name libsrtp535 End Project Dependency536 }}}537 538 ###############################################################################539 540 Project: "test_pjsip"=".\pjsip\build\test_pjsip.dsp" - Package Owner=<4>541 542 Package=<5>543 {{{544 }}}545 546 Package=<4>547 {{{548 Begin Project Dependency549 Project_Dep_Name pjlib550 End Project Dependency551 Begin Project Dependency552 Project_Dep_Name pjlib_util553 End Project Dependency554 Begin Project Dependency555 Project_Dep_Name pjmedia556 End Project Dependency557 Begin Project Dependency558 Project_Dep_Name pjmedia_codec559 End Project Dependency560 Begin Project Dependency561 Project_Dep_Name pjsip_core562 End Project Dependency563 Begin Project Dependency564 Project_Dep_Name pjsip_simple565 End Project Dependency566 Begin Project Dependency567 Project_Dep_Name pjsip_ua568 End Project Dependency569 Begin Project Dependency570 Project_Dep_Name pjsua_lib571 End Project Dependency572 578 }}} 573 579 -
pjproject/branches/projects/aps-direct/pjsip-apps/build/Samples-vc.mak
r2178 r2468 14 14 PJMEDIA_LIB = ..\..\pjmedia\lib\pjmedia-$(TARGET)$(LIBEXT) 15 15 PJMEDIA_CODEC_LIB = ..\..\pjmedia\lib\pjmedia-codec-$(TARGET)$(LIBEXT) 16 PJMEDIA_AUDIODEV_LIB = ..\..\pjmedia\lib\pjmedia-audiodev-$(TARGET)$(LIBEXT) 16 17 PJSIP_LIB = ..\..\pjsip\lib\pjsip-core-$(TARGET)$(LIBEXT) 17 18 PJSIP_UA_LIB = ..\..\pjsip\lib\pjsip-ua-$(TARGET)$(LIBEXT) … … 30 31 31 32 LIBS = $(PJSUA_LIB_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE_LIB) \ 32 $(PJSIP_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_ LIB) $(PJNATH_LIB) \33 $(PJ LIB_UTIL_LIB) $(PJLIB_LIB) \33 $(PJSIP_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_AUDIODEV_LIB) \ 34 $(PJMEDIA_LIB) $(PJNATH_LIB) $(PJLIB_UTIL_LIB) $(PJLIB_LIB) \ 34 35 $(THIRD_PARTY_LIBS) 35 36 … … 50 51 51 52 52 SAMPLES = $(BINDIR)\confsample.exe \ 53 SAMPLES = $(BINDIR)\auddemo.exe \ 54 $(BINDIR)\confsample.exe \ 53 55 $(BINDIR)\confbench.exe \ 54 56 $(BINDIR)\encdec.exe \ … … 66 68 $(BINDIR)\siprtp.exe \ 67 69 $(BINDIR)\sipstateless.exe \ 68 $(BINDIR)\sndinfo.exe \69 $(BINDIR)\sndtest.exe \70 70 $(BINDIR)\stateful_proxy.exe \ 71 71 $(BINDIR)\stateless_proxy.exe \ -
pjproject/branches/projects/aps-direct/pjsip-apps/build/Samples.mak
r2183 r2468 14 14 BINDIR := ../bin/samples 15 15 16 SAMPLES := confsample \ 16 SAMPLES := auddemo \ 17 confsample \ 17 18 encdec \ 18 19 latency \ … … 29 30 siprtp \ 30 31 sipstateless \ 31 sndinfo \32 sndtest \33 32 stateful_proxy \ 34 33 stateless_proxy \ -
pjproject/branches/projects/aps-direct/pjsip-apps/src/pjsua/pjsua_app.c
r2460 r2468 4060 4060 app_config.cfg.cb.on_nat_detect = &on_nat_detect; 4061 4061 4062 /* Set sound device latency */ 4063 if (app_config.capture_lat > 0) 4064 app_config.media_cfg.snd_rec_latency = app_config.capture_lat; 4065 if (app_config.playback_lat) 4066 app_config.media_cfg.snd_play_latency = app_config.playback_lat; 4067 4062 4068 /* Initialize pjsua */ 4063 4069 status = pjsua_init(&app_config.cfg, &app_config.log_cfg, … … 4318 4324 if (status != PJ_SUCCESS) 4319 4325 goto on_error; 4320 4321 /* Set sound device latency */4322 pjmedia_snd_set_latency(app_config.capture_lat, app_config.playback_lat);4323 4326 4324 4327 /* Use null sound device? */ -
pjproject/branches/projects/aps-direct/pjsip-apps/src/samples/auddemo.c
r2464 r2468 30 30 31 31 static unsigned dev_count; 32 static pjmedia_aud_dev_id dev_id[MAX_DEVICES];33 32 34 33 static void app_perror(const char *title, pj_status_t status) … … 54 53 PJ_LOG(3,(THIS_FILE, "Found %d devices:", dev_count)); 55 54 56 dev_count = pjmedia_aud_dev_enum(PJ_ARRAY_SIZE(dev_id), dev_id);57 58 55 for (i=0; i<dev_count; ++i) { 59 56 pjmedia_aud_dev_info info; 60 57 61 status = pjmedia_aud_dev_get_info( dev_id[i], &info);58 status = pjmedia_aud_dev_get_info(i, &info); 62 59 if (status != PJ_SUCCESS) 63 60 continue; … … 71 68 { 72 69 static char text[200]; 70 unsigned i; 73 71 74 72 text[0] = '\0'; 75 73 76 if (caps & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) { 77 strcat(text, "extfmt "); 78 } 79 80 if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) { 81 strcat(text, "inlatency "); 82 } 83 84 if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) { 85 strcat(text, "outlatency "); 86 } 87 88 if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING) { 89 strcat(text, "invol "); 90 } 91 92 if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) { 93 strcat(text, "outvol "); 94 } 95 96 if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_VOLUME) { 97 strcat(text, "insignal "); 98 } 99 100 if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_VOLUME) { 101 strcat(text, "outsignal "); 102 } 103 104 if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE) { 105 strcat(text, "inroute "); 106 } 107 108 if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE) { 109 strcat(text, "outroute "); 110 } 111 112 if (caps & PJMEDIA_AUD_DEV_CAP_EC) { 113 strcat(text, "ec "); 114 } 115 116 if (caps & PJMEDIA_AUD_DEV_CAP_EC_TAIL) { 117 strcat(text, "ectail "); 118 } 119 120 if (caps & PJMEDIA_AUD_DEV_CAP_VAD) { 121 strcat(text, "vad "); 122 } 123 124 if (caps & PJMEDIA_AUD_DEV_CAP_CNG) { 125 strcat(text, "cng "); 126 } 127 128 if (caps & PJMEDIA_AUD_DEV_CAP_PLC) { 129 strcat(text, "plc "); 74 for (i=0; i<31; ++i) { 75 if ((1 << i) & caps) { 76 const char *capname; 77 capname = pjmedia_aud_dev_cap_name((pjmedia_aud_dev_cap)(1 << i), 78 NULL); 79 strcat(text, capname); 80 strcat(text, " "); 81 } 130 82 } 131 83 … … 145 97 } 146 98 147 status = pjmedia_aud_dev_get_info( dev_id[index], &info);99 status = pjmedia_aud_dev_get_info(index, &info); 148 100 if (status != PJ_SUCCESS) { 149 101 app_perror("pjmedia_aud_dev_get_info() error", status); … … 154 106 PJ_LOG(3, (THIS_FILE, "-------------------------")); 155 107 156 PJ_LOG(3, (THIS_FILE, H": %u (0x%x)", "ID", dev_id[index], dev_id[index]));108 PJ_LOG(3, (THIS_FILE, H": %u (0x%x)", "ID", index, index)); 157 109 PJ_LOG(3, (THIS_FILE, H": %s", "Name", info.name)); 158 110 PJ_LOG(3, (THIS_FILE, H": %s", "Driver", info.driver)); … … 205 157 unsigned chnum) 206 158 { 207 pjmedia_aud_ dev_param param;159 pjmedia_aud_param param; 208 160 pjmedia_aud_test_results result; 209 161 pj_status_t status; 210 162 211 163 if (dir & PJMEDIA_DIR_CAPTURE) { 212 status = pjmedia_aud_dev_default_param( dev_id[rec_id], ¶m);164 status = pjmedia_aud_dev_default_param(rec_id, ¶m); 213 165 } else { 214 status = pjmedia_aud_dev_default_param( dev_id[play_id], ¶m);166 status = pjmedia_aud_dev_default_param(play_id, ¶m); 215 167 } 216 168 … … 221 173 222 174 param.dir = dir; 223 param.rec_id = dev_id[rec_id];224 param.play_id = dev_id[play_id];175 param.rec_id = rec_id; 176 param.play_id = play_id; 225 177 param.clock_rate = clock_rate; 226 178 param.channel_count = chnum; … … 286 238 pj_pool_t *pool = NULL; 287 239 pjmedia_port *wav = NULL; 288 pjmedia_aud_ dev_param param;240 pjmedia_aud_param param; 289 241 pjmedia_aud_stream *strm = NULL; 290 242 char line[10]; … … 304 256 } 305 257 306 status = pjmedia_aud_dev_default_param( dev_id[rec_index], ¶m);258 status = pjmedia_aud_dev_default_param(rec_index, ¶m); 307 259 if (status != PJ_SUCCESS) { 308 260 app_perror("pjmedia_aud_dev_default_param()", status); … … 354 306 pj_pool_t *pool = NULL; 355 307 pjmedia_port *wav = NULL; 356 pjmedia_aud_ dev_param param;308 pjmedia_aud_param param; 357 309 pjmedia_aud_stream *strm = NULL; 358 310 char line[10]; … … 371 323 } 372 324 373 status = pjmedia_aud_dev_default_param( dev_id[play_index], ¶m);325 status = pjmedia_aud_dev_default_param(play_index, ¶m); 374 326 if (status != PJ_SUCCESS) { 375 327 app_perror("pjmedia_aud_dev_default_param()", status); -
pjproject/branches/projects/aps-direct/pjsip/include/pjsua-lib/pjsua.h
r2460 r2468 4201 4201 unsigned ec_tail_len; 4202 4202 4203 /** 4204 * Audio capture buffer length, in milliseconds. 4205 * 4206 * Default: PJMEDIA_SND_DEFAULT_REC_LATENCY 4207 */ 4208 unsigned snd_rec_latency; 4209 4210 /** 4211 * Audio playback buffer length, in milliseconds. 4212 * 4213 * Default: PJMEDIA_SND_DEFAULT_PLAY_LATENCY 4214 */ 4215 unsigned snd_play_latency; 4216 4203 4217 /** 4204 4218 * Jitter buffer initial prefetch delay in msec. The value must be … … 4805 4819 * 4806 4820 */ 4821 #if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 4822 PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_aud_dev_info info[], 4823 unsigned *count); 4824 #else 4807 4825 PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_snd_dev_info info[], 4808 4826 unsigned *count); 4809 4827 #endif 4810 4828 4811 4829 … … 4880 4898 4881 4899 /** 4882 * Configure the echo canceller tail length of the sound port. 4900 * Change the echo cancellation settings. The behavior of this function 4901 * depends on whether the sound device is currently active, and if it is, 4902 * whether device or software AEC is being used. 4903 * 4904 * If the sound device is currently active, and if the device supports AEC, 4905 * this function will forward the change request to the device and it will 4906 * be up to the device on whether support the request. If software AEC is 4907 * being used (the software EC will be used if the device does not support 4908 * AEC), this function will change the software EC settings. In all cases, 4909 * the setting will be saved for future opening of the sound device. 4910 * 4911 * If the sound device is not currently active, this will only change the 4912 * default AEC settings and the setting will be applied next time the 4913 * sound device is opened. 4883 4914 * 4884 4915 * @param tail_ms The tail length, in miliseconds. Set to zero to … … 4911 4942 */ 4912 4943 PJ_DECL(pj_status_t) pjsua_get_ec_tail(unsigned *p_tail_ms); 4913 4914 4915 /**4916 * Set sound device route.4917 *4918 * @param route Sound device route to be set.4919 *4920 * @return PJ_SUCCESS on success, or the appropriate error code.4921 */4922 PJ_DECL(pj_status_t) pjsua_set_snd_route(pjmedia_snd_route route);4923 4944 4924 4945 -
pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_core.c
r2394 r2468 178 178 cfg->ilbc_mode = PJSUA_DEFAULT_ILBC_MODE; 179 179 cfg->ec_tail_len = PJSUA_DEFAULT_EC_TAIL_LEN; 180 cfg->snd_rec_latency = PJMEDIA_SND_DEFAULT_REC_LATENCY; 181 cfg->snd_play_latency = PJMEDIA_SND_DEFAULT_PLAY_LATENCY; 180 182 cfg->jb_init = cfg->jb_min_pre = cfg->jb_max_pre = cfg->jb_max = -1; 181 183 cfg->snd_auto_close_time = -1; -
pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_media.c
r2462 r2468 1515 1515 * Open sound device with extended setting. 1516 1516 */ 1517 static pj_status_t open_snd_dev_ext( int capture_dev, 1518 int playback_dev, 1519 unsigned clock_rate, 1520 unsigned channel_count, 1521 unsigned samples_per_frame, 1522 const pjmedia_snd_setting *setting) 1517 static pj_status_t open_snd_dev_ext(pjmedia_aud_param *param) 1523 1518 { 1524 1519 pjmedia_port *conf_port; 1525 1520 pj_status_t status; 1526 1521 1527 PJ_ASSERT_RETURN( setting, PJ_EINVAL);1522 PJ_ASSERT_RETURN(param, PJ_EINVAL); 1528 1523 1529 1524 /* Check if NULL sound device is used */ 1530 if (NULL_SND_DEV_ID == capture_dev || NULL_SND_DEV_ID == playback_dev) {1525 if (NULL_SND_DEV_ID==param->rec_id || NULL_SND_DEV_ID==param->play_id) { 1531 1526 return pjsua_set_null_snd_dev(); 1532 1527 } … … 1545 1540 1546 1541 PJ_LOG(4,(THIS_FILE, "Opening sound device @%d/%d/%s", 1547 clock_rate,channel_count,1548 ( setting->format.id==PJMEDIA_FORMAT_L16?"raw":"encoded")));1542 param->clock_rate, param->channel_count, 1543 (param->ext_fmt.id==PJMEDIA_FORMAT_L16?"pcm":"encoded"))); 1549 1544 1550 1545 status = pjmedia_snd_port_create2( pjsua_var.snd_pool, 1551 PJMEDIA_DIR_CAPTURE_PLAYBACK, 1552 capture_dev, 1553 playback_dev, 1554 clock_rate, 1555 channel_count, 1556 samples_per_frame, 1557 16, 1558 setting, 1559 &pjsua_var.snd_port); 1546 param, &pjsua_var.snd_port); 1560 1547 1561 1548 /* Update port 0 info when sound dev opened successfully. */ 1562 1549 if (status == PJ_SUCCESS) { 1563 conf_port->info.format = setting->format; 1564 conf_port->info.clock_rate = clock_rate; 1565 conf_port->info.samples_per_frame = samples_per_frame; 1566 conf_port->info.channel_count = channel_count; 1550 pj_memcpy(&conf_port->info.format, ¶m->ext_fmt, 1551 sizeof(conf_port->info.format)); 1552 conf_port->info.clock_rate = param->clock_rate; 1553 conf_port->info.samples_per_frame = param->samples_per_frame; 1554 conf_port->info.channel_count = param->channel_count; 1567 1555 conf_port->info.bits_per_sample = 16; 1568 1556 } else { … … 1583 1571 1584 1572 /* Save the device IDs */ 1585 pjsua_var.cap_dev = capture_dev;1586 pjsua_var.play_dev = p layback_dev;1573 pjsua_var.cap_dev = param->rec_id; 1574 pjsua_var.play_dev = param->play_id; 1587 1575 1588 1576 /* Update sound device name. */ 1589 do{1590 const pjmedia_snd_dev_info *play_info;1591 pjmedia_ snd_stream *strm;1592 pjmedia_ snd_stream_infosi;1577 { 1578 pjmedia_aud_dev_info play_info; 1579 pjmedia_aud_stream *strm; 1580 pjmedia_aud_param si; 1593 1581 pj_str_t tmp; 1594 1582 1595 1583 strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 1596 pjmedia_ snd_stream_get_info(strm, &si);1597 play_info = pjmedia_snd_get_dev_info(si.rec_id);1598 1599 pjmedia_conf_set_port0_name(pjsua_var.mconf,1600 pj_cstr(&tmp, play_info->name));1601 } while(0);1584 pjmedia_aud_stream_get_param(strm, &si); 1585 if (pjmedia_aud_dev_get_info(si.play_id, &play_info)==PJ_SUCCESS) { 1586 pjmedia_conf_set_port0_name(pjsua_var.mconf, 1587 pj_cstr(&tmp, play_info.name)); 1588 } 1589 }; 1602 1590 1603 1591 return PJ_SUCCESS; … … 1612 1600 /* Close sound device */ 1613 1601 if (pjsua_var.snd_port) { 1614 pjmedia_ snd_dev_info cap_info, play_info;1615 pjmedia_ snd_stream *strm;1616 pjmedia_ snd_stream_info si;1602 pjmedia_aud_dev_info cap_info, play_info; 1603 pjmedia_aud_stream *strm; 1604 pjmedia_aud_param param; 1617 1605 1618 1606 strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 1619 pjmedia_snd_stream_get_info(strm, &si); 1620 cap_info = *(pjmedia_snd_get_dev_info(si.rec_id)); 1621 play_info = *(pjmedia_snd_get_dev_info(si.play_id)); 1607 pjmedia_aud_stream_get_param(strm, ¶m); 1608 1609 if (pjmedia_aud_dev_get_info(param.rec_id, &cap_info) != PJ_SUCCESS) 1610 cap_info.name[0] = '\0'; 1611 if (pjmedia_aud_dev_get_info(param.play_id, &play_info) != PJ_SUCCESS) 1612 play_info.name[0] = '\0'; 1622 1613 1623 1614 PJ_LOG(4,(THIS_FILE, "Closing %s sound playback device and " … … 1797 1788 1798 1789 if (need_reopen) { 1799 pjmedia_snd_setting setting; 1800 1801 pj_bzero(&setting, sizeof(setting)); 1802 setting.format = peer_info.format; 1803 setting.plc = PJ_FALSE; 1804 setting.route = PJMEDIA_SND_ROUTE_DEFAULT; 1790 pjmedia_aud_param param; 1791 1792 status = pjmedia_aud_dev_default_param(pjsua_var.cap_dev, ¶m); 1793 if (status != PJ_SUCCESS) { 1794 pjsua_perror(THIS_FILE, "Error retrieving default audio " 1795 "device parameters", status); 1796 return status; 1797 } 1798 1799 param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 1800 param.rec_id = pjsua_var.cap_dev; 1801 param.play_id = pjsua_var.play_dev; 1802 param.clock_rate = peer_info.clock_rate; 1803 param.samples_per_frame = peer_info.samples_per_frame; 1804 param.channel_count = peer_info.channel_count; 1805 param.bits_per_sample = peer_info.bits_per_sample; 1806 /* Latency setting */ 1807 param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY | 1808 PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 1809 param.input_latency_ms = pjsua_var.media_cfg.snd_rec_latency; 1810 param.output_latency_ms = pjsua_var.media_cfg.snd_play_latency; 1811 /* EC settings */ 1812 if (pjsua_var.media_cfg.ec_tail_len) { 1813 param.flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 1814 param.ec_enabled = PJ_TRUE; 1815 param.ec_tail_ms = pjsua_var.media_cfg.ec_tail_len; 1816 } else { 1817 param.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 1818 } 1819 /* Format */ 1820 param.flags |= (PJMEDIA_AUD_DEV_CAP_EXT_FORMAT | 1821 PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE); 1822 param.ext_fmt = peer_info.format; 1823 //param.plc = PJ_FALSE; 1824 param.out_route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT; 1805 1825 1806 status = open_snd_dev_ext(pjsua_var.cap_dev, pjsua_var.play_dev, 1807 peer_info.clock_rate, 1808 peer_info.channel_count, 1809 peer_info.samples_per_frame, 1810 &setting); 1826 status = open_snd_dev_ext(¶m); 1811 1827 if (status != PJ_SUCCESS) { 1812 1828 pjsua_perror(THIS_FILE, "Error opening sound device", status); … … 2307 2323 * Enum sound devices. 2308 2324 */ 2325 #if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 2326 PJ_DEF(pj_status_t) pjsua_enum_snd_devs( pjmedia_aud_dev_info info[], 2327 unsigned *count) 2328 { 2329 unsigned i, dev_count; 2330 2331 dev_count = pjmedia_aud_dev_count(); 2332 2333 if (dev_count > *count) dev_count = *count; 2334 2335 for (i=0; i<dev_count; ++i) { 2336 pj_status_t status; 2337 2338 status = pjmedia_aud_dev_get_info(i, &info[i]); 2339 if (status != PJ_SUCCESS) 2340 return status; 2341 } 2342 2343 *count = dev_count; 2344 2345 return PJ_SUCCESS; 2346 } 2347 #else /* PJMEDIA_AUDIO_API */ 2309 2348 PJ_DEF(pj_status_t) pjsua_enum_snd_devs( pjmedia_snd_dev_info info[], 2310 2349 unsigned *count) … … 2312 2351 unsigned i, dev_count; 2313 2352 2314 dev_count = pjmedia_ snd_get_dev_count();2353 dev_count = pjmedia_aud_dev_count(); 2315 2354 2316 2355 if (dev_count > *count) dev_count = *count; 2356 pj_bzero(info, dev_count * sizeof(pjmedia_snd_dev_info)); 2317 2357 2318 2358 for (i=0; i<dev_count; ++i) { 2319 const pjmedia_snd_dev_info *ci; 2320 2321 ci = pjmedia_snd_get_dev_info(i); 2322 pj_memcpy(&info[i], ci, sizeof(*ci)); 2359 pjmedia_aud_dev_info ai; 2360 pj_status_t status; 2361 2362 status = pjmedia_aud_dev_get_info(i, &ai); 2363 if (status != PJ_SUCCESS) 2364 return status; 2365 2366 strncpy(info[i].name, ai.name, sizeof(info[i].name)); 2367 info[i].name[sizeof(info[i].name)-1] = '\0'; 2368 info[i].input_count = ai.input_count; 2369 info[i].output_count = ai.output_count; 2370 info[i].default_samples_per_sec = ai.default_samples_per_sec; 2323 2371 } 2324 2372 … … 2327 2375 return PJ_SUCCESS; 2328 2376 } 2377 #endif 2378 2379 2329 2380 /* 2330 2381 * Select or change sound device. Application may call this function at … … 2335 2386 { 2336 2387 pjmedia_port *conf_port; 2337 const pjmedia_snd_dev_info *play_info; 2388 pjmedia_aud_dev_info play_info; 2389 pjmedia_aud_param param; 2338 2390 unsigned clock_rates[] = {0, 44100, 48000, 32000, 16000, 8000}; 2339 2391 unsigned selected_clock_rate = 0; 2340 2392 unsigned i; 2341 pjmedia_snd_stream *strm; 2342 pjmedia_snd_stream_info si; 2393 pjmedia_aud_stream *strm; 2343 2394 pj_str_t tmp; 2344 2395 pj_status_t status = -1; … … 2353 2404 2354 2405 /* Create memory pool for sound device. */ 2355 pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 4000, 4000);2406 pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 1000, 1000); 2356 2407 PJ_ASSERT_RETURN(pjsua_var.snd_pool, PJ_ENOMEM); 2357 2408 … … 2365 2416 pj_assert(conf_port != NULL); 2366 2417 2418 /* Create default parameters for the device */ 2419 status = pjmedia_aud_dev_default_param(capture_dev, ¶m); 2420 if (status != PJ_SUCCESS) { 2421 return status; 2422 } 2423 param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 2424 param.rec_id = capture_dev; 2425 param.play_id = playback_dev; 2426 param.channel_count = pjsua_var.media_cfg.channel_count; 2427 /* Latency settings */ 2428 param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY | 2429 PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 2430 param.input_latency_ms = pjsua_var.media_cfg.snd_rec_latency; 2431 param.output_latency_ms = pjsua_var.media_cfg.snd_play_latency; 2432 /* EC settings */ 2433 if (pjsua_var.media_cfg.ec_tail_len) { 2434 param.flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 2435 param.ec_enabled = PJ_TRUE; 2436 param.ec_tail_ms = pjsua_var.media_cfg.ec_tail_len; 2437 } else { 2438 param.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 2439 } 2440 2367 2441 /* Attempts to open the sound device with different clock rates */ 2368 2442 for (i=0; i<PJ_ARRAY_SIZE(clock_rates); ++i) { 2369 2443 char errmsg[PJ_ERR_MSG_SIZE]; 2370 unsigned samples_per_frame;2371 2444 2372 2445 PJ_LOG(4,(THIS_FILE, … … 2374 2447 "@%d Hz", clock_rates[i])); 2375 2448 2376 samples_per_frame = clock_rates[i] * 2377 pjsua_var.media_cfg.audio_frame_ptime * 2378 pjsua_var.media_cfg.channel_count / 1000; 2449 param.clock_rate = clock_rates[i]; 2450 param.samples_per_frame = clock_rates[i] * 2451 pjsua_var.media_cfg.audio_frame_ptime * 2452 pjsua_var.media_cfg.channel_count / 1000; 2379 2453 2380 2454 /* Create the sound device. Sound port will start immediately. */ 2381 status = pjmedia_snd_port_create(pjsua_var.snd_pool, capture_dev, 2382 playback_dev, 2383 clock_rates[i], 2384 pjsua_var.media_cfg.channel_count, 2385 samples_per_frame, 2386 16, 0, &pjsua_var.snd_port); 2455 status = pjmedia_snd_port_create2(pjsua_var.snd_pool, ¶m, 2456 &pjsua_var.snd_port); 2387 2457 2388 2458 if (status == PJ_SUCCESS) { … … 2438 2508 } 2439 2509 2440 /* Set AEC */2441 pjmedia_snd_port_set_ec( pjsua_var.snd_port, pjsua_var.snd_pool,2442 pjsua_var.media_cfg.ec_tail_len,2443 pjsua_var.media_cfg.ec_options);2444 2445 2510 /* Connect sound port to the bridge */ 2446 2511 status = pjmedia_snd_port_connect(pjsua_var.snd_port, … … 2460 2525 /* Update sound device name. */ 2461 2526 strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 2462 pjmedia_ snd_stream_get_info(strm, &si);2463 p lay_info = pjmedia_snd_get_dev_info(si.rec_id);2464 2465 if ( si.clock_rate != pjsua_var.media_cfg.clock_rate) {2527 pjmedia_aud_stream_get_param(strm, ¶m); 2528 pjmedia_aud_dev_get_info(param.play_id, &play_info); 2529 2530 if (param.clock_rate != pjsua_var.media_cfg.clock_rate) { 2466 2531 char tmp_buf[128]; 2467 2532 int tmp_buf_len = sizeof(tmp_buf); 2468 2533 2469 2534 tmp_buf_len = pj_ansi_snprintf(tmp_buf, sizeof(tmp_buf)-1, "%s (%dKHz)", 2470 play_info ->name, si.clock_rate/1000);2535 play_info.name, param.clock_rate/1000); 2471 2536 pj_strset(&tmp, tmp_buf, tmp_buf_len); 2472 2537 pjmedia_conf_set_port0_name(pjsua_var.mconf, &tmp); 2473 2538 } else { 2474 2539 pjmedia_conf_set_port0_name(pjsua_var.mconf, 2475 pj_cstr(&tmp, play_info ->name));2540 pj_cstr(&tmp, play_info.name)); 2476 2541 } 2477 2542 … … 2580 2645 } 2581 2646 2582 /*2583 * Header for specific Symbian APS audio routing.2584 */2585 #include <pjmedia/symbian_sound_aps.h>2586 2587 /*2588 * Set sound device route.2589 */2590 PJ_DEF(pj_status_t) pjsua_set_snd_route(pjmedia_snd_route route)2591 {2592 #if PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_SYMB_APS_SOUND2593 pjmedia_snd_stream *strm;2594 2595 if (!pjsua_var.snd_port)2596 return PJ_ENOTFOUND;2597 2598 strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port);2599 return pjmedia_snd_aps_set_route(strm, route);2600 #else2601 PJ_UNUSED_ARG(route);2602 return PJ_ENOTSUP;2603 #endif2604 }2605 2647 2606 2648 /*****************************************************************************
Note: See TracChangeset
for help on using the changeset viewer.