webrtc: fix answer creation with multiple streams and similar caps

This commit is contained in:
Matthew Waters 2018-11-26 22:10:57 +11:00
parent ebb9c3c298
commit bd92b2f7c4
2 changed files with 54 additions and 1 deletions

View file

@ -2396,6 +2396,7 @@ _create_answer_task (GstWebRTCBin * webrtc, const GstStructure * options)
GString *bundled_mids = NULL;
gchar *bundle_ufrag = NULL;
gchar *bundle_pwd = NULL;
GList *seen_transceivers = NULL;
if (!webrtc->pending_remote_description) {
GST_ERROR_OBJECT (webrtc,
@ -2576,6 +2577,13 @@ _create_answer_task (GstWebRTCBin * webrtc, const GstStructure * options)
rtp_trans =
g_array_index (webrtc->priv->transceivers,
GstWebRTCRTPTransceiver *, j);
if (g_list_find (seen_transceivers, rtp_trans)) {
/* Don't double allocate a transceiver to multiple mlines */
rtp_trans = NULL;
continue;
}
trans_caps =
_find_codec_preferences (webrtc, rtp_trans, GST_PAD_SINK, j);
@ -2590,7 +2598,7 @@ _create_answer_task (GstWebRTCBin * webrtc, const GstStructure * options)
if (answer_caps && !gst_caps_is_empty (answer_caps)) {
GST_LOG_OBJECT (webrtc,
"found compatible transceiver %" GST_PTR_FORMAT
" for offer media %u", trans, i);
" for offer media %u", rtp_trans, i);
if (trans_caps)
gst_caps_unref (trans_caps);
break;
@ -2619,6 +2627,7 @@ _create_answer_task (GstWebRTCBin * webrtc, const GstStructure * options)
answer_dir = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
answer_caps = gst_caps_ref (offer_caps);
}
seen_transceivers = g_list_prepend (seen_transceivers, rtp_trans);
if (!rtp_trans) {
trans = _create_webrtc_transceiver (webrtc, answer_dir, i);
@ -2724,6 +2733,8 @@ out:
if (bundled)
g_strfreev (bundled);
g_list_free (seen_transceivers);
return ret;
}

View file

@ -2213,6 +2213,47 @@ GST_START_TEST (test_duplicate_nego)
GST_END_TEST;
GST_START_TEST (test_dual_audio)
{
struct test_webrtc *t = create_audio_test ();
const gchar *expected_offer[] = { "sendrecv", "sendrecv", };
const gchar *expected_answer[] = { "sendrecv", "recvonly" };
struct validate_sdp offer = { on_sdp_media_direction, expected_offer, NULL };
struct validate_sdp answer =
{ on_sdp_media_direction, expected_answer, NULL };
GstHarness *h;
GstWebRTCRTPTransceiver *trans;
GArray *transceivers;
/* test that each mline gets a unique transceiver even with the same caps */
h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
add_fake_audio_src_harness (h, 96);
t->harnesses = g_list_prepend (t->harnesses, h);
h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
add_fake_audio_src_harness (h, 96);
t->harnesses = g_list_prepend (t->harnesses, h);
t->on_negotiation_needed = NULL;
test_validate_sdp (t, &offer, &answer);
g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
fail_unless (transceivers != NULL);
fail_unless_equals_int (2, transceivers->len);
trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 0);
fail_unless (trans != NULL);
fail_unless_equals_int (trans->mline, 0);
trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
fail_unless (trans != NULL);
fail_unless_equals_int (trans->mline, 1);
g_array_unref (transceivers);
test_webrtc_free (t);
}
static Suite *
webrtcbin_suite (void)
{
@ -2247,6 +2288,7 @@ webrtcbin_suite (void)
tcase_add_test (tc, test_bundle_audio_video_max_bundle_max_bundle);
tcase_add_test (tc, test_bundle_audio_video_max_bundle_none);
tcase_add_test (tc, test_bundle_audio_video_max_compat_max_bundle);
tcase_add_test (tc, test_dual_audio);
tcase_add_test (tc, test_duplicate_nego);
if (sctpenc && sctpdec) {
tcase_add_test (tc, test_data_channel_create);