diff --git a/daemon/call.c b/daemon/call.c index 6ecbd2ebc..458ac2988 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -3275,13 +3275,63 @@ static struct call_media * monologue_add_zero_media(struct call_monologue *sende return sender_media; } +// reset all bundle state +__attribute__((nonnull(1))) +static void monologue_bundle_reset(struct call_monologue *ml) { + for (unsigned int i = 0; i < ml->medias->len; i++) { + __auto_type media = ml->medias->pdata[i]; + if (!media) + continue; + + if (t_hash_table_is_set(media->pt_media)) + t_hash_table_remove_all(media->pt_media); + + media->bundle = NULL; + } +} + +__attribute__((nonnull(1))) +static void track_bundle_media_pt(struct call_media *media, pt_media_ht tracker) { + __auto_type bundle = media->bundle; + + // fill PT to media mapping + if (!t_hash_table_is_set(bundle->pt_media)) + bundle->pt_media = pt_media_ht_new(); + + for (__auto_type l = media->codecs.codec_prefs.head; l; l = l->next) { + __auto_type pt = l->data; + + // previous duplicate? + if (t_hash_table_lookup(tracker, GINT_TO_POINTER(pt->payload_type))) + continue; + + ilog(LOG_DEBUG, "Associating payload type %d with media #%u", + pt->payload_type, media->index); + + if (t_hash_table_insert(bundle->pt_media, GINT_TO_POINTER(pt->payload_type), media)) + continue; + + // new duplicate + ilog(LOG_DEBUG, "Payload type %d is not unique, forgetting about it", pt->payload_type); + + t_hash_table_remove(bundle->pt_media, GINT_TO_POINTER(pt->payload_type)); + t_hash_table_insert(tracker, GINT_TO_POINTER(pt->payload_type), media); + } +} + __attribute__((nonnull(1, 2))) static void monologue_bundle_accept(struct call_monologue *ml, sdp_ng_flags *flags) { if (!ML_ISSET(ml, BUNDLE)) return; + + monologue_bundle_reset(ml); + if (!t_hash_table_is_set(flags->bundles)) return; + // track PTs that appear in multiple medias + g_auto(pt_media_ht) exclude_pt = pt_media_ht_new(); + // iterate all medias and set up bundle groups as requested for (unsigned int i = 0; i < ml->medias->len; i++) { __auto_type media = ml->medias->pdata[i]; @@ -3305,6 +3355,8 @@ static void monologue_bundle_accept(struct call_monologue *ml, sdp_ng_flags *fla STR_FMT(bundle_head)); continue; } + + track_bundle_media_pt(media, exclude_pt); } } @@ -4602,6 +4654,7 @@ void call_media_free(struct call_media **mdp) { t_hash_table_destroy(md->extmap_ht); t_hash_table_destroy(md->ext_name_ht); t_queue_clear_full(&md->extmap, rtp_extension_free); + t_hash_table_destroy_ptr(&md->pt_media); g_free(md); *mdp = NULL; } diff --git a/include/call.h b/include/call.h index 5ee5726c4..b0a40a3c7 100644 --- a/include/call.h +++ b/include/call.h @@ -336,6 +336,7 @@ TYPED_DIRECT_FUNCS(media_direct_hash, media_direct_eq, struct call_media) TYPED_GHASHTABLE(subscription_ht, struct call_media, subscription_list, media_direct_hash, media_direct_eq, NULL, NULL) TYPED_GHASHTABLE(media_id_ht, str, struct call_media, str_hash, str_equal, NULL, NULL) +TYPED_GHASHTABLE(pt_media_ht, void, struct call_media, g_direct_hash, g_direct_equal, NULL, NULL) struct session_bandwidth { long as, rr, rs, ct, tias; @@ -509,6 +510,7 @@ struct call_media { str media_id; str label; struct call_media *bundle; + pt_media_ht pt_media; sdes_q sdes_in, sdes_out; struct dtls_fingerprint fingerprint; /* as received */ const struct dtls_hash_func *fp_hash_func; /* outgoing */