diff options
Diffstat (limited to 'pjmedia/src/pjmedia/jbuf.c')
-rw-r--r-- | pjmedia/src/pjmedia/jbuf.c | 149 |
1 files changed, 142 insertions, 7 deletions
diff --git a/pjmedia/src/pjmedia/jbuf.c b/pjmedia/src/pjmedia/jbuf.c index b85eea61..9ae84b64 100644 --- a/pjmedia/src/pjmedia/jbuf.c +++ b/pjmedia/src/pjmedia/jbuf.c @@ -68,6 +68,7 @@ typedef struct jb_framelist_t int *frame_type; /**< frame type array */ pj_size_t *content_len; /**< frame length array */ pj_uint32_t *bit_info; /**< frame bit info array */ + pj_uint32_t *ts; /**< timestamp array */ /* States */ unsigned head; /**< index of head, pointed frame @@ -197,7 +198,10 @@ static pj_status_t jb_framelist_init( pj_pool_t *pool, pj_pool_alloc(pool, sizeof(framelist->bit_info[0])* framelist->max_count); - + framelist->ts = (pj_uint32_t*) + pj_pool_alloc(pool, + sizeof(framelist->ts[0])* + framelist->max_count); return jb_framelist_reset(framelist); @@ -258,7 +262,9 @@ static int jb_framelist_origin(const jb_framelist_t *framelist) static pj_bool_t jb_framelist_get(jb_framelist_t *framelist, void *frame, pj_size_t *size, pjmedia_jb_frame_type *p_type, - pj_uint32_t *bit_info) + pj_uint32_t *bit_info, + pj_uint32_t *ts, + int *seq) { if (framelist->size) { pj_bool_t prev_discarded = PJ_FALSE; @@ -294,6 +300,10 @@ static pj_bool_t jb_framelist_get(jb_framelist_t *framelist, if (bit_info) *bit_info = framelist->bit_info[framelist->head]; } + if (ts) + *ts = framelist->ts[framelist->head]; + if (seq) + *seq = framelist->origin; //pj_bzero(framelist->content + // framelist->head * framelist->frame_size, @@ -301,6 +311,7 @@ static pj_bool_t jb_framelist_get(jb_framelist_t *framelist, framelist->frame_type[framelist->head] = PJMEDIA_JB_MISSING_FRAME; framelist->content_len[framelist->head] = 0; framelist->bit_info[framelist->head] = 0; + framelist->ts[framelist->head] = 0; framelist->origin++; framelist->head = (framelist->head + 1) % framelist->max_count; @@ -317,6 +328,53 @@ static pj_bool_t jb_framelist_get(jb_framelist_t *framelist, } +static pj_bool_t jb_framelist_peek(jb_framelist_t *framelist, + unsigned offset, + const void **frame, + pj_size_t *size, + pjmedia_jb_frame_type *type, + pj_uint32_t *bit_info, + pj_uint32_t *ts, + int *seq) +{ + unsigned pos, idx; + + if (offset >= jb_framelist_eff_size(framelist)) + return PJ_FALSE; + + pos = framelist->head; + idx = offset; + + /* Find actual peek position, note there may be discarded frames */ + while (1) { + if (framelist->frame_type[pos] != PJMEDIA_JB_DISCARDED_FRAME) { + if (idx == 0) + break; + else + --idx; + } + pos = (pos + 1) % framelist->max_count; + } + + /* Return the frame pointer */ + if (frame) + *frame = framelist->content + pos*framelist->frame_size; + if (type) + *type = (pjmedia_jb_frame_type) + framelist->frame_type[pos]; + if (size) + *size = framelist->content_len[pos]; + if (bit_info) + *bit_info = framelist->bit_info[pos]; + if (ts) + *ts = framelist->ts[pos]; + if (seq) + *seq = framelist->origin + offset; + + return PJ_TRUE; +} + + /* Remove oldest frames as many as param 'count' */ static unsigned jb_framelist_remove_head(jb_framelist_t *framelist, unsigned count) @@ -385,6 +443,7 @@ static pj_status_t jb_framelist_put_at(jb_framelist_t *framelist, const void *frame, unsigned frame_size, pj_uint32_t bit_info, + pj_uint32_t ts, unsigned frame_type) { int distance; @@ -438,6 +497,7 @@ static pj_status_t jb_framelist_put_at(jb_framelist_t *framelist, framelist->frame_type[pos] = frame_type; framelist->content_len[pos] = frame_size; framelist->bit_info[pos] = bit_info; + framelist->ts[pos] = ts; /* update framelist size */ if (framelist->origin + (int)framelist->size <= index) @@ -747,7 +807,7 @@ PJ_DEF(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb, pj_size_t frame_size, int frame_seq) { - pjmedia_jbuf_put_frame2(jb, frame, frame_size, 0, frame_seq, NULL); + pjmedia_jbuf_put_frame3(jb, frame, frame_size, 0, frame_seq, 0, NULL); } PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb, @@ -757,6 +817,18 @@ PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb, int frame_seq, pj_bool_t *discarded) { + pjmedia_jbuf_put_frame3(jb, frame, frame_size, bit_info, frame_seq, 0, + discarded); +} + +PJ_DEF(void) pjmedia_jbuf_put_frame3(pjmedia_jbuf *jb, + const void *frame, + pj_size_t frame_size, + pj_uint32_t bit_info, + int frame_seq, + pj_uint32_t ts, + pj_bool_t *discarded) +{ pj_size_t min_frame_size; int new_size, cur_size, frame_type = PJMEDIA_JB_NORMAL_FRAME; pj_status_t status; @@ -824,7 +896,7 @@ PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb, /* Attempt to store the frame */ min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size); status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame, - min_frame_size, bit_info, frame_type); + min_frame_size, bit_info, ts, frame_type); /* Jitter buffer is full, remove some older frames */ while (status == PJ_ETOOMANY) { @@ -847,7 +919,7 @@ PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb, #endif removed = jb_framelist_remove_head(&jb->jb_framelist, distance); status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame, - min_frame_size, bit_info, frame_type); + min_frame_size, bit_info, ts, frame_type); jb->jb_discard += removed; } @@ -879,7 +951,8 @@ PJ_DEF(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb, void *frame, char *p_frame_type) { - pjmedia_jbuf_get_frame2(jb, frame, NULL, p_frame_type, NULL); + pjmedia_jbuf_get_frame3(jb, frame, NULL, p_frame_type, NULL, + NULL, NULL); } /* @@ -891,6 +964,21 @@ PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, char *p_frame_type, pj_uint32_t *bit_info) { + pjmedia_jbuf_get_frame3(jb, frame, size, p_frame_type, bit_info, + NULL, NULL); +} + +/* + * Get frame from jitter buffer. + */ +PJ_DEF(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb, + void *frame, + pj_size_t *size, + char *p_frame_type, + pj_uint32_t *bit_info, + pj_uint32_t *ts, + int *seq) +{ if (jb->jb_status == JB_STATUS_PREFETCHING) { /* Can't return frame because jitter buffer is filling up @@ -914,7 +1002,7 @@ PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, /* Try to retrieve a frame from frame list */ res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype, - bit_info); + bit_info, ts, seq); if (res) { /* We've successfully retrieved a frame from the frame list, but * the frame could be a blank frame! @@ -982,3 +1070,50 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_get_state( const pjmedia_jbuf *jb, return PJ_SUCCESS; } + +PJ_DEF(void) pjmedia_jbuf_peek_frame( pjmedia_jbuf *jb, + unsigned offset, + const void **frame, + pj_size_t *size, + char *p_frm_type, + pj_uint32_t *bit_info, + pj_uint32_t *ts, + int *seq) +{ + pjmedia_jb_frame_type ftype; + pj_bool_t res; + + res = jb_framelist_peek(&jb->jb_framelist, offset, frame, size, &ftype, + bit_info, ts, seq); + if (!res) + *p_frm_type = PJMEDIA_JB_ZERO_EMPTY_FRAME; + else if (ftype == PJMEDIA_JB_NORMAL_FRAME) + *p_frm_type = PJMEDIA_JB_NORMAL_FRAME; + else + *p_frm_type = PJMEDIA_JB_MISSING_FRAME; +} + + +PJ_DEF(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb, + unsigned frame_cnt) +{ + unsigned count, last_discard_num; + + last_discard_num = jb->jb_framelist.discarded_num; + count = jb_framelist_remove_head(&jb->jb_framelist, frame_cnt); + + /* Remove some more when there were discarded frames included */ + while (jb->jb_framelist.discarded_num < last_discard_num) { + /* Calculate frames count to be removed next */ + frame_cnt = last_discard_num - jb->jb_framelist.discarded_num; + + /* Normalize non-discarded frames count just been removed */ + count -= frame_cnt; + + /* Remove more frames */ + last_discard_num = jb->jb_framelist.discarded_num; + count += jb_framelist_remove_head(&jb->jb_framelist, frame_cnt); + } + + return count; +} |