From 19af8034a49b5d21be61f45875f017b1dba0f2ac Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 15 Apr 2025 14:09:45 -0400 Subject: [PATCH] MT#55283 split SSRC hash into in and out Change-Id: Ie1d378ee455e6fadb39a16f4c1d86f604870c536 --- daemon/call.c | 8 +++++--- daemon/call_interfaces.c | 2 +- daemon/codec.c | 2 +- daemon/dtmf.c | 2 +- daemon/media_player.c | 2 +- daemon/media_socket.c | 8 ++++---- daemon/redis.c | 30 +++++++++++++++++------------- daemon/rtcp.c | 6 +++--- daemon/ssrc.c | 12 ++++++------ include/call.h | 3 ++- t/test-transcode.c | 4 ++-- 11 files changed, 43 insertions(+), 36 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 023961a10..1ce0b5a56 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -667,7 +667,8 @@ struct call_media *call_media_new(call_t *call) { mutex_init(&med->dtmf_lock); med->sdp_attr_print = sdp_insert_media_attributes; RESET_BANDWIDTH(med->sdp_media_bandwidth, -1); - ssrc_hash_call_init(&med->ssrc_hash); + ssrc_hash_call_init(&med->ssrc_hash_in); + ssrc_hash_call_init(&med->ssrc_hash_out); return med; } @@ -4180,7 +4181,7 @@ void call_destroy(call_t *c) { atomic64_get_na(&ps->stats_out->errors)); } - for (k = md->ssrc_hash.nq.head; k; k = k->next) { + for (k = md->ssrc_hash_in.nq.head; k; k = k->next) { struct ssrc_entry_call *se = k->data; // stats output only - no cleanups @@ -4298,7 +4299,8 @@ void call_media_free(struct call_media **mdp) { t38_gateway_put(&md->t38_gateway); ice_candidates_free(&md->ice_candidates); mutex_destroy(&md->dtmf_lock); - ssrc_hash_destroy(&md->ssrc_hash); + ssrc_hash_destroy(&md->ssrc_hash_in); + ssrc_hash_destroy(&md->ssrc_hash_out); g_free(md); *mdp = NULL; } diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index ead232c78..ac08b6b84 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -2888,7 +2888,7 @@ static void ng_stats_media(ng_command_ctx_t *ctx, parser_arg list, const struct BF_M("transcoding", TRANSCODING); BF_M("block egress", BLOCK_EGRESS); - ng_stats_ssrc(parser, ssrc, &m->ssrc_hash); + ng_stats_ssrc(parser, ssrc, &m->ssrc_hash_in); // XXX out stats: for (auto_iter(l, m->streams.head); l; l = l->next) { diff --git a/daemon/codec.c b/daemon/codec.c index d50b0665c..ebdd14a14 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -822,7 +822,7 @@ reset: __handler_stats_entry(handler); - ssrc_hash_foreach(&handler->media->ssrc_hash, __reset_sequencer, NULL); + ssrc_hash_foreach(&handler->media->ssrc_hash_in, __reset_sequencer, NULL); no_handler_reset: __delay_buffer_setup(&handler->delay_buffer, handler, handler->media->call, handler->media->buffer_delay); diff --git a/daemon/dtmf.c b/daemon/dtmf.c index f04c4af48..9bc18a140 100644 --- a/daemon/dtmf.c +++ b/daemon/dtmf.c @@ -731,7 +731,7 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_media * struct ssrc_ctx *ssrc_out = get_ssrc_ctx(sh->attrs.transcoding ? ssrc_in->ssrc_map_out : ssrc_in->parent->h.ssrc, - &sink_media->ssrc_hash, SSRC_DIR_OUTPUT); + &sink_media->ssrc_hash_out, SSRC_DIR_OUTPUT); if (!ssrc_out) return "No output SSRC context present"; // XXX generate stream diff --git a/daemon/media_player.c b/daemon/media_player.c index 566a7d99e..96c1ca7c8 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -1143,7 +1143,7 @@ void media_player_set_media(struct media_player *mp, struct call_media *media) { mp->crypt_handler = determine_handler(&transport_protocols[PROTO_RTP_AVP], media, true); } if (!mp->ssrc_out || mp->ssrc_out->parent->h.ssrc != mp->ssrc) { - struct ssrc_ctx *ssrc_ctx = get_ssrc_ctx(mp->ssrc, &media->ssrc_hash, SSRC_DIR_OUTPUT); + struct ssrc_ctx *ssrc_ctx = get_ssrc_ctx(mp->ssrc, &media->ssrc_hash_out, SSRC_DIR_OUTPUT); ssrc_ctx->next_rtcp = rtpe_now; mp->ssrc_out = ssrc_ctx; } diff --git a/daemon/media_socket.c b/daemon/media_socket.c index ad13d9297..4f8e42aea 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -2275,7 +2275,7 @@ static void media_packet_rtp_in(struct packet_handler_ctx *phc) if (G_LIKELY(!phc->rtcp && !rtp_payload(&phc->mp.rtp, &phc->mp.payload, &phc->s))) { unkern = __stream_ssrc_in(phc->in_srtp, phc->mp.rtp->ssrc, &phc->mp.ssrc_in, - &phc->mp.media->ssrc_hash); + &phc->mp.media->ssrc_hash_in); // check the payload type // XXX redundant between SSRC handling and codec_handler stuff -> combine @@ -2305,7 +2305,7 @@ static void media_packet_rtp_in(struct packet_handler_ctx *phc) } else if (phc->rtcp && !rtcp_payload(&phc->mp.rtcp, NULL, &phc->s)) { unkern = __stream_ssrc_in(phc->in_srtp, phc->mp.rtcp->ssrc, &phc->mp.ssrc_in, - &phc->mp.media->ssrc_hash); + &phc->mp.media->ssrc_hash_in); } if (unkern) @@ -2320,12 +2320,12 @@ static void media_packet_rtp_out(struct packet_handler_ctx *phc, struct sink_han if (G_LIKELY(!phc->rtcp && phc->mp.rtp)) { unkern = __stream_ssrc_out(phc->out_srtp, phc->mp.rtp->ssrc, phc->mp.ssrc_in, - &phc->mp.ssrc_out, &phc->mp.media_out->ssrc_hash, + &phc->mp.ssrc_out, &phc->mp.media_out->ssrc_hash_out, sh->attrs.transcoding ? true : false); } else if (phc->rtcp && phc->mp.rtcp) { unkern = __stream_ssrc_out(phc->out_srtp, phc->mp.rtcp->ssrc, phc->mp.ssrc_in, - &phc->mp.ssrc_out, &phc->mp.media_out->ssrc_hash, + &phc->mp.ssrc_out, &phc->mp.media_out->ssrc_hash_out, sh->attrs.transcoding ? true : false); } diff --git a/daemon/redis.c b/daemon/redis.c index 37a9b88c8..c9e646f89 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1977,18 +1977,21 @@ static void json_build_ssrc_iter(const ng_parser_t *parser, parser_arg dict, hel struct call_media *md = arg.md; uint32_t ssrc = parser_get_ll(dict, "ssrc"); - struct ssrc_entry_call *se = get_ssrc(ssrc, &md->ssrc_hash); - if (!se) - return; - - atomic_set_na(&se->input_ctx.stats->ext_seq, parser_get_ll(dict, "in_srtp_index")); - atomic_set_na(&se->input_ctx.stats->rtcp_seq, parser_get_ll(dict, "in_srtcp_index")); - payload_tracker_add(&se->input_ctx.tracker, parser_get_ll(dict, "in_payload_type")); - atomic_set_na(&se->output_ctx.stats->ext_seq, parser_get_ll(dict, "out_srtp_index")); - atomic_set_na(&se->output_ctx.stats->rtcp_seq, parser_get_ll(dict, "out_srtcp_index")); - payload_tracker_add(&se->output_ctx.tracker, parser_get_ll(dict, "out_payload_type")); + struct ssrc_entry_call *se_in = get_ssrc(ssrc, &md->ssrc_hash_in); + struct ssrc_entry_call *se_out = get_ssrc(ssrc, &md->ssrc_hash_out); - obj_put(&se->h); + if (se_in) { + atomic_set_na(&se_in->input_ctx.stats->ext_seq, parser_get_ll(dict, "in_srtp_index")); + atomic_set_na(&se_in->input_ctx.stats->rtcp_seq, parser_get_ll(dict, "in_srtcp_index")); + payload_tracker_add(&se_in->input_ctx.tracker, parser_get_ll(dict, "in_payload_type")); + obj_put(&se_in->h); + } + if (se_out) { + atomic_set_na(&se_out->output_ctx.stats->ext_seq, parser_get_ll(dict, "out_srtp_index")); + atomic_set_na(&se_out->output_ctx.stats->rtcp_seq, parser_get_ll(dict, "out_srtcp_index")); + payload_tracker_add(&se_out->output_ctx.tracker, parser_get_ll(dict, "out_payload_type")); + obj_put(&se_out->h); + } } static int json_build_ssrc(struct call_media *md, parser_arg arg) { @@ -2715,10 +2718,11 @@ static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c, void **to_free) { } // SSRC table dump - LOCK(&media->ssrc_hash.lock); + // XXX needs fixing + LOCK(&media->ssrc_hash_in.lock); snprintf(tmp, sizeof(tmp), "ssrc_table-%u", media->unique_id); parser_arg list = parser->dict_add_list_dup(root, tmp); - for (GList *m = media->ssrc_hash.nq.head; m; m = m->next) { + for (GList *m = media->ssrc_hash_in.nq.head; m; m = m->next) { struct ssrc_entry_call *se = m->data; inner = parser->list_add_dict(list); diff --git a/daemon/rtcp.c b/daemon/rtcp.c index e4f5629fe..b4be671a8 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -1303,7 +1303,7 @@ static void transcode_rr(struct rtcp_process_ctx *ctx, struct report_block *rr) return; // reverse SSRC mapping - struct ssrc_ctx *map_ctx = get_ssrc_ctx(ctx->scratch.rr.ssrc, &ctx->mp->media->ssrc_hash, + struct ssrc_ctx *map_ctx = get_ssrc_ctx(ctx->scratch.rr.ssrc, &ctx->mp->media->ssrc_hash_out, SSRC_DIR_OUTPUT); rr->ssrc = htonl(map_ctx->ssrc_map_out); @@ -1312,7 +1312,7 @@ static void transcode_rr(struct rtcp_process_ctx *ctx, struct report_block *rr) // for reception stats struct ssrc_ctx *input_ctx = get_ssrc_ctx(map_ctx->ssrc_map_out, - &ctx->mp->media_out->ssrc_hash, + &ctx->mp->media_out->ssrc_hash_in, SSRC_DIR_INPUT); if (!input_ctx) return; @@ -1575,7 +1575,7 @@ void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out) { log_info_stream_fd(ps->selected_sfd); GQueue rrs = G_QUEUE_INIT; - rtcp_receiver_reports(&rrs, &media->ssrc_hash); + rtcp_receiver_reports(&rrs, &media->ssrc_hash_in); ilogs(rtcp, LOG_DEBUG, "Generating and sending RTCP SR for %x and up to %i source(s)", ssrc_out->parent->h.ssrc, rrs.length); diff --git a/daemon/ssrc.c b/daemon/ssrc.c index 69d291f26..86249ce57 100644 --- a/daemon/ssrc.c +++ b/daemon/ssrc.c @@ -320,7 +320,7 @@ static void *__do_time_report_item(struct call_media *m, size_t struct_size, siz sti->ntp_ts_lsw = ntp_lsw; sti->ntp_ts_msw = ntp_msw; - e = get_ssrc(ssrc, &m->ssrc_hash); + e = get_ssrc(ssrc, &m->ssrc_hash_in); if (G_UNLIKELY(!e)) { free_func(sti); return NULL; @@ -346,7 +346,7 @@ static struct ssrc_entry_call *hunt_ssrc(struct call_media *media, uint32_t ssrc for (__auto_type sub = media->media_subscriptions.head; sub; sub = sub->next) { struct media_subscription * ms = sub->data; - struct ssrc_entry_call *e = find_ssrc(ssrc, &ms->media->ssrc_hash, NULL); + struct ssrc_entry_call *e = find_ssrc(ssrc, &ms->media->ssrc_hash_in, NULL); if (e) return e; } @@ -448,7 +448,7 @@ void ssrc_receiver_report(struct call_media *m, stream_fd *sfd, const struct ssr int pt; int64_t rtt = calc_rtt(m, - .ht = &m->ssrc_hash, + .ht = &m->ssrc_hash_in, .tv = tv, .pt_p = &pt, .ssrc = rr->ssrc, @@ -456,7 +456,7 @@ void ssrc_receiver_report(struct call_media *m, stream_fd *sfd, const struct ssr .delay = rr->dlsr, .reports_queue_offset = G_STRUCT_OFFSET(struct ssrc_entry_call, sender_reports)); - struct ssrc_entry_call *other_e = get_ssrc(rr->from, &m->ssrc_hash); + struct ssrc_entry_call *other_e = get_ssrc(rr->from, &m->ssrc_hash_in); if (G_UNLIKELY(!other_e)) goto out_nl; @@ -580,7 +580,7 @@ void ssrc_receiver_dlrr(struct call_media *m, const struct ssrc_xr_dlrr *dlrr, dlrr->lrr, dlrr->dlrr); calc_rtt(m, - .ht = &m->ssrc_hash, + .ht = &m->ssrc_hash_in, .tv = tv, .pt_p = NULL, .ssrc = dlrr->ssrc, @@ -602,7 +602,7 @@ void ssrc_voip_metrics(struct call_media *m, const struct ssrc_xr_voip_metrics * vm->ext_r_factor, vm->mos_lq, vm->mos_cq, vm->rx_config, vm->jb_nom, vm->jb_max, vm->jb_abs_max); - struct ssrc_entry_call *e = get_ssrc(vm->ssrc, &m->ssrc_hash); + struct ssrc_entry_call *e = get_ssrc(vm->ssrc, &m->ssrc_hash_in); if (!e) return; e->last_rtt_xr = vm->rnd_trip_delay; diff --git a/include/call.h b/include/call.h index 0cbb0ba27..a41eae154 100644 --- a/include/call.h +++ b/include/call.h @@ -506,7 +506,8 @@ struct call_media { packet_stream_q streams; /* normally RTP + RTCP */ endpoint_map_q endpoint_maps; - struct ssrc_hash ssrc_hash; + struct ssrc_hash ssrc_hash_in; + struct ssrc_hash ssrc_hash_out; struct codec_store codecs; struct codec_store offered_codecs; diff --git a/t/test-transcode.c b/t/test-transcode.c index 014902536..50b01918b 100644 --- a/t/test-transcode.c +++ b/t/test-transcode.c @@ -261,13 +261,13 @@ static void __packet_seq_ts(const char *file, int line, struct call_media *media .call = &call, .media = media, .media_out = other_media, - .ssrc_in = get_ssrc_ctx(ssrc, &media->ssrc_hash, SSRC_DIR_INPUT), + .ssrc_in = get_ssrc_ctx(ssrc, &media->ssrc_hash_in, SSRC_DIR_INPUT), .sfd = &sfd, }; // from __stream_ssrc() if (!MEDIA_ISSET(media, TRANSCODING)) mp.ssrc_in->ssrc_map_out = ntohl(ssrc); - mp.ssrc_out = get_ssrc_ctx(mp.ssrc_in->ssrc_map_out, &other_media->ssrc_hash, SSRC_DIR_OUTPUT); + mp.ssrc_out = get_ssrc_ctx(mp.ssrc_in->ssrc_map_out, &other_media->ssrc_hash_out, SSRC_DIR_OUTPUT); payload_tracker_add(&mp.ssrc_in->tracker, pt_in & 0x7f); int packet_len = sizeof(struct rtp_header) + pl.len;