diff --git a/daemon/codec.c b/daemon/codec.c index f5973ec7f..794a7d408 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -33,6 +33,11 @@ struct mqtt_timer { struct call_media *media; }; +typedef void (*raw_input_func_t)(struct media_packet *mp, unsigned int); + +static void __buffer_delay_raw(struct delay_buffer *dbuf, + raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate); + static codec_handler_func handler_func_passthrough; static struct timerthread codec_timers_thread; @@ -127,7 +132,9 @@ struct delay_buffer { struct delay_frame { AVFrame *frame; struct media_packet mp; - encoder_input_func_t func; + unsigned int clockrate; + encoder_input_func_t encoder_func; + raw_input_func_t raw_func; struct codec_handler *handler; struct codec_ssrc_handler *ch; }; @@ -325,6 +332,14 @@ static void __make_passthrough(struct codec_handler *handler, int dtmf_pt, int c handler->dtmf_payload_type = dtmf_pt; handler->cn_payload_type = cn_pt; handler->passthrough = 1; + +#ifdef WITH_TRANSCODING + if (handler->media->buffer_delay) { + __delay_buffer_setup(&handler->delay_buffer, handler, handler->media->call, + handler->media->buffer_delay); + handler->kernelize = 0; + } +#endif } static void __make_passthrough_ssrc(struct codec_handler *handler) { int dtmf_pt = handler->dtmf_payload_type; @@ -344,6 +359,14 @@ static void __make_passthrough_ssrc(struct codec_handler *handler) { handler->dtmf_payload_type = dtmf_pt; handler->cn_payload_type = cn_pt; handler->passthrough = 1; + +#ifdef WITH_TRANSCODING + if (handler->media->buffer_delay) { + __delay_buffer_setup(&handler->delay_buffer, handler, handler->media->call, + handler->media->buffer_delay); + handler->kernelize = 0; + } +#endif } static void __reset_sequencer(void *p, void *dummy) { @@ -1378,7 +1401,9 @@ static int handler_func_passthrough(struct codec_handler *h, struct media_packet codec_calc_jitter(mp->ssrc_in, ntohl(mp->rtp->timestamp), h->source_pt.clock_rate, &mp->tv); codec_calc_lost(mp->ssrc_in, ntohs(mp->rtp->seq_num)); } - codec_add_raw_packet(mp, h->source_pt.clock_rate); + + __buffer_delay_raw(h->delay_buffer, codec_add_raw_packet, mp, h->source_pt.clock_rate); + return 0; } @@ -2032,7 +2057,8 @@ static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_p // keep track of other stats here? - codec_add_raw_packet(mp, h->source_pt.clock_rate); + __buffer_delay_raw(h->delay_buffer, codec_add_raw_packet, mp, h->source_pt.clock_rate); + return 0; } @@ -2154,7 +2180,7 @@ static void __buffer_delay_frame(struct delay_buffer *dbuf, struct codec_ssrc_ha struct delay_frame *dframe = g_slice_alloc0(sizeof(*dframe)); dframe->frame = frame; - dframe->func = input_func; + dframe->encoder_func = input_func; dframe->ch = obj_get(&ch->h); media_packet_copy(&dframe->mp, mp); @@ -2165,6 +2191,31 @@ static void __buffer_delay_frame(struct delay_buffer *dbuf, struct codec_ssrc_ha } +static void __buffer_delay_raw(struct delay_buffer *dbuf, + raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate) +{ + if (__buffer_delay_do_direct(dbuf)) { + // direct passthrough + input_func(mp, clockrate); + return; + } + + struct delay_frame *dframe = g_slice_alloc0(sizeof(*dframe)); + dframe->raw_func = input_func; + dframe->clockrate = clockrate; + media_packet_copy(&dframe->mp, mp); + + // also copy packet payload + dframe->mp.raw = mp->raw; + dframe->mp.raw.s = g_malloc(mp->raw.len + RTP_BUFFER_TAIL_ROOM); + memcpy(dframe->mp.raw.s, mp->raw.s, mp->raw.len); + + LOCK(&dbuf->lock); + g_queue_insert_sorted(&dbuf->frames, dframe, delay_frame_cmp, NULL); + + __delay_buffer_schedule(dbuf); +} + // consumes `packet` if buffered (returns 1) static int __buffer_dtx(struct dtx_buffer *dtxb, struct codec_ssrc_handler *decoder_handler, struct codec_ssrc_handler *input_handler, @@ -2215,8 +2266,9 @@ static int __buffer_dtx(struct dtx_buffer *dtxb, struct codec_ssrc_handler *deco } static void delay_frame_free(struct delay_frame *dframe) { - media_packet_release(&dframe->mp); av_frame_free(&dframe->frame); + g_free(dframe->mp.raw.s); + media_packet_release(&dframe->mp); if (dframe->ch) obj_put(&dframe->ch->h); g_slice_free1(sizeof(*dframe), dframe); @@ -2276,9 +2328,11 @@ static void __delay_frame_process(struct delay_buffer *dbuf, struct delay_frame struct codec_ssrc_handler *csh = dframe->ch; if (csh && csh->handler && csh->encoder) { - dframe->func(csh->encoder, dframe->frame, csh->handler->packet_encoded, + dframe->encoder_func(csh->encoder, dframe->frame, csh->handler->packet_encoded, csh, &dframe->mp); } + else if (dframe->raw_func) + dframe->raw_func(&dframe->mp, dframe->clockrate); else ilog(LOG_ERR | LOG_FLAG_LIMIT, "Delay buffer bug"); } @@ -2729,6 +2783,8 @@ static void __delay_buffer_setup(struct delay_buffer **dbufp, dbuf->call = obj_get(call); dbuf->delay = delay; mutex_init(&dbuf->lock); + + *dbufp = dbuf; } static void __ssrc_handler_stop(void *p, void *dummy) { struct codec_ssrc_handler *ch = p; @@ -3194,6 +3250,15 @@ out: return ret; } +#else + +// dummy/stub +static void __buffer_delay_raw(struct delay_buffer *dbuf, + raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate) +{ + input_func(mp, clockrate); +} + #endif