MT#55283 facilitate media reuse for updated subs

For a repeated subscribe-request on an existing monologue, make sure
that existing media sections are re-used for the same subscriptions as
they were previously, and only create new ones in an append-only fashion
for media subs which didn't previously exist.

Change-Id: I410c6af17eb31a5c5c43c78a7f82ba867f8480b7
pull/2056/head
Richard Fuchs 2 months ago
parent 6a7cba0aa2
commit c27ecf4828

@ -4038,7 +4038,9 @@ void media_subscriptions_clear(subscription_q *q) {
i_queue_clear_full(q, media_subscription_free);
}
static void __unsubscribe_media_link(struct call_media *which, struct media_subscription *ms)
__attribute__((nonnull(1, 2)))
static inline void __unsubscribe_media_link_store(struct call_media *which, struct media_subscription *ms,
subscription_store_ht ht)
{
struct media_subscription *rev_ms = ms->reverse;
struct call_media *from = ms->media;
@ -4055,11 +4057,23 @@ static void __unsubscribe_media_link(struct call_media *which, struct media_subs
t_hash_table_remove(from->media_subscribers_ht, rev_ms->media);
g_free(ms);
g_free(rev_ms);
if (t_hash_table_is_set(ht))
t_hash_table_insert(ht, from, rev_ms);
else
g_free(rev_ms);
}
__attribute__((nonnull(1, 2)))
static void __unsubscribe_media_link(struct call_media *which, struct media_subscription *ms)
{
__unsubscribe_media_link_store(which, ms, subscription_store_ht_null());
}
/**
* Unsubscribe one particular media subscriber from this call media.
*/
__attribute__((nonnull(1, 2)))
bool __unsubscribe_media(struct call_media *which, struct call_media *from)
{
if (!t_hash_table_is_set(which->media_subscriptions_ht)
@ -4098,23 +4112,27 @@ static void __unsubscribe_all_offer_answer_medias(struct call_media *cm, medias_
__unsubscribe_media(cm, other_cm);
}
}
static void __unsubscribe_medias_from_all(struct call_monologue *ml) {
__attribute__((nonnull(1)))
static inline void __unsubscribe_medias_from_all(struct call_monologue *ml, subscription_store_ht ht)
{
for (int i = 0; i < ml->medias->len; i++)
{
struct call_media * media = ml->medias->pdata[i];
struct call_media *media = ml->medias->pdata[i];
if (!media)
continue;
IQUEUE_FOREACH_SAFE(&media->media_subscriptions, subscription)
__unsubscribe_media_link(media, subscription);
__unsubscribe_media_link_store(media, subscription, ht);
}
}
/**
* Check whether this monologue medias are subscribed to a single other monologue medias.
*/
struct call_monologue *ml_medias_subscribed_to_single_ml(struct call_monologue *ml) {
/* detect monologues multiplicity */
struct call_monologue * return_ml = NULL;
struct call_monologue *return_ml = NULL;
for (unsigned int i = 0; i < ml->medias->len; i++)
{
struct call_media *media = ml->medias->pdata[i];
@ -4129,7 +4147,7 @@ struct call_monologue *ml_medias_subscribed_to_single_ml(struct call_monologue *
}
return return_ml;
}
struct media_subscription *__add_media_subscription(struct call_media * which, struct call_media * to,
struct media_subscription *__add_media_subscription(struct call_media *which, struct call_media *to,
const struct sink_attrs *attrs)
{
struct media_subscription *ret;
@ -4359,9 +4377,9 @@ int monologue_publish(struct call_monologue *ml, sdp_streams_q *streams, sdp_ng_
}
/* called with call->master_lock held in W */
__attribute__((nonnull(1, 2, 3, 4)))
__attribute__((nonnull(1, 2, 3)))
static int monologue_subscribe_request1(struct call_media *src_media, struct call_monologue *dst_ml,
sdp_ng_flags *flags, unsigned int *index)
sdp_ng_flags *flags, subscription_store_ht ht)
{
unsigned int idx_diff = 0, rev_idx_diff = 0;
g_auto(str_ht) mid_tracker_dst = str_ht_new();
@ -4369,8 +4387,16 @@ static int monologue_subscribe_request1(struct call_media *src_media, struct cal
struct stream_params *sp = &src_media->sp;
struct call_media *dst_media = call_get_media(dst_ml, &src_media->type, src_media->type_id,
NULL, false, (*index)++, mid_tracker_dst);
// check if we have a matching existing subscription
struct call_media *dst_media = NULL;
__auto_type ms = t_hash_table_lookup(ht, src_media);
if (ms)
dst_media = ms->media;
if (!dst_media) {
// new media needed
dst_media = call_get_media(dst_ml, &src_media->type, src_media->type_id,
NULL, false, dst_ml->medias->len + 1, mid_tracker_dst);
}
/* subscribe dst_ml (subscriber) to src_ml, don't forget to carry the egress flag, if required */
__add_media_subscription(dst_media, src_media, &(struct sink_attrs) { .egress = !!flags->egress });
@ -4446,12 +4472,13 @@ static int monologue_subscribe_request1(struct call_media *src_media, struct cal
return 0;
}
/* called with call->master_lock held in W */
__attribute__((nonnull(1, 2, 3)))
int monologue_subscribe_request(const subscription_q *srms, struct call_monologue *dst_ml, sdp_ng_flags *flags) {
unsigned int index = 1; /* running counter for output/dst medias */
g_auto(subscription_store_ht) ht = subscription_store_ht_new();
__unsubscribe_medias_from_all(dst_ml);
__unsubscribe_medias_from_all(dst_ml, ht);
__call_monologue_init_from_flags(dst_ml, NULL, flags);
IQUEUE_FOREACH(srms, ms) {
@ -4459,7 +4486,7 @@ int monologue_subscribe_request(const subscription_q *srms, struct call_monologu
if (!src_media)
continue;
int ret = monologue_subscribe_request1(src_media, dst_ml, flags, &index);
int ret = monologue_subscribe_request1(src_media, dst_ml, flags, ht);
if (ret)
return -1;

@ -853,8 +853,8 @@ struct media_subscription *__add_media_subscription(struct call_media * which, s
bool __unsubscribe_media(struct call_media * which, struct call_media * from);
struct media_subscription *call_ml_get_top_ms(struct call_monologue *ml);
bool call_ml_sendonly_inactive(struct call_monologue *ml);
struct media_subscription *call_media_get_top_ms(struct call_media * cm);
struct media_subscription *call_get_media_subscription(subscription_ht ht, struct call_media * cm);
struct media_subscription *call_media_get_top_ms(struct call_media *cm);
struct media_subscription *call_get_media_subscription(subscription_ht ht, struct call_media *cm);
struct call_monologue *ml_medias_subscribed_to_single_ml(struct call_monologue *ml);
__attribute__((nonnull(1)))
@ -931,6 +931,11 @@ bool __init_stream(struct packet_stream *ps);
const rtp_payload_type *__rtp_stats_codec(struct call_media *m);
TYPED_GHASHTABLE(subscription_store_ht, struct call_media, struct media_subscription,
media_direct_hash, media_direct_eq, NULL, media_subscription_free)
#include "str.h"
#include "rtp.h"

Loading…
Cancel
Save