|
|
|
@ -2880,6 +2880,16 @@ static void media_set_siprec_label(struct call_media *other_media, struct call_m |
|
|
|
other_media->label = media->label; |
|
|
|
} |
|
|
|
|
|
|
|
__attribute__((nonnull(1))) |
|
|
|
static unsigned int media_extmap_id(struct call_media *media) { |
|
|
|
// XXX slow search? |
|
|
|
for (unsigned int i = 1; i < 255; i++) { |
|
|
|
if (!media->extmap_ops->lookup(media, i)) |
|
|
|
return i; |
|
|
|
} |
|
|
|
return -1u; |
|
|
|
} |
|
|
|
|
|
|
|
__attribute__((nonnull(1))) |
|
|
|
static void media_reset_extmap(struct call_media *media, |
|
|
|
bool (*exclude)(struct rtp_extension *), |
|
|
|
@ -3002,7 +3012,8 @@ static void media_update_extmap(struct call_media *media, struct stream_params * |
|
|
|
void (*manip)(struct rtp_extension *, const struct sdp_ng_flags *), |
|
|
|
const struct sdp_ng_flags *flags) |
|
|
|
{ |
|
|
|
media_reset_extmap(media, NULL, NULL); |
|
|
|
extmap_ht orig; |
|
|
|
media_reset_extmap(media, NULL, &orig); |
|
|
|
|
|
|
|
// take over from `sp` |
|
|
|
media->extmap = sp->extmap; |
|
|
|
@ -3012,11 +3023,29 @@ static void media_update_extmap(struct call_media *media, struct stream_params * |
|
|
|
for (__auto_type ll = media->extmap.head; ll; ll = ll->next) { |
|
|
|
__auto_type ext = ll->data; |
|
|
|
|
|
|
|
// previously present? |
|
|
|
__auto_type orig_ext = t_hash_table_lookup(orig, GUINT_TO_POINTER(ext->id)); |
|
|
|
if (orig_ext && !str_cmp_str(&orig_ext->name, &ext->name)) { |
|
|
|
// swap with original object, remove from HT, free new one |
|
|
|
ll->data = orig_ext; |
|
|
|
t_hash_table_remove(orig, GUINT_TO_POINTER(ext->id)); |
|
|
|
rtp_extension_free(ext); |
|
|
|
ext = orig_ext; |
|
|
|
} |
|
|
|
|
|
|
|
media_init_extmap(media, ext); |
|
|
|
|
|
|
|
if (manip) |
|
|
|
manip(ext, flags); |
|
|
|
} |
|
|
|
|
|
|
|
// clean up of orig table |
|
|
|
extmap_ht_iter iter; |
|
|
|
t_hash_table_iter_init(&iter, orig); |
|
|
|
struct rtp_extension *ext; |
|
|
|
while (t_hash_table_iter_next(&iter, NULL, &ext)) |
|
|
|
rtp_extension_free(ext); |
|
|
|
t_hash_table_destroy(orig); |
|
|
|
} |
|
|
|
|
|
|
|
__attribute__((nonnull(1))) |
|
|
|
@ -3035,6 +3064,8 @@ static void media_set_extmap(struct call_media *media, const extmap_q *emq, |
|
|
|
// copy entries |
|
|
|
for (auto_iter(ll, emq->head); ll; ll = ll->next) { |
|
|
|
__auto_type ext_o = ll->data; |
|
|
|
if (ext_o->synthetic) |
|
|
|
continue; |
|
|
|
if (manip && !manip(&ext_o->name, flags)) |
|
|
|
continue; |
|
|
|
|
|
|
|
@ -3500,6 +3531,68 @@ static void monologue_bundle_set_sinks(struct call_monologue *ml) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
__attribute__((nonnull(1, 2))) |
|
|
|
static void monologue_bundle_offer(struct call_monologue *ml, sdp_ng_flags *flags) { |
|
|
|
if (!flags->bundle_offer || flags->opmode != OP_OFFER) |
|
|
|
return; |
|
|
|
|
|
|
|
ML_SET(ml, BUNDLE); |
|
|
|
|
|
|
|
// track PTs that appear in multiple medias |
|
|
|
g_auto(pt_media_ht) exclude_pt = pt_media_ht_new(); |
|
|
|
|
|
|
|
struct call_media *bundle = NULL; |
|
|
|
|
|
|
|
// 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]; |
|
|
|
if (!media) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (!media->streams.length || !media->streams.head->data->selected_sfd) |
|
|
|
continue; // disabled stream |
|
|
|
|
|
|
|
// we should have a MID, but check anyway |
|
|
|
if (!media->media_id.len) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (media->bundle) { |
|
|
|
// already bundled |
|
|
|
if (!bundle) |
|
|
|
bundle = media->bundle; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// first media to bundle is the head |
|
|
|
if (!bundle) |
|
|
|
bundle = media; |
|
|
|
|
|
|
|
// set bundle group |
|
|
|
media->bundle = bundle; |
|
|
|
|
|
|
|
// offer MID header extension |
|
|
|
if (!media->extmap_id[RTP_EXT_MID]) { |
|
|
|
unsigned int id = media_extmap_id(media); |
|
|
|
if (id == -1u) |
|
|
|
ilog(LOG_WARN, "Out of IDs for RTP header extension"); |
|
|
|
else { |
|
|
|
__auto_type ext = g_new0(struct rtp_extension, 1); |
|
|
|
// XXX string duplication and duplicate lookup via init_extmap -> get_handler |
|
|
|
ext->name = STR("urn:ietf:params:rtp-hdrext:sdes:mid"); |
|
|
|
ext->id = id; |
|
|
|
ext->synthetic = true; |
|
|
|
t_queue_push_tail(&media->extmap, ext); |
|
|
|
media_init_extmap(media, ext); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
track_bundle_media_pt(media, exclude_pt); |
|
|
|
} |
|
|
|
|
|
|
|
monologue_bundle_check_consistency(ml); |
|
|
|
monologue_bundle_check_heads(ml); |
|
|
|
} |
|
|
|
|
|
|
|
__attribute__((nonnull(1, 2))) |
|
|
|
static void monologue_bundle_accept(struct call_monologue *ml, sdp_ng_flags *flags) { |
|
|
|
if (!ML_ISSET(ml, BUNDLE)) |
|
|
|
@ -3790,6 +3883,7 @@ int monologue_offer_answer(struct call_monologue *monologues[2], sdp_streams_q * |
|
|
|
} |
|
|
|
|
|
|
|
monologue_bundle_accept(sender_ml, flags); |
|
|
|
monologue_bundle_offer(receiver_ml, flags); |
|
|
|
monologue_bundle_check_consistency(receiver_ml); |
|
|
|
monologue_bundle_set_fds(receiver_ml); |
|
|
|
monologue_bundle_set_sinks(sender_ml); |
|
|
|
|