From 256b9917ecf48ade1800ae606408db9b8825a3b4 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 6 May 2021 15:23:31 -0400 Subject: [PATCH] TT#121752 associate SSRC hash to monologue instead of entire call This solves problems when the same SSRC is looped through the same call multiple times in different mono/dialogues, with different parameters. Change-Id: I1d033cb1f012574d82b5bcbfffe11eb5f983cfd8 --- daemon/call.c | 59 ++++++++++++++++--------------- daemon/call_interfaces.c | 3 +- daemon/dtmf.c | 6 +++- daemon/media_player.c | 2 +- daemon/media_socket.c | 20 +++++++---- daemon/redis.c | 76 ++++++++++++++++++++++------------------ daemon/rtcp.c | 11 +++--- daemon/ssrc.c | 18 ++++------ include/call.h | 2 +- t/test-transcode.c | 12 +++---- 10 files changed, 113 insertions(+), 96 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 7480dcd42..4aae241e3 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2715,36 +2715,37 @@ void call_destroy(struct call *c) { statistics_update_totals(ps); } } - } - k = g_hash_table_get_values(c->ssrc_hash->ht); - for (l = k; l; l = l->next) { - struct ssrc_entry_call *se = l->data; + k = g_hash_table_get_values(ml->ssrc_hash->ht); + for (l = k; l; l = l->next) { + struct ssrc_entry_call *se = l->data; - // stats output only - no cleanups + // stats output only - no cleanups + + if (!se->stats_blocks.length || !se->lowest_mos || !se->highest_mos) + continue; + int mos_samples = (se->stats_blocks.length - se->no_mos_count); + if (mos_samples < 1) mos_samples = 1; + + ilog(LOG_INFO, "--- SSRC %s%" PRIx32 "%s", FMT_M(se->h.ssrc)); + ilog(LOG_INFO, "------ Average MOS %" PRIu64 ".%" PRIu64 ", " + "lowest MOS %" PRIu64 ".%" PRIu64 " (at %u:%02u), " + "highest MOS %" PRIu64 ".%" PRIu64 " (at %u:%02u) lost:%d", + se->average_mos.mos / mos_samples / 10, + se->average_mos.mos / mos_samples % 10, + se->lowest_mos->mos / 10, + se->lowest_mos->mos % 10, + (unsigned int) (timeval_diff(&se->lowest_mos->reported, &c->created) / 1000000) / 60, + (unsigned int) (timeval_diff(&se->lowest_mos->reported, &c->created) / 1000000) % 60, + se->highest_mos->mos / 10, + se->highest_mos->mos % 10, + (unsigned int) (timeval_diff(&se->highest_mos->reported, &c->created) / 1000000) / 60, + (unsigned int) (timeval_diff(&se->highest_mos->reported, &c->created) / 1000000) % 60, + se->packets_lost); + } + g_list_free(k); + } - if (!se->stats_blocks.length || !se->lowest_mos || !se->highest_mos) - continue; - int mos_samples = (se->stats_blocks.length - se->no_mos_count); - if (mos_samples < 1) mos_samples = 1; - - ilog(LOG_INFO, "--- SSRC %s%" PRIx32 "%s", FMT_M(se->h.ssrc)); - ilog(LOG_INFO, "------ Average MOS %" PRIu64 ".%" PRIu64 ", " - "lowest MOS %" PRIu64 ".%" PRIu64 " (at %u:%02u), " - "highest MOS %" PRIu64 ".%" PRIu64 " (at %u:%02u) lost:%d", - se->average_mos.mos / mos_samples / 10, - se->average_mos.mos / mos_samples % 10, - se->lowest_mos->mos / 10, - se->lowest_mos->mos % 10, - (unsigned int) (timeval_diff(&se->lowest_mos->reported, &c->created) / 1000000) / 60, - (unsigned int) (timeval_diff(&se->lowest_mos->reported, &c->created) / 1000000) % 60, - se->highest_mos->mos / 10, - se->highest_mos->mos % 10, - (unsigned int) (timeval_diff(&se->highest_mos->reported, &c->created) / 1000000) / 60, - (unsigned int) (timeval_diff(&se->highest_mos->reported, &c->created) / 1000000) % 60, - se->packets_lost); - } - g_list_free(k); no_stats_output: // cleanups @@ -2827,6 +2828,7 @@ static void __call_free(void *p) { g_hash_table_destroy(m->media_ids); if (m->last_sdp) g_string_free(m->last_sdp, TRUE); + free_ssrc_hash(&m->ssrc_hash); g_slice_free1(sizeof(*m), m); } @@ -2845,7 +2847,6 @@ static void __call_free(void *p) { g_hash_table_destroy(c->tags); g_hash_table_destroy(c->viabranches); g_hash_table_destroy(c->labels); - free_ssrc_hash(&c->ssrc_hash); while (c->streams.head) { ps = g_queue_pop_head(&c->streams); @@ -2879,7 +2880,6 @@ static struct call *call_create(const str *callid) { c->created = rtpe_now; c->dtls_cert = dtls_cert(); c->tos = rtpe_config.default_tos; - c->ssrc_hash = create_ssrc_hash_call(); for (int i = 0; i < NUM_CALL_ITERATORS; i++) mutex_init(&c->iterator[i].lock); @@ -2991,6 +2991,7 @@ struct call_monologue *__monologue_create(struct call *call) { ret->other_tags = g_hash_table_new(str_hash, str_equal); ret->branches = g_hash_table_new(str_hash, str_equal); ret->media_ids = g_hash_table_new(str_hash, str_equal); + ret->ssrc_hash = create_ssrc_hash_call(); g_queue_init(&ret->medias); gettimeofday(&ret->started, NULL); diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 910c7c948..21ba8755e 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -57,6 +57,7 @@ static GHashTable *sdp_fragments; INLINE int call_ng_flags_prefix(struct sdp_ng_flags *out, str *s_ori, const char *prefix, void (*cb)(struct sdp_ng_flags *, str *, void *), void *ptr); static void call_ng_flags_str_ht(struct sdp_ng_flags *out, str *s, void *htp); +static void ng_stats_ssrc(bencode_item_t *dict, struct ssrc_hash *ht); static int call_stream_address_gstring(GString *o, struct packet_stream *ps, enum stream_address_format format) { @@ -1719,6 +1720,7 @@ static void ng_stats_monologue(bencode_item_t *dict, const struct call_monologue bencode_dictionary_add_integer(sub, "created", ml->created); if (ml->active_dialogue) bencode_dictionary_add_str(sub, "in dialogue with", &ml->active_dialogue->tag); + ng_stats_ssrc(bencode_dictionary_add_dictionary(sub, "SSRC"), ml->ssrc_hash); medias = bencode_dictionary_add_list(sub, "medias"); @@ -1821,7 +1823,6 @@ void ng_call_stats(struct call *call, const str *fromtag, const str *totag, benc bencode_dictionary_add_integer(output, "created", call->created.tv_sec); bencode_dictionary_add_integer(output, "created_us", call->created.tv_usec); bencode_dictionary_add_integer(output, "last signal", call->last_signal); - ng_stats_ssrc(bencode_dictionary_add_dictionary(output, "SSRC"), call->ssrc_hash); tags = bencode_dictionary_add_dictionary(output, "tags"); diff --git a/daemon/dtmf.c b/daemon/dtmf.c index 28cb633d6..eaf106887 100644 --- a/daemon/dtmf.c +++ b/daemon/dtmf.c @@ -235,7 +235,11 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_monolog { struct call *call = monologue->call; - struct ssrc_ctx *ssrc_out = get_ssrc_ctx(ssrc_in->ssrc_map_out, call->ssrc_hash, SSRC_DIR_OUTPUT, + if (!media->monologue || !media->monologue->active_dialogue) + return "No dialogue association"; + + struct ssrc_ctx *ssrc_out = get_ssrc_ctx(ssrc_in->ssrc_map_out, + media->monologue->active_dialogue->ssrc_hash, SSRC_DIR_OUTPUT, monologue); 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 796b3e430..053f49c9a 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -111,7 +111,7 @@ struct media_player *media_player_new(struct call_monologue *ml) { uint32_t ssrc = 0; while (ssrc == 0) ssrc = ssl_random(); - struct ssrc_ctx *ssrc_ctx = get_ssrc_ctx(ssrc, ml->call->ssrc_hash, SSRC_DIR_OUTPUT, ml); + struct ssrc_ctx *ssrc_ctx = get_ssrc_ctx(ssrc, ml->ssrc_hash, SSRC_DIR_OUTPUT, ml); ssrc_ctx->next_rtcp = rtpe_now; struct media_player *mp = obj_alloc0("media_player", sizeof(*mp), __media_player_free); diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 6b2f9fac6..4bf95f91c 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1453,10 +1453,18 @@ noop: // check and update SSRC pointers static void __stream_ssrc(struct packet_stream *in_srtp, struct packet_stream *out_srtp, uint32_t ssrc_bs, - struct ssrc_ctx **ssrc_in_p, struct ssrc_ctx **ssrc_out_p, struct ssrc_hash *ssrc_hash, struct packet_handler_ctx *phc) + struct packet_handler_ctx *phc) { uint32_t in_ssrc = ntohl(ssrc_bs); uint32_t out_ssrc; + struct ssrc_ctx **ssrc_in_p = &phc->mp.ssrc_in; + struct ssrc_ctx **ssrc_out_p = &phc->mp.ssrc_out; + + if (!phc->mp.media || !phc->mp.media_out) + return; + + struct ssrc_hash *ssrc_hash_in = phc->mp.media->monologue->ssrc_hash; + struct ssrc_hash *ssrc_hash_out = phc->mp.media_out->monologue->ssrc_hash; // input direction mutex_lock(&in_srtp->in_lock); @@ -1468,7 +1476,7 @@ static void __stream_ssrc(struct packet_stream *in_srtp, struct packet_stream *o ssrc_ctx_put(ssrc_in_p); ssrc_ctx_put(&in_srtp->ssrc_in); (*ssrc_in_p) = in_srtp->ssrc_in = - get_ssrc_ctx(in_ssrc, ssrc_hash, SSRC_DIR_INPUT, in_srtp->media->monologue); + get_ssrc_ctx(in_ssrc, ssrc_hash_in, SSRC_DIR_INPUT, in_srtp->media->monologue); ssrc_ctx_hold(in_srtp->ssrc_in); phc->unkernelize = 1; @@ -1493,7 +1501,7 @@ static void __stream_ssrc(struct packet_stream *in_srtp, struct packet_stream *o ssrc_ctx_put(ssrc_out_p); ssrc_ctx_put(&out_srtp->ssrc_out); (*ssrc_out_p) = out_srtp->ssrc_out = - get_ssrc_ctx(out_ssrc, ssrc_hash, SSRC_DIR_OUTPUT, out_srtp->media->monologue); + get_ssrc_ctx(out_ssrc, ssrc_hash_out, SSRC_DIR_OUTPUT, out_srtp->media->monologue); ssrc_ctx_hold(out_srtp->ssrc_out); // coverity[missing_lock : FALSE] @@ -1618,8 +1626,7 @@ static void media_packet_rtp(struct packet_handler_ctx *phc) rtp_padding(phc->mp.rtp, &phc->mp.payload); if (G_LIKELY(phc->out_srtp != NULL)) - __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtp->ssrc, &phc->mp.ssrc_in, - &phc->mp.ssrc_out, phc->mp.call->ssrc_hash, phc); + __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtp->ssrc, phc); // check the payload type // XXX redundant between SSRC handling and codec_handler stuff -> combine @@ -1647,8 +1654,7 @@ static void media_packet_rtp(struct packet_handler_ctx *phc) } else if (phc->rtcp && !rtcp_payload(&phc->mp.rtcp, NULL, &phc->s)) { if (G_LIKELY(phc->out_srtp != NULL)) - __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtcp->ssrc, &phc->mp.ssrc_in, - &phc->mp.ssrc_out, phc->mp.call->ssrc_hash, phc); + __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtcp->ssrc, phc); } } diff --git a/daemon/redis.c b/daemon/redis.c index 6df9ddf02..c94e41928 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -78,6 +78,7 @@ static int redisCommandNR(redisContext *r, const char *fmt, ...) static int redis_check_conn(struct redis *r); static void json_restore_call(struct redis *r, const str *id, int foreign); static int redis_connect(struct redis *r, int wait); +static int json_build_ssrc(struct call_monologue *ml, JsonReader *root_reader); static void redis_pipe(struct redis *r, const char *fmt, ...) { va_list ap; @@ -1392,7 +1393,7 @@ static int redis_streams(struct call *c, struct redis_list *streams) { return 0; } -static int redis_tags(struct call *c, struct redis_list *tags) { +static int redis_tags(struct call *c, struct redis_list *tags, JsonReader *root_reader) { unsigned int i; int ii; struct redis_hash *rh; @@ -1420,6 +1421,9 @@ static int redis_tags(struct call *c, struct redis_list *tags) { if (!redis_hash_get_int(&ii, rh, "block_media")) ml->block_media = ii ? 1 : 0; + if (json_build_ssrc(ml, root_reader)) + return -1; + tags->ptrs[i] = ml; } @@ -1705,16 +1709,21 @@ static int json_link_maps(struct call *c, struct redis_list *maps, return 0; } -static int json_build_ssrc(struct call *c, JsonReader *root_reader) { - if (!json_reader_read_member(root_reader, "ssrc_table")) - return -1; +static int json_build_ssrc(struct call_monologue *ml, JsonReader *root_reader) { + char tmp[2048]; + snprintf(tmp, sizeof(tmp), "ssrc_table-%u", ml->unique_id); + if (!json_reader_read_member(root_reader, "ssrc_table")) { + // non-fatal for backwards compatibility + json_reader_end_member(root_reader); + return 0; + } int nmemb = json_reader_count_elements(root_reader); for (int jidx=0; jidx < nmemb; ++jidx) { if (!json_reader_read_element(root_reader, jidx)) return -1; uint32_t ssrc = json_reader_get_ll(root_reader, "ssrc"); - struct ssrc_entry_call *se = get_ssrc(ssrc, c->ssrc_hash); + struct ssrc_entry_call *se = get_ssrc(ssrc, ml->ssrc_hash); se->input_ctx.srtp_index = json_reader_get_ll(root_reader, "in_srtp_index"); se->input_ctx.srtcp_index = json_reader_get_ll(root_reader, "in_srtcp_index"); payload_tracker_add(&se->input_ctx.tracker, json_reader_get_ll(root_reader, "in_payload_type")); @@ -1826,7 +1835,7 @@ static void json_restore_call(struct redis *r, const str *callid, int foreign) { if (redis_streams(c, &streams)) goto err8; err = "failed to create tags"; - if (redis_tags(c, &tags)) + if (redis_tags(c, &tags, root_reader)) goto err8; err = "failed to create medias"; if (json_medias(c, &medias, root_reader)) @@ -1850,9 +1859,6 @@ static void json_restore_call(struct redis *r, const str *callid, int foreign) { err = "failed to link maps"; if (json_link_maps(c, &maps, &sfds, root_reader)) goto err8; - err = "failed to restore SSRC table"; - if (json_build_ssrc(c, root_reader)) - goto err8; // presence of this key determines whether we were recording at all if (!redis_hash_get_str(&s, &call, "recording_meta_prefix")) { @@ -2277,6 +2283,33 @@ char* redis_encode_json(struct call *c) { JSON_ADD_STRING("%u",media->unique_id); } json_builder_end_array (builder); + + // SSRC table dump + rwlock_lock_r(&ml->ssrc_hash->lock); + k = g_hash_table_get_values(ml->ssrc_hash->ht); + snprintf(tmp, sizeof(tmp), "ssrc_table-%u", ml->unique_id); + json_builder_set_member_name(builder, tmp); + json_builder_begin_array (builder); + for (m = k; m; m = m->next) { + struct ssrc_entry_call *se = m->data; + json_builder_begin_object (builder); + + JSON_SET_SIMPLE("ssrc","%" PRIu32, se->h.ssrc); + // XXX use function for in/out + JSON_SET_SIMPLE("in_srtp_index","%" PRIu64, se->input_ctx.srtp_index); + JSON_SET_SIMPLE("in_srtcp_index","%" PRIu64, se->input_ctx.srtcp_index); + JSON_SET_SIMPLE("in_payload_type","%i", se->input_ctx.tracker.most[0]); + JSON_SET_SIMPLE("out_srtp_index","%" PRIu64, se->output_ctx.srtp_index); + JSON_SET_SIMPLE("out_srtcp_index","%" PRIu64, se->output_ctx.srtcp_index); + JSON_SET_SIMPLE("out_payload_type","%i", se->output_ctx.tracker.most[0]); + // XXX add rest of info + + json_builder_end_object (builder); + } + json_builder_end_array (builder); + + g_list_free(k); + rwlock_unlock_r(&ml->ssrc_hash->lock); } @@ -2396,31 +2429,6 @@ char* redis_encode_json(struct call *c) { json_builder_end_array (builder); } - // SSRC table dump - rwlock_lock_r(&c->ssrc_hash->lock); - k = g_hash_table_get_values(c->ssrc_hash->ht); - json_builder_set_member_name(builder, "ssrc_table"); - json_builder_begin_array (builder); - for (m = k; m; m = m->next) { - struct ssrc_entry_call *se = m->data; - json_builder_begin_object (builder); - - JSON_SET_SIMPLE("ssrc","%" PRIu32, se->h.ssrc); - // XXX use function for in/out - JSON_SET_SIMPLE("in_srtp_index","%" PRIu64, se->input_ctx.srtp_index); - JSON_SET_SIMPLE("in_srtcp_index","%" PRIu64, se->input_ctx.srtcp_index); - JSON_SET_SIMPLE("in_payload_type","%i", se->input_ctx.tracker.most[0]); - JSON_SET_SIMPLE("out_srtp_index","%" PRIu64, se->output_ctx.srtp_index); - JSON_SET_SIMPLE("out_srtcp_index","%" PRIu64, se->output_ctx.srtcp_index); - JSON_SET_SIMPLE("out_payload_type","%i", se->output_ctx.tracker.most[0]); - // XXX add rest of info - - json_builder_end_object (builder); - } - json_builder_end_array (builder); - - g_list_free(k); - rwlock_unlock_r(&c->ssrc_hash->lock); } json_builder_end_object (builder); diff --git a/daemon/rtcp.c b/daemon/rtcp.c index e2751f1d4..6c19830a8 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -1306,14 +1306,17 @@ static void transcode_rr(struct rtcp_process_ctx *ctx, struct report_block *rr) return; if (ctx->scratch.rr.from != ctx->mp->ssrc_in->parent->h.ssrc) return; + if (!ctx->mp->media || !ctx->mp->media_out) + return; // reverse SSRC mapping - struct ssrc_ctx *map_ctx = get_ssrc_ctx(ctx->scratch.rr.ssrc, ctx->mp->call->ssrc_hash, + struct ssrc_ctx *map_ctx = get_ssrc_ctx(ctx->scratch.rr.ssrc, ctx->mp->media->monologue->ssrc_hash, SSRC_DIR_OUTPUT, ctx->mp->media->monologue); rr->ssrc = htonl(map_ctx->ssrc_map_out); // for reception stats - struct ssrc_ctx *input_ctx = get_ssrc_ctx(map_ctx->ssrc_map_out, ctx->mp->call->ssrc_hash, + struct ssrc_ctx *input_ctx = get_ssrc_ctx(map_ctx->ssrc_map_out, + ctx->mp->media_out->monologue->ssrc_hash, SSRC_DIR_INPUT, NULL); // substitute our own values @@ -1552,8 +1555,6 @@ void rtcp_receiver_reports(GQueue *out, struct ssrc_hash *hash, struct call_mono // call must be locked in R void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out) { - struct call *call = media->call; - // figure out where to send it struct packet_stream *ps = media->streams.head->data; if (MEDIA_ISSET(media, RTCP_MUX)) @@ -1578,7 +1579,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, call->ssrc_hash, ps->media->monologue); + rtcp_receiver_reports(&rrs, media->monologue->ssrc_hash, ps->media->monologue); 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 dfc9f230f..0535aa343 100644 --- a/daemon/ssrc.c +++ b/daemon/ssrc.c @@ -227,7 +227,6 @@ static void *__do_time_report_item(struct call_media *m, size_t struct_size, siz const struct timeval *tv, uint32_t ssrc, uint32_t ntp_msw, uint32_t ntp_lsw, GDestroyNotify free_func, struct ssrc_entry **e_p) { - struct call *c = m->call; struct ssrc_entry *e; struct ssrc_time_item *sti; @@ -236,7 +235,7 @@ static void *__do_time_report_item(struct call_media *m, size_t struct_size, siz sti->ntp_middle_bits = ntp_msw << 16 | ntp_lsw >> 16; sti->ntp_ts = ntp_ts_to_double(ntp_msw, ntp_lsw); - e = get_ssrc(ssrc, c->ssrc_hash); + e = get_ssrc(ssrc, m->monologue->ssrc_hash); if (G_UNLIKELY(!e)) { free_func(sti); return NULL; @@ -254,7 +253,7 @@ static void *__do_time_report_item(struct call_media *m, size_t struct_size, siz return sti; } -static long long __calc_rtt(struct call *c, uint32_t ssrc, uint32_t ntp_middle_bits, +static long long __calc_rtt(struct call_monologue *ml, uint32_t ssrc, uint32_t ntp_middle_bits, uint32_t delay, size_t reports_queue_offset, const struct timeval *tv, int *pt_p) { if (pt_p) @@ -263,7 +262,7 @@ static long long __calc_rtt(struct call *c, uint32_t ssrc, uint32_t ntp_middle_b if (!ntp_middle_bits || !delay) return 0; - struct ssrc_entry_call *e = get_ssrc(ssrc, c->ssrc_hash); + struct ssrc_entry_call *e = get_ssrc(ssrc, ml->ssrc_hash); if (G_UNLIKELY(!e)) return 0; @@ -329,18 +328,16 @@ void ssrc_sender_report(struct call_media *m, const struct ssrc_sender_report *s void ssrc_receiver_report(struct call_media *m, const struct ssrc_receiver_report *rr, const struct timeval *tv) { - struct call *c = m->call; - ilog(LOG_DEBUG, "RR from %s%x%s about %s%x%s: FL %u TL %u HSR %u J %u LSR %u DLSR %u", FMT_M(rr->from), FMT_M(rr->ssrc), rr->fraction_lost, rr->packets_lost, rr->high_seq_received, rr->jitter, rr->lsr, rr->dlsr); int pt; - long long rtt = __calc_rtt(c, rr->ssrc, rr->lsr, rr->dlsr, + long long rtt = __calc_rtt(m->monologue->active_dialogue, rr->ssrc, rr->lsr, rr->dlsr, G_STRUCT_OFFSET(struct ssrc_entry_call, sender_reports), tv, &pt); - struct ssrc_entry_call *other_e = get_ssrc(rr->from, c->ssrc_hash); + struct ssrc_entry_call *other_e = get_ssrc(rr->from, m->monologue->ssrc_hash); if (G_UNLIKELY(!other_e)) goto out_nl; @@ -443,7 +440,7 @@ void ssrc_receiver_dlrr(struct call_media *m, const struct ssrc_xr_dlrr *dlrr, FMT_M(dlrr->from), FMT_M(dlrr->ssrc), dlrr->lrr, dlrr->dlrr); - __calc_rtt(m->call, dlrr->ssrc, dlrr->lrr, dlrr->dlrr, + __calc_rtt(m->monologue->active_dialogue, dlrr->ssrc, dlrr->lrr, dlrr->dlrr, G_STRUCT_OFFSET(struct ssrc_entry_call, rr_time_reports), tv, NULL); } @@ -460,8 +457,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 call *c = m->call; - struct ssrc_entry_call *e = get_ssrc(vm->ssrc, c->ssrc_hash); + struct ssrc_entry_call *e = get_ssrc(vm->ssrc, m->monologue->ssrc_hash); if (!e) return; e->last_rtt_xr = vm->rnd_trip_delay; diff --git a/include/call.h b/include/call.h index abd7567e4..6ee852ce5 100644 --- a/include/call.h +++ b/include/call.h @@ -397,6 +397,7 @@ struct call_monologue { GString *last_sdp; char *sdp_username; char *sdp_session_name; + struct ssrc_hash *ssrc_hash; unsigned int block_dtmf:1; unsigned int block_media:1; @@ -452,7 +453,6 @@ struct call { GQueue stream_fds; GQueue endpoint_maps; struct dtls_cert *dtls_cert; /* for outgoing */ - struct ssrc_hash *ssrc_hash; struct mqtt_timer *mqtt_timer; str callid; diff --git a/t/test-transcode.c b/t/test-transcode.c index 804fa5883..920ba3216 100644 --- a/t/test-transcode.c +++ b/t/test-transcode.c @@ -80,20 +80,21 @@ static void __start(const char *file, int line) { ssrc_A = 1234; ssrc_B = 2345; ZERO(call); - call.ssrc_hash = create_ssrc_hash_call(); call.tags = g_hash_table_new(g_str_hash, g_str_equal); str_init(&call.callid, "test-call"); bencode_buffer_init(&call.buffer); media_A = call_media_new(&call); // originator media_B = call_media_new(&call); // output destination - ml_A = (struct call_monologue) {0,}; + ml_A = (struct call_monologue) { .ssrc_hash = create_ssrc_hash_call(), 0, }; str_init(&ml_A.tag, "tag_A"); media_A->monologue = &ml_A; media_A->protocol = &transport_protocols[PROTO_RTP_AVP]; - ml_B = (struct call_monologue) {0,}; + ml_B = (struct call_monologue) { .ssrc_hash = create_ssrc_hash_call(), 0, }; str_init(&ml_B.tag, "tag_B"); media_B->monologue = &ml_B; media_B->protocol = &transport_protocols[PROTO_RTP_AVP]; + ml_A.active_dialogue = &ml_B; + ml_B.active_dialogue = &ml_A; __init(); } @@ -229,12 +230,12 @@ static void __packet_seq_ts(const char *file, int line, struct call_media *media struct media_packet mp = { .call = &call, .media = media, - .ssrc_in = get_ssrc_ctx(ssrc, call.ssrc_hash, SSRC_DIR_INPUT, NULL), + .ssrc_in = get_ssrc_ctx(ssrc, media->monologue->ssrc_hash, SSRC_DIR_INPUT, NULL), }; // from __stream_ssrc() if (!MEDIA_ISSET(media, TRANSCODE)) mp.ssrc_in->ssrc_map_out = ntohl(ssrc); - mp.ssrc_out = get_ssrc_ctx(mp.ssrc_in->ssrc_map_out, call.ssrc_hash, SSRC_DIR_OUTPUT, NULL); + mp.ssrc_out = get_ssrc_ctx(mp.ssrc_in->ssrc_map_out, media->monologue->active_dialogue->ssrc_hash, SSRC_DIR_OUTPUT, NULL); payload_tracker_add(&mp.ssrc_in->tracker, pt_in & 0x7f); int packet_len = sizeof(struct rtp_header) + pl.len; @@ -345,7 +346,6 @@ static void end(void) { call_media_free(&media_B); bencode_buffer_free(&call.buffer); g_hash_table_destroy(call.tags); - free_ssrc_hash(&call.ssrc_hash); g_queue_clear(&call.medias); __cleanup(); printf("\n");