diff --git a/daemon/codec.c b/daemon/codec.c index 96ca7b6ee..829eb49f1 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -154,6 +154,7 @@ struct delay_frame { struct codec_handler *handler; struct codec_ssrc_handler *ch; struct codec_ssrc_handler *input_ch; + int seq_adj; }; struct silence_event { @@ -270,6 +271,7 @@ static int __buffer_delay_packet(struct delay_buffer *dbuf, unsigned long ts_delay, int payload_type, packet_input_func_t packet_func, struct media_packet *mp, unsigned int clockrate); +static void __buffer_delay_seq(struct delay_buffer *dbuf, struct media_packet *mp, int seq_adj); static struct codec_handler codec_handler_stub_ssrc = { @@ -1889,7 +1891,7 @@ static int packet_dtmf_fwd(struct codec_ssrc_handler *ch, struct codec_ssrc_hand int ret = __buffer_delay_packet(input_h->delay_buffer, ch, input_ch, packet, ts_delay, payload_type, codec_add_dtmf_packet, mp, h->source_pt.clock_rate); - mp->ssrc_out->parent->seq_diff--; + __buffer_delay_seq(input_h->delay_buffer, mp, -1); return ret; } @@ -2287,13 +2289,16 @@ static int delay_frame_cmp(const void *A, const void *B, void *ptr) { } // consumes frame +// `frame` can be NULL (discarded/lost packet) static void __buffer_delay_frame(struct delay_buffer *dbuf, struct codec_ssrc_handler *ch, encoder_input_func_t input_func, AVFrame *frame, struct media_packet *mp, uint32_t ts) { if (__buffer_delay_do_direct(dbuf)) { // input now - input_func(ch->encoder, frame, ch->handler->packet_encoded, ch, mp); - av_frame_free(&frame); + if (frame) { + input_func(ch->encoder, frame, ch->handler->packet_encoded, ch, mp); + av_frame_free(&frame); + } return; } @@ -2373,7 +2378,29 @@ static int __buffer_delay_packet(struct delay_buffer *dbuf, return 1; } +static void __buffer_delay_seq(struct delay_buffer *dbuf, struct media_packet *mp, int seq_adj) { + if (!mp->ssrc_out) + return; + + if (__buffer_delay_do_direct(dbuf)) { + mp->ssrc_out->parent->seq_diff += seq_adj; + return; + } + + LOCK(&dbuf->lock); + + // peg the adjustment to the most recent frame if any + struct delay_frame *dframe = g_queue_peek_head(&dbuf->frames); + if (!dframe) { + mp->ssrc_out->parent->seq_diff += seq_adj; + return; + } + + dframe->seq_adj += seq_adj; +} + // consumes `packet` if buffered (returns 1) +// `packet` can be NULL (discarded packet for seq tracking) static int __buffer_dtx(struct dtx_buffer *dtxb, struct codec_ssrc_handler *decoder_handler, struct codec_ssrc_handler *input_handler, struct transcode_packet *packet, struct media_packet *mp, @@ -2384,7 +2411,7 @@ static int __buffer_dtx(struct dtx_buffer *dtxb, struct codec_ssrc_handler *deco if (!dtxb || !mp->sfd || !mp->ssrc_in || !mp->ssrc_out) return 0; - unsigned long ts = packet->ts; + unsigned long ts = packet ? packet->ts : 0; // allocate packet object struct dtx_packet *dtxp = g_slice_alloc0(sizeof(*dtxp)); @@ -2414,12 +2441,13 @@ static int __buffer_dtx(struct dtx_buffer *dtxb, struct codec_ssrc_handler *deco timerthread_obj_schedule_abs(&dtxb->ct.tt_obj, &dtxb->ct.next); } - // packet now consumed + // packet now consumed if there was one + int ret = packet ? 0 : 1; packet = NULL; mutex_unlock(&dtxb->lock); - return 1; + return ret; } static void delay_frame_free(struct delay_frame *dframe) { @@ -2558,15 +2586,6 @@ static void delay_packet_manipulate(struct delay_frame *dframe) { } } static void __delay_frame_process(struct delay_buffer *dbuf, struct delay_frame *dframe) { - if (dframe->mp.rtp) { - // adjust output seq num. pushing packets into the delay buffer looks as if they - // were consumed and resulted in a decreased seq_diff. we need to adjust the - // perceived seq num forward to compensate for this. each entry in the buffer - // accounts for one packet that was only delayed and not consumed: - //LOCK(&dbuf->lock); // XXX needed? - dframe->mp.rtp->seq_num = htons(ntohs(dframe->mp.rtp->seq_num) + dbuf->frames.length + 1); - } - struct codec_ssrc_handler *csh = dframe->ch; if (csh && csh->handler && csh->encoder && dframe->encoder_func) { @@ -2583,8 +2602,9 @@ static void __delay_frame_process(struct delay_buffer *dbuf, struct delay_frame dframe->packet_func(csh, dframe->input_ch, dframe->packet, dframe->ts_delay, dframe->payload_type, &dframe->mp); } - else - ilog(LOG_ERR | LOG_FLAG_LIMIT, "Delay buffer bug"); + + if (dframe->seq_adj) + dframe->mp.ssrc_out->parent->seq_diff += dframe->seq_adj; } static void __delay_send_later(struct codec_timer *ct) { struct delay_buffer *dbuf = (void *) ct; @@ -3441,7 +3461,8 @@ static int packet_decoded_common(decoder_t *decoder, AVFrame *frame, void *u1, v ch->encoder->codec_options.amr.cmr = mp->media_out->u.amr.cmr; uint32_t ts = mp->rtp ? ntohl(mp->rtp->timestamp) : frame->pts; - __buffer_delay_frame(h->delay_buffer, ch, input_func, frame, mp, ts); + __buffer_delay_frame(h->input_handler ? h->input_handler->delay_buffer : h->delay_buffer, + ch, input_func, frame, mp, ts); frame = NULL; // consumed discard: @@ -3461,10 +3482,12 @@ static int packet_decoded_direct(decoder_t *decoder, AVFrame *frame, void *u1, v static int __rtp_decode(struct codec_ssrc_handler *ch, struct codec_ssrc_handler *input_ch, struct transcode_packet *packet, struct media_packet *mp) { - int ret = decoder_input_data_ptime(ch->decoder, packet->payload, packet->ts, &mp->ptime, - ch->handler->packet_decoded, - ch, mp); - mp->ssrc_out->parent->seq_diff--; + int ret = 0; + if (packet) + ret = decoder_input_data_ptime(ch->decoder, packet->payload, packet->ts, &mp->ptime, + ch->handler->packet_decoded, + ch, mp); + __buffer_delay_seq(input_ch->handler->delay_buffer, mp, -1); return ret; } static int packet_decode(struct codec_ssrc_handler *ch, struct codec_ssrc_handler *input_ch, @@ -3486,12 +3509,8 @@ static int packet_decode(struct codec_ssrc_handler *ch, struct codec_ssrc_handle ilogs(transcoding, LOG_DEBUG, "Resetting decoder DTMF state due to TS discrepancy"); input_ch->dtmf_start_ts = 0; } - else { - ilogs(transcoding, LOG_DEBUG, "Decoder is in DTMF state, discaring codec packet"); - if (mp->ssrc_out) - mp->ssrc_out->parent->seq_diff--; - goto out; - } + else + packet = NULL; } }