From 70befc0b21dfd94f76d8d401df4dd6e5595550cf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 30 Apr 2021 16:21:14 -0400 Subject: [PATCH] webrtcbin: Implement caps queries on sinkpad based on codec preferences Also includes a unit test. Part-of: --- ext/webrtc/gstwebrtcbin.c | 75 ++++++++++++++++++++++++++++++++++++++++ tests/check/elements/webrtcbin.c | 38 ++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c index 44c1f03..0994d35 100644 --- a/ext/webrtc/gstwebrtcbin.c +++ b/ext/webrtc/gstwebrtcbin.c @@ -310,6 +310,80 @@ gst_webrtcbin_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) return gst_pad_event_default (pad, parent, event); } +static gboolean +gst_webrtcbin_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstWebRTCBinPad *wpad = GST_WEBRTC_BIN_PAD (pad); + gboolean ret = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_ACCEPT_CAPS: + GST_OBJECT_LOCK (wpad->trans); + if (wpad->trans->codec_preferences) { + GstCaps *caps; + + gst_query_parse_accept_caps (query, &caps); + + gst_query_set_accept_caps_result (query, + gst_caps_can_intersect (caps, wpad->trans->codec_preferences)); + ret = TRUE; + } + GST_OBJECT_UNLOCK (wpad->trans); + break; + + case GST_QUERY_CAPS: + { + GstCaps *codec_preferences = NULL; + + GST_OBJECT_LOCK (wpad->trans); + if (wpad->trans->codec_preferences) + codec_preferences = gst_caps_ref (wpad->trans->codec_preferences); + GST_OBJECT_UNLOCK (wpad->trans); + + if (codec_preferences) { + GstCaps *filter = NULL; + GstCaps *filter_prefs = NULL; + GstPad *target; + + gst_query_parse_caps (query, &filter); + + if (filter) { + filter_prefs = gst_caps_intersect_full (filter, codec_preferences, + GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (codec_preferences); + } else { + filter_prefs = codec_preferences; + } + + target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)); + if (target) { + GstCaps *result; + + result = gst_pad_query_caps (target, filter_prefs); + gst_query_set_caps_result (query, result); + gst_caps_unref (result); + + gst_object_unref (target); + } else { + gst_query_set_caps_result (query, filter_prefs); + } + + gst_caps_unref (filter_prefs); + ret = TRUE; + } + break; + } + default: + break; + } + + if (ret) + return TRUE; + + return gst_pad_query_default (pad, parent, query); +} + + static void gst_webrtc_bin_pad_init (GstWebRTCBinPad * pad) { @@ -334,6 +408,7 @@ gst_webrtc_bin_pad_new (const gchar * name, GstPadDirection direction) gst_object_unref (template); gst_pad_set_event_function (GST_PAD (pad), gst_webrtcbin_sink_event); + gst_pad_set_query_function (GST_PAD (pad), gst_webrtcbin_sink_query); GST_DEBUG_OBJECT (pad, "new visible pad with direction %s", direction == GST_PAD_SRC ? "src" : "sink"); diff --git a/tests/check/elements/webrtcbin.c b/tests/check/elements/webrtcbin.c index 942f0b2..fba3572 100644 --- a/tests/check/elements/webrtcbin.c +++ b/tests/check/elements/webrtcbin.c @@ -3880,6 +3880,43 @@ GST_START_TEST (test_force_second_media) GST_END_TEST; +GST_START_TEST (test_codec_preferences_caps) +{ + GstHarness *h; + GstPad *pad; + GstWebRTCRTPTransceiver *trans; + GstCaps *caps, *caps2; + + h = gst_harness_new_with_padnames ("webrtcbin", "sink_0", NULL); + pad = gst_element_get_static_pad (h->element, "sink_0"); + + g_object_get (pad, "transceiver", &trans, NULL); + + caps = gst_caps_from_string ("application/x-rtp, media=video," + "encoding-name=VP8, payload=115; application/x-rtp, media=video," + " encoding-name=H264, payload=104"); + g_object_set (trans, "codec-preferences", caps, NULL); + + caps2 = gst_pad_query_caps (pad, NULL); + fail_unless (gst_caps_is_equal (caps, caps2)); + gst_caps_unref (caps2); + gst_caps_unref (caps); + + caps = gst_caps_from_string (VP8_RTP_CAPS (115)); + fail_unless (gst_pad_query_accept_caps (pad, caps)); + gst_harness_set_src_caps (h, g_steal_pointer (&caps)); + + caps = gst_caps_from_string (VP8_RTP_CAPS (99)); + fail_unless (!gst_pad_query_accept_caps (pad, caps)); + gst_caps_unref (caps); + + gst_object_unref (pad); + gst_object_unref (trans); + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * webrtcbin_suite (void) { @@ -3927,6 +3964,7 @@ webrtcbin_suite (void) tcase_add_test (tc, test_reject_create_offer); tcase_add_test (tc, test_reject_set_description); tcase_add_test (tc, test_force_second_media); + tcase_add_test (tc, test_codec_preferences_caps); if (sctpenc && sctpdec) { tcase_add_test (tc, test_data_channel_create); tcase_add_test (tc, test_data_channel_remote_notify); -- 2.7.4