webrtc_sink: Enable in-band FEC of OPUS decoder 83/267983/8
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 14 Dec 2021 06:42:48 +0000 (15:42 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 28 Dec 2021 07:03:47 +0000 (16:03 +0900)
[Version] 0.3.33
[Issue Type] New feature

Change-Id: I48d271615a1f742e15c2ba2d10e4de023d4430cc
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc_private.c
src/webrtc_sink.c
src/webrtc_source.c

index d5a960c6e31336041c8f7b88193e07f5961bc987..b408a5fee3dbf2723d05318601b92f68114c1a92 100644 (file)
@@ -212,6 +212,7 @@ do { \
        g_free(dot_name); \
 } while (0)
 
+#define GET_AV_IDX(x_is_audio) (x_is_audio) ? AV_IDX_AUDIO : AV_IDX_VIDEO
 #define GET_MEDIA_TYPE_NAME(x_is_audio) (x_is_audio) ? "audio" : "video"
 
 #define DEFAULT_ELEMENT_FAKESINK        "fakesink"
@@ -623,7 +624,7 @@ GstElement *_create_element_from_registry(element_info_s *elem_info);
 webrtc_gst_slot_s* _get_slot_by_id(GHashTable *slots, unsigned int id);
 int _add_no_target_ghostpad_to_slot(webrtc_gst_slot_s *slot, bool is_src, GstPad **new_pad);
 int _set_ghost_pad_target(GstPad *ghost_pad, GstElement *target_element, bool is_src);
-int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad);
+int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad, bool is_audio);
 int _add_forwarding_sink_bin(webrtc_s *webrtc, GstPad *src_pad, bool is_audio);
 int _set_stream_info_to_sink(webrtc_s *webrtc, unsigned int track_id, sound_stream_info_h stream_info);
 int _set_display_to_sink(webrtc_s *webrtc, unsigned int track_id, unsigned int type, void *display);
@@ -707,6 +708,7 @@ int _remove_filesrc_pad_block_probe(webrtc_s *webrtc);
 
 gchar * _get_media_type_from_pad(GstPad *pad);
 gchar * _get_mime_type_from_pad(GstPad *pad);
+int _get_payload_id_from_pad(GstPad *pad);
 bool _is_supported_media_type(const char *media_type);
 bool _is_audio_media_type(const char *media_type);
 
index 05943ab44ecd7b642c58a4f10afb718063a49c4a..db6a63134f28269bb52a1f31b26e84f562eddb95 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.3.32
+Version:    0.3.33
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index d18f38d8c76de44bd39c29b90dff47d3ab77265a..c49e97455285965be280a9abd0c730cd20723392 100644 (file)
@@ -1271,6 +1271,25 @@ gchar * _get_mime_type_from_pad(GstPad *pad)
        return mime_type;
 }
 
+int _get_payload_id_from_pad(GstPad *pad)
+{
+       GstCaps *caps = NULL;
+       gint id = -1;
+
+       RET_VAL_IF(pad == NULL, -1, "pad is NULL");
+
+       caps = gst_pad_get_current_caps(pad);
+       RET_VAL_IF(caps == NULL, -1, "caps is NULL");
+
+       if (!gst_structure_get_int(gst_caps_get_structure(caps, 0), "payload", &id))
+               LOG_ERROR("failed to gst_structure_get_int()");
+       else
+               LOG_DEBUG("payload id[%d]", id);
+
+       gst_caps_unref(caps);
+
+       return id;
+}
 //LCOV_EXCL_STOP
 
 bool _is_supported_media_type(const char *media_type)
@@ -1324,7 +1343,7 @@ static void __webrtcbin_pad_added_cb(GstElement *webrtcbin, GstPad *new_pad, gpo
                ret = _add_forwarding_sink_bin(webrtc, new_pad, is_audio);
                RET_IF(ret != WEBRTC_ERROR_NONE, "failed to _add_forwarding_sink_bin()");
        } else {
-               ret = _add_rendering_sink_bin(webrtc, new_pad);
+               ret = _add_rendering_sink_bin(webrtc, new_pad, is_audio);
                RET_IF(ret != WEBRTC_ERROR_NONE, "failed to _add_rendering_sink_bin()");
        }
 
