From 8ad5b79c96b8218e563d64e45d904f8e913771ba Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Fri, 4 Apr 2025 09:20:42 -0400 Subject: [PATCH] MT#55283 introduce last PT tracking Extend PT tracker to not just track the most used PT, but also which PT has been used last. Use a simple circular array. Use this new tracking to determine whether a DTX buffer should remain active. The "most used PT" approach isn't reliable for this, as it leads to a DTX buffer restarting only after the PT has become the "most used," so only after about 10 packets. Meanwhile a newly appearing SSRC would have a new DTX buffer active immediately. Being strict about which PT was used last resolves this inconsistency. Change-Id: If912e4d10e6737a82f6adc0b19d502075aa18a93 --- daemon/codec.c | 25 ++++++++++++++++--------- daemon/ssrc.c | 6 ++++++ include/ssrc.h | 3 +++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index 01d2aab14..4b65b14fc 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -3800,26 +3800,33 @@ static void __dtx_send_later(struct codec_timer *ct) { else if (dtxb->ct.next.tv_sec == 0) shutdown = true; else { - shutdown = true; // default if no most used PTs are known + shutdown = true; // default if no last used PTs are known + + for (int i = 0; i < G_N_ELEMENTS(ps->ssrc_in[0]->tracker.last_pts); i++) { + int pt_idx = ps->ssrc_in[0]->tracker.last_pt_idx - i; + pt_idx += G_N_ELEMENTS(ps->ssrc_in[0]->tracker.last_pts); + pt_idx %= G_N_ELEMENTS(ps->ssrc_in[0]->tracker.last_pts); + int last_pt = ps->ssrc_in[0]->tracker.last_pts[pt_idx]; + if (last_pt == 255) + break; - for (int i = 0; i < ps->ssrc_in[0]->tracker.most_len; i++) { - unsigned char most_pt = ps->ssrc_in[0]->tracker.most[i]; shutdown = false; - // we are good if the most used PT is + // we are good if the last used PT is // either us - if (ch->handler->source_pt.payload_type == most_pt) + if (ch->handler->source_pt.payload_type == last_pt) break; // or our input PT (which is the audio PT if we are supplemental) - if (ch->handler->input_handler && ch->handler->input_handler->source_pt.payload_type == most_pt) + if (ch->handler->input_handler + && ch->handler->input_handler->source_pt.payload_type == last_pt) break; // looks like codec change, but... shutdown = true; - // another possibility is that the most used PT is actually a supplemental type. check this, - // and if true move on to the next most used PT. + // another possibility is that the most used PT is actually a supplemental type. + // check this, and if true move on to the next most used PT. rtp_payload_type *pt = t_hash_table_lookup(ps->media->codecs.codecs, - GUINT_TO_POINTER(most_pt)); + GUINT_TO_POINTER(last_pt)); if (pt && pt->codec_def && pt->codec_def->supplemental) continue; diff --git a/daemon/ssrc.c b/daemon/ssrc.c index e24ad720f..375916d34 100644 --- a/daemon/ssrc.c +++ b/daemon/ssrc.c @@ -672,8 +672,10 @@ void payload_tracker_init(struct payload_tracker *t) { memset(&t->count, 0, sizeof(t->count)); memset(&t->idx, -1, sizeof(t->idx)); memset(&t->most, -1, sizeof(t->most)); + memset(&t->last_pts, 255, sizeof(t->last_pts)); t->last_idx = 0; t->most_len = 0; + t->last_pt_idx = -1; } //#define PT_DBG(x...) ilog(LOG_DEBUG, x) #define PT_DBG(x...) ((void)0) @@ -683,6 +685,10 @@ void payload_tracker_add(struct payload_tracker *t, int pt) { mutex_lock(&t->lock); + int pt_idx = (t->last_pt_idx + 1) % G_N_ELEMENTS(t->last_pts); + t->last_pts[pt_idx] = pt; + t->last_pt_idx = pt_idx; + PT_DBG("new pt: %i", pt); PT_DBG("last idx: %u", t->last_idx); int old_pt = t->last[t->last_idx]; diff --git a/include/ssrc.h b/include/ssrc.h index c458d3d08..180565b0e 100644 --- a/include/ssrc.h +++ b/include/ssrc.h @@ -35,6 +35,9 @@ struct payload_tracker { unsigned char idx[128]; // each pt's index into most[] unsigned char most[128]; // sorted list of pts unsigned int most_len; // idx for new entries + + unsigned char last_pts[16]; + int last_pt_idx; }; struct ssrc_ctx { struct ssrc_entry_call *parent;