📄 jitter.c
字号:
late_ratio_short = 0;
late_ratio_long = 0;
for (i=0;i<LATE_BINS;i++)
{
late_ratio_short += jitter->shortterm_margin[i];
late_ratio_long += jitter->longterm_margin[i];
}
ontime_ratio_short = jitter->shortterm_margin[LATE_BINS];
ontime_ratio_long = jitter->longterm_margin[LATE_BINS];
early_ratio_short = early_ratio_long = 0;
for (i=LATE_BINS+1;i<MAX_MARGIN;i++)
{
early_ratio_short += jitter->shortterm_margin[i];
early_ratio_long += jitter->longterm_margin[i];
}
if (0&&jitter->pointer_timestamp%1000==0)
{
/*fprintf (stderr, "%f %f %f %f %f %f\n", early_ratio_short, early_ratio_long, ontime_ratio_short, ontime_ratio_long, late_ratio_short, late_ratio_long);*/
/*fprintf (stderr, "%f %f\n", early_ratio_short + ontime_ratio_short + late_ratio_short, early_ratio_long + ontime_ratio_long + late_ratio_long);*/
}
/* Adjusting the buffering */
if (late_ratio_short > .1 || late_ratio_long > .03)
{
/* If too many packets are arriving late */
jitter->shortterm_margin[MAX_MARGIN-1] += jitter->shortterm_margin[MAX_MARGIN-2];
jitter->longterm_margin[MAX_MARGIN-1] += jitter->longterm_margin[MAX_MARGIN-2];
for (i=MAX_MARGIN-3;i>=0;i--)
{
jitter->shortterm_margin[i+1] = jitter->shortterm_margin[i];
jitter->longterm_margin[i+1] = jitter->longterm_margin[i];
}
jitter->shortterm_margin[0] = 0;
jitter->longterm_margin[0] = 0;
jitter->pointer_timestamp -= jitter->tick_size;
jitter->current_timestamp -= jitter->tick_size;
/*fprintf (stderr, "i");*/
/*fprintf (stderr, "interpolate (getting some slack)\n");*/
} else if (late_ratio_short + ontime_ratio_short < .005 && late_ratio_long + ontime_ratio_long < .01 && early_ratio_short > .8)
{
/* Many frames arriving early */
jitter->shortterm_margin[0] += jitter->shortterm_margin[1];
jitter->longterm_margin[0] += jitter->longterm_margin[1];
for (i=1;i<MAX_MARGIN-1;i++)
{
jitter->shortterm_margin[i] = jitter->shortterm_margin[i+1];
jitter->longterm_margin[i] = jitter->longterm_margin[i+1];
}
jitter->shortterm_margin[MAX_MARGIN-1] = 0;
jitter->longterm_margin[MAX_MARGIN-1] = 0;
/*fprintf (stderr, "drop frame\n");*/
/*fprintf (stderr, "d");*/
jitter->pointer_timestamp += jitter->tick_size;
jitter->current_timestamp += jitter->tick_size;
/*fprintf (stderr, "dropping packet (getting more aggressive)\n");*/
}
/* Searching for the packet that fits best */
/* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
if (jitter->buf[i] && jitter->timestamp[i]==jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size))
break;
}
/* If no match, try for an "older" packet that still spans (fully) the current chunk */
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
{
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GE32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp+chunk_size))
break;
}
}
/* If still no match, try for an "older" packet that spans part of the current chunk */
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
{
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
if (jitter->buf[i] && jitter->timestamp[i]<=jitter->pointer_timestamp && GT32(jitter->timestamp[i]+jitter->span[i],jitter->pointer_timestamp))
break;
}
}
/* If still no match, try for earliest packet possible */
if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
{
int found = 0;
spx_uint32_t best_time=0;
int best_span=0;
int besti=0;
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
{
/* check if packet starts within current chunk */
if (jitter->buf[i] && LT32(jitter->timestamp[i],jitter->pointer_timestamp+chunk_size) && GE32(jitter->timestamp[i],jitter->pointer_timestamp))
{
if (!found || LT32(jitter->timestamp[i],best_time) || (jitter->timestamp[i]==best_time && GT32(jitter->span[i],best_span)))
{
best_time = jitter->timestamp[i];
best_span = jitter->span[i];
besti = i;
found = 1;
}
}
}
if (found)
{
i=besti;
incomplete = 1;
/*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->timestamp[i], jitter->pointer_timestamp, chunk_size, jitter->span[i]);*/
}
}
/* If we find something */
if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
{
/* We (obviously) haven't lost this packet */
jitter->lost_count = 0;
jitter->loss_rate = .999*jitter->loss_rate;
/* Check for potential overflow */
packet->len = jitter->len[i];
/* Copy packet */
for (j=0;j<packet->len;j++)
packet->data[j] = jitter->buf[i][j];
/* Remove packet */
speex_free(jitter->buf[i]);
jitter->buf[i] = NULL;
/* Set timestamp and span (if requested) */
if (start_offset)
*start_offset = jitter->timestamp[i]-jitter->pointer_timestamp;
packet->timestamp = jitter->timestamp[i];
packet->span = jitter->span[i];
/* Point at the end of the current packet */
jitter->pointer_timestamp = jitter->timestamp[i]+jitter->span[i];
if (incomplete)
return JITTER_BUFFER_INCOMPLETE;
else
return JITTER_BUFFER_OK;
}
/* If we haven't found anything worth returning */
/*fprintf (stderr, "not found\n");*/
jitter->lost_count++;
/*fprintf (stderr, "m");*/
/*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/
jitter->loss_rate = .999*jitter->loss_rate + .001;
if (start_offset)
*start_offset = 0;
packet->timestamp = jitter->pointer_timestamp;
packet->span = jitter->tick_size;
jitter->pointer_timestamp += chunk_size;
packet->len = 0;
return JITTER_BUFFER_MISSING;
}
/** Get pointer timestamp of jitter buffer */
int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
{
return jitter->pointer_timestamp;
}
void jitter_buffer_tick(JitterBuffer *jitter)
{
jitter->current_timestamp += jitter->tick_size;
}
void speex_jitter_init(SpeexJitter *jitter, void *decoder, int sampling_rate)
{
jitter->dec = decoder;
speex_decoder_ctl(decoder, SPEEX_GET_FRAME_SIZE, &jitter->frame_size);
jitter->packets = jitter_buffer_init(jitter->frame_size);
speex_bits_init(&jitter->current_packet);
jitter->valid_bits = 0;
}
void speex_jitter_destroy(SpeexJitter *jitter)
{
jitter_buffer_destroy(jitter->packets);
speex_bits_destroy(&jitter->current_packet);
}
void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp)
{
JitterBufferPacket p;
p.data = packet;
p.len = len;
p.timestamp = timestamp;
p.span = jitter->frame_size;
jitter_buffer_put(jitter->packets, &p);
}
void speex_jitter_get(SpeexJitter *jitter, short *out, int *current_timestamp)
{
int i;
int ret;
char data[2048];
JitterBufferPacket packet;
packet.data = data;
if (jitter->valid_bits)
{
/* Try decoding last received packet */
ret = speex_decode_int(jitter->dec, &jitter->current_packet, out);
if (ret == 0)
{
jitter_buffer_tick(jitter->packets);
return;
} else {
jitter->valid_bits = 0;
}
}
ret = jitter_buffer_get(jitter->packets, &packet, NULL);
if (ret != JITTER_BUFFER_OK)
{
/* No packet found */
/*fprintf (stderr, "lost/late frame\n");*/
/*Packet is late or lost*/
speex_decode_int(jitter->dec, NULL, out);
} else {
speex_bits_read_from(&jitter->current_packet, packet.data, packet.len);
/* Decode packet */
ret = speex_decode_int(jitter->dec, &jitter->current_packet, out);
if (ret == 0)
{
jitter->valid_bits = 1;
} else {
/* Error while decoding */
for (i=0;i<jitter->frame_size;i++)
out[i]=0;
}
}
jitter_buffer_tick(jitter->packets);
}
int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter)
{
return jitter_buffer_get_pointer_timestamp(jitter->packets);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -