From 85fc7ff70c5f6bf85df9c86592e8baf245fa6729 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Wed, 11 Oct 2023 16:58:10 +0200 Subject: [PATCH] MT#57719 Move `monologue_subscribe_*` to media subs Stop using the call subscriptions model in the subscribe request/answer functionality and move to the media subscriptions. Change-Id: I8aab2b1b4cdf9a3c5a04172c395ca509295ce0a3 --- daemon/call.c | 98 +++++++++++++------------- daemon/call_interfaces.c | 115 ++++++++++++++++++------------- daemon/janus.c | 37 +++++----- include/call.h | 5 +- include/call_interfaces.h | 2 + t/auto-daemon-tests-websocket.py | 64 ++++------------- 6 files changed, 152 insertions(+), 169 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 0bcc3a6ca..fe30be7a2 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2978,6 +2978,10 @@ void call_subscriptions_clear(GQueue *q) { g_queue_clear_full(q, call_subscription_free); } +void media_subscriptions_clear(GQueue *q) { + g_queue_clear_full(q, media_subscription_free); +} + static void __unsubscribe_media_link(struct call_media * which, GList * which_cm_link) { struct media_subscription * ms = which_cm_link->data; @@ -3440,11 +3444,6 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca return -1; } - __add_subscription(dst_ml, src_ml, idx_diff, &(struct sink_attrs) { .egress = !!flags->egress }); - if (flags->rtcp_mirror) - __add_subscription(src_ml, dst_ml, rev_idx_diff, - &(struct sink_attrs) { .egress = !!flags->egress, .rtcp_only = true }); - __update_init_subscribers(src_ml, NULL, NULL, flags->opmode); __update_init_subscribers(dst_ml, NULL, NULL, flags->opmode); @@ -3452,23 +3451,28 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca } /* called with call->master_lock held in W */ __attribute__((nonnull(1, 2, 3))) -int monologue_subscribe_request(const GQueue *srcs, struct call_monologue *dst_ml, +int monologue_subscribe_request(const GQueue *srms, struct call_monologue *dst_ml, struct sdp_ng_flags *flags) { - __unsubscribe_from_all(dst_ml); - __unsubscribe_medias_from_all(dst_ml); /* analogy for media subscriptions */ + unsigned int index = 1; /* running counter for output/dst medias */ + __unsubscribe_medias_from_all(dst_ml); __call_monologue_init_from_flags(dst_ml, flags); - unsigned int index = 1; // running counter for output/dst medias - - for (GList *sl = srcs->head; sl; sl = sl->next) { - struct call_subscription *cs = sl->data; - struct call_monologue *src_ml = cs->monologue; + AUTO_CLEANUP(GQueue mls, g_queue_clear) = G_QUEUE_INIT; /* to avoid duplications */ + for (GList *sl = srms->head; sl; sl = sl->next) + { + struct media_subscription *ms = sl->data; + struct call_monologue *src_ml = ms->monologue; + if (!src_ml) + continue; - int ret = monologue_subscribe_request1(src_ml, dst_ml, flags, &index); - if (ret) - return -1; + if (!g_queue_find(&mls, src_ml)) { + int ret = monologue_subscribe_request1(src_ml, dst_ml, flags, &index); + g_queue_push_tail(&mls, src_ml); + if (ret) + return -1; + } } return 0; } @@ -3476,33 +3480,20 @@ int monologue_subscribe_request(const GQueue *srcs, struct call_monologue *dst_m /* called with call->master_lock held in W */ __attribute__((nonnull(1, 2, 3))) int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flags *flags, GQueue *streams) { - GList *src_ml_it = dst_ml->subscriptions.head; - unsigned int index = 1; // running counter for input/src medias struct media_subscription *rev_ms = NULL; - for (GList *l = streams->head; l; l = l->next) { - if (!src_ml_it) - return -1; - - struct stream_params *sp = l->data; - - struct call_subscription *cs = src_ml_it->data; /* TODO: deprecate me */ - struct call_monologue *src_ml = cs->monologue; + for (GList * l = streams->head; l; l = l->next) + { + struct stream_params * sp = l->data; - // grab the matching source ml: - // we need to move to the next one when we've reached the last media of - // the current source ml - if (index > src_ml->medias->len) { - src_ml_it = src_ml_it->next; - if (!src_ml_it) - return -1; - index = 1; // starts over at 1 - cs = src_ml_it->data; - src_ml = cs->monologue; - } + /* set src_media based on subscription (assuming it is one-to-one) */ + struct call_media * dst_media = __get_media(dst_ml, sp, flags, 0); + GList * src_ml_media_it = dst_media->media_subscriptions.head; + struct media_subscription * ms = src_ml_media_it->data; + struct call_media * src_media = ms->media; - struct call_media *dst_media = __get_media(dst_ml, sp, flags, 0); - struct call_media *src_media = __get_media(src_ml, sp, flags, index++); + if (!dst_media || !src_media) + continue; rev_ms = call_get_media_subscription(src_media->media_subscribers_ht, dst_media); if (rev_ms) @@ -3517,8 +3508,7 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flag .allow_asymmetric = !!flags->allow_asymmetric_codecs); codec_store_strip(&dst_media->codecs, &flags->codec_strip, flags->codec_except); codec_store_offer(&dst_media->codecs, &flags->codec_offer, &sp->codecs); - } - else { + } else { codec_store_populate(&dst_media->codecs, &sp->codecs, .answer_only = true, .allow_asymmetric = !!flags->allow_asymmetric_codecs); if (!codec_store_is_full_answer(&src_media->codecs, &dst_media->codecs)) @@ -3539,20 +3529,30 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flag MEDIA_CLEAR(dst_media, RECV); bf_copy(&dst_media->media_flags, MEDIA_FLAG_SEND, &sp->sp_flags, SP_FLAG_RECV); - // XXX check answer SDP parameters - + /* TODO: check answer SDP parameters */ MEDIA_SET(dst_media, INITIALIZED); } __update_init_subscribers(dst_ml, streams, flags, flags->opmode); dialogue_unkernelize(dst_ml, "subscribe answer event"); - for (GList *l = dst_ml->subscriptions.head; l; l = l->next) { - struct call_subscription *cs = l->data; - struct call_monologue *src_ml = cs->monologue; - set_monologue_flags_per_subscribers(src_ml); - __update_init_subscribers(src_ml, NULL, NULL, flags->opmode); - dialogue_unkernelize(src_ml, "subscribe answer event"); + AUTO_CLEANUP(GQueue mls, g_queue_clear) = G_QUEUE_INIT; /* to avoid duplications */ + for (int i = 0; i < dst_ml->medias->len; i++) + { + struct call_media * dst_media = dst_ml->medias->pdata[i]; + if (!dst_media) + continue; + + for (GList * sub = dst_media->media_subscriptions.head; sub; sub = sub->next) + { + struct media_subscription * ms = sub->data; + if (!g_queue_find(&mls, ms->monologue)) { + set_monologue_flags_per_subscribers(ms->monologue); + __update_init_subscribers(ms->monologue, NULL, NULL, flags->opmode); + dialogue_unkernelize(ms->monologue, "subscribe answer event"); + g_queue_push_tail(&mls, ms->monologue); + } + } } return 0; diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index bd6bb2227..5acdb7fbc 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -2748,12 +2748,13 @@ static const char *media_block_match(struct call **call, struct call_monologue * return NULL; } -static void add_ml_to_sub_list(GQueue *q, struct call_monologue *ml) { - struct call_subscription *cs = g_slice_alloc0(sizeof(*cs)); - cs->monologue = ml; - g_queue_push_tail(q, cs); +void add_media_to_sub_list(GQueue *q, struct call_media *media, struct call_monologue *ml) { + struct media_subscription *ms = g_slice_alloc0(sizeof(*ms)); + ms->media = media; + ms->monologue = ml; + g_queue_push_tail(q, ms); } -static const char *media_block_match_mult(struct call **call, GQueue *mls, +static const char *media_block_match_mult(struct call **call, GQueue *medias, struct sdp_ng_flags *flags, bencode_item_t *input, enum call_opmode opmode) { call_ng_process_flags(flags, input, opmode); @@ -2765,38 +2766,54 @@ static const char *media_block_match_mult(struct call **call, GQueue *mls, return "Unknown call-ID"; if (flags->all == ALL_ALL) { - // get and add all offer/answer mls - for (GList *l = (*call)->monologues.tail; l; l = l->prev) { - struct call_monologue *ml = l->data; - if (ml->tagtype != FROM_TAG && ml->tagtype != TO_TAG) + for (GList *l = (*call)->medias.head; l; l = l->next) { + struct call_media *media = l->data; + if (!media || (media->monologue->tagtype != FROM_TAG && + media->monologue->tagtype != TO_TAG)) + { + continue; - add_ml_to_sub_list(mls, ml); + } + add_media_to_sub_list(medias, media, media->monologue); } return NULL; } - // is a single ml given? + /* is a single ml given? */ struct call_monologue *ml = NULL; const char *err = media_block_match1(*call, &ml, flags); if (err) return err; if (ml) { - add_ml_to_sub_list(mls, ml); + for (int i = 0; i < ml->medias->len; i++) + { + struct call_media * media = ml->medias->pdata[i]; + if (!media) + continue; + add_media_to_sub_list(medias, media, ml); + } return NULL; } - // handle from-tag list + /* handle from-tag list */ for (GList *l = flags->from_tags.head; l; l = l->next) { str *s = l->data; struct call_monologue *mlf = call_get_monologue(*call, s); - if (!mlf) + if (!mlf) { ilog(LOG_WARN, "Given from-tag " STR_FORMAT_M " not found", STR_FMT_M(s)); - else - add_ml_to_sub_list(mls, mlf); + } else { + for (int i = 0; i < mlf->medias->len; i++) + { + struct call_media * media = mlf->medias->pdata[i]; + if (!media) + continue; + add_media_to_sub_list(medias, media, mlf); + } + } } - if (!mls->length) - return "No monologues matched"; + if (!medias->length) + return "No medias found (no monologues matched)"; return NULL; } @@ -3422,52 +3439,54 @@ const char *call_subscribe_request_ng(bencode_item_t *input, bencode_item_t *out AUTO_CLEANUP(struct sdp_ng_flags flags, call_ng_free_flags); char rand_buf[65]; AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); - AUTO_CLEANUP(GQueue srcs, call_subscriptions_clear) = G_QUEUE_INIT; + AUTO_CLEANUP(GQueue srms, media_subscriptions_clear) = G_QUEUE_INIT; AUTO_CLEANUP(str sdp_out, str_free_dup) = STR_NULL; - // get source monologue - err = media_block_match_mult(&call, &srcs, &flags, input, OP_REQUEST); + /* get source monologue */ + err = media_block_match_mult(&call, &srms, &flags, input, OP_REQUEST); if (err) return err; if (flags.sdp.len) ilog(LOG_INFO, "Subscribe-request with SDP received - ignoring SDP"); - if (!srcs.length) - return "No call participant specified"; + if (!srms.length) + return "No call participants specified (no medias found)"; - // special case with just one source: we can use the original SDP + /* special case with just one source: we can use the original SDP + * TODO: deprecate it, since initially added for monologue subscriptions. + */ struct call_monologue *sdp_ml = NULL; - if (srcs.length == 1) { - struct call_subscription *cs = srcs.head->data; - sdp_ml = cs->monologue; + if (srms.length == 1) { + struct media_subscription *ms = srms.head->data; + sdp_ml = ms->monologue; if (!sdp_ml->last_in_sdp.len || !sdp_ml->last_in_sdp_parsed.length) sdp_ml = NULL; } - // the `label=` option was possibly used above to select the from-tag -- - // switch it out with `to-label=` or `set-label=` for monologue_subscribe_request - // below which sets the label based on `label` for a newly created monologue + /* the `label=` option was possibly used above to select the from-tag -- + * switch it out with `to-label=` or `set-label=` for monologue_subscribe_request + * below which sets the label based on `label` for a newly created monologue */ flags.label = flags.to_label; if (flags.set_label.len) // set-label takes priority flags.label = flags.set_label; - // get destination monologue + /* get destination monologue */ if (!flags.to_tag.len) { - // generate one + /* generate one */ flags.to_tag = STR_CONST_INIT(rand_buf); rand_hex_str(flags.to_tag.s, flags.to_tag.len / 2); } struct call_monologue *dest_ml = call_get_or_create_monologue(call, &flags.to_tag); - // rewrite SDP, or create new? + /* rewrite SDP, or create new? */ struct sdp_chopper *chopper = NULL; if (sdp_ml) { chopper = sdp_chopper_new(&sdp_ml->last_in_sdp); bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper); } - int ret = monologue_subscribe_request(&srcs, dest_ml, &flags); + int ret = monologue_subscribe_request(&srms, dest_ml, &flags); if (ret) return "Failed to request subscription"; @@ -3475,28 +3494,28 @@ const char *call_subscribe_request_ng(bencode_item_t *input, bencode_item_t *out ret = sdp_replace(chopper, &sdp_ml->last_in_sdp_parsed, dest_ml, &flags); if (ret) return "Failed to rewrite SDP"; - } - else { - // create new SDP + } else { + /* create new SDP */ ret = sdp_create(&sdp_out, dest_ml, &flags); } - // place return output SDP + /* place return output SDP */ if (chopper) { if (chopper->output->len) bencode_dictionary_add_string_len(output, "sdp", chopper->output->str, chopper->output->len); - } - else if (sdp_out.len) { + } else if (sdp_out.len) { bencode_buffer_destroy_add(output->buffer, g_free, sdp_out.s); bencode_dictionary_add_str(output, "sdp", &sdp_out); - sdp_out = STR_NULL; // ownership passed to output + sdp_out = STR_NULL; /* ownership passed to output */ } - // add single response ml tag if there's just one, but always add a list - if (srcs.length == 1) { - struct call_subscription *cs = srcs.head->data; - struct call_monologue *source_ml = cs->monologue; + /* add single response ml tag if there's just one, but always add a list + * TODO: deprecate it, since initially added for monologue subscriptions. + */ + if (srms.length == 1) { + struct media_subscription *ms = srms.head->data; + struct call_monologue *source_ml = ms->monologue; bencode_dictionary_add_str_dup(output, "from-tag", &source_ml->tag); } bencode_item_t *tag_medias = NULL, *media_labels = NULL; @@ -3505,9 +3524,9 @@ const char *call_subscribe_request_ng(bencode_item_t *input, bencode_item_t *out media_labels = bencode_dictionary_add_dictionary(output, "media-labels"); } bencode_item_t *from_list = bencode_dictionary_add_list(output, "from-tags"); - for (GList *l = srcs.head; l; l = l->next) { - struct call_subscription *cs = l->data; - struct call_monologue *source_ml = cs->monologue; + for (GList *l = srms.head; l; l = l->next) { + struct media_subscription *ms = l->data; + struct call_monologue *source_ml = ms->monologue; bencode_list_add_str_dup(from_list, &source_ml->tag); if (tag_medias) { bencode_item_t *tag_label = bencode_list_add_dictionary(tag_medias); diff --git a/daemon/janus.c b/daemon/janus.c index df28024d6..3694f812c 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -410,7 +410,7 @@ static void janus_publishers_list(JsonBuilder *builder, struct call *call, struc // global janus_lock is held static const char *janus_videoroom_join_sub(struct janus_handle *handle, struct janus_room *room, int *retcode, - uint64_t feed_id, struct call *call, GQueue *srcs) + uint64_t feed_id, struct call *call, GQueue *medias) { // does the feed actually exist? get the feed handle *retcode = 512; @@ -428,10 +428,13 @@ static const char *janus_videoroom_join_sub(struct janus_handle *handle, struct if (!source_ml) return "Feed not found"; - struct call_subscription *cs = g_slice_alloc0(sizeof(*cs)); - cs->monologue = source_ml; - g_queue_push_tail(srcs, cs); - + for (int i = 0; i < source_ml->medias->len; i++) + { + struct call_media * media = source_ml->medias->pdata[i]; + if (!media) + continue; + add_media_to_sub_list(medias, media, source_ml); + } return NULL; } @@ -533,7 +536,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan else { // subscriber - AUTO_CLEANUP(GQueue srcs, call_subscriptions_clear) = G_QUEUE_INIT; + AUTO_CLEANUP(GQueue srms, media_subscriptions_clear) = G_QUEUE_INIT; // get single feed ID if there is one if (json_reader_read_member(reader, "feed")) { @@ -542,7 +545,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan if (!feed_id) return "JSON object contains invalid 'message.feed' key"; const char *ret = janus_videoroom_join_sub(handle, room, retcode, feed_id, - call, &srcs); + call, &srms); if (ret) return ret; } @@ -576,7 +579,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan if (!g_queue_find_custom(&ret_streams, &fid, g_int64_cmp)) { const char *ret = janus_videoroom_join_sub(handle, room, retcode, fid, - call, &srcs); + call, &srms); if (ret) return ret; @@ -594,7 +597,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan json_reader_end_member(reader); *retcode = 456; - if (!srcs.length) + if (!srms.length) return "No feeds to subscribe to given"; struct call_monologue *dest_ml = janus_get_monologue(handle->id, call, @@ -622,21 +625,12 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan flags.rtcp_mux_demux = 1; } - int ret = monologue_subscribe_request(&srcs, dest_ml, &flags); + int ret = monologue_subscribe_request(&srms, dest_ml, &flags); if (ret) return "Subscribe error"; - // create SDP: if there's only one subscription, we can use the original - // SDP, otherwise we generate a new one - if (srcs.length == 1) { - struct call_subscription *cs = srcs.head->data; - struct call_monologue *source_ml = cs->monologue; - struct sdp_chopper *chopper = sdp_chopper_new(&source_ml->last_in_sdp); - ret = sdp_replace(chopper, &source_ml->last_in_sdp_parsed, dest_ml, &flags); - sdp_chopper_destroy_ret(chopper, jsep_sdp_out); - } - else - ret = sdp_create(jsep_sdp_out, dest_ml, &flags); + /* create SDP */ + ret = sdp_create(jsep_sdp_out, dest_ml, &flags); if (!dest_ml->janus_session) dest_ml->janus_session = obj_get(session); @@ -645,6 +639,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan if (ret) return "Error generating SDP"; + *jsep_type_out = "offer"; } diff --git a/include/call.h b/include/call.h index 18d79f442..b5d114231 100644 --- a/include/call.h +++ b/include/call.h @@ -745,7 +745,8 @@ void __add_sink_handler(GQueue *, struct packet_stream *, const struct sink_attr void call_subscription_free(void *); void call_subscriptions_clear(GQueue *q); - +void media_subscription_free(void *); +void media_subscriptions_clear(GQueue *q); struct call *call_get_or_create(const str *callid, bool exclusive); struct call *call_get_opmode(const str *callid, enum call_opmode opmode); @@ -763,7 +764,7 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi struct stream_params *sp, struct sdp_ng_flags *flags); int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_flags *flags); -int monologue_subscribe_request(const GQueue *srcs, struct call_monologue *dst, struct sdp_ng_flags *); +int monologue_subscribe_request(const GQueue *srms, struct call_monologue *dst, struct sdp_ng_flags *); int monologue_subscribe_answer(struct call_monologue *dst, struct sdp_ng_flags *, GQueue *); int monologue_unsubscribe(struct call_monologue *dst, struct sdp_ng_flags *); diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 14c174b19..ec62185b0 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -248,6 +248,8 @@ const char *call_subscribe_request_ng(bencode_item_t *, bencode_item_t *); const char *call_subscribe_answer_ng(struct ng_buffer *, bencode_item_t *, bencode_item_t *); const char *call_unsubscribe_ng(bencode_item_t *, bencode_item_t *); +void add_media_to_sub_list(GQueue *q, struct call_media *media, struct call_monologue *ml); + void save_last_sdp(struct call_monologue *ml, str *sdp, GQueue *parsed, GQueue *streams); void call_ng_flags_init(struct sdp_ng_flags *out, enum call_opmode opmode); void call_ng_free_flags(struct sdp_ng_flags *flags); diff --git a/t/auto-daemon-tests-websocket.py b/t/auto-daemon-tests-websocket.py index eb2d59f31..ba0db5331 100644 --- a/t/auto-daemon-tests-websocket.py +++ b/t/auto-daemon-tests-websocket.py @@ -577,11 +577,11 @@ class TestVideoroom(unittest.TestCase): sdp, re.compile( "^v=0\r\n" - "o=x 123 123 IN IP4 203.0.113.3\r\n" - "c=IN IP4 203.0.113.1\r\n" - "s=foobar\r\n" + "o=- \d+ \d+ IN IP4 203.0.113.1\r\n" + "s=rtpengine.*?\r\n" "t=0 0\r\n" "m=audio \d+ UDP/TLS/RTP/SAVPF 8\r\n" + "c=IN IP4 203.0.113.1\r\n" "a=mid:1\r\n" "a=rtpmap:8 PCMA/8000\r\n" "a=sendonly\r\n" @@ -865,11 +865,11 @@ class TestVideoroom(unittest.TestCase): sdp, re.compile( "^v=0\r\n" - "o=x 123 123 IN IP4 203.0.113.3\r\n" - "c=IN IP4 203.0.113.1\r\n" - "s=foobar\r\n" + "o=- \d+ \d+ IN IP4 203.0.113.1\r\n" + "s=rtpengine.*?\r\n" "t=0 0\r\n" "m=audio \d+ UDP/TLS/RTP/SAVPF 8\r\n" + "c=IN IP4 203.0.113.1\r\n" "a=mid:1\r\n" "a=rtpmap:8 PCMA/8000\r\n" "a=sendonly\r\n" @@ -1716,24 +1716,11 @@ class TestVideoroom(unittest.TestCase): sdp, re.compile( "^v=0\r\n" - "o=- 3959345330719813235 2 IN IP4 127.0.0.1\r\n" - "s=-\r\n" + "o=- \d+ \d+ IN IP4 203.0.113.1\r\n" + "s=rtpengine.*?\r\n" "t=0 0\r\n" - "a=extmap-allow-mixed\r\n" - "a=msid-semantic: WMS hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC\r\n" "m=audio \d+ UDP/TLS/RTP/SAVPF 111\r\n" "c=IN IP4 203.0.113.1\r\n" - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" - "a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" - "a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" - "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" - "a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n" - "a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\n" - "a=msid:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC 2de0f1b0-3a39-450e-9804-8305ec87452b\r\n" - "a=ssrc:677770262 cname:NMNDwVd66x2SfiO0\r\n" - "a=ssrc:677770262 msid:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC 2de0f1b0-3a39-450e-9804-8305ec87452b\r\n" - "a=ssrc:677770262 mslabel:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC\r\n" - "a=ssrc:677770262 label:2de0f1b0-3a39-450e-9804-8305ec87452b\r\n" "a=mid:0\r\n" "a=rtpmap:111 opus/48000/2\r\n" "a=fmtp:111 useinbandfec=1; minptime=10\r\n" @@ -1750,28 +1737,6 @@ class TestVideoroom(unittest.TestCase): "a=end-of-candidates\r\n" "m=video \d+ UDP/TLS/RTP/SAVPF 96\r\n" "c=IN IP4 203.0.113.1\r\n" - "a=extmap:14 urn:ietf:params:rtp-hdrext:toffset\r\n" - "a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" - "a=extmap:13 urn:3gpp:video-orientation\r\n" - "a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" - "a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\n" - "a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\r\n" - "a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\r\n" - "a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\r\n" - "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" - "a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n" - "a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\n" - "a=msid:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC 6d6ec7a7-e3d7-4c82-b03c-45e017713abd\r\n" - "a=rtcp-rsize\r\n" - "a=ssrc-group:FID 3005569364 2001490794\r\n" - "a=ssrc:3005569364 cname:NMNDwVd66x2SfiO0\r\n" - "a=ssrc:3005569364 msid:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC 6d6ec7a7-e3d7-4c82-b03c-45e017713abd\r\n" - "a=ssrc:3005569364 mslabel:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC\r\n" - "a=ssrc:3005569364 label:6d6ec7a7-e3d7-4c82-b03c-45e017713abd\r\n" - "a=ssrc:2001490794 cname:NMNDwVd66x2SfiO0\r\n" - "a=ssrc:2001490794 msid:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC 6d6ec7a7-e3d7-4c82-b03c-45e017713abd\r\n" - "a=ssrc:2001490794 mslabel:hJifdaJwqEqHxSG0pVbs1DrLAwiHqz7fKlqC\r\n" - "a=ssrc:2001490794 label:6d6ec7a7-e3d7-4c82-b03c-45e017713abd\r\n" "a=mid:1\r\n" "a=rtpmap:96 VP8/90000\r\n" "a=rtcp-fb:96 goog-remb\r\n" @@ -1983,11 +1948,11 @@ class TestVideoroom(unittest.TestCase): sdp, re.compile( "^v=0\r\n" - "o=x 123 123 IN IP4 203.0.113.2\r\n" - "c=IN IP4 203.0.113.1\r\n" - "s=foobar\r\n" + "o=- \d+ \d+ IN IP4 203.0.113.1\r\n" + "s=rtpengine.*?\r\n" "t=0 0\r\n" "m=audio \d+ UDP/TLS/RTP/SAVPF 8\r\n" + "c=IN IP4 203.0.113.1\r\n" "a=mid:audio\r\n" "a=rtpmap:8 PCMA/8000\r\n" "a=sendonly\r\n" @@ -3116,16 +3081,17 @@ class TestVideoroom(unittest.TestCase): match_re = re.compile( "^v=0\r\n" - "o=x 123 123 IN IP4 203.0.113.2\r\n" - "c=IN IP4 203.0.113.1\r\n" - "s=foobar\r\n" + "o=- \d+ \d+ IN IP4 203.0.113.1\r\n" + "s=rtpengine.*?\r\n" "t=0 0\r\n" "m=audio (\d+) RTP/AVP 96\r\n" + "c=IN IP4 203.0.113.1\r\n" "a=mid:a\r\n" "a=rtpmap:96 opus/48000/2\r\n" "a=sendonly\r\n" "a=rtcp:\d+\r\n" "m=video (\d+) RTP/AVP 97\r\n" + "c=IN IP4 203.0.113.1\r\n" "a=mid:v\r\n" "a=rtpmap:97 VP9/90000\r\n" "a=sendonly\r\n"