diff --git a/daemon/call.c b/daemon/call.c index e4edece98..26eefd82a 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -5207,7 +5207,7 @@ static void media_stop(struct call_media *m) { return; t38_gateway_stop(m->t38_gateway); audio_player_stop(m); - codec_handlers_stop(&m->codec_handlers_store, NULL); + codec_handlers_stop(&m->codec_handlers_store, NULL, false); rtcp_timer_stop(&m->rtcp_timer); mqtt_timer_stop(&m->mqtt_timer); } diff --git a/daemon/codec.c b/daemon/codec.c index 921c77630..47e2ac089 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -1466,7 +1466,7 @@ void __codec_handlers_update(struct call_media *receiver, struct call_media *sin if (proto_is_not_rtp(receiver->protocol)) { __generator_stop_all(receiver); __generator_stop_all(sink); - codec_handlers_stop(&receiver->codec_handlers_store, sink); + codec_handlers_stop(&receiver->codec_handlers_store, sink, a.clear_delay_buffer); return; } @@ -1482,7 +1482,10 @@ void __codec_handlers_update(struct call_media *receiver, struct call_media *sin // we're doing some kind of media passthrough - shut down local generators __generator_stop(receiver); __generator_stop(sink); - codec_handlers_stop(&receiver->codec_handlers_store, sink); + + // clear_delay_buffer is enabled by play-media to ensure media packets don't get scheduled + // alongside the delay buffer packets resulting in choppy audio + codec_handlers_stop(&receiver->codec_handlers_store, sink, a.clear_delay_buffer); // XXX this can cause unnecessary shutdown/resets of codec handlers bool is_transcoding = false; @@ -4157,7 +4160,7 @@ static void __ssrc_handler_stop(void *p, void *arg) { } codec_cc_stop(ch->chain); } -void codec_handlers_stop(codec_handlers_q *q, struct call_media *sink) { +void codec_handlers_stop(codec_handlers_q *q, struct call_media *sink, bool clear_delay_buffer) { for (__auto_type l = q->head; l; l = l->next) { struct codec_handler *h = l->data; @@ -4166,7 +4169,7 @@ void codec_handlers_stop(codec_handlers_q *q, struct call_media *sink) { if (h->delay_buffer) { mutex_lock(&h->delay_buffer->lock); - __delay_buffer_shutdown(h->delay_buffer, true); + __delay_buffer_shutdown(h->delay_buffer, !clear_delay_buffer); mutex_unlock(&h->delay_buffer->lock); delay_buffer_stop(&h->delay_buffer); @@ -4876,7 +4879,7 @@ void codec_update_all_handlers(struct call_monologue *ml) { dialogue_unconfirm(ml, "updating codec handlers"); } -void codec_update_all_source_handlers(struct call_monologue *ml, const sdp_ng_flags *flags) { +void codec_update_all_source_handlers(struct call_monologue *ml, const sdp_ng_flags *flags, bool clear_delay_buffer) { for (int i = 0; i < ml->medias->len; i++) { @@ -4892,7 +4895,7 @@ void codec_update_all_source_handlers(struct call_monologue *ml, const sdp_ng_fl if (!source_media) continue; - codec_handlers_update(source_media, sink_media, .flags = flags); + codec_handlers_update(source_media, sink_media, .flags = flags, .clear_delay_buffer = clear_delay_buffer); } } diff --git a/daemon/media_player.c b/daemon/media_player.c index 341a748ac..d3490bc75 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -1637,7 +1637,7 @@ const char * call_play_media_for_ml(struct call_monologue *ml, { #ifdef WITH_TRANSCODING /* if mixing is enabled, codec handlers of all sources must be updated */ - codec_update_all_source_handlers(ml, flags); + codec_update_all_source_handlers(ml, flags, true); /* this starts the audio player if needed */ update_init_monologue_subscribers(ml, OP_PLAY_MEDIA); @@ -1670,7 +1670,7 @@ long long call_stop_media_for_ml(struct call_monologue *ml) #ifdef WITH_TRANSCODING long long ret = media_player_stop(ml->player); /* restore to non-mixing if needed */ - codec_update_all_source_handlers(ml, NULL); + codec_update_all_source_handlers(ml, NULL, false); update_init_monologue_subscribers(ml, OP_STOP_MEDIA); /* mark MoH as already not used (it can be unset now) */ ml->player->opts.moh = 0; @@ -2016,7 +2016,7 @@ static void media_player_run(void *ptr) { if (mp->opts.block_egress) MEDIA_CLEAR(mp->media, BLOCK_EGRESS); - codec_update_all_source_handlers(mp->media->monologue, NULL); + codec_update_all_source_handlers(mp->media->monologue, NULL, false); update_init_monologue_subscribers(mp->media->monologue, OP_PLAY_MEDIA); rwlock_unlock_w(&call->master_lock); diff --git a/include/codec.h b/include/codec.h index 679e5aafd..ecbc30464 100644 --- a/include/codec.h +++ b/include/codec.h @@ -156,7 +156,7 @@ struct codec_handler *codec_handler_make_dummy(const rtp_payload_type *dst_pt, s str_case_value_ht codec_set); void codec_calc_jitter(struct ssrc_entry_call *, unsigned long ts, unsigned int clockrate, int64_t); void codec_update_all_handlers(struct call_monologue *ml); -void codec_update_all_source_handlers(struct call_monologue *ml, const sdp_ng_flags *flags); +void codec_update_all_source_handlers(struct call_monologue *ml, const sdp_ng_flags *flags, bool clear_delay_buffer); struct codec_store_args { str_case_value_ht codec_set; @@ -228,6 +228,9 @@ struct chu_args { const struct stream_params *sp; bool allow_asymmetric; bool reset_transcoding; + // when false (default if not passed) the delay buffer is flushed as normal + // used by play-media to ensure media packets aren't sent alongside delayed packets + bool clear_delay_buffer; }; #define codec_handlers_update(r, s, ...) \ __codec_handlers_update(r, s, (struct chu_args) {__VA_ARGS__}) @@ -246,7 +249,7 @@ uint64_t codec_encoder_pts(struct codec_ssrc_handler *ch, struct ssrc_entry_call void codec_decoder_skip_pts(struct codec_ssrc_handler *ch, uint64_t); uint64_t codec_decoder_unskip_pts(struct codec_ssrc_handler *ch); void codec_tracker_update(struct codec_store *, struct codec_store *); -void codec_handlers_stop(codec_handlers_q *, struct call_media *sink); +void codec_handlers_stop(codec_handlers_q *, struct call_media *sink, bool clear_delay_buffer); void packet_encoded_packetize(AVPacket *pkt, struct codec_ssrc_handler *ch, struct media_packet *mp, @@ -282,7 +285,7 @@ INLINE void __codec_handlers_update(struct call_media *receiver, struct call_med } INLINE void codec_handler_free(struct codec_handler **handler) { } INLINE void codec_tracker_update(struct codec_store *cs, struct codec_store *ocs) { } -INLINE void codec_handlers_stop(codec_handlers_q *q, struct call_media *sink) { } +INLINE void codec_handlers_stop(codec_handlers_q *q, struct call_media *sink, bool clear_delay_buffer) { } INLINE void ensure_codec_def(rtp_payload_type *pt, struct call_media *media) { } #endif