- Timestamp:
- Feb 4, 2008 11:52:43 PM (17 years ago)
- Location:
- pjproject/branches/projects/jbuf2/pjmedia
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/jbuf2/pjmedia/include/pjmedia/jbuf2.h
r1775 r1778 56 56 { 57 57 PJMEDIA_JB_PH_IDLE = 0, /**< No activity in PUT/GET or both */ 58 PJMEDIA_JB_PH_LEARNING = 1, /**< Normal encoded frame*/59 PJMEDIA_JB_PH_RUNNING = 2, /**< Normal PCM frame*/58 PJMEDIA_JB_PH_LEARNING = 1, /**< Learning */ 59 PJMEDIA_JB_PH_RUNNING = 2, /**< Running */ 60 60 } pjmedia_jb2_phase; 61 61 … … 137 137 138 138 /** 139 * This structure describes jitter buffer callback 140 */ 141 typedef struct pjmedia_jb2_cb 142 { 143 pj_status_t (*decode) (pjmedia_jb2_frame *frame, void *userdata); 144 pj_status_t (*plc) (pjmedia_jb2_frame *frame, void *userdata); 145 pj_status_t (*cng) (pjmedia_jb2_frame *frame, void *userdata); 146 void *user_data; 147 } pjmedia_jb2_cb; 148 149 150 /** 139 151 * This structure describes jitter buffer current status. 140 152 */ … … 162 174 163 175 } pjmedia_jb2_setting; 164 165 typedef struct pjmedia_jb2_cb166 {167 pj_status_t (*decode) (pjmedia_jb2_frame *frame);168 pj_status_t (*plc) (pjmedia_jb2_frame *frame);169 pj_status_t (*cng) (pjmedia_jb2_frame *frame);170 } pjmedia_jb2_cb;171 176 172 177 -
pjproject/branches/projects/jbuf2/pjmedia/src/pjmedia/jbuf2.c
r1775 r1778 42 42 /* Max frames specifies maximum frames allowed to be allocated. 43 43 */ 44 #define MAX_FRAMES 10044 #define MAX_FRAMES 20 45 45 46 46 /* History constants specify entries number of history, … … 133 133 PJ_DECL_LIST_MEMBER(struct jb_frame_list); 134 134 pjmedia_jb2_frame frame; 135 void *orig_buffer; 135 136 } jb_frame_list; 136 137 … … 168 169 pjmedia_jb2_state state; 169 170 170 /* last get frame*/171 /* frame history */ 171 172 pjmedia_jb2_frame last_frame_out; 173 pjmedia_jb2_frame last_frame_cn; 172 174 173 175 /* state update */ … … 183 185 }; 184 186 185 static void init_jb(pjmedia_jb2_t *jb);186 187 static void update_state(pjmedia_jb2_t *jb, pj_bool_t on_get); 187 188 static void compensate_drift(pjmedia_jb2_t *jb); … … 201 202 pj_list_erase(f); 202 203 } else if (jb->state.frame_cnt >= jb->setting.max_frames) { 203 TRACE__((THIS_FILE, "Frame numbers(%d) exceeds max(%d)!", 204 jb->state.frame_cnt, jb->setting.max_frames)); 204 TRACE__((THIS_FILE, "Frame numbers %d(=%d?) exceeds max(%d)!", 205 jb->state.frame_cnt, pj_list_size(&jb->frames), 206 jb->setting.max_frames)); 205 207 return NULL; 206 208 } else { … … 210 212 return NULL; 211 213 } 212 f->frame.buffer = pj_pool_alloc(jb->pool, jb->setting.frame_size); 213 if (NULL == f->frame.buffer) return NULL; 214 f->orig_buffer = pj_pool_alloc(jb->pool, jb->setting.frame_size); 215 f->frame.buffer = f->orig_buffer; 216 if (NULL == f->frame.buffer) { 217 TRACE__((THIS_FILE, "Failed to allocate frame buffer!")); 218 return NULL; 219 } 214 220 ++jb->state.frame_cnt; 215 221 } … … 223 229 pj_list_erase(f); 224 230 pj_list_push_back(&jb->frames_pool, f); 231 f->frame.buffer = f->orig_buffer; 225 232 } 226 233 … … 327 334 } 328 335 329 static voidjb_vbuf_expand(jb_vbuf *buf, unsigned size)336 static pj_bool_t jb_vbuf_expand(jb_vbuf *buf, unsigned size) 330 337 { 331 338 jb_frame_list *f; 332 339 int step; 340 int orig_buf_cnt = buf->cnt; 333 341 334 342 pj_assert(buf); … … 338 346 339 347 f = alloc_frame(buf->jb); 348 if (!f) { 349 unsigned i; 350 /* Rollback */ 351 for (i=orig_buf_cnt; i<buf->cnt; ++i) { 352 buf->size -= buf->f[i]->frame.size; 353 buf->jb->state.cur_size -= buf->f[i]->frame.size/2; 354 release_frame(buf->jb, buf->f[i]); 355 } 356 buf->cnt = orig_buf_cnt; 357 return PJ_FALSE; 358 } 359 340 360 f->frame.pt = buf->f[buf->cnt-1]->frame.pt; 341 361 f->frame.seq = buf->f[buf->cnt-1]->frame.seq; … … 353 373 size -= step; 354 374 } 355 } 356 357 static void init_jb(pjmedia_jb2_t *jb) 375 return PJ_TRUE; 376 } 377 378 /* Decode consecutive undecoded frames. */ 379 static pj_status_t decode_frames(pjmedia_jb2_t *jb, jb_frame_list* start, 380 int max) 381 { 382 jb_frame_list* tmp = start; 383 pj_status_t status; 384 385 PJ_ASSERT_RETURN(jb && start && jb->cb.decode, PJ_EINVAL); 386 387 /* Decoded already */ 388 if (start->frame.type != PJMEDIA_JB_FT_NORMAL_FRAME) 389 return PJ_SUCCESS; 390 391 /* In the beginning, make sure it is sequenced from last_frame_out, 392 * otherwise we cannot detect packet loss. 393 */ 394 if (start->prev == &jb->frames && /* beginning */ 395 jb->last_frame_out.seq && /* last out defined */ 396 start->frame.seq > jb->last_frame_out.seq && /* bad sequence */ 397 (start->frame.seq - jb->last_frame_out.seq > 1)) 398 { 399 return PJ_SUCCESS; 400 } 401 402 /* Not in the beginning, make sure previous frame is sequenced & decoded */ 403 if (start->prev != &jb->frames && /* not beginning */ 404 ((start->frame.seq > start->prev->frame.seq && /* bad sequence */ 405 (start->frame.seq - start->prev->frame.seq > 1)) || 406 start->prev->frame.type == PJMEDIA_JB_FT_NORMAL_FRAME)) /* undecoded */ 407 { 408 return PJ_SUCCESS; 409 } 410 411 do { 412 status = jb->cb.decode(&tmp->frame, jb->cb.user_data); 413 414 if (status != PJ_SUCCESS) { 415 TRACE__((THIS_FILE,"Failed to decode frame!")); 416 release_frame(jb, tmp); 417 return PJMEDIA_JB2_EFAILDECODE; 418 } 419 tmp->frame.type = PJMEDIA_JB_FT_NORMAL_RAW_FRAME; 420 tmp = tmp->next; 421 422 jb->state.cur_size += jb->setting.samples_per_frame; 423 424 } while (tmp != &jb->frames && 425 tmp->frame.type == PJMEDIA_JB_FT_NORMAL_FRAME && 426 (tmp->frame.ts - tmp->prev->frame.ts <= 427 jb->setting.samples_per_frame) && 428 (!max || --max > 0)); 429 430 return PJ_SUCCESS; 431 } 432 433 PJ_DEF(pj_status_t) pjmedia_jb2_create( pj_pool_t *pool, 434 const pj_str_t *name, 435 const pjmedia_jb2_setting *setting, 436 const pjmedia_jb2_cb *cb, 437 pjmedia_jb2_t **p_jb ) 438 { 439 pjmedia_jb2_t *jb; 440 441 PJ_ASSERT_RETURN(pool && setting && cb && p_jb, PJ_EINVAL); 442 443 if (setting->max_frames > MAX_FRAMES) { 444 PJ_LOG(4,(THIS_FILE, "Max frames requested is too big!")); 445 return PJ_EINVAL; 446 } 447 448 jb = PJ_POOL_ZALLOC_T(pool, pjmedia_jb2_t); 449 jb->pool = pool; 450 451 if (name) 452 pj_strdup_with_null(jb->pool, &jb->name, name); 453 else 454 pj_strdup2_with_null(pool, &jb->name, "jb2"); 455 456 pj_list_init(&jb->frames_pool); 457 pj_list_init(&jb->frames); 458 459 jb->setting = *setting; 460 jb->cb = *cb; 461 462 /* Init CN frame */ 463 pj_bzero(&jb->last_frame_cn, sizeof(jb->last_frame_cn)); 464 jb->last_frame_cn.buffer = pj_pool_zalloc(pool, setting->frame_size); 465 jb->last_frame_cn.size = 0; 466 467 if (!jb->setting.max_frames) 468 jb->setting.max_frames = MAX_FRAMES; 469 470 pjmedia_jb2_reset(jb); 471 472 *p_jb = jb; 473 474 return PJ_SUCCESS; 475 } 476 477 PJ_DEF(pj_status_t) pjmedia_jb2_destroy(pjmedia_jb2_t *jb) 478 { 479 pjmedia_jb2_stat jb_stat; 480 pjmedia_jb2_state jb_state; 481 482 PJ_ASSERT_RETURN(jb, PJ_EINVAL); 483 484 pjmedia_jb2_get_state(jb, &jb_state); 485 PJ_LOG(5, (jb->name.ptr, "JB state:")); 486 PJ_LOG(5, (jb->name.ptr, "Drift\t = %5d/%d", jb_state.drift, 487 jb_state.drift_span)); 488 PJ_LOG(5, (jb->name.ptr, "Level\t = %5d ticks", jb_state.level)); 489 PJ_LOG(5, (jb->name.ptr, "Size\t = %5d samples", jb_state.cur_size)); 490 PJ_LOG(5, (jb->name.ptr, "Opt.Size\t = %5d samples", jb_state.opt_size)); 491 PJ_LOG(5, (jb->name.ptr, "Pool\t = %5d frames", jb_state.frame_cnt)); 492 493 pjmedia_jb2_get_stat(jb, &jb_stat); 494 PJ_LOG(5, (jb->name.ptr, "JB statistic:")); 495 PJ_LOG(5, (jb->name.ptr, "in \t = %5d frames", jb_stat.in)); 496 PJ_LOG(5, (jb->name.ptr, "out\t = %5d frames", jb_stat.out)); 497 PJ_LOG(5, (jb->name.ptr, "lost\t = %5d frames", jb_stat.lost)); 498 PJ_LOG(5, (jb->name.ptr, "late\t = %5d frames", jb_stat.late)); 499 PJ_LOG(5, (jb->name.ptr, "ooo\t = %5d frames", jb_stat.ooo)); 500 PJ_LOG(5, (jb->name.ptr, "empty\t = %5d times", jb_stat.empty)); 501 PJ_LOG(5, (jb->name.ptr, "full\t = %5d times", jb_stat.full)); 502 PJ_LOG(5, (jb->name.ptr, "max_size\t = %5d samples", jb_stat.max_size)); 503 PJ_LOG(5, (jb->name.ptr, "max_level\t = %5d", jb_stat.max_level)); 504 PJ_LOG(5, (jb->name.ptr, "max_comp\t = %5d samples", jb_stat.max_comp)); 505 PJ_LOG(5, (jb->name.ptr, "max_drift\t = %5d/%d", jb_stat.max_drift, 506 jb_stat.max_drift_span)); 507 508 return PJ_SUCCESS; 509 } 510 511 PJ_DEF(pj_status_t) pjmedia_jb2_reset(pjmedia_jb2_t *jb) 358 512 { 359 513 jb_frame_list *f, *next_f; 360 514 int i; 515 516 PJ_ASSERT_RETURN(jb, PJ_EINVAL); 517 518 /* Reset tick */ 519 jb->tick = 0; 361 520 362 521 /* Reset frames */ … … 369 528 pj_list_init(&jb->frames); 370 529 371 /* Init last frame out*/530 /* Init frame history */ 372 531 pj_bzero(&jb->last_frame_out, sizeof(jb->last_frame_out)); 373 532 … … 400 559 jb->drift_state.acc_mod_span = 1; 401 560 402 /* Inform user about JB (re)init */403 }404 405 /* Decode all consecutive undecoded frames. */406 static pj_status_t decode_frames(pjmedia_jb2_t *jb, jb_frame_list* start,407 int max)408 {409 jb_frame_list* tmp = start;410 pj_status_t status;411 412 PJ_ASSERT_RETURN(jb && start && jb->cb.decode, PJ_EINVAL);413 414 /* Decoded already */415 if (start->frame.type != PJMEDIA_JB_FT_NORMAL_FRAME)416 return PJ_SUCCESS;417 418 do {419 status = jb->cb.decode(&tmp->frame);420 421 pj_assert(tmp->frame.size == jb->setting.frame_size);422 423 if (status != PJ_SUCCESS) {424 TRACE__((THIS_FILE,"Failed to decode frame!"));425 return PJMEDIA_JB2_EFAILDECODE;426 }427 tmp->frame.type = PJMEDIA_JB_FT_NORMAL_RAW_FRAME;428 tmp = tmp->next;429 430 jb->state.cur_size += jb->setting.samples_per_frame;431 432 } while (tmp != &jb->frames &&433 tmp->frame.type == PJMEDIA_JB_FT_NORMAL_FRAME &&434 (tmp->frame.ts - tmp->prev->frame.ts ==435 jb->setting.samples_per_frame) &&436 (!max || --max > 0));437 438 return PJ_SUCCESS;439 }440 441 PJ_DEF(pj_status_t) pjmedia_jb2_create( pj_pool_t *pool,442 const pj_str_t *name,443 const pjmedia_jb2_setting *setting,444 const pjmedia_jb2_cb *cb,445 pjmedia_jb2_t **p_jb )446 {447 pjmedia_jb2_t *jb;448 449 PJ_ASSERT_RETURN(pool && setting && cb && p_jb, PJ_EINVAL);450 451 if (setting->max_frames > MAX_FRAMES) {452 PJ_LOG(4,(THIS_FILE, "Max frames requested is too big!"));453 return PJ_EINVAL;454 }455 456 jb = PJ_POOL_ZALLOC_T(pool, pjmedia_jb2_t);457 jb->pool = pool;458 459 if (name)460 pj_strdup_with_null(jb->pool, &jb->name, name);461 else462 pj_strdup2(pool, &jb->name, "jb2");463 464 pj_list_init(&jb->frames_pool);465 pj_list_init(&jb->frames);466 467 jb->setting = *setting;468 jb->cb = *cb;469 470 pjmedia_jb2_reset(jb);471 472 *p_jb = jb;473 474 return PJ_SUCCESS;475 }476 477 PJ_DEF(pj_status_t) pjmedia_jb2_destroy(pjmedia_jb2_t *jb)478 {479 PJ_UNUSED_ARG(jb);480 PJ_ASSERT_RETURN(jb, PJ_EINVAL);481 482 return PJ_SUCCESS;483 }484 485 PJ_DEF(pj_status_t) pjmedia_jb2_reset(pjmedia_jb2_t *jb)486 {487 PJ_ASSERT_RETURN(jb, PJ_EINVAL);488 489 /* Reset tick */490 jb->tick = 0;491 492 /* Reset statistic */493 pj_bzero(&jb->stat, sizeof(pjmedia_jb2_stat));494 495 if (!jb->setting.max_frames)496 jb->setting.max_frames = MAX_FRAMES;497 498 /* Init buffers */499 init_jb(jb);500 501 561 return PJ_SUCCESS; 502 562 } … … 593 653 if (tmp->frame.type == PJMEDIA_JB_FT_NORMAL_RAW_FRAME) { 594 654 jb->state.cur_size += jb->setting.samples_per_frame; 595 } 596 else if (tmp->prev != &jb->frames && 597 (tmp->frame.ts - tmp->prev->frame.ts == 598 jb->setting.samples_per_frame) && 599 tmp->prev->frame.type != PJMEDIA_JB_FT_NORMAL_FRAME) 600 { 655 } else { 601 656 status = decode_frames(jb, tmp, 0); 602 657 } … … 620 675 621 676 if (jb->state.phase == PJMEDIA_JB_PH_IDLE) 622 goto ON_RETURN;677 goto RETURN_EMPTY_FRAME; 623 678 624 679 /* Check first frame */ … … 632 687 jb_frame_list *tmp_plc; 633 688 689 ++jb->stat.in; 690 ++jb->stat.lost; 691 634 692 /* Generate PLC frame*/ 635 693 tmp_plc = alloc_frame(jb); 636 if (!tmp_plc) return PJ_ENOMEM; 637 638 /* Fill buffer with PLC */ 639 if (jb->cb.plc) { 640 status = jb->cb.plc(&tmp_plc->frame); 641 if (status != PJ_SUCCESS) 642 return status; 694 if (!tmp_plc) { 695 status = PJ_ENOMEM; 696 jb->last_frame_out = tmp->frame; 697 release_frame(jb, tmp); 698 goto RETURN_EMPTY_FRAME; 643 699 } 644 645 tmp_plc->frame.type = PJMEDIA_JB_FT_INTERP_RAW_FRAME;646 700 tmp_plc->frame.pt = jb->last_frame_out.pt; 647 701 tmp_plc->frame.seq = jb->last_frame_out.seq + 1; … … 649 703 tmp_plc->frame.ts = jb->last_frame_out.ts + 650 704 jb->setting.samples_per_frame; 651 652 705 pj_list_push_front(&jb->frames, tmp_plc); 653 ++jb->stat.in; 654 ++jb->stat.lost; 655 TRACE__((THIS_FILE,"Frame lost!")); 706 707 /* Fill buffer with PLC */ 708 if (jb->cb.plc) { 709 status = jb->cb.plc(&tmp_plc->frame, jb->cb.user_data); 710 if (status != PJ_SUCCESS) { 711 TRACE__((THIS_FILE,"PLC failed")); 712 jb->last_frame_out = tmp->frame; 713 release_frame(jb, tmp_plc); 714 goto RETURN_EMPTY_FRAME; 715 } 716 tmp_plc->frame.type = PJMEDIA_JB_FT_INTERP_RAW_FRAME; 717 718 TRACE__((THIS_FILE,"Lost frame recovered!")); 719 } else { 720 pj_bzero(tmp_plc->frame.buffer, jb->setting.frame_size); 721 tmp_plc->frame.type = PJMEDIA_JB_FT_NULL_FRAME; 722 TRACE__((THIS_FILE,"Lost frame!")); 723 } 656 724 657 725 jb->state.cur_size += jb->setting.samples_per_frame; 658 726 } 659 727 660 /* Or there is CN packet */ 661 else if (tmp->frame.pt == PT_CN) { 662 unsigned cn_samples; 663 jb_frame_list *tmp_cn, *pos; 664 665 /* Generate CN frames */ 666 if (jb->last_frame_out.ts) 667 cn_samples = tmp->frame.ts - jb->last_frame_out.ts; 728 /* Or there is CN packet/jumping timestamp */ 729 else if (tmp->frame.pt == PT_CN || (jb->last_frame_out.ts && 730 (tmp->frame.ts - jb->last_frame_out.ts > 731 jb->setting.samples_per_frame))) 732 { 733 unsigned cn_frames; 734 735 /* Count CN frames */ 736 if (jb->last_frame_out.ts && tmp->frame.ts > jb->last_frame_out.ts) 737 cn_frames = (tmp->frame.ts - jb->last_frame_out.ts) / 738 jb->setting.samples_per_frame; 668 739 else 669 cn_samples = jb->setting.samples_per_frame; 670 671 pos = &jb->frames; 672 for (i = 0; i<cn_samples; i += jb->setting.samples_per_frame) 673 { 674 tmp_cn = alloc_frame(jb); 675 if (!tmp_cn) return PJ_ENOMEM; 676 677 /* Fill buffer with CNG */ 678 status = jb->cb.cng(&tmp_cn->frame); 679 if (status != PJ_SUCCESS) 680 return status; 681 682 tmp_cn->frame.type = PJMEDIA_JB_FT_INTERP_RAW_FRAME; 683 tmp_cn->frame.pt = jb->last_frame_out.pt; 684 tmp_cn->frame.seq = tmp->frame.seq; 685 tmp_cn->frame.size = jb->setting.frame_size; 686 tmp_cn->frame.ts = jb->last_frame_out.seq + i + 687 jb->setting.samples_per_frame; 688 689 pj_list_insert_after(pos, tmp_cn); 690 pos = tmp_cn; 691 jb->state.cur_size += jb->setting.samples_per_frame; 740 cn_frames = 1; 741 742 jb->last_frame_out = tmp->frame; 743 744 if (tmp->frame.pt == PT_CN) { 745 /* Save CN info */ 746 jb->last_frame_cn.size = tmp->frame.size; 747 pj_memcpy(jb->last_frame_cn.buffer, tmp->frame.buffer, 748 tmp->frame.size); 749 jb->stat.in += cn_frames; 750 release_frame(jb, tmp); 751 } else { 752 jb->stat.in += cn_frames - 1; 753 status = decode_frames(jb, tmp, 2); 692 754 } 693 694 /* Discard this CN frame, replaced by real PCM frames */695 release_frame(jb, tmp);696 697 /* Update statistic */698 jb->stat.in += cn_samples - 1;699 755 } 700 756 … … 705 761 */ 706 762 status = decode_frames(jb, tmp, 2); 707 if (status != PJ_SUCCESS) 708 return status; 709 } 710 } 711 712 /* Compensate drift right before any frame fetched */ 713 compensate_drift(jb); 763 } 764 } 714 765 715 766 /* Consistency checking, when cur_size!=0, there should be frame(s) 716 767 * in the JB frames list. 717 768 */ 718 pj_assert((jb->state.cur_size ==0) ||769 pj_assert((jb->state.cur_size == 0) || 719 770 (!pj_list_empty(&jb->frames) && jb->state.cur_size)); 720 771 721 772 /* Not enough samples in PCM buffer */ 722 if (jb->state.cur_size < jb->setting.samples_per_frame) {773 if (jb->state.cur_size == 0) { 723 774 if (jb->state.phase != PJMEDIA_JB_PH_LEARNING) { 724 TRACE__((THIS_FILE,"Not enough PCM samples (%d)!", 725 jb->state.cur_size)); 775 TRACE__((THIS_FILE,"JB empty!")); 726 776 ++jb->stat.empty; 727 777 } 778 728 779 goto RETURN_EMPTY_FRAME; 729 780 } 781 782 /* Compensate drift right before any frame fetched */ 783 compensate_drift(jb); 730 784 731 785 /* Prepare the requested frame */ … … 739 793 740 794 /* Fill frame buffer, make sure size == setting.frame_size */ 741 while (f->size < jb->setting.frame_size ) {795 while (f->size < jb->setting.frame_size && jb->state.cur_size) { 742 796 next_frm = tmp->next; 743 797 … … 754 808 pj_memcpy((pj_int8_t*)f->buffer + f->size, tmp->frame.buffer, i); 755 809 tmp->frame.size -= i; 756 757 /* Shift the buffer, don't shift the pointer! */ 758 pj_memmove(tmp->frame.buffer, (pj_int8_t*)tmp->frame.buffer + i, 759 tmp->frame.size); 760 } 810 tmp->frame.buffer = (pj_int8_t*)tmp->frame.buffer + i; 811 } 812 813 pj_assert(jb->state.cur_size >= (i/ 814 (jb->setting.frame_size/jb->setting.samples_per_frame))); 815 jb->state.cur_size -= i/ 816 (jb->setting.frame_size/jb->setting.samples_per_frame); 761 817 762 818 f->size += i; … … 764 820 } 765 821 766 jb->state.cur_size -= jb->setting.samples_per_frame; 822 if (jb->tick % 100 == 0) { 823 pjmedia_jb2_state jb_state; 824 825 pjmedia_jb2_get_state(jb, &jb_state); 826 PJ_LOG(5, (jb->name.ptr, "JB state:")); 827 PJ_LOG(5, (jb->name.ptr, "Drift\t = %5d/%d", jb_state.drift, 828 jb_state.drift_span)); 829 PJ_LOG(5, (jb->name.ptr, "Level\t = %5d ticks", jb_state.level)); 830 PJ_LOG(5, (jb->name.ptr, "Size\t = %5d samples", jb_state.cur_size)); 831 PJ_LOG(5, (jb->name.ptr, "Opt.Size\t = %5d samples", jb_state.opt_size)); 832 PJ_LOG(5, (jb->name.ptr, "Pool\t = %5d frames", jb_state.frame_cnt)); 833 } 767 834 768 835 /* JB still learning the level */ 769 if (jb->state.phase == PJMEDIA_JB_PH_LEARNING)770 goto RETURN_EMPTY_FRAME;836 //if (jb->state.phase == PJMEDIA_JB_PH_LEARNING) 837 //goto RETURN_EMPTY_FRAME; 771 838 772 839 goto ON_RETURN; … … 774 841 RETURN_EMPTY_FRAME: 775 842 776 f->type = PJMEDIA_JB_FT_NULL_FRAME;777 843 f->pt = jb->last_frame_out.pt; 778 844 f->seq = jb->last_frame_out.seq; 779 f->size = jb->setting.frame_size;780 845 f->ts = jb->last_frame_out.ts; 781 pj_bzero(f->buffer, f->size);782 846 783 847 /* Instead of returning zero samples, it'd be better to return noise */ 848 if (jb->cb.cng && jb->last_frame_cn.size) { 849 f->type = PJMEDIA_JB_FT_INTERP_RAW_FRAME; 850 f->size = jb->last_frame_cn.size; 851 pj_memcpy(f->buffer, jb->last_frame_cn.buffer, f->size); 852 status = jb->cb.cng(f, jb->cb.user_data); 853 if (status != PJ_SUCCESS) { 854 f->type = PJMEDIA_JB_FT_NULL_FRAME; 855 f->size = jb->setting.frame_size; 856 pj_bzero(f->buffer, f->size); 857 TRACE__((THIS_FILE,"CNG failed")); 858 } 859 } else { 860 f->type = PJMEDIA_JB_FT_NULL_FRAME; 861 f->size = jb->setting.frame_size; 862 pj_bzero(f->buffer, f->size); 863 } 784 864 785 865 ON_RETURN: … … 800 880 801 881 /* Reinit JB */ 802 init_jb(jb);882 pjmedia_jb2_reset(jb); 803 883 } 804 884 … … 866 946 #endif 867 947 868 TRACE__((THIS_FILE, "History=%s Level=%d Opt.size=%d", dbg_hist, 869 jb->state.level, jb->state.opt_size)); 948 TRACE__((THIS_FILE, "History=%s level=%d opt.size=%d cur.size=%d", 949 dbg_hist, jb->state.level, 950 jb->state.opt_size, jb->state.cur_size)); 870 951 } 871 952 /* Reset level counter */ … … 902 983 jb->state.drift = new_drift; 903 984 jb->state.drift_span = new_drift_span; 985 986 /* Validate drift by comparing current drift to drift margin constant. 987 * Note that the drift value need to be rescaled to the same span before 988 * comparing. 989 */ 990 // drift_span = PJ_MIN(jb->stat.in - jb->hist[HISTORY_COUNT-1].in, 991 //jb->stat.out - jb->hist[HISTORY_COUNT-1].out) 992 //* (int)jb->setting.samples_per_frame; 993 // drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN / drift_span; 994 new_drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN / 995 (int)jb->state.drift_span; 996 if (PJ_ABS(new_drift) > MAX_DRIFT_MARGIN) { 997 TRACE__((THIS_FILE, "Abnormal drift (%d/%d), reinit jitter buffer!", 998 new_drift, MAX_DRIFT_MARGIN_SPAN)); 999 1000 /* Reinit JB */ 1001 pjmedia_jb2_reset(jb); 1002 } 1003 904 1004 905 1005 TRACE__((THIS_FILE, "Drift info update: %d/%d (in=%d out=%d)", … … 937 1037 unsigned *ref_, unsigned *match_) 938 1038 { 939 const int MATCH_THRESHOLD = MATCH_WINDOW_LEN*1 200;1039 const int MATCH_THRESHOLD = MATCH_WINDOW_LEN*1000; 940 1040 unsigned ref, ptr, end; 941 1041 int i, similarity, s1, s2; … … 1068 1168 1069 1169 dest = buf->size/2; 1070 jb_vbuf_expand(buf, distance*2); 1170 if (!jb_vbuf_expand(buf, distance*2)) 1171 return 0; 1071 1172 1072 1173 // memcpy … … 1132 1233 jb_vbuf buf; 1133 1234 int sample_size, uncomp_cnt; 1134 pj_int32_t drift,itmp;1235 pj_int32_t itmp; 1135 1236 1136 1237 /* No drift, just leave */ 1137 1238 if (!jb->state.drift || !jb->state.drift_span) { 1138 1239 jb->drift_state.last_ts = 0; 1139 return;1140 }1141 1142 /* Validate drift by comparing current drift to drift margin constant.1143 * Note that the drift value need to be rescaled to the same span before1144 * comparing.1145 */1146 // drift_span = PJ_MIN(jb->stat.in - jb->hist[HISTORY_COUNT-1].in,1147 //jb->stat.out - jb->hist[HISTORY_COUNT-1].out)1148 //* (int)jb->setting.samples_per_frame;1149 // drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN / drift_span;1150 drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN /1151 (int)jb->state.drift_span;1152 if (PJ_ABS(drift) > MAX_DRIFT_MARGIN) {1153 TRACE__((THIS_FILE, "Abnormal drift (%d/%d), reinit jitter buffer!",1154 drift, MAX_DRIFT_MARGIN_SPAN));1155 1156 /* Reinit JB */1157 init_jb(jb);1158 1159 1240 return; 1160 1241 } … … 1195 1276 itmp *= uncomp_cnt; 1196 1277 1197 TRACE__((THIS_FILE, "Introducing new culprit:%d/%d mod:%d cur_size:%d",1198 culprit, buf.cnt, itmp, jb->state.cur_size));1278 //TRACE__((THIS_FILE, "Introducing new culprit:%d/%d mod:%d cur_size:%d", 1279 //culprit, buf.cnt, itmp, jb->state.cur_size)); 1199 1280 pj_assert(buf.size/2 <= (int)jb->state.cur_size); 1200 1281 … … 1224 1305 culprit += jb->drift_state.pending; 1225 1306 1307 /* Normalization here, drift calculation is not always accurate, 1308 * a bit hacky. 1309 */ 1310 if (culprit > (int) jb->state.opt_size) 1311 //&& 1312 //PJ_ABS(jb->state.cur_size-jb->state.opt_size) <= jb->setting.frame_size) 1313 { 1314 culprit = 0; 1315 } 1316 1226 1317 /* Culprit may be negative when pending is negative, 1227 1318 * which means last compensation was more than needed, … … 1246 1337 1247 1338 /* IN > OUT (need to shrink) */ 1248 /* Simple method: just drop samples */1249 1339 if (jb->state.drift > 0) { 1250 1340 … … 1264 1354 1265 1355 /* IN < OUT ==> (need to grow) */ 1266 /* Another simple method: insert null samples */1267 1356 else { 1268 1357
Note: See TracChangeset
for help on using the changeset viewer.