From e4d88bd9cc2e6f9515516d97270141a5e1a404dd Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Thu, 12 Sep 2024 09:18:26 +0900 Subject: [PATCH] webrtc_internal: Add webrtc_set_sw_video_decoder() It'd be useful when an user wants to use sw video decoder to a particular track id even if the system supports a hw decoder by configuration. [Version] 1.1.44 [Issue Type] Internal API Change-Id: I1bb5c12422c5e7a901abb9ed54d00b84c57c00f1 Signed-off-by: Sangchul Lee --- include/webrtc_internal.h | 19 +++++++++++++++++++ include/webrtc_private.h | 2 ++ packaging/capi-media-webrtc.spec | 2 +- src/webrtc_internal.c | 18 ++++++++++++++++++ src/webrtc_sink.c | 30 +++++++++++++++++++++++++++--- 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/include/webrtc_internal.h b/include/webrtc_internal.h index ec4b0902..d5f8ede8 100644 --- a/include/webrtc_internal.h +++ b/include/webrtc_internal.h @@ -192,6 +192,25 @@ int webrtc_set_display_surface_id(webrtc_h webrtc, unsigned int track_id, int su */ int webrtc_set_display_qos(webrtc_h webrtc, unsigned int track_id, bool enable); +/** + * @brief Sets sw video decoder forcedly regardless of system configuration. + * @since_tizen 7.0 + * @remarks Call this function within webrtc_track_added_cb(), otherwise #WEBRTC_ERROR_INVALID_OPERATION will be returned.\n + * If webrtc_set_encoded_video_frame_cb() has been called, it will return #WEBRTC_ERROR_INVALID_OPERATION. + * @param[in] webrtc WebRTC handle + * @param[in] track_id The track id + * @param[in] enable Enable or not (@c true = use sw video decoder, @c false = follow system configuration) + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation + * @pre webrtc_track_added_cb() must be set by calling webrtc_set_track_added_cb(). + * @see webrtc_set_track_added_cb() + * @see webrtc_unset_track_added_cb() + */ +int webrtc_set_sw_video_decoder(webrtc_h webrtc, unsigned int track_id, bool enable); + /** * @internal * @brief Gets the video resolution of the video track. diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 4ae96694..4b1e715e 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -633,6 +633,7 @@ typedef struct _webrtc_gst_slot_s { GstElement *appsrc; GstCaps *appsrc_caps; bool hw_decoder_used; + bool sw_decoder_set_by_api; bool drop; } render; } av[AV_IDX_MAX]; @@ -877,6 +878,7 @@ int _get_display_mode_from_sink(webrtc_s *webrtc, unsigned int track_id, webrtc_ int _set_display_visible_to_sink(webrtc_s *webrtc, unsigned int track_id, bool visible); int _get_display_visible_from_sink(webrtc_s *webrtc, unsigned int track_id, bool *visible); int _set_display_qos_to_sink(webrtc_s *webrtc, unsigned int track_id, bool enable); +int _set_sw_video_decoder_to_sink(webrtc_s *webrtc, unsigned int track_id, bool enable); int _set_audio_mute_to_sink(webrtc_s *webrtc, unsigned int track_id, bool mute); int _get_audio_mute_from_sink(webrtc_s *webrtc, unsigned int track_id, bool *muted); int _get_video_resolution_from_sink(webrtc_s *webrtc, unsigned int track_id, int *width, int *height); diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index b0847da5..1690d56e 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: 1.1.43 +Version: 1.1.44 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_internal.c b/src/webrtc_internal.c index 4f3278fc..8cd7e0eb 100644 --- a/src/webrtc_internal.c +++ b/src/webrtc_internal.c @@ -78,6 +78,24 @@ int webrtc_set_display_qos(webrtc_h webrtc, unsigned int track_id, bool enable) return _set_display_qos_to_sink(webrtc, track_id, enable); } +int webrtc_set_sw_video_decoder(webrtc_h webrtc, unsigned int track_id, bool enable) +{ + g_autoptr(GMutexLocker) locker = NULL; + webrtc_s *_webrtc = (webrtc_s *)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(track_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "track id is 0"); + + locker = g_mutex_locker_new(&_webrtc->mutex); + + RET_VAL_IF(_webrtc->track_added_cb.callback == NULL, WEBRTC_ERROR_INVALID_OPERATION, "track added callback was not set"); + RET_VAL_IF(_webrtc->encoded_video_frame_cb.callback, WEBRTC_ERROR_INVALID_OPERATION, "encoded video frame callback was set"); + RET_VAL_IF(!_is_owner_of_track_build_context(_webrtc, track_id), WEBRTC_ERROR_INVALID_OPERATION, + "this function should be called within the track added callback"); + + return _set_sw_video_decoder_to_sink(_webrtc, track_id, enable); +} + int webrtc_get_video_resolution(webrtc_h webrtc, unsigned int track_id, int *width, int *height) { g_autoptr(GMutexLocker) locker = NULL; diff --git a/src/webrtc_sink.c b/src/webrtc_sink.c index a35be005..24b3ed08 100644 --- a/src/webrtc_sink.c +++ b/src/webrtc_sink.c @@ -560,11 +560,13 @@ int _decodebin_autoplug_select_cb(GstElement *decodebin, GstPad *pad, GstCaps *c { gchar *factory_name; const gchar *klass; - webrtc_s *webrtc = (webrtc_s *)user_data; + webrtc_s *webrtc; + webrtc_gst_slot_s *sink = (webrtc_gst_slot_s *)user_data; GStrv str_arr; - RET_VAL_IF(webrtc == NULL, GST_AUTOPLUG_SELECT_SKIP, "webrtc is NULL, skip it"); + RET_VAL_IF(sink == NULL, GST_AUTOPLUG_SELECT_SKIP, "sink is NULL, skip it"); + webrtc = sink->webrtc; factory_name = GST_OBJECT_NAME(factory); klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS); @@ -590,6 +592,9 @@ int _decodebin_autoplug_select_cb(GstElement *decodebin, GstPad *pad, GstCaps *c 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); return GST_AUTOPLUG_SELECT_SKIP; + } else if (sink->av[AV_IDX_VIDEO].render.sw_decoder_set_by_api) { + LOG_WARNING("skip using this video hw decoder element[%s], 'sw_decoder_set_by_api' has been set", factory_name); + return GST_AUTOPLUG_SELECT_SKIP; #ifndef TIZEN_TV } else { if (webrtc->ini.resource_acquisition.video_decoder) { @@ -739,7 +744,7 @@ int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad, bool is_audio, we sink->av[GET_AV_IDX(is_audio)].pt = _get_payload_type_from_pad(src_pad); g_signal_connect(decodebin, "pad-added", G_CALLBACK(__decodebin_pad_added_cb), webrtc); - g_signal_connect(decodebin, "autoplug-select", G_CALLBACK(_decodebin_autoplug_select_cb), webrtc); + g_signal_connect(decodebin, "autoplug-select", G_CALLBACK(_decodebin_autoplug_select_cb), sink); g_signal_connect(decodebin, "element-added", G_CALLBACK(__decodebin_element_added_cb), sink); if (!gst_bin_add(sink->bin, decodebin)) { @@ -1360,6 +1365,25 @@ int _set_display_qos_to_sink(webrtc_s *webrtc, unsigned int track_id, bool enabl return WEBRTC_ERROR_NONE; } +int _set_sw_video_decoder_to_sink(webrtc_s *webrtc, unsigned int track_id, bool enable) +{ + webrtc_gst_slot_s *sink; + + RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(track_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "track id is 0"); + + sink = __find_sink_slot_by_id(webrtc, track_id); + RET_VAL_IF(sink == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "sink is NULL"); + RET_VAL_IF(sink->encoded_frame_cb != NULL, WEBRTC_ERROR_INVALID_OPERATION, "it may be a forwarding sink for encoded frame callback"); + RET_VAL_IF((sink->media_types & MEDIA_TYPE_VIDEO) == 0x0, WEBRTC_ERROR_INVALID_OPERATION, "it's not a video track"); + + LOG_INFO("webrtc[%p] track_id[%u] enable[%d]", webrtc, track_id, enable); + + sink->av[AV_IDX_VIDEO].render.sw_decoder_set_by_api = enable; + + return WEBRTC_ERROR_NONE; +} + int _set_audio_mute_to_sink(webrtc_s *webrtc, unsigned int track_id, bool mute) { webrtc_gst_slot_s *sink; -- 2.34.1