diff options
author | Benny Prijono <bennylp@teluu.com> | 2008-03-21 13:47:23 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2008-03-21 13:47:23 +0000 |
commit | 5b79998fe36e220752c5e6cdf5ca6b06faa0f407 (patch) | |
tree | 75554c79630bdf8c055e2c4c0b3a18567d777cc5 /pjmedia/src | |
parent | 34dadcac285d6637b69f9415690e6f7b44c30f01 (diff) |
Ticket #505: optimizing the jitter buffer delay
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1887 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia/src')
-rw-r--r-- | pjmedia/src/pjmedia/jbuf.c | 142 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/stream.c | 9 |
2 files changed, 75 insertions, 76 deletions
diff --git a/pjmedia/src/pjmedia/jbuf.c b/pjmedia/src/pjmedia/jbuf.c index 8a15d8b7..0070b4de 100644 --- a/pjmedia/src/pjmedia/jbuf.c +++ b/pjmedia/src/pjmedia/jbuf.c @@ -29,6 +29,8 @@ #define THIS_FILE "jbuf.c" +#define SAFE_SHRINKING_DIFF 2 +#define USE_PREFETCH_BUFFERING 0 typedef struct jb_framelist_t { @@ -54,11 +56,8 @@ struct pjmedia_jbuf int jb_level; // delay between source & destination // (calculated according of the number of get/put operations) - int jb_last_level; // last delay - int jb_last_jitter; // last jitter calculated - int jb_max_hist_jitter; // max jitter during the last jitter calculations + int jb_max_hist_level; // max level during the last level calculations int jb_stable_hist; // num of times the delay has been lower then the prefetch num - unsigned jb_op_count; // of of operations. int jb_last_op; // last operation executed on the framelist->flist_buffer (put/get) int jb_last_seq_no; // seq no. of the last frame inserted to the framelist->flist_buffer int jb_prefetch; // no. of frame to insert before removing some @@ -83,7 +82,7 @@ struct pjmedia_jbuf /* Enabling this would log the jitter buffer state about once per * second. */ -#if 0 +#if 1 # define TRACE__(args) PJ_LOG(4,args) #else # define TRACE__(args) @@ -304,8 +303,6 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, jb->jb_frame_ptime = ptime; jb->jb_last_seq_no = -1; jb->jb_level = 0; - jb->jb_last_level = 0; - jb->jb_last_jitter = 0; jb->jb_last_op = JB_OP_INIT; jb->jb_prefetch = PJ_MIN(PJMEDIA_JB_DEFAULT_INIT_DELAY,max_count*4/5); jb->jb_prefetch_cnt = 0; @@ -313,7 +310,7 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, jb->jb_max_prefetch = max_count*4/5; jb->jb_stable_hist = 0; jb->jb_status = JB_STATUS_INITIALIZING; - jb->jb_max_hist_jitter = 0; + jb->jb_max_hist_level = 0; jb->jb_max_count = max_count; *p_jb = jb; @@ -366,13 +363,11 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb) { jb->jb_last_seq_no = -1; jb->jb_level = 0; - jb->jb_last_level = 0; - jb->jb_last_jitter = 0; jb->jb_last_op = JB_OP_INIT; jb->jb_prefetch_cnt = 0; jb->jb_stable_hist = 0; jb->jb_status = JB_STATUS_INITIALIZING; - jb->jb_max_hist_jitter = 0; + jb->jb_max_hist_level = 0; jb_framelist_remove_head(&jb->jb_framelist, jb_framelist_size(&jb->jb_framelist)); @@ -388,81 +383,80 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb) static void jbuf_calculate_jitter(pjmedia_jbuf *jb) { - unsigned stable_history_limit; + int diff; - stable_history_limit = 1000 / jb->jb_frame_ptime; + /* Only apply burst-level calculation on PUT operation since if VAD is + * active the burst-level may not be accurate. + */ + if (jb->jb_last_op == JB_OP_PUT) { - jb->jb_last_jitter = PJ_ABS(jb->jb_level-jb->jb_last_level); - jb->jb_last_level = jb->jb_level; - jb->jb_max_hist_jitter = PJ_MAX(jb->jb_max_hist_jitter,jb->jb_last_jitter); - jb->jb_op_count++; + jb->jb_max_hist_level = PJ_MAX(jb->jb_max_hist_level,jb->jb_level); - if (jb->jb_last_jitter < jb->jb_prefetch) { - jb->jb_stable_hist += jb->jb_last_jitter; - if (jb->jb_stable_hist > (int)stable_history_limit) { - int seq_diff = (jb->jb_prefetch - jb->jb_max_hist_jitter)/3; - if (seq_diff<1) seq_diff = 1; + /* Level is decreasing */ + if (jb->jb_level < jb->jb_prefetch) { - jb->jb_prefetch -= seq_diff; - if (jb->jb_prefetch < jb->jb_min_prefetch) - jb->jb_prefetch = jb->jb_min_prefetch; + static const int stable_history_limit = 100; + + jb->jb_stable_hist++; + + /* Only update the prefetch if 'stable' condition is reached + * (not just short time impulse) + */ + if (jb->jb_stable_hist > (int)stable_history_limit) { + diff = (jb->jb_prefetch - jb->jb_max_hist_level) / 3; - jb->jb_stable_hist = 0; - jb->jb_max_hist_jitter = 0; + if (diff < 1) + diff = 1; - TRACE__((THIS_FILE,"jb updated(1), prefetch=%d, size=%d", - jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist))); + jb->jb_prefetch -= diff; + if (jb->jb_prefetch < jb->jb_min_prefetch) + jb->jb_prefetch = jb->jb_min_prefetch; - /* These code is used to shorten the delay in the jitter buffer. + TRACE__((jb->name.ptr,"jb updated(1), prefetch=%d, size=%d", + jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist))); - if (jb->jb_op_count >= stable_history_limit*2 && - (int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) - { - jb_framelist_remove_head(&jb->jb_framelist,1); - - PJ_LOG(5,(jb->name.ptr, - "jbuf optimizing, prefetch: %d, size=%d", - jb->jb_prefetch, - jb_framelist_size(&jb->jb_framelist))); - jb->jb_op_count = 0; + jb->jb_stable_hist = 0; + jb->jb_max_hist_level = 0; } - */ + } + /* Level is increasing */ + else if (jb->jb_level > jb->jb_prefetch) { + + /* Instaneous set prefetch */ + jb->jb_prefetch = PJ_MIN(jb->jb_max_hist_level, + (int)(jb->jb_max_count*4/5)); + if (jb->jb_prefetch > jb->jb_max_prefetch) + jb->jb_prefetch = jb->jb_max_prefetch; + jb->jb_stable_hist = 0; + jb->jb_max_hist_level = 0; + + TRACE__((jb->name.ptr,"jb updated(2), prefetch=%d, size=%d", + jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist))); } - } else { - jb->jb_prefetch = PJ_MIN(jb->jb_last_jitter, - (int)(jb->jb_max_count*4/5)); - if (jb->jb_prefetch > jb->jb_max_prefetch) - jb->jb_prefetch = jb->jb_max_prefetch; - jb->jb_stable_hist = 0; - jb->jb_max_hist_jitter = 0; - - TRACE__((THIS_FILE,"jb updated(2), prefetch=%d, size=%d", - jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist))); - - /* These code is used to shorten the delay in the jitter buffer - when the current size is larger than the prefetch. But it does - not really work when the stream supports multiple frames, since - the size may grow only temporarily. - - if (jb->jb_op_count >= stable_history_limit * 2) { - if ((int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) - { - jb_framelist_remove_head(&jb->jb_framelist,1); - - PJ_LOG(5,(jb->name.ptr, - "jbuf optimizing prefetch: %d, size=%d", - jb->jb_prefetch, - jb_framelist_size(&jb->jb_framelist))); - } - jb->jb_op_count = 0; + /* Level is unchanged */ + else { + jb->jb_stable_hist = 0; } - */ } + + /* These code is used for shortening the delay in the jitter buffer. */ + diff = jb_framelist_size(&jb->jb_framelist) - jb->jb_prefetch; + if (diff > SAFE_SHRINKING_DIFF) { + + /* Drop some frames so jitter buffer size should be == jb_prefetch */ + jb_framelist_remove_head(&jb->jb_framelist, diff); + + TRACE__((jb->name.ptr, + "JB shrinking %d frames, size=%d", diff, + jb_framelist_size(&jb->jb_framelist))); + } + + jb->jb_level = 0; } -static void jbuf_update(pjmedia_jbuf *jb, int oper) +PJ_INLINE(void) jbuf_update(pjmedia_jbuf *jb, int oper) { if(jb->jb_last_op != oper) { jbuf_calculate_jitter(jb); @@ -489,8 +483,6 @@ PJ_DEF(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb, if(jb->jb_status == JB_STATUS_INITIALIZING) { jb->jb_status = JB_STATUS_PROCESSING; jb->jb_level = 0; - jb->jb_last_level = 0; - jb->jb_last_jitter = 0; } else { jbuf_update(jb, JB_OP_PUT); } @@ -537,10 +529,12 @@ PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, { pjmedia_jb_frame_type ftype; - jb->jb_level--; + jb->jb_level++; jbuf_update(jb, JB_OP_GET); +#if USE_PREFETCH_BUFFERING + if (jb_framelist_size(&jb->jb_framelist) == 0) { jb->jb_prefetch_cnt = 0; } @@ -560,6 +554,8 @@ PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, return; } +#endif + /* Retrieve a frame from frame list */ if (jb_framelist_get(&jb->jb_framelist,frame,size,&ftype) == PJ_FALSE) { /* Can't return frame because jitter buffer is empty! */ diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c index 2044dfe4..5045c055 100644 --- a/pjmedia/src/pjmedia/stream.c +++ b/pjmedia/src/pjmedia/stream.c @@ -1458,17 +1458,20 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, if (info->jb_min_pre >= 0) jb_min_pre = info->jb_min_pre; else - jb_min_pre = 60 / stream->codec_param.info.frm_ptime; + //jb_min_pre = 60 / stream->codec_param.info.frm_ptime; + jb_min_pre = 1; if (info->jb_max_pre > 0) jb_max_pre = info->jb_max_pre; else - jb_max_pre = 240 / stream->codec_param.info.frm_ptime; + //jb_max_pre = 240 / stream->codec_param.info.frm_ptime; + jb_max_pre = jb_max * 4 / 5; if (info->jb_init >= 0) jb_init = info->jb_init; else - jb_init = (jb_min_pre + jb_max_pre) / 2; + //jb_init = (jb_min_pre + jb_max_pre) / 2; + jb_init = jb_min_pre; /* Create jitter buffer */ |