Skip to content

Commit

Permalink
jbuf: improve adaptive mode (#344)
Browse files Browse the repository at this point in the history
Replaces the out of order fault count by an expected sequence number difference
of out of order packets. The buffer has to be large enough to insert expected
out of order packets.
  • Loading branch information
cspiel1 authored May 8, 2022
1 parent 80451dd commit 920daeb
Showing 1 changed file with 38 additions and 82 deletions.
120 changes: 38 additions & 82 deletions src/jbuf/jbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
#endif

enum {
JBUF_FAULT_INC = 200,
JBUF_FAULT_HI = 3 * JBUF_FAULT_INC,
JBUF_RDIFF_EMA_COEFF = 512,
JBUF_RDIFF_UP_SPEED = 512,
};


Expand All @@ -52,13 +52,6 @@ struct frame {
};


enum jb_state {
JS_GOOD = 0,
JS_LOW,
JS_HIGH,
};


/**
* Defines a jitter buffer
*
Expand All @@ -76,10 +69,8 @@ struct jbuf {
uint16_t seq_get; /**< Sequence number of last played frame */
uint32_t ssrc; /**< Previous ssrc */
int pt; /**< Payload type */
bool started; /**< Jitter buffer is in start phase */
bool running; /**< Jitter buffer is running */
enum jb_state st; /**< computed jitter buffer state */
uint32_t faults; /**< Reorder faults */
int32_t rdiff; /**< Average out of order reverse diff */

struct lock *lock; /**< Makes jitter buffer thread safe */
enum jbuf_type jbtype; /**< Jitter buffer type */
Expand Down Expand Up @@ -188,7 +179,6 @@ int jbuf_alloc(struct jbuf **jbp, uint32_t min, uint32_t max)
jb->min = min;
jb->max = max;
jb->wish = min;
jb->faults = JBUF_FAULT_HI / 2;

DEBUG_INFO("alloc: delay=%u-%u frames\n", min, max);

Expand Down Expand Up @@ -238,40 +228,37 @@ int jbuf_set_type(struct jbuf *jb, enum jbuf_type jbtype)
}


/**
* Checks if the number of packets present in the jitter buffer is ok
* (JS_GOOD), should be increased (JS_LOW) or decremented (JS_HIGH).
*
* @param jb Jitter buffer
*
* @return JS_GOOD, JS_LOW, JS_HIGH.
*/
/* ------------------------------------------------------------------------- */
static enum jb_state jbuf_state(const struct jbuf *jb)
static void calc_rdiff(struct jbuf *jb, uint16_t seq)
{
return jb->st;
}

int32_t rdiff;
int32_t adiff;
int32_t s; /**< EMA coefficient */
uint32_t wish;

static void seq_failure(struct jbuf *jb)
{
if (jb->jbtype != JBUF_ADAPTIVE)
return;

if (jb->faults >= JBUF_FAULT_HI)
jb->st = JS_LOW;
else
jb->faults += JBUF_FAULT_INC;
}
if (!jb->seq_get)
return;

rdiff = (int16_t)(jb->seq_put + 1 - seq);
adiff = abs(rdiff * JBUF_RDIFF_EMA_COEFF);
s = adiff > jb->rdiff ? JBUF_RDIFF_UP_SPEED :
jb->wish > 2 ? 1 :
jb->wish > 1 ? 2 : 3;
jb->rdiff += (adiff - jb->rdiff) * s / JBUF_RDIFF_EMA_COEFF;

static void seq_ok(struct jbuf *jb)
{
if (jb->jbtype != JBUF_ADAPTIVE)
return;
wish = (uint32_t) (jb->rdiff / JBUF_RDIFF_EMA_COEFF);
if (wish < jb->min)
wish = jb->min;

if (jb->faults)
--jb->faults;
if (wish >= jb->max)
wish = jb->max - 1;

if (wish != jb->wish) {
DEBUG_INFO("wish size changed %u\n", jb->wish);
jb->wish = wish;
}
}


