webrtcbin: Implement caps queries on sinkpad based on codec preferences

Also includes a unit test.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2183>
This commit is contained in:
Olivier Crête 2021-04-30 16:21:14 -04:00
parent dc6655542d
commit 70befc0b21
2 changed files with 113 additions and 0 deletions

View 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");

View 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);