提交 9c475bb6 authored 作者: Michael Jerris's avatar Michael Jerris

backport change from the iaxclient sf repository rev 648, 649, 650, 656.

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5158 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 343d77a4
......@@ -226,6 +226,10 @@ extern unsigned int iax_session_get_capability(struct iax_session *s);
extern char iax_pref_codec_add(struct iax_session *session, unsigned int format);
extern void iax_pref_codec_del(struct iax_session *session, unsigned int format);
extern int iax_pref_codec_get(struct iax_session *session, unsigned int *array, int len);
/* Fine tune jitterbuffer */
extern void iax_set_jb_target_extra( long value );
extern char *iax_get_peer_ip(struct iax_session *session);
extern char *iax_event_get_apparent_ip(struct iax_event *event);
extern void iax_set_samplerate(struct iax_session *session, unsigned short samplemask);
......
......@@ -140,6 +140,9 @@ static int netfd = -1;
/* Max timeouts */
static int maxretries = 10;
/* configurable jitterbuffer options */
static long jb_target_extra = -1;
static int do_shutdown = 0;
/* external global networking replacements */
......@@ -521,6 +524,7 @@ struct iax_session *iax_session_new(void)
jbconf.max_jitterbuf = 0;
jbconf.resync_threshold = 1000;
jbconf.max_contig_interp = 0;
jbconf.target_extra = jb_target_extra;
jb_setconf(s->jb, &jbconf);
}
#endif
......@@ -944,6 +948,12 @@ int iax_shutdown(void)
return do_shutdown++;
}
void iax_set_jb_target_extra( long value )
{
/* store in jb_target_extra, a static global */
jb_target_extra = value ;
}
int iax_init(char *ip, int preferredportno)
{
int portno = preferredportno;
......
......@@ -14,17 +14,19 @@
*/
#include "iax2.h"
#include "jitterbuf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "jitterbuf.h"
/* define these here, just for ancient compiler systems */
#define JB_LONGMAX 2147483647L
#define JB_LONGMIN (-JB_LONGMAX - 1L)
/* MS VC can't do __VA_ARGS__ */
#if defined(WIN32) && defined(_MSC_VER)
#if (defined(WIN32) || defined(_WIN32_WCE)) && defined(_MSC_VER)
#define jb_warn if (warnf) warnf
#define jb_err if (errf) errf
#define jb_dbg if (dbgf) dbgf
......@@ -72,11 +74,11 @@ void jb_reset(jitterbuf *jb)
{
/* only save settings */
jb_conf s = jb->info.conf;
memset(jb,0,sizeof(jitterbuf));
memset(jb, 0, sizeof(*jb));
jb->info.conf = s;
/* initialize length */
jb->info.current = jb->info.target = JB_TARGET_EXTRA;
/* initialize length, using the configured value */
jb->info.current = jb->info.target = jb->info.conf.target_extra;
jb->info.silence_begin_ts = -1;
}
......@@ -84,9 +86,10 @@ jitterbuf * jb_new()
{
jitterbuf *jb;
if (!(jb = (jitterbuf *)malloc(sizeof(*jb))))
return NULL;
jb = malloc(sizeof(jitterbuf));
if(!jb) return NULL;
jb->info.conf.target_extra = JB_TARGET_EXTRA;
jb_reset(jb);
......@@ -101,7 +104,7 @@ void jb_destroy(jitterbuf *jb)
/* free all the frames on the "free list" */
frame = jb->free;
while(frame != NULL) {
while (frame != NULL) {
jb_frame *next = frame->next;
free(frame);
frame = next;
......@@ -113,10 +116,6 @@ void jb_destroy(jitterbuf *jb)
/* simple history manipulation */
/* maybe later we can make the history buckets variable size, or something? */
/* drop parameter determines whether we will drop outliers to minimize
* delay */
#if 0
static int longcmp(const void *a, const void *b)
{
......@@ -124,6 +123,10 @@ static int longcmp(const void *a, const void *b)
}
#endif
/* simple history manipulation */
/* maybe later we can make the history buckets variable size, or something? */
/* drop parameter determines whether we will drop outliers to minimize
* delay */
static int history_put(jitterbuf *jb, time_in_ms_t ts, time_in_ms_t now, long ms)
{
time_in_ms_t delay = now - (ts - jb->info.resync_offset);
......@@ -156,36 +159,38 @@ static int history_put(jitterbuf *jb, time_in_ms_t ts, time_in_ms_t now, long ms
}
}
kicked = jb->history[jb->hist_ptr & JB_HISTORY_SZ];
kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
/* optimization; the max/min buffers don't need to be recalculated, if this packet's
* entry doesn't change them. This happens if this packet is not involved, _and_ any packet
* that got kicked out of the history is also not involved
* We do a number of comparisons, but it's probably still worthwhile, because it will usually
* succeed, and should be a lot faster than going through all 500 packets in history */
if(!jb->hist_maxbuf_valid)
/* optimization; the max/min buffers don't need to be recalculated,
* if this packet's entry doesn't change them. This happens if this
* packet is not involved, _and_ any packet that got kicked out of
* the history is also not involved. We do a number of comparisons,
* but it's probably still worthwhile, because it will usually
* succeed, and should be a lot faster than going through all 500
* packets in history */
if (!jb->hist_maxbuf_valid)
return 0;
/* don't do this until we've filled history
* (reduces some edge cases below) */
if(jb->hist_ptr < JB_HISTORY_SZ)
if (jb->hist_ptr < JB_HISTORY_SZ)
goto invalidate;
/* if the new delay would go into min */
if(delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
goto invalidate;
/* or max.. */
if(delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
goto invalidate;
/* or the kicked delay would be in min */
if(kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
goto invalidate;
if(kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
goto invalidate;
/* if we got here, we don't need to invalidate, 'cause this delay didn't
......@@ -203,12 +208,13 @@ static void history_calc_maxbuf(jitterbuf *jb)
{
int i,j;
if(jb->hist_ptr == 0) return;
if (jb->hist_ptr == 0)
return;
/* initialize maxbuf/minbuf to the latest value */
for(i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
/*
for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
/*
* jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
* jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
*/
......@@ -222,18 +228,18 @@ static void history_calc_maxbuf(jitterbuf *jb)
/* start at the beginning, or JB_HISTORY_SZ frames ago */
i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0;
for(;i<jb->hist_ptr;i++) {
for (;i<jb->hist_ptr;i++) {
time_in_ms_t toins = jb->history[i % JB_HISTORY_SZ];
/* if the maxbuf should get this */
if(toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) {
if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) {
/* insertion-sort it into the maxbuf */
for(j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
/* found where it fits */
if(toins > jb->hist_maxbuf[j]) {
if (toins > jb->hist_maxbuf[j]) {
/* move over */
memmove(jb->hist_maxbuf+j+1,jb->hist_maxbuf+j, (JB_HISTORY_MAXBUF_SZ-(j+1)) * sizeof(long));
memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0]));
/* insert */
jb->hist_maxbuf[j] = toins;
......@@ -243,14 +249,14 @@ static void history_calc_maxbuf(jitterbuf *jb)
}
/* if the minbuf should get this */
if(toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) {
if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) {
/* insertion-sort it into the maxbuf */
for(j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
/* found where it fits */
if(toins < jb->hist_minbuf[j]) {
if (toins < jb->hist_minbuf[j]) {
/* move over */
memmove(jb->hist_minbuf+j+1,jb->hist_minbuf+j, (JB_HISTORY_MAXBUF_SZ-(j+1)) * sizeof(long));
memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0]));
/* insert */
jb->hist_minbuf[j] = toins;
......@@ -259,14 +265,14 @@ static void history_calc_maxbuf(jitterbuf *jb)
}
}
if(0) {
if (0) {
int k;
fprintf(stderr, "toins = %ld\n", toins);
fprintf(stderr, "maxbuf =");
for(k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
fprintf(stderr, "%ld ", jb->hist_maxbuf[k]);
fprintf(stderr, "\nminbuf =");
for(k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
fprintf(stderr, "%ld ", jb->hist_minbuf[k]);
fprintf(stderr, "\n");
}
......@@ -281,7 +287,7 @@ static void history_get(jitterbuf *jb)
int index;
int count;
if(!jb->hist_maxbuf_valid)
if (!jb->hist_maxbuf_valid)
history_calc_maxbuf(jb);
/* count is how many items in history we're examining */
......@@ -291,10 +297,11 @@ static void history_get(jitterbuf *jb)
index = count * JB_HISTORY_DROPPCT / 100;
/* sanity checks for index */
if(index > (JB_HISTORY_MAXBUF_SZ - 1)) index = JB_HISTORY_MAXBUF_SZ - 1;
if (index > (JB_HISTORY_MAXBUF_SZ - 1))
index = JB_HISTORY_MAXBUF_SZ - 1;
if(index < 0) {
if (index < 0) {
jb->info.min = 0;
jb->info.jitter = 0;
return;
......@@ -317,21 +324,16 @@ static void history_get(jitterbuf *jb)
}
/* returns 1 if frame was inserted into head of queue, 0 otherwise */
static int queue_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t ts)
static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, time_in_ms_t ts)
{
jb_frame *frame;
jb_frame *p;
int head = 0;
time_in_ms_t resync_ts = ts - jb->info.resync_offset;
frame = jb->free;
if(frame) {
if ((frame = jb->free)) {
jb->free = frame->next;
} else {
frame = malloc(sizeof(jb_frame));
}
if(!frame) {
} else if (!(frame = (jb_frame *)malloc(sizeof(*frame)))) {
jb_err("cannot allocate frame\n");
return 0;
}
......@@ -348,7 +350,7 @@ static int queue_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t
* jb->frames->prev points to the highest ts
*/
if(!jb->frames) { /* queue is empty */
if (!jb->frames) { /* queue is empty */
jb->frames = frame;
frame->next = frame;
frame->prev = frame;
......@@ -369,7 +371,7 @@ static int queue_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t
p = jb->frames;
/* frame is out of order */
if(ts < p->prev->ts) jb->info.frames_ooo++;
if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
while (resync_ts < p->prev->ts && p->prev != jb->frames)
p = p->prev;
......@@ -385,14 +387,18 @@ static int queue_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t
static time_in_ms_t queue_next(jitterbuf *jb)
{
if(jb->frames) return jb->frames->ts;
else return -1;
if (jb->frames)
return jb->frames->ts;
else
return -1;
}
static time_in_ms_t queue_last(jitterbuf *jb)
{
if(jb->frames) return jb->frames->prev->ts;
else return -1;
if (jb->frames)
return jb->frames->prev->ts;
else
return -1;
}
static jb_frame *_queue_get(jitterbuf *jb, time_in_ms_t ts, int all)
......@@ -400,17 +406,17 @@ static jb_frame *_queue_get(jitterbuf *jb, time_in_ms_t ts, int all)
jb_frame *frame;
frame = jb->frames;
if(!frame)
if (!frame)
return NULL;
/*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */
if(all || ts >= frame->ts) {
if (all || ts >= frame->ts) {
/* remove this frame */
frame->prev->next = frame->next;
frame->next->prev = frame->prev;
if(frame->next == frame)
if (frame->next == frame)
jb->frames = NULL;
else
jb->frames = frame->next;
......@@ -444,15 +450,16 @@ static jb_frame *queue_getall(jitterbuf *jb)
/* some diagnostics */
static void jb_dbginfo(jitterbuf *jb)
{
if(dbgf == NULL) return;
if (dbgf == NULL)
return;
jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur);
jb_dbg(" jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,
jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
if(jb->info.frames_in > 0)
if (jb->info.frames_in > 0)
jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),
jb->info.frames_late * 100/jb->info.frames_in);
......@@ -471,12 +478,12 @@ static void jb_chkqueue(jitterbuf *jb)
int i=0;
jb_frame *p = jb->frames;
if(!p) {
if (!p) {
return;
}
do {
if(p->next == NULL) {
if (p->next == NULL) {
jb_err("Queue is BROKEN at item [%d]", i);
}
i++;
......@@ -491,7 +498,7 @@ static void jb_dbgqueue(jitterbuf *jb)
jb_dbg("queue: ");
if(!p) {
if (!p) {
jb_dbg("EMPTY\n");
return;
}
......@@ -505,15 +512,18 @@ static void jb_dbgqueue(jitterbuf *jb)
}
#endif
int jb_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t ts, time_in_ms_t now)
enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, time_in_ms_t ts, time_in_ms_t now)
{
jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
jb->info.frames_in++;
if(type == JB_TYPE_VOICE) {
/* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
* IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
if (type == JB_TYPE_VOICE) {
/* presently, I'm only adding VOICE frames to history and drift
* calculations; mostly because with the IAX integrations, I'm
* sending retransmitted control frames with their awkward
* timestamps through
*/
if (history_put(jb,ts,now,ms))
return JB_DROP;
}
......@@ -527,21 +537,21 @@ int jb_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t ts, time_i
}
static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long interpl)
static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long interpl)
{
jb_frame *frame;
time_in_ms_t diff;
/*if((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */
/*if ((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */
/* get jitter info */
history_get(jb);
/* target */
jb->info.target = jb->info.jitter + jb->info.min + JB_TARGET_EXTRA;
jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra;
/* if a hard clamp was requested, use it */
if((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
jb_dbg("clamping target from %d to %d\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
}
......@@ -552,32 +562,33 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
/* jb->info.last_voice_ms, jb->info.last_adjustment, now); */
/* let's work on non-silent case first */
if(!jb->info.silence_begin_ts) {
if (!jb->info.silence_begin_ts) {
/* we want to grow */
if( (diff > 0) &&
if ((diff > 0) &&
/* we haven't grown in the delay length */
(((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||
/* we need to grow more than the "length" we have left */
(diff > queue_last(jb) - queue_next(jb)) ) ) {
/* grow by interp frame len */
/* grow by interp frame length */
jb->info.current += interpl;
jb->info.next_voice_ts += interpl;
jb->info.last_voice_ms = interpl;
jb->info.last_adjustment = now;
jb->info.cnt_contig_interp++;
jb_dbg("G");
/* assume silence instead of continuing to interpolate */
if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp)
if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
}
jb_dbg("G");
return JB_INTERP;
}
frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
/* not a voice frame; just return it. */
if(frame && frame->type != JB_TYPE_VOICE) {
if (frame && frame->type != JB_TYPE_VOICE) {
/* track start of silence */
if(frame->type == JB_TYPE_SILENCE) {
if (frame->type == JB_TYPE_SILENCE) {
jb->info.silence_begin_ts = frame->ts;
jb->info.cnt_contig_interp = 0;
}
......@@ -589,7 +600,7 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
}
/* voice frame is later than expected */
if(frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
/* either we interpolated past this frame in the last jb_get */
/* or the frame is still in order, but came a little too quick */
......@@ -616,7 +627,7 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
}
/* keep track of frame sizes, to allow for variable sized-frames */
if(frame && frame->ms > 0) {
if (frame && frame->ms > 0) {
jb->info.last_voice_ms = frame->ms;
}
......@@ -624,13 +635,14 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
/* unless we don't have a frame, then shrink 1 frame */
/* every 80ms (though perhaps we can shrink even faster */
/* in this case) */
if(diff < -JB_TARGET_EXTRA &&
if (diff < -jb->info.conf.target_extra &&
((!frame && jb->info.last_adjustment + 80 < now) ||
(jb->info.last_adjustment + 500 < now))) {
jb->info.last_adjustment = now;
jb->info.cnt_contig_interp = 0;
if(frame) {
if (frame) {
*frameout = *frame;
/* shrink by frame size we're throwing out */
jb->info.current -= frame->ms;
......@@ -650,7 +662,7 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
}
/* lost frame */
if(!frame) {
if (!frame) {
/* this is a bit of a hack for now, but if we're close to
* target, and we find a missing frame, it makes sense to
* grow, because the frame might just be a bit late;
......@@ -666,7 +678,7 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
* But, this still seemed like a good idea, except that it ended up making a single actual
* lost frame get interpolated two or more times, when there was "room" to grow, so it might
* be a bit of a bad idea overall */
/*if(diff > -1 * jb->info.last_voice_ms) {
/*if (diff > -1 * jb->info.last_voice_ms) {
jb->info.current += jb->info.last_voice_ms;
jb->info.last_adjustment = now;
jb_warn("g");
......@@ -678,8 +690,9 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
jb->info.last_voice_ms = interpl;
jb->info.cnt_contig_interp++;
/* assume silence instead of continuing to interpolate */
if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp)
if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
}
jb_dbg("L");
return JB_INTERP;
}
......@@ -688,8 +701,8 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
*frameout = *frame;
jb->info.next_voice_ts += frame->ms;
jb->info.frames_out++;
decrement_losspct(jb);
jb->info.cnt_contig_interp = 0;
decrement_losspct(jb);
jb_dbg("v");
return JB_OK;
} else {
......@@ -701,14 +714,14 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
/* jb->info.silence_begin_ts = 0; */
/* shrink interpl len every 10ms during silence */
if (diff < -JB_TARGET_EXTRA &&
if (diff < -jb->info.conf.target_extra &&
jb->info.last_adjustment + 10 <= now) {
jb->info.current -= interpl;
jb->info.last_adjustment = now;
}
frame = queue_get(jb, now - jb->info.current);
if(!frame) {
if (!frame) {
return JB_NOFRAME;
} else if (frame->type != JB_TYPE_VOICE) {
/* normal case; in silent mode, got a non-voice frame */
......@@ -745,39 +758,41 @@ static int _jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long int
time_in_ms_t jb_next(jitterbuf *jb)
{
if(jb->info.silence_begin_ts) {
if (jb->info.silence_begin_ts) {
if (jb->frames) {
time_in_ms_t next = queue_next(jb);
if(next > 0) {
history_get(jb);
/* shrink during silence */
if (jb->info.target - jb->info.current < -JB_TARGET_EXTRA)
if (jb->info.target - jb->info.current < -jb->info.conf.target_extra)
return jb->info.last_adjustment + 10;
return next + jb->info.target;
}
else return JB_LONGMAX;
else
return JB_LONGMAX;
} else {
return jb->info.next_voice_ts;
}
}
int jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long interpl)
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, time_in_ms_t now, long interpl)
{
int ret = _jb_get(jb,frameout,now,interpl);
enum jb_return_code ret = _jb_get(jb, frameout, now, interpl);
#if 0
static int lastts=0;
int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
if(thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
lastts = thists;
#endif
return ret;
}
int jb_getall(jitterbuf *jb, jb_frame *frameout)
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
{
jb_frame *frame;
frame = queue_getall(jb);
if(!frame) {
if (!frame) {
return JB_NOFRAME;
}
......@@ -786,9 +801,8 @@ int jb_getall(jitterbuf *jb, jb_frame *frameout)
}
int jb_getinfo(jitterbuf *jb, jb_info *stats)
enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
{
history_get(jb);
*stats = jb->info;
......@@ -796,7 +810,7 @@ int jb_getinfo(jitterbuf *jb, jb_info *stats)
return JB_OK;
}
int jb_setconf(jitterbuf *jb, jb_conf *conf)
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
{
/* take selected settings from the struct */
......@@ -804,6 +818,16 @@ int jb_setconf(jitterbuf *jb, jb_conf *conf)
jb->info.conf.resync_threshold = conf->resync_threshold;
jb->info.conf.max_contig_interp = conf->max_contig_interp;
/* -1 indicates use of the default JB_TARGET_EXTRA value */
jb->info.conf.target_extra = ( conf->target_extra == -1 )
? JB_TARGET_EXTRA
: conf->target_extra
;
/* update these to match new target_extra setting */
jb->info.current = jb->info.conf.target_extra;
jb->info.target = jb->info.conf.target_extra;
return JB_OK;
}
......
......@@ -35,27 +35,30 @@ extern "C" {
/* ms between growing and shrinking; may not be honored if jitterbuffer runs out of space */
#define JB_ADJUST_DELAY 40
/* return codes */
#define JB_OK 0
#define JB_EMPTY 1
#define JB_NOFRAME 2
#define JB_INTERP 3
#define JB_DROP 4
#define JB_SCHED 5
enum jb_return_code {
/* return codes */
JB_OK, /* 0 */
JB_EMPTY, /* 1 */
JB_NOFRAME, /* 2 */
JB_INTERP, /* 3 */
JB_DROP, /* 4 */
JB_SCHED /* 5 */
};
enum jb_frame_type {
/* frame types */
#define JB_TYPE_CONTROL 0
#define JB_TYPE_VOICE 1
#define JB_TYPE_VIDEO 2 /* reserved */
#define JB_TYPE_SILENCE 3
JB_TYPE_CONTROL, /* 0 */
JB_TYPE_VOICE, /* 1 */
JB_TYPE_VIDEO, /* 2 - reserved */
JB_TYPE_SILENCE /* 3 */
};
typedef struct jb_conf {
/* settings */
long max_jitterbuf; /* defines a hard clamp to use in setting the jitter buffer delay */
long resync_threshold; /* the jb will resync when delay increases to (2 * jitter) + this param */
long max_contig_interp; /* the max interp frames to return in a row */
long target_extra; /* amount of additional jitterbuffer adjustment, overrides JB_TARGET_EXTRA */
} jb_conf;
typedef struct jb_info {
......@@ -88,7 +91,7 @@ typedef struct jb_frame {
void *data; /* the frame data */
time_in_ms_t ts; /* the relative delivery time expected */
long ms; /* the time covered by this frame, in sec/8000 */
int type; /* the type of frame */
enum jb_frame_type type; /* the type of frame */
struct jb_frame *next, *prev;
} jb_frame;
......@@ -102,22 +105,21 @@ typedef struct jitterbuf {
time_in_ms_t hist_minbuf[JB_HISTORY_MAXBUF_SZ]; /* a sorted buffer of the min delays (lowest first) */
int hist_maxbuf_valid; /* are the "maxbuf"/minbuf valid? */
jb_frame *frames; /* queued frames */
jb_frame *free; /* free frames (avoid malloc?) */
} jitterbuf;
/* new jitterbuf */
extern jitterbuf * jb_new(void);
jitterbuf * jb_new(void);
/* destroy jitterbuf */
extern void jb_destroy(jitterbuf *jb);
void jb_destroy(jitterbuf *jb);
/* reset jitterbuf */
/* NOTE: The jitterbuffer should be empty before you call this, otherwise
* you will leak queued frames, and some internal structures */
extern void jb_reset(jitterbuf *jb);
void jb_reset(jitterbuf *jb);
/* queue a frame data=frame data, timings (in ms): ms=length of frame (for voice), ts=ts (sender's time)
* now=now (in receiver's time) return value is one of
......@@ -125,7 +127,7 @@ extern void jb_reset(jitterbuf *jb);
* JB_DROP: Drop this frame immediately
* JB_SCHED: Frame added. Call jb_next() to get a new time for the next frame
*/
extern int jb_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t ts, time_in_ms_t now);
enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, time_in_ms_t ts, time_in_ms_t now);
/* get a frame for time now (receiver's time) return value is one of
* JB_OK: You've got frame!
......@@ -134,20 +136,20 @@ extern int jb_put(jitterbuf *jb, void *data, int type, long ms, time_in_ms_t
* JB_INTERP: Please interpolate an interpl-length frame for this time (either we need to grow, or there was a lost frame)
* JB_EMPTY: The jb is empty.
*/
extern int jb_get(jitterbuf *jb, jb_frame *frame, time_in_ms_t now, long interpl);
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, time_in_ms_t now, long interpl);
/* unconditionally get frames from jitterbuf until empty */
extern int jb_getall(jitterbuf *jb, jb_frame *frameout);
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout);
/* when is the next frame due out, in receiver's time (0=EMPTY)
* This value may change as frames are added (esp non-audio frames) */
extern time_in_ms_t jb_next(jitterbuf *jb);
time_in_ms_t jb_next(jitterbuf *jb);
/* get jitterbuf info: only "statistics" may be valid */
extern int jb_getinfo(jitterbuf *jb, jb_info *stats);
enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats);
/* set jitterbuf conf */
extern int jb_setconf(jitterbuf *jb, jb_conf *conf);
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf);
typedef void (*jb_output_function_t)(const char *fmt, ...);
extern void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论