summaryrefslogtreecommitdiff
path: root/pjmedia/src/pjmedia/jbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjmedia/src/pjmedia/jbuf.c')
-rw-r--r--pjmedia/src/pjmedia/jbuf.c149
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;
+}