From ad43726dcaaadf132ef1d99c290635cc7e7c8c8c Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Fri, 5 Aug 2022 11:46:18 +0900 Subject: [PATCH] webrtc_sink: Enable 'use-tbm' property of videosink if H/W decoder is used It supports both WEBRTC_DISPLAY_TYPE_OVERLAY and WEBRTC_DISPLAY_TYPE_ECORE_WL display types. videoconvert is also excluded in this situation. [Version] 0.3.195 [Issue Type] Improvement Change-Id: If6e432762ee75b42a570a871342ce154400cf702 Signed-off-by: Sangchul Lee --- include/webrtc_private.h | 1 + packaging/capi-media-webrtc.spec | 2 +- src/webrtc_sink.c | 89 ++++++++++++++++++++++---------- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 30e71701..023851e2 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -549,6 +549,7 @@ typedef struct _webrtc_gst_slot_s { GstElement *pipeline; GstElement *appsrc; GstCaps *appsrc_caps; + bool hw_decoder_used; } render; } av[AV_IDX_MAX]; struct { diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 1a3fc324..70720e3f 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.3.194 +Version: 0.3.195 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_sink.c b/src/webrtc_sink.c index fe4ce3b6..b1b6a62e 100644 --- a/src/webrtc_sink.c +++ b/src/webrtc_sink.c @@ -165,15 +165,18 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr #endif if (sink->display->type == WEBRTC_DISPLAY_TYPE_OVERLAY || sink->display->type == WEBRTC_DISPLAY_TYPE_ECORE_WL) { + g_object_set(G_OBJECT(videosink), + "use-tbm", sink->av[AV_IDX_VIDEO].render.hw_decoder_used, + "display-geometry-method", (gint)sink->display->mode, /* 0: letter box, 1: origin size, 2: full screen */ + "visible", (gboolean)sink->display->visible, + NULL); + + /* FIXME: The order of setting property and display is important when 'use-tbm' is true. The reverse does not work */ gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(videosink), sink->display->overlay_surface_id); RET_VAL_IF(!g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(videosink)), "display-geometry-method"), WEBRTC_ERROR_INVALID_OPERATION, "could not find 'display-geometry-method' property"); RET_VAL_IF(!g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(videosink)), "visible"), WEBRTC_ERROR_INVALID_OPERATION, "could not find 'visible' property"); - g_object_set(G_OBJECT(videosink), - "display-geometry-method", (gint)sink->display->mode, /* 0: letter box, 1: origin size, 2: full screen */ - "visible", (gboolean)sink->display->visible, - NULL); } else if (sink->display->type == WEBRTC_DISPLAY_TYPE_EVAS) { GstCaps *caps; @@ -195,10 +198,17 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr gst_caps_unref(caps); } - if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL))) - goto exit; - PREPEND_ELEMENT(element_list, videoconvert); - link_to = videoconvert; + if (sink->av[AV_IDX_VIDEO].render.hw_decoder_used && + (sink->display->type == WEBRTC_DISPLAY_TYPE_OVERLAY || + sink->display->type == WEBRTC_DISPLAY_TYPE_ECORE_WL)) { + link_to = videosink; + + } else { + if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL))) + goto exit; + PREPEND_ELEMENT(element_list, videoconvert); + link_to = videoconvert; + } } if (!_add_elements_to_bin(sink->bin, element_list)) { @@ -348,16 +358,51 @@ static void __invoke_track_added_cb(webrtc_s *webrtc, const gchar *name, bool is } } +static bool __is_factory_name_for_hw(gchar *factory_name) +{ + RET_VAL_IF(factory_name == NULL, FALSE, "factory_name is NULL"); + + /* more can be added later on */ + if (g_str_has_prefix(factory_name, "sprd") || + g_str_has_prefix(factory_name, "omx") || + g_str_has_prefix(factory_name, "v4l2")) { + LOG_DEBUG("factory_name[%s]", factory_name); + return true; + } + + return false; +} + +static bool __is_hw_decoder_element(GstElementFactory *factory, bool is_audio) +{ + gchar *factory_name; + const gchar *klass; + + RET_VAL_IF(factory == NULL, false, "factory is NULL"); + + factory_name = GST_OBJECT_NAME(factory); + klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS); + + if (is_audio) + return (g_strrstr(klass, "Decoder/Audio/Hardware") || + (g_strrstr(klass, "Decoder/Audio") && __is_factory_name_for_hw(factory_name))); + + return (g_strrstr(klass, "Decoder/Video/Hardware") || + (g_strrstr(klass, "Decoder/Video") && __is_factory_name_for_hw(factory_name))); +} + static void __decodebin_element_added_cb(GstElement *decodebin, GstElement *element, gpointer user_data) { - const webrtc_gst_slot_s *sink = (webrtc_gst_slot_s *)user_data; + webrtc_gst_slot_s *sink = (webrtc_gst_slot_s *)user_data; + GstElementFactory *factory; gchar *factory_name = NULL; RET_IF(decodebin == NULL, "decodebin is NULL"); RET_IF(element == NULL, "element is NULL"); RET_IF(sink == NULL, "sink is NULL"); - factory_name = GST_OBJECT_NAME(gst_element_get_factory(element)); + factory = gst_element_get_factory(element); + factory_name = GST_OBJECT_NAME(factory); LOG_INFO("element[name: %s] was added to decodebin", GST_ELEMENT_NAME(element)); @@ -383,6 +428,9 @@ static void __decodebin_element_added_cb(GstElement *decodebin, GstElement *elem NULL); } } + + sink->av[AV_IDX_AUDIO].render.hw_decoder_used = __is_hw_decoder_element(factory, true); + sink->av[AV_IDX_VIDEO].render.hw_decoder_used = __is_hw_decoder_element(factory, false); } static void __decodebin_pad_added_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data) @@ -433,20 +481,6 @@ static void __decodebin_pad_added_cb(GstElement *decodebin, GstPad *new_pad, gpo GENERATE_DOT(webrtc, webrtc->gst.pipeline, "%s.%s", GST_ELEMENT_NAME(webrtc->gst.pipeline), GST_ELEMENT_NAME(decodebin)); } -static bool __is_factory_name_for_hw(gchar *factory_name) -{ - RET_VAL_IF(factory_name == NULL, FALSE, "factory_name is NULL"); - - /* more can be added later on */ - if (g_str_has_prefix(factory_name, "sprd") || - g_str_has_prefix(factory_name, "omx")) { - LOG_DEBUG("factory_name[%s]", factory_name); - return true; - } - - return false; -} - int _decodebin_autoplug_select_cb(GstElement *decodebin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, gpointer user_data) { gchar *factory_name; @@ -469,15 +503,14 @@ int _decodebin_autoplug_select_cb(GstElement *decodebin, GstPad *pad, GstCaps *c } } - if (g_strrstr(klass, "Decoder/Audio/Hardware") || - (g_strrstr(klass, "Decoder/Audio") && __is_factory_name_for_hw(factory_name))) { + if (__is_hw_decoder_element(factory, true)) { str_arr = webrtc->ini.rendering_sink.a_hw_decoder_elements; if (str_arr == NULL || !g_strv_contains((const gchar * const *)str_arr, factory_name)) { LOG_WARNING("this audio hw decoder element[%s] is not specified in ini file, skip it", factory_name); return GST_AUTOPLUG_SELECT_SKIP; } - } else if (g_strrstr(klass, "Decoder/Video/Hardware") || - (g_strrstr(klass, "Decoder/Video") && __is_factory_name_for_hw(factory_name))) { + + } else if (__is_hw_decoder_element(factory, false)) { str_arr = webrtc->ini.rendering_sink.v_hw_decoder_elements; if (str_arr == NULL || !g_strv_contains((const gchar * const *)str_arr, factory_name)) { LOG_WARNING("this video hw decoder element[%s] is not specified in ini file, skip it", factory_name); -- 2.34.1