- Timestamp:
- Feb 3, 2008 4:55:31 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
r1770 r1775 49 49 */ 50 50 typedef struct pjmedia_jb2_t pjmedia_jb2_t; 51 52 /** 53 * Types of jitter buffer phase. 54 */ 55 typedef enum pjmedia_jb2_phase 56 { 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 */ 60 } pjmedia_jb2_phase; 51 61 52 62 /** … … 79 89 typedef struct pjmedia_jb2_state 80 90 { 81 /* frames */ 91 pjmedia_jb2_phase phase; 92 93 /* in frames */ 82 94 pj_uint16_t level; 83 95 pj_uint32_t frame_cnt; 84 96 85 /* samples */97 /* in samples */ 86 98 pj_int32_t drift; 87 99 pj_uint32_t drift_span; … … 97 109 typedef struct pjmedia_jb2_stat 98 110 { 99 /* frames */111 /* in frames */ 100 112 pj_uint32_t lost; 101 113 pj_uint32_t late; … … 104 116 pj_uint32_t in; 105 117 106 /* ticks */118 /* in ticks */ 107 119 pj_uint32_t full; 108 120 pj_uint32_t empty; 109 121 110 /* samples */122 /* in samples */ 111 123 pj_uint32_t max_size; 112 124 pj_int32_t max_drift; … … 114 126 pj_int32_t max_comp; 115 127 116 /* ticks */128 /* in frames */ 117 129 pj_uint16_t max_level; 118 130 } pjmedia_jb2_stat; -
pjproject/branches/projects/jbuf2/pjmedia/src/pjmedia/jbuf2.c
r1773 r1775 118 118 * 119 119 * History structure: 120 * - JB holds array of history, each element represent condition of JB at120 * - JB holds array of history, each element represents condition of JB at 121 121 * specified time t (marked by tick), ordered as the newest is the first. 122 122 * - History has age, when it is expired, history will be shifted/discarded. … … 177 177 pj_int16_t cur_level; 178 178 pj_uint32_t tick; 179 pj_bool_t idle;180 179 jb_drift_state drift_state; 181 180 … … 202 201 pj_list_erase(f); 203 202 } else if (jb->state.frame_cnt >= jb->setting.max_frames) { 204 TRACE__((THIS_FILE, "Frame numbers exceeds max(%d)!",203 TRACE__((THIS_FILE, "Frame numbers(%d) exceeds max(%d)!", 205 204 jb->state.frame_cnt, jb->setting.max_frames)); 206 205 return NULL; … … 233 232 pjmedia_jb2_t *jb; 234 233 jb_frame_list *f[8]; 235 intcnt;234 unsigned cnt; 236 235 237 236 /* public */ 238 intsize;237 unsigned size; 239 238 } jb_vbuf; 240 239 … … 270 269 static pj_int16_t jb_vbuf_get_sample(jb_vbuf *buf, unsigned idx) 271 270 { 272 inti;271 unsigned i; 273 272 unsigned idx_ = idx; 274 273 … … 289 288 pj_int16_t val) 290 289 { 291 inti;290 unsigned i; 292 291 unsigned idx_ = idx; 293 292 … … 304 303 } 305 304 306 /* Can only shrink */ 307 static void jb_vbuf_shrink_to(jb_vbuf *buf, int size) 305 static void jb_vbuf_shrink(jb_vbuf *buf, unsigned size) 308 306 { 309 307 int i; 310 308 311 pj_assert(buf && size < buf->size);312 313 for (i = buf->cnt-1; i>=0 && buf->size>size; --i) {314 if ( (buf->size - (int)buf->f[i]->frame.size) >= size) {309 pj_assert(buf && size <= buf->size); 310 311 for (i = buf->cnt-1; i>=0 && size>0; --i) { 312 if (buf->f[i]->frame.size <= size) { 315 313 buf->cnt--; 316 314 buf->size -= buf->f[i]->frame.size; 315 size -= buf->f[i]->frame.size; 317 316 /* modify jb */ 318 317 buf->jb->state.cur_size -= buf->f[i]->frame.size/2; 319 318 buf->f[i]->frame.size = 0; 320 //release_frame(buf->jb, buf->f[i]);321 319 } else { 322 int diff = buf->size - size; 323 buf->f[i]->frame.size -= diff; 324 buf->size -= diff; 320 buf->f[i]->frame.size -= size; 321 buf->size -= size; 325 322 /* modify jb */ 326 buf->jb->state.cur_size -= diff/2; 327 } 323 buf->jb->state.cur_size -= size/2; 324 size = 0; 325 } 326 } 327 } 328 329 static void jb_vbuf_expand(jb_vbuf *buf, unsigned size) 330 { 331 jb_frame_list *f; 332 int step; 333 334 pj_assert(buf); 335 336 while (size > 0) { 337 step = PJ_MIN(buf->jb->setting.frame_size, size); 338 339 f = alloc_frame(buf->jb); 340 f->frame.pt = buf->f[buf->cnt-1]->frame.pt; 341 f->frame.seq = buf->f[buf->cnt-1]->frame.seq; 342 f->frame.size = step; 343 f->frame.ts = buf->f[buf->cnt-1]->frame.ts; 344 f->frame.type = buf->f[buf->cnt-1]->frame.type; 345 346 pj_list_insert_after(buf->f[buf->cnt - 1], f); 347 buf->jb->state.cur_size += step/2; 348 349 pj_assert(buf->cnt <= sizeof(buf->f)/sizeof(buf->f[0])); 350 buf->f[buf->cnt++] = f; 351 buf->size += step; 352 353 size -= step; 328 354 } 329 355 } … … 362 388 pj_bzero(&jb->state, sizeof(pjmedia_jb2_state)); 363 389 jb->state.frame_cnt = i; 364 jb->state.level = 1;390 jb->state.level = 0; 365 391 366 392 /* Reset drift state */ 367 393 pj_bzero(&jb->drift_state, sizeof(jb_drift_state)); 368 394 369 /* Set not idle*/370 jb-> idle = PJ_FALSE;395 /* Set start learning */ 396 jb->state.phase = PJMEDIA_JB_PH_LEARNING; 371 397 372 398 /* Reset current level */ … … 511 537 pos = jb->frames.prev; 512 538 513 if (jb-> idle)539 if (jb->state.phase == PJMEDIA_JB_PH_IDLE) 514 540 goto ON_RETURN; 515 541 … … 557 583 tmp->frame.pt = f->pt; 558 584 tmp->frame.seq = f->seq; 559 tmp->frame.size = (f->seq == 1? 160: f->size);585 tmp->frame.size = f->size; 560 586 tmp->frame.ts = f->ts; 561 587 tmp->frame.type = f->type; … … 566 592 /* Decode frame(s) if needed */ 567 593 if (tmp->frame.type == PJMEDIA_JB_FT_NORMAL_RAW_FRAME) { 568 if (f->seq == 1) 569 jb->state.cur_size += 80; 570 else 571 jb->state.cur_size += jb->setting.samples_per_frame; 594 jb->state.cur_size += jb->setting.samples_per_frame; 572 595 } 573 596 else if (tmp->prev != &jb->frames && … … 596 619 update_state(jb, PJ_TRUE); 597 620 598 if (jb-> idle)621 if (jb->state.phase == PJMEDIA_JB_PH_IDLE) 599 622 goto ON_RETURN; 600 623 … … 698 721 /* Not enough samples in PCM buffer */ 699 722 if (jb->state.cur_size < jb->setting.samples_per_frame) { 723 if (jb->state.phase != PJMEDIA_JB_PH_LEARNING) { 724 TRACE__((THIS_FILE,"Not enough PCM samples (%d)!", 725 jb->state.cur_size)); 726 ++jb->stat.empty; 727 } 700 728 goto RETURN_EMPTY_FRAME; 701 729 } … … 727 755 tmp->frame.size -= i; 728 756 729 /* Shift buffer, don't shift the pointer! */757 /* Shift the buffer, don't shift the pointer! */ 730 758 pj_memmove(tmp->frame.buffer, (pj_int8_t*)tmp->frame.buffer + i, 731 759 tmp->frame.size); … … 738 766 jb->state.cur_size -= jb->setting.samples_per_frame; 739 767 768 /* JB still learning the level */ 769 if (jb->state.phase == PJMEDIA_JB_PH_LEARNING) 770 goto RETURN_EMPTY_FRAME; 771 740 772 goto ON_RETURN; 741 773 742 774 RETURN_EMPTY_FRAME: 743 TRACE__((THIS_FILE,"Return empty frame!"));744 745 ++jb->stat.empty;746 775 747 776 f->type = PJMEDIA_JB_FT_NULL_FRAME; … … 752 781 pj_bzero(f->buffer, f->size); 753 782 754 /* Instead of return zero samples, it'd be better to return noise */783 /* Instead of returning zero samples, it'd be better to return noise */ 755 784 756 785 ON_RETURN: … … 767 796 768 797 /* JB idle? */ 769 if (jb-> idle) {798 if (jb->state.phase == PJMEDIA_JB_PH_IDLE) { 770 799 TRACE__((THIS_FILE, "Idle ended, reinit jitter buffer.")); 771 jb->idle = PJ_FALSE;772 800 773 801 /* Reinit JB */ … … 803 831 /* Calculate optimum size */ 804 832 jb->state.opt_size = jb->setting.samples_per_frame * level_sum / 805 level_factor + jb->setting.samples_per_frame; 833 level_factor 834 + jb->setting.samples_per_frame / 2; 806 835 if (jb->state.opt_size > 807 836 jb->setting.max_frames * jb->setting.samples_per_frame) … … 812 841 813 842 } 843 844 /* Switching phase: learning -> running, 845 * if history has shifted and current size reaches optimum size. 846 */ 847 if (jb->state.phase == PJMEDIA_JB_PH_LEARNING) { 848 if (jb->hist[1].level > 0 && 849 jb->state.cur_size >= jb->state.opt_size) 850 { 851 jb->state.phase = PJMEDIA_JB_PH_RUNNING; 852 TRACE__((THIS_FILE, "JB start running (%d>=%d)", 853 jb->state.cur_size, jb->state.opt_size)); 854 } else { 855 TRACE__((THIS_FILE, "Learning %d->%d", jb->state.cur_size, 856 jb->state.opt_size)); 857 } 858 } 859 860 814 861 #ifdef INC_OPT_SIZE_TO_DRIFT_CALC 815 862 /* Include opt_size to drift calculation */ … … 836 883 /* Check idle */ 837 884 if (jb->hist[0].in == jb->stat.in || jb->hist[0].out == jb->stat.out) { 838 if ( !jb->idle)885 if (jb->state.phase != PJMEDIA_JB_PH_IDLE) 839 886 TRACE__((THIS_FILE, "Idle operation detected.")); 840 887 841 jb-> idle = PJ_TRUE;888 jb->state.phase = PJMEDIA_JB_PH_IDLE; 842 889 843 890 goto SHIFT_HISTORY; … … 887 934 /* Find matching samples pattern, longest possible distance for !left_ref */ 888 935 static pj_status_t find_matched_window(jb_vbuf *buf, pj_bool_t left_ref, 889 intpref_dist,936 unsigned pref_dist, 890 937 unsigned *ref_, unsigned *match_) 891 938 { … … 945 992 /* Find matching samples pattern, shortest possible distance for !left_ref */ 946 993 static pj_status_t find_matched_window2(jb_vbuf *buf, pj_bool_t left_ref, 947 intpref_dist,994 unsigned pref_dist, 948 995 unsigned *ref_, unsigned *match_) 949 996 { 950 997 const int MATCH_THRESHOLD = MATCH_WINDOW_LEN*1200; 951 unsignedref, ptr, end;998 int ref, ptr, end; 952 999 int i, similarity, s1, s2; 953 1000 … … 971 1018 ref = buf->size/2 - MATCH_WINDOW_LEN; 972 1019 end = -1; 973 ptr = ref - MATCH_WINDOW_LEN; 1020 if (ref - MATCH_WINDOW_LEN >= (int)pref_dist) 1021 ptr = ref - MATCH_WINDOW_LEN - pref_dist; 1022 else 1023 ptr = ref - MATCH_WINDOW_LEN; 974 1024 } 975 1025 … … 990 1040 return PJ_SUCCESS; 991 1041 } 992 ptr += left_ref ? -1 : -1;1042 --ptr; 993 1043 } 994 1044 … … 996 1046 } 997 1047 998 /* Add n samples tobuf, the additional samples will be put in dest,1048 /* Add n samples for buf, the additional samples will be put in dest, 999 1049 * the buf may be modified but the buf size is not. Function will return 1000 1050 * the number of inserted samples. 1001 1051 */ 1002 static int insert_samples(jb_vbuf *buf, int n, 1003 void *dest, pj_size_t dest_size) 1004 { 1005 unsigned ref, match; 1052 static int insert_samples(jb_vbuf *buf, int n) 1053 { 1054 unsigned ref, match, dest; 1006 1055 pj_status_t status; 1007 1056 int i, distance; … … 1011 1060 n = MATCH_WINDOW_LEN; 1012 1061 1013 if (n > (int)dest_size / 2) 1014 n = dest_size / 2; 1015 1016 status = find_matched_window(buf, PJ_FALSE, n, &ref, &match); 1062 status = find_matched_window2(buf, PJ_FALSE, n, &ref, &match); 1017 1063 if (status != PJ_SUCCESS) 1018 1064 return 0; … … 1020 1066 distance = ref - match; 1021 1067 pj_assert(distance > 0); 1068 1069 dest = buf->size/2; 1070 jb_vbuf_expand(buf, distance*2); 1022 1071 1023 1072 // memcpy 1024 1073 for (i = 0; i < distance; ++i) { 1025 1074 s1 = jb_vbuf_get_sample(buf, match + MATCH_WINDOW_LEN + i); 1026 *((pj_int16_t*)dest + i) = s1;1075 jb_vbuf_set_sample(buf, dest + i, s1); 1027 1076 } 1028 1077 … … 1068 1117 1069 1118 // memmove 1070 for (i = 0; i < buf->size/2 - distance - MATCH_WINDOW_LEN; ++i) {1119 for (i = 0; i < (int)buf->size/2 - distance - MATCH_WINDOW_LEN; ++i) { 1071 1120 s1 = jb_vbuf_get_sample(buf, match + MATCH_WINDOW_LEN + i); 1072 1121 jb_vbuf_set_sample(buf, ref + MATCH_WINDOW_LEN + i, s1); 1073 1122 } 1074 1123 1075 jb_vbuf_shrink _to(buf, buf->size -distance*2);1124 jb_vbuf_shrink(buf, distance*2); 1076 1125 1077 1126 return distance; … … 1175 1224 culprit += jb->drift_state.pending; 1176 1225 1177 /* Culprit may be negative when pending is negative. 1178 * pending the compensation if this happens. 1226 /* Culprit may be negative when pending is negative, 1227 * which means last compensation was more than needed, 1228 * nothing to compensate if this happens. 1179 1229 */ 1180 if (culprit < 0) {1230 if (culprit <= 0) { 1181 1231 jb->drift_state.pending = culprit; 1182 1232 return; 1183 1233 } 1184 1185 /* Nothing to compensate */1186 if (!culprit)1187 return;1188 1234 1189 1235 orig_cur_size = jb->state.cur_size; … … 1205 1251 int deleted = 0; 1206 1252 1207 //if (jb->state.cur_size > 1208 // (jb->setting.samples_per_frame + culprit)) 1253 if (culprit > (int)jb->state.cur_size || 1254 jb->state.cur_size > 1255 (jb->setting.samples_per_frame + culprit)) 1209 1256 { 1210 1257 deleted = delete_samples(&buf, culprit); … … 1221 1268 1222 1269 int inserted = 0; 1223 jb_frame_list *tmp_f;1224 1270 1225 tmp_f = alloc_frame(jb); 1226 if (tmp_f) { 1227 inserted = insert_samples(&buf, 1228 culprit, tmp_f->frame.buffer, 1229 jb->setting.frame_size); 1230 1231 if (inserted > 0) { 1232 tmp_f->frame.pt = buf.f[buf.cnt-1]->frame.pt; 1233 tmp_f->frame.seq = buf.f[buf.cnt-1]->frame.seq; 1234 tmp_f->frame.size = inserted * sample_size; 1235 tmp_f->frame.ts = buf.f[buf.cnt-1]->frame.ts; 1236 tmp_f->frame.type = buf.f[buf.cnt-1]->frame.type; 1237 1238 jb->state.cur_size += inserted; 1239 pj_list_insert_after(buf.f[buf.cnt-1], tmp_f); 1240 } else { 1241 pj_list_push_back(&jb->frames_pool, tmp_f); 1242 } 1243 } 1271 inserted = insert_samples(&buf, culprit); 1272 1244 1273 jb->drift_state.pending = culprit - inserted; 1245 1274
Note: See TracChangeset
for help on using the changeset viewer.