webrtcbin: Implement caps queries on sinkpad based on codec preferences
authorOlivier Crête <olivier.crete@collabora.com>
Fri, 30 Apr 2021 20:21:14 +0000 (16:21 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Thu, 13 May 2021 19:05:00 +0000 (15:05 -0400)
Also includes a unit test.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2183>

ext/webrtc/gstwebrtcbin.c
tests/check/elements/webrtcbin.c

index 44c1f03..0994d35 100644 (file)
@@ -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");
index 942f0b2..fba3572 100644 (file)
@@ -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);