Ticket #438: delaybuf.patch
File delaybuf.patch, 6.1 KB (added by nanang, 17 years ago) |
---|
-
pjmedia/src/pjmedia/delaybuf.c
38 38 { 39 39 STATE_WAITING, 40 40 STATE_LEARNING, 41 STATE_PAUSED, 41 42 STATE_RUNNING 42 43 }; 43 44 … … 63 64 */ 64 65 #define SAFE_MARGIN 2 65 66 67 /* Delay buf will continuously detect activity of operations. If only one 68 * operation is called sequentially (bursting) for more than max_level + 69 * IDLE_MARGIN, delay buffer will assume the other operation is idle and 70 * delay buffer will automatically change its state to STATE_PAUSED. 71 */ 72 #define IDLE_MARGIN 2 73 66 74 /* 67 75 * Some experimental data (with SAFE_MARGIN=1): 68 76 * … … 97 105 unsigned buf_cnt; /**< Number of buffered samples */ 98 106 unsigned max_cnt; /**< Max number of buffered samples */ 99 107 100 struct { 101 unsigned level; /**< Burst level storage on learning */ 102 } op[2]; 108 unsigned level; /**< Burst level storage on learning */ 103 109 enum OP last_op; /**< Last op (GET or PUT) of learning*/ 104 110 unsigned state_count; /**< Counter of op cycles of learning*/ 105 111 106 112 unsigned max_level; /**< Learning result: burst level */ 107 113 108 114 pjmedia_wsola *wsola; /**< Drift handler */ 115 116 unsigned max_burst; /**< Maximum burst before media flow 117 is suspended */ 109 118 }; 110 119 111 120 PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool, … … 135 144 pj_ansi_strncpy(b->obj_name, name, PJ_MAX_OBJ_NAME-1); 136 145 b->samples_per_frame = samples_per_frame; 137 146 b->max_frames = max_frames; 147 b->max_burst = max_frames + IDLE_MARGIN; 138 148 139 149 status = pj_lock_create_recursive_mutex(pool, b->obj_name, 140 150 &b->lock); … … 145 155 pj_pool_zalloc(pool, samples_per_frame * max_frames * 146 156 sizeof(pj_int16_t)); 147 157 158 status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 159 PJMEDIA_WSOLA_NO_PLC, &b->wsola); 160 if (status != PJ_SUCCESS) 161 return status; 162 148 163 if (delay >= 0) { 164 /* Fixed delay */ 149 165 if (delay == 0) 150 166 delay = 1; 151 167 b->max_level = delay; 152 168 b->max_cnt = delay * samples_per_frame; 153 169 b->state = STATE_RUNNING; 154 170 } else { 171 /* Learning the best delay */ 155 172 b->max_cnt = max_frames * samples_per_frame; 156 b->last_op = OP_UNDEFINED;157 173 b->state = STATE_WAITING; 158 174 } 175 b->last_op = OP_UNDEFINED; 159 176 160 status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame,161 PJMEDIA_WSOLA_NO_PLC, &b->wsola);162 if (status != PJ_SUCCESS)163 return status;164 165 177 *p_b = b; 166 178 167 179 TRACE__((b->obj_name,"Delay buffer created")); … … 241 253 242 254 b->buf_cnt -= erase_cnt; 243 255 244 PJ_LOG(5,(b->obj_name," Successfully shrinking %d samples, "256 PJ_LOG(5,(b->obj_name,"Overflow, %d samples reduced, " 245 257 "buf_cnt=%d", erase_cnt, b->buf_cnt)); 246 258 } 247 259 … … 280 292 return; 281 293 } 282 294 283 shrink_buffer(b, old_max_cnt - new_max_cnt); 295 /* If current samples number is more than new max cnt, 296 * we need to shrink buffer first */ 297 if (b->buf_cnt > new_max_cnt) 298 shrink_buffer(b, b->buf_cnt - new_max_cnt); 284 299 285 300 /* Adjust buffer to accomodate the new max_cnt so the samples is secured. 286 301 * This is done by make get_pos = 0 … … 320 335 321 336 static void update(pjmedia_delay_buf *b, enum OP op) 322 337 { 323 enum OP other = (enum OP) !op;338 switch (b->state) { 324 339 325 switch (b->state) {326 340 case STATE_RUNNING: 341 if (op != b->last_op) { 342 b->last_op = op; 343 b->level = 1; 344 break; 345 } 346 ++b->level; 347 348 if (b->level > b->max_burst) { 349 b->state = STATE_PAUSED; 350 pjmedia_delay_buf_reset(b); 351 PJ_LOG(5,(b->obj_name, "Delay buffer suspended")); 352 } 353 327 354 break; 355 356 case STATE_PAUSED: 357 if (op != b->last_op) { 358 b->last_op = op; 359 b->level = 1; 360 b->state = STATE_RUNNING; 361 PJ_LOG(5,(b->obj_name, "Delay buffer resumed")); 362 } 363 break; 364 328 365 case STATE_WAITING: 329 ++b->op[op].level; 330 if (b->op[other].level != 0) { 331 ++b->state_count; 332 if (b->state_count == WAITING_COUNT) { 366 if (op != b->last_op) { 367 b->last_op = op; 368 if (++b->state_count == WAITING_COUNT) { 333 369 /* Start learning */ 334 370 pjmedia_delay_buf_learn(b); 371 break; 335 372 } 336 373 } 337 b->last_op = op;338 374 break; 375 339 376 case STATE_LEARNING: 340 ++b->op[op].level; 341 if (b->last_op == other) { 342 unsigned last_level = b->op[other].level; 343 if (last_level > b->max_level) 344 b->max_level = last_level; 345 b->op[other].level = 0; 346 b->state_count++; 347 if (b->state_count == LEARN_COUNT) { 377 if (op != b->last_op) { 378 b->last_op = op; 379 if (b->level > b->max_level) 380 b->max_level = b->level; 381 b->level = 1; 382 383 if (++b->state_count == LEARN_COUNT) { 348 384 /* give SAFE_MARGIN compensation for added stability */ 349 385 b->max_level += SAFE_MARGIN; 386 b->max_burst = b->max_level + IDLE_MARGIN; 350 387 351 388 /* buffer not enough! */ 352 389 if (b->max_level > b->max_frames) { … … 366 403 PJ_LOG(4,(b->obj_name,"Delay buffer start running, level=%u", 367 404 b->max_level)); 368 405 } 406 407 break; 369 408 } 370 b->last_op = op; 409 410 ++b->level; 371 411 break; 372 412 } 373 413 … … 391 431 return status; 392 432 } 393 433 434 if (b->state == STATE_PAUSED) { 435 pj_lock_release(b->lock); 436 return PJ_SUCCESS; 437 } 438 394 439 /* Overflow checking */ 395 440 if (b->buf_cnt + b->samples_per_frame > b->max_cnt) 396 441 { … … 434 479 435 480 update(b, OP_GET); 436 481 482 if (b->state == STATE_PAUSED) { 483 pjmedia_zero_samples(frame, b->samples_per_frame); 484 pj_lock_release(b->lock); 485 return PJ_SUCCESS; 486 } 487 437 488 /* Starvation checking */ 438 489 if (b->buf_cnt < b->samples_per_frame) { 439 490 … … 504 555 pj_lock_acquire(b->lock); 505 556 506 557 b->last_op = OP_UNDEFINED; 507 b-> op[OP_GET].level = b->op[OP_PUT].level = 0;558 b->level = 1; 508 559 b->state = STATE_LEARNING; 509 560 b->state_count = 0; 510 b->max_level = 0;561 b->max_level = 1; 511 562 b->max_cnt = b->max_frames * b->samples_per_frame; 512 563 513 564 pjmedia_delay_buf_reset(b); … … 532 583 533 584 pj_lock_release(b->lock); 534 585 535 PJ_LOG(5,(b->obj_name,"Delay buffer resetted"));586 PJ_LOG(5,(b->obj_name,"Delay buffer is reset")); 536 587 537 588 return PJ_SUCCESS; 538 589 }