📄 jitter.c
字号:
/* 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] && LE32(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] && LE32(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 = (spx_int32_t)jitter->timestamp[i]-(spx_int32_t)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; /* Adjusting the buffering bssed on the amount of packets that are early/on time/late */ 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");*/ } 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;}/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset){ int i; float late_ratio_short; float late_ratio_long; float ontime_ratio_short; float ontime_ratio_long; float early_ratio_short; float early_ratio_long; if (LT32(jitter->current_timestamp+jitter->tick_size, jitter->pointer_timestamp)) { jitter->current_timestamp = jitter->pointer_timestamp; speex_warning("did you forget to call jitter_buffer_tick() by any chance?"); } /*fprintf (stderr, "get packet %d %d\n", jitter->pointer_timestamp, jitter->current_timestamp);*/ /* FIXME: This should be only what remaining of the current tick */ late_ratio_short = 0; late_ratio_long = 0; /* Count the proportion of packets that are late */ for (i=0;i<LATE_BINS;i++) { late_ratio_short += jitter->shortterm_margin[i]; late_ratio_long += jitter->longterm_margin[i]; } /* Count the proportion of packets that are just on time */ ontime_ratio_short = jitter->shortterm_margin[LATE_BINS]; ontime_ratio_long = jitter->longterm_margin[LATE_BINS]; early_ratio_short = early_ratio_long = 0; /* Count the proportion of packets that are early */ for (i=LATE_BINS+1;i<MAX_MARGIN;i++) { early_ratio_short += jitter->shortterm_margin[i]; early_ratio_long += jitter->longterm_margin[i]; } /* Adjusting the buffering bssed on the amount of packets that are early/on time/late */ 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; jitter->interp_requested = 1; return JITTER_BUFFER_ADJUST_INTERPOLATE; } 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; return JITTER_BUFFER_ADJUST_DROP; } return JITTER_BUFFER_ADJUST_OK;}/* Used like the ioctl function to control the jitter buffer parameters */int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr){ int count, i; switch(request) { case JITTER_BUFFER_SET_MARGIN: jitter->buffer_margin = *(spx_int32_t*)ptr; break; case JITTER_BUFFER_GET_MARGIN: *(spx_int32_t*)ptr = jitter->buffer_margin; break; case JITTER_BUFFER_GET_AVALIABLE_COUNT: count = 0; for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) { if (jitter->buf[i] && LE32(jitter->pointer_timestamp, jitter->timestamp[i])) { count++; } } *(spx_int32_t*)ptr = count; break; default: speex_warning_int("Unknown jitter_buffer_ctl request: ", request); return -1; } return 0;}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_update_delay(jitter->packets, &packet, NULL); 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 + -