webrtc_internal: Add webrtc_set_sw_video_decoder() 83/320783/2 accepted/tizen_9.0_unified tizen_9.0 accepted/tizen/9.0/unified/20241125.180024
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 12 Sep 2024 00:18:26 +0000 (09:18 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Fri, 22 Nov 2024 08:04:58 +0000 (17:04 +0900)
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 <sc11.lee@samsung.com>
include/webrtc_internal.h
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc_internal.c
src/webrtc_sink.c

index ec4b09025fad375e37e7008c8eba0efcdef67979..d5f8ede86670d7fb8ad1ba1ec66c4f1c18a35a42 100644 (file)
@@ -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.
index 4ae966945b780ffca7a63a3e8406c3467bf4e109..4b1e715e04c549c5c2e8a610da1b6e74e24a701b 100644 (file)
@@ -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);
index b0847da5fda12c69066328eb44b63cf41f273ca7..1690d56ebae4f8c2a0b96e37ccf0b3e18261f90b 100644 (file)
@@ -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
index 4f3278fc097265c54955cf380afa72c3a8df65de..8cd7e0eb6a6c65951d124056e87f716b7a2b01be 100644 (file)
@@ -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;
index a35be005e82d5e4d989bab419bbe34143a304950..24b3ed0811788a7d603867b54f943f671df51b7f 100644 (file)
@@ -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;