Expand Down Expand Up @@ -308,19 +295,18 @@ int jbuf_put(struct jbuf *jb, const struct rtp_header *hdr, void *mem)

if (jb->running) {

if (jb->jbtype == JBUF_ADAPTIVE)
calc_rdiff(jb, seq);

/* Packet arrived too late to be put into buffer */
if (jb->seq_get && seq_less(seq, jb->seq_get + 1)) {
STAT_INC(n_late);
DEBUG_INFO("packet too late: seq=%u "
"(seq_put=%u seq_get=%u)\n",
seq, jb->seq_put, jb->seq_get);
err = ETIMEDOUT;
seq_failure(jb);
goto out;
}
else {
seq_ok(jb);
}

}

Expand All @@ -343,7 +329,7 @@ int jbuf_put(struct jbuf *jb, const struct rtp_header *hdr, void *mem)
const uint16_t seq_le = ((struct frame *)le->data)->hdr.seq;

if (seq_less(seq_le, seq)) { /* most likely */
DEBUG_INFO("put: out-of-sequence"
DEBUG_PRINTF("put: out-of-sequence"
" - inserting after seq=%u (seq=%u)\n",
seq_le, seq);
list_insert_after(&jb->framel, le, &f->le, f);
Expand All @@ -364,7 +350,7 @@ int jbuf_put(struct jbuf *jb, const struct rtp_header *hdr, void *mem)

/* no earlier timestamps found, put in head */
if (!le) {
DEBUG_INFO("put: out-of-sequence"
DEBUG_PRINTF("put: out-of-sequence"
" - put in head (seq=%u)\n", seq);
list_prepend(&jb->framel, &f->le, f);
}
Expand Down Expand Up @@ -406,27 +392,10 @@ int jbuf_get(struct jbuf *jb, struct rtp_header *hdr, void **mem)

lock_write_get(jb->lock);
STAT_INC(n_get);
switch (jb->jbtype) {
case JBUF_ADAPTIVE:
if (jb->wish < jb->max-1 && jb->n < jb->max-1 &&
jbuf_state(jb) == JS_LOW) {
DEBUG_INFO("inc buffer due to reordered "
"packets n=%u max=%u\n",
jb->n, jb->max);
err = ENOENT;
jb->st = JS_GOOD;
++jb->wish;
goto out;
}
break;

default:
break;
}

if (jb->n <= jb->min || !jb->framel.head) {
if (jb->n <= jb->wish || !jb->framel.head) {
DEBUG_INFO("not enough buffer frames - wait.. "
"(n=%u min=%u)\n", jb->n, jb->min);
"(n=%u wish=%u)\n", jb->n, jb->wish);
STAT_INC(n_underflow);
err = ENOENT;
goto out;
Expand Down Expand Up @@ -461,23 +430,11 @@ int jbuf_get(struct jbuf *jb, struct rtp_header *hdr, void **mem)

frame_deref(jb, f);

switch (jb->jbtype) {
case JBUF_ADAPTIVE:
/* zero faults --> min == 0 */
if (jb->wish > jb->min &&
jb->wish > (jb->faults + JBUF_FAULT_INC - 1) /
JBUF_FAULT_INC)
--jb->wish;

if (jb->n > jb->wish) {
DEBUG_INFO("reducing jitter buffer "
"(n=%u min=%u wish=%u max=%u)\n",
jb->n, jb->min, jb->wish, jb->max);
err = EAGAIN;
}
break;
default:
break;
if (jb->jbtype == JBUF_ADAPTIVE && jb->n > jb->wish) {
DEBUG_INFO("reducing jitter buffer "
"(n=%u min=%u wish=%u max=%u)\n",
jb->n, jb->min, jb->wish, jb->max);
err = EAGAIN;
}

out:
Expand Down Expand Up @@ -523,7 +480,6 @@ void jbuf_flush(struct jbuf *jb)
memset(&jb->stat, 0, sizeof(jb->stat));
jb->stat.n_flush = n_flush;
#endif
jb->started = false;
lock_rel(jb->lock);
}

Expand Down

0 comments on commit 920daeb

Please sign in to comment.