index cacd7f96bedc7f2a662b1ddb118b8c01b08cb017..ab131a61adce2a52224bab107fe64c9b428b0ab6 100644 (file)
@@ -342,18 +342,38 @@ static void __invoke_track_added_cb(webrtc_s *webrtc, const gchar *name, bool is
 
 static void __decodebin_element_added_cb(GstElement *decodebin, GstElement *element, gpointer user_data)
 {
+       webrtc_gst_slot_s *sink = (webrtc_gst_slot_s *)user_data;
        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));
 
        LOG_INFO("element[name: %s] was added to decodebin", GST_ELEMENT_NAME(element));
 
        if (g_strrstr(factory_name, "rtpvp8depay")) {
-               LOG_INFO("set wait-for-keyframe to rtpvp8depay");
+               LOG_INFO("set wait-for-keyframe to %s", factory_name);
                g_object_set(G_OBJECT(element), "wait-for-keyframe", TRUE, NULL);
+
+       } else if (g_strrstr(factory_name, "opusdec")) {
+               int i;
+               for (i = 0; i < MAX_MLINE_NUM; i ++) { /* FIXME: we don't know mline in this situation, so retrieve the array here. */
+                       if (!sink->webrtc->data_recovery_types[i].inbandfec.use)
+                               continue;
+                       if (sink->webrtc->data_recovery_types[i].inbandfec.pt != (int)sink->av[AV_IDX_AUDIO].payload_id)
+                               continue;
+                       if (!g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(element)), "use-inband-fec")) {
+                               LOG_WARNING("could not find 'use-inband-fec' property");
+                               break;
+                       }
+                       LOG_INFO("set plc and use-inband-fec to %s", factory_name);
+                       g_object_set(G_OBJECT(element),
+                               "plc", TRUE,
+                               "use-inband-fec", TRUE,
+                               NULL);
+               }
        }
 }
 
@@ -431,7 +451,7 @@ int _decodebin_autoplug_select_cb(GstElement *decodebin, GstPad *pad, GstCaps *c
        factory_name = GST_OBJECT_NAME(factory);
        klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
 
-       LOG_INFO("decodebin[%p] factory[name:%s, klass:%s]", decodebin, factory_name, klass);
+       LOG_DEBUG("decodebin[%p] factory[name:%s, klass:%s]", decodebin, factory_name, klass);
 
        str_arr = webrtc->ini.general.gst_excluded_elements;
        while (str_arr && *str_arr) {
@@ -504,7 +524,7 @@ void _sink_slot_destroy_cb(gpointer data)
        g_free(sink);
 }
 
-int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad)
+int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad, bool is_audio)
 {
        int ret = WEBRTC_ERROR_NONE;
        unsigned int id;
@@ -530,11 +550,13 @@ int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad)
        if (!decodebin)
                goto error_before_insert;
 
+       sink->av[GET_AV_IDX(is_audio)].payload_id = _get_payload_id_from_pad(src_pad);
+
        gst_bin_add(sink->bin, decodebin);
 
        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, "element-added", G_CALLBACK(__decodebin_element_added_cb), NULL);
+       g_signal_connect(decodebin, "element-added", G_CALLBACK(__decodebin_element_added_cb), sink);
 
        ret = _add_no_target_ghostpad_to_slot(sink, false, &sink_pad);
        if (ret != WEBRTC_ERROR_NONE)
index 334cd1de4bcc6d5b2a897f0abd957fa148549c88..927c2735655df11f05e98144430363bd11ac9a23 100644 (file)
@@ -77,7 +77,6 @@ do { \
        LOG_DEBUG("%s is prepended", GST_ELEMENT_NAME(x_element)); \
 } while (0)
 
-#define GET_AV_IDX(x_is_audio) (x_is_audio) ? AV_IDX_AUDIO : AV_IDX_VIDEO
 #define GET_AV_IDX_BY_TYPE(x_media_type) GET_AV_IDX(x_media_type == MEDIA_TYPE_AUDIO)
 
 typedef struct {