- Timestamp:
- Apr 28, 2006 1:00:26 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
r411 r415 20 20 #include <pjmedia/errno.h> 21 21 #include <pj/assert.h> 22 #include <pj/log.h> 23 #include <pj/rand.h> 22 24 #include <pj/string.h> /* pj_memset() */ 25 26 27 //#define SIMULATE_LOST_PCT 10 28 29 30 #define THIS_FILE "sound_port.c" 31 32 enum 33 { 34 PJMEDIA_PLC_ENABLED = 1, 35 }; 36 37 #define DEFAULT_OPTIONS PJMEDIA_PLC_ENABLED 38 39 23 40 24 41 struct pjmedia_snd_port … … 29 46 pjmedia_dir dir; 30 47 pjmedia_port *port; 48 unsigned options; 49 50 void *last_frame; 51 unsigned last_frame_size; 52 unsigned last_replay_count; 31 53 32 54 unsigned clock_rate; … … 74 96 pj_assert(frame.size == size); 75 97 98 #ifdef SIMULATE_LOST_PCT 99 /* Simulate packet lost */ 100 if (pj_rand() % 100 < SIMULATE_LOST_PCT) { 101 PJ_LOG(4,(THIS_FILE, "Frame dropped")); 102 goto no_frame; 103 } 104 #endif 105 106 /* Keep frame if PLC is enabled. */ 107 if (snd_port->options & PJMEDIA_PLC_ENABLED) { 108 /* Must have the same length as last_frame_size */ 109 pj_assert(frame.size == snd_port->last_frame_size); 110 111 /* Copy frame to last_frame */ 112 pj_memcpy(snd_port->last_frame, output, snd_port->last_frame_size); 113 114 snd_port->last_replay_count = 0; 115 } 116 76 117 return PJ_SUCCESS; 77 118 78 119 no_frame: 79 pj_memset(output, 0, size); 120 121 /* Replay last frame if PLC is enabled */ 122 if ((snd_port->options & PJMEDIA_PLC_ENABLED) && 123 snd_port->last_replay_count < 8) 124 { 125 126 /* Must have the same length as last_frame_size */ 127 pj_assert(size == snd_port->last_frame_size); 128 129 /* Replay last frame */ 130 pj_memcpy(output, snd_port->last_frame, snd_port->last_frame_size); 131 132 /* Reduce replay frame signal level to half */ 133 if (snd_port->bits_per_sample == 16) { 134 unsigned i, count; 135 pj_int16_t *samp; 136 137 count = snd_port->last_frame_size / 2; 138 samp = (pj_int16_t *) snd_port->last_frame; 139 140 for (i=0; i<count; ++i) 141 samp[i] = (pj_int16_t) (samp[i] >> 2); 142 143 } 144 145 #ifdef SIMULATE_LOST_PCT 146 PJ_LOG(4,(THIS_FILE, "Frame replayed")); 147 #endif 148 149 ++snd_port->last_replay_count; 150 151 } else { 152 153 /* Just zero the frame */ 154 pj_memset(output, 0, size); 155 156 } 157 158 80 159 return PJ_SUCCESS; 81 160 } … … 119 198 * This may be called even when the sound stream has already been started. 120 199 */ 121 static pj_status_t start_sound_device( pjmedia_snd_port *snd_port ) 200 static pj_status_t start_sound_device( pj_pool_t *pool, 201 pjmedia_snd_port *snd_port ) 122 202 { 123 203 pj_status_t status; … … 167 247 return status; 168 248 249 250 /* If we have player components, allocate buffer to save the last 251 * frame played to the speaker. The last frame is used for packet 252 * lost concealment (PLC) algorithm. 253 */ 254 if ((snd_port->dir & PJMEDIA_DIR_PLAYBACK) && 255 (snd_port->options & PJMEDIA_PLC_ENABLED)) 256 { 257 258 snd_port->last_frame_size = snd_port->samples_per_frame * 259 snd_port->channel_count * 260 snd_port->bits_per_sample / 8; 261 snd_port->last_frame = pj_pool_zalloc(pool, 262 snd_port->last_frame_size); 263 } 264 169 265 /* Start sound stream. */ 170 266 status = pjmedia_snd_stream_start(snd_port->snd_stream); … … 212 308 213 309 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 214 PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);215 310 216 311 snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port)); … … 220 315 snd_port->play_id = play_id; 221 316 snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 317 snd_port->options = options | DEFAULT_OPTIONS; 222 318 snd_port->clock_rate = clock_rate; 223 319 snd_port->channel_count = channel_count; … … 227 323 *p_port = snd_port; 228 324 325 229 326 /* Start sound device immediately. 230 327 * If there's no port connected, the sound callback will return 231 328 * empty signal. 232 329 */ 233 return start_sound_device( snd_port );330 return start_sound_device( pool, snd_port ); 234 331 235 332 } … … 250 347 251 348 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 252 PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);253 349 254 350 snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port)); … … 257 353 snd_port->rec_id = dev_id; 258 354 snd_port->dir = PJMEDIA_DIR_CAPTURE; 355 snd_port->options = options | DEFAULT_OPTIONS; 259 356 snd_port->clock_rate = clock_rate; 260 357 snd_port->channel_count = channel_count; … … 268 365 * empty signal. 269 366 */ 270 return start_sound_device( snd_port );367 return start_sound_device( pool, snd_port ); 271 368 } 272 369 … … 287 384 288 385 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 289 PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);290 386 291 387 snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port)); … … 294 390 snd_port->play_id = dev_id; 295 391 snd_port->dir = PJMEDIA_DIR_PLAYBACK; 392 snd_port->options = options | DEFAULT_OPTIONS; 296 393 snd_port->clock_rate = clock_rate; 297 394 snd_port->channel_count = channel_count; … … 305 402 * empty signal. 306 403 */ 307 return start_sound_device( snd_port );404 return start_sound_device( pool, snd_port ); 308 405 } 309 406
Note: See TracChangeset
for help on using the changeset viewer.