summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-05-11 14:22:01 +0000
committerBenny Prijono <bennylp@teluu.com>2006-05-11 14:22:01 +0000
commitaf23f4acec679cb8a42074206dbe463f8160a370 (patch)
treef77c79943540fb6ad1a163c2b874a509c6fa58f8 /pjmedia
parent0be368c425f5dc81a29a0c55799bfd66c041b966 (diff)
Fixed bug: incorrect remote and local PT for telephone-events (swapped)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@435 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia/jbuf.h109
-rw-r--r--pjmedia/src/pjmedia/jbuf.c112
-rw-r--r--pjmedia/src/pjmedia/session.c12
-rw-r--r--pjmedia/src/pjmedia/stream.c13
4 files changed, 186 insertions, 60 deletions
diff --git a/pjmedia/include/pjmedia/jbuf.h b/pjmedia/include/pjmedia/jbuf.h
index c289e337..4a5c1abb 100644
--- a/pjmedia/include/pjmedia/jbuf.h
+++ b/pjmedia/include/pjmedia/jbuf.h
@@ -45,13 +45,35 @@ PJ_BEGIN_DECL
*/
enum pjmedia_jb_frame_type
{
- PJMEDIA_JB_MISSING_FRAME = 0, /**< No frame because it's missing. */
- PJMEDIA_JB_NORMAL_FRAME = 1, /**< Normal frame is being returned. */
- PJMEDIA_JB_ZERO_FRAME = 2, /**< Zero frame is being returned. */
+ PJMEDIA_JB_MISSING_FRAME = 0, /**< No frame because it's missing */
+ PJMEDIA_JB_NORMAL_FRAME = 1, /**< Normal frame is being returned */
+ PJMEDIA_JB_ZERO_PREFETCH_FRAME = 2, /**< Zero frame is being returned
+ because JB is bufferring. */
+ PJMEDIA_JB_ZERO_EMPTY_FRAME = 3 /**< Zero frame is being returned
+ because JB is empty. */
};
/**
+ * This structure describes jitter buffer current status.
+ */
+struct pjmedia_jb_state
+{
+ unsigned frame_size; /**< Individual frame size, in bytes. */
+ unsigned prefetch; /**< Current prefetch value, in frames */
+ unsigned min_prefetch; /**< Minimum allowed prefetch, in frms. */
+ unsigned max_prefetch; /**< Maximum allowed prefetch, in frms. */
+ unsigned size; /**< Current buffer size, in frames. */
+};
+
+
+/**
+ * @see pjmedia_jb_state
+ */
+typedef struct pjmedia_jb_state pjmedia_jb_state;
+
+
+/**
* The constant PJMEDIA_JB_DEFAULT_INIT_DELAY specifies default jitter
* buffer prefetch count during jitter buffer creation.
*/
@@ -59,30 +81,70 @@ enum pjmedia_jb_frame_type
/**
- * Create the jitter buffer. This function may allocate large chunk of
- * memory to keep the frames in the buffer.
+ * Create an adaptive jitter buffer according to the specification. If
+ * application wants to have a fixed jitter buffer, it may call
+ * #pjmedia_jbuf_set_fixed() after the jitter buffer is created.
+ *
+ * This function may allocate large chunk of memory to keep the frames in
+ * the buffer.
*
* @param pool The pool to allocate memory.
* @param name Name to identify the jitter buffer for logging
* purpose.
* @param frame_size The size of each frame that will be kept in the
- * jitter buffer. The value here normaly corresponds
- * to the RTP payload size according to the codec
- * being used.
- * @param init_delay Initial jitter buffer delay, in number of frames.
- * @param max_count Maximum jitter buffer delay, in number of frames.
+ * jitter buffer, in bytes. This should correspond
+ * to the minimum frame size supported by the codec.
+ * For example, a 10ms frame (80 bytes) would be
+ * recommended for G.711 codec.
+ * @param max_count Maximum number of frames that can be kept in the
+ * jitter buffer. This effectively means the maximum
+ * delay that may be introduced by this jitter
+ * buffer.
* @param p_jb Pointer to receive jitter buffer instance.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool,
const pj_str_t *name,
- int frame_size,
- int init_delay,
- int max_count,
+ unsigned frame_size,
+ unsigned max_count,
pjmedia_jbuf **p_jb);
/**
+ * Set the jitter buffer to fixed delay mode. The default behavior
+ * is to adapt the delay with actual packet delay.
+ *
+ * @param jb The jitter buffer
+ * @param prefetch The fixed delay value, in number of frames.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_jbuf_set_fixed( pjmedia_jbuf *jb,
+ unsigned prefetch);
+
+
+/**
+ * Set the jitter buffer to adaptive mode.
+ *
+ * @param jb The jitter buffer.
+ * @param prefetch The prefetch value to be applied to the jitter
+ * buffer.
+ * @param min_prefetch The minimum delay that must be applied to each
+ * incoming packets, in number of frames. The
+ * default value is zero.
+ * @param max_prefetch The maximum allowable value for prefetch delay,
+ * in number of frames. The default value is equal
+ * to the size of the jitter buffer.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_jbuf_set_adaptive( pjmedia_jbuf *jb,
+ unsigned prefetch,
+ unsigned min_prefetch,
+ unsigned max_prefetch);
+
+
+/**
* Destroy jitter buffer instance.
*
* @param jb The jitter buffer.
@@ -155,28 +217,17 @@ PJ_DECL(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,
void *frame,
char *p_frm_type);
-/**
- * Retrieve the current value of jitter buffer minimum delay, in number
- * of frames.
- *
- * @param jb The jitter buffer.
- *
- * @return Number of frames, indicating the minimum delay that
- * will be applied by the jitter buffer between frame
- * arrival and frame retrieval.
- */
-PJ_DECL(unsigned) pjmedia_jbuf_get_min_delay_size(pjmedia_jbuf *jb);
-
/**
- * Retrieve the current delay value, in number of frames.
+ * Get jitter buffer state.
*
* @param jb The jitter buffer.
+ * @param state Buffer to receive jitter buffer state.
*
- * @return Number of frames, indicating the delay between frame
- * arrival and frame retrieval.
+ * @return PJ_SUCCESS on success.
*/
-PJ_DECL(unsigned) pjmedia_jbuf_get_delay(pjmedia_jbuf *jb);
+PJ_DECL(pj_status_t) pjmedia_jbuf_get_state( pjmedia_jbuf *jb,
+ pjmedia_jb_state *state );
diff --git a/pjmedia/src/pjmedia/jbuf.c b/pjmedia/src/pjmedia/jbuf.c
index 4392e855..cfee2379 100644
--- a/pjmedia/src/pjmedia/jbuf.c
+++ b/pjmedia/src/pjmedia/jbuf.c
@@ -64,6 +64,8 @@ struct pjmedia_jbuf
int jb_prefetch; // no. of frame to insert before removing some
// (at the beginning of the framelist->flist_buffer operation)
int jb_prefetch_cnt; // prefetch counter
+ int jb_min_prefetch; // Minimum allowable prefetch
+ int jb_max_prefetch; // Maximum allowable prefetch
int jb_status; // status is 'init' until the first 'put' operation
@@ -137,7 +139,8 @@ static pj_bool_t jb_framelist_get(jb_framelist *framelist,
pj_memset(framelist->flist_buffer +
framelist->flist_head * framelist->flist_frame_size,
0, framelist->flist_frame_size);
- framelist->flist_frame_type[framelist->flist_head] = 0;
+ framelist->flist_frame_type[framelist->flist_head] =
+ PJMEDIA_JB_MISSING_FRAME;
framelist->flist_origin++;
framelist->flist_head = (framelist->flist_head + 1 ) %
@@ -181,7 +184,7 @@ static void jb_framelist_remove_head( jb_framelist *framelist,
0,
step1*framelist->flist_frame_size);
pj_memset(framelist->flist_frame_type+framelist->flist_head,
- 0,
+ PJMEDIA_JB_MISSING_FRAME,
step1*sizeof(framelist->flist_frame_type[0]));
if (step2) {
@@ -189,7 +192,7 @@ static void jb_framelist_remove_head( jb_framelist *framelist,
0,
step2*framelist->flist_frame_size);
pj_memset(framelist->flist_frame_type,
- 0,
+ PJMEDIA_JB_MISSING_FRAME,
step2*sizeof(framelist->flist_frame_type[0]));
}
@@ -263,9 +266,8 @@ enum pjmedia_jb_op
PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool,
const pj_str_t *name,
- int frame_size,
- int initial_prefetch,
- int max_count,
+ unsigned frame_size,
+ unsigned max_count,
pjmedia_jbuf **p_jb)
{
pjmedia_jbuf *jb;
@@ -284,8 +286,10 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool,
jb->jb_last_level = 0;
jb->jb_last_jitter = 0;
jb->jb_last_op = JB_OP_INIT;
- jb->jb_prefetch = PJ_MIN(initial_prefetch, max_count*4/5);
+ jb->jb_prefetch = PJ_MIN(PJMEDIA_JB_DEFAULT_INIT_DELAY,max_count*4/5);
jb->jb_prefetch_cnt = 0;
+ jb->jb_min_prefetch = 0;
+ 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;
@@ -296,6 +300,47 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool,
}
+/*
+ * Set the jitter buffer to fixed delay mode. The default behavior
+ * is to adapt the delay with actual packet delay.
+ *
+ */
+PJ_DEF(pj_status_t) pjmedia_jbuf_set_fixed( pjmedia_jbuf *jb,
+ unsigned prefetch)
+{
+ PJ_ASSERT_RETURN(jb, PJ_EINVAL);
+ PJ_ASSERT_RETURN(prefetch <= jb->jb_max_count, PJ_EINVAL);
+
+ jb->jb_min_prefetch = jb->jb_max_prefetch =
+ jb->jb_prefetch = prefetch;
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Set the jitter buffer to adaptive mode.
+ */
+PJ_DEF(pj_status_t) pjmedia_jbuf_set_adaptive( pjmedia_jbuf *jb,
+ unsigned prefetch,
+ unsigned min_prefetch,
+ unsigned max_prefetch)
+{
+ PJ_ASSERT_RETURN(jb, PJ_EINVAL);
+ PJ_ASSERT_RETURN(min_prefetch < max_prefetch &&
+ prefetch >= min_prefetch &&
+ prefetch <= max_prefetch &&
+ max_prefetch <= jb->jb_max_count,
+ PJ_EINVAL);
+
+ jb->jb_prefetch = prefetch;
+ jb->jb_min_prefetch = min_prefetch;
+ jb->jb_max_prefetch = max_prefetch;
+
+ return PJ_SUCCESS;
+}
+
+
PJ_DEF(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb)
{
jb->jb_last_seq_no = -1;
@@ -336,7 +381,8 @@ static void jbuf_calculate_jitter(pjmedia_jbuf *jb)
if (seq_diff<1) seq_diff = 1;
jb->jb_prefetch -= seq_diff;
- if (jb->jb_prefetch < 1) jb->jb_prefetch = 1;
+ if (jb->jb_prefetch < jb->jb_min_prefetch)
+ jb->jb_prefetch = jb->jb_min_prefetch;
jb->jb_stable_hist = 0;
jb->jb_max_hist_jitter = 0;
@@ -357,6 +403,8 @@ static void jbuf_calculate_jitter(pjmedia_jbuf *jb)
} 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;
@@ -431,6 +479,9 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_put_frame(pjmedia_jbuf *jb,
return PJ_SUCCESS;
}
+/*
+ * Get frame from jitter buffer.
+ */
PJ_DEF(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,
void *frame,
char *p_frame_type)
@@ -445,14 +496,31 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,
jb->jb_prefetch_cnt = 0;
}
- if ((jb->jb_prefetch_cnt < jb->jb_prefetch) ||
- jb_framelist_get(&jb->jb_framelist,frame,&ftype) == PJ_FALSE)
- {
+ if ((jb->jb_prefetch_cnt < jb->jb_prefetch)) {
+ /* Can't return frame because jitter buffer is filling up
+ * minimum prefetch.
+ */
+ pj_memset(frame, 0, jb->jb_frame_size);
+ if (jb_framelist_size(&jb->jb_framelist) == 0)
+ *p_frame_type = PJMEDIA_JB_ZERO_EMPTY_FRAME;
+ else
+ *p_frame_type = PJMEDIA_JB_ZERO_PREFETCH_FRAME;
+
+ return PJ_SUCCESS;
+ }
+
+ /* Retrieve a frame from frame list */
+ if (jb_framelist_get(&jb->jb_framelist,frame,&ftype) == PJ_FALSE) {
+ /* Can't return frame because jitter buffer is empty! */
pj_memset(frame, 0, jb->jb_frame_size);
- *p_frame_type = PJMEDIA_JB_ZERO_FRAME;
+ *p_frame_type = PJMEDIA_JB_ZERO_EMPTY_FRAME;
+
return PJ_SUCCESS;
}
+ /* We've successfully retrieved a frame from the frame list, but
+ * the frame could be a blank frame!
+ */
if (ftype == PJMEDIA_JB_NORMAL_FRAME) {
*p_frame_type = PJMEDIA_JB_NORMAL_FRAME;
} else {
@@ -462,14 +530,20 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,
return PJ_SUCCESS;
}
-PJ_DEF(unsigned) pjmedia_jbuf_get_min_delay_size(pjmedia_jbuf *jb)
+/*
+ * Get jitter buffer state.
+ */
+PJ_DEF(pj_status_t) pjmedia_jbuf_get_state( pjmedia_jbuf *jb,
+ pjmedia_jb_state *state )
{
- return jb->jb_prefetch;
-}
+ PJ_ASSERT_RETURN(jb && state, PJ_EINVAL);
-PJ_DEF(unsigned) pjmedia_jbuf_get_delay(pjmedia_jbuf *jb)
-{
- return jb_framelist_size(&jb->jb_framelist);
-}
+ state->frame_size = jb->jb_frame_size;
+ state->prefetch = jb->jb_prefetch;
+ state->min_prefetch = jb->jb_min_prefetch;
+ state->max_prefetch = jb->jb_max_prefetch;
+ state->size = jb_framelist_size(&jb->jb_framelist);
+ return PJ_SUCCESS;
+}
diff --git a/pjmedia/src/pjmedia/session.c b/pjmedia/src/pjmedia/session.c
index c09926b8..42207cad 100644
--- a/pjmedia/src/pjmedia/session.c
+++ b/pjmedia/src/pjmedia/session.c
@@ -302,8 +302,8 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
- /* Get local DTMF payload type */
- si->tx_event_pt = -1;
+ /* Get incomming payload type for telephone-events */
+ si->rx_event_pt = -1;
for (i=0; i<local_m->attr_count; ++i) {
pjmedia_sdp_rtpmap r;
@@ -313,13 +313,13 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
if (pjmedia_sdp_attr_get_rtpmap(attr, &r) != PJ_SUCCESS)
continue;
if (pj_strcmp(&r.enc_name, &ID_TELEPHONE_EVENT) == 0) {
- si->tx_event_pt = pj_strtoul(&r.pt);
+ si->rx_event_pt = pj_strtoul(&r.pt);
break;
}
}
- /* Get remote DTMF payload type */
- si->rx_event_pt = -1;
+ /* Get outgoing payload type for telephone-events */
+ si->tx_event_pt = -1;
for (i=0; i<rem_m->attr_count; ++i) {
pjmedia_sdp_rtpmap r;
@@ -329,7 +329,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
if (pjmedia_sdp_attr_get_rtpmap(attr, &r) != PJ_SUCCESS)
continue;
if (pj_strcmp(&r.enc_name, &ID_TELEPHONE_EVENT) == 0) {
- si->rx_event_pt = pj_strtoul(&r.pt);
+ si->tx_event_pt = pj_strtoul(&r.pt);
break;
}
}
diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c
index d7a38df4..41f506a0 100644
--- a/pjmedia/src/pjmedia/stream.c
+++ b/pjmedia/src/pjmedia/stream.c
@@ -174,9 +174,7 @@ static pj_status_t get_frame( pjmedia_port *port, pjmedia_frame *frame)
/* Unlock jitter buffer mutex. */
pj_mutex_unlock( stream->jb_mutex );
- if (status != PJ_SUCCESS || frame_type == PJMEDIA_JB_ZERO_FRAME ||
- frame_type == PJMEDIA_JB_MISSING_FRAME)
- {
+ if (status != PJ_SUCCESS || frame_type != PJMEDIA_JB_NORMAL_FRAME) {
frame->type = PJMEDIA_FRAME_TYPE_NONE;
return PJ_SUCCESS;
}
@@ -627,8 +625,10 @@ static void on_rx_rtp( pj_ioqueue_key_t *key,
PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset"));
} else {
+ unsigned ext_seq;
+ ext_seq = channel->rtp.seq_ctrl.cycles | pj_ntohs(hdr->seq);
status = pjmedia_jbuf_put_frame(stream->jb, payload, payloadlen,
- pj_ntohs(hdr->seq));
+ ext_seq);
}
pj_mutex_unlock( stream->jb_mutex );
@@ -914,11 +914,12 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
info->fmt.clock_rate);
status = pjmedia_jbuf_create(pool, &stream->port.info.name,
stream->frame_size,
- jbuf_init, jbuf_max,
- &stream->jb);
+ jbuf_max, &stream->jb);
if (status != PJ_SUCCESS)
goto err_cleanup;
+ /* Set jitter buffer to adaptive */
+ pjmedia_jbuf_set_adaptive( stream->jb, jbuf_init, 1, jbuf_max * 4 / 5);
/* Create decoder channel: */