webrtc_source: Improve error handling when failure on adding element to bin 32/265932/1
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 2 Nov 2021 03:32:42 +0000 (12:32 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 2 Nov 2021 03:33:41 +0000 (12:33 +0900)
If an error occurs when calling gst_bin_add() for element list,
error handling codes for unreferencing the elements should be divided
with two phases, one is for elements already added to the bin, the other
one is for the rest of elements in the list.

[Version] 0.2.144
[Issue Type] Improvement

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

index 6a94242a619e66b2233e4042694b9e65c872e1ac..4e528b6caf72525423a06c334dbf93ba71e5f3d4 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.2.143
+Version:    0.2.144
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 66d52c01a5bc97898e76d1139afc4402e3fbb48b..9932ab993821d2decf97e9bf97c0d6cc591a49dc 100644 (file)
@@ -1130,7 +1130,7 @@ static void __remove_probe_from_pad_for_pause(webrtc_gst_slot_s *source, unsigne
        source->av[idx].src_pad = NULL;
 }
 
-static bool __add_elements_to_bin(GstBin *bin, GList *element_list)
+static bool __remove_elements_from_bin(GstBin *bin, GList *element_list)
 {
        GstElement *element;
        GList *list;
@@ -1139,35 +1139,50 @@ static bool __add_elements_to_bin(GstBin *bin, GList *element_list)
        RET_VAL_IF(bin == NULL, false, "bin is NULL");
        RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
 
-       for (list = element_list; list; list = list->next) {
+       for (list = element_list; list; list = g_list_next(list)) {
                element = (GstElement *)list->data;
-               RET_VAL_IF(!gst_bin_add(bin, element), false,
-                       "failed to gst_bin_add(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
+               RET_VAL_IF(!gst_bin_remove(bin, element), false,
+                       "failed to gst_bin_remove(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
                count++;
        }
 
-       LOG_DEBUG("%d elements are added to bin[%s]", count, GST_ELEMENT_NAME(bin));
+       LOG_DEBUG("%d elements are removed from bin[%s]", count, GST_ELEMENT_NAME(bin));
 
        return true;
 }
 
-static bool __remove_elements_from_bin(GstBin *bin, GList *element_list)
+static void __foreach_unref_object_cb(gpointer data, gpointer user_data)
+{
+       GstElement *element = (GstElement *)data;
+
+       LOG_DEBUG("%s is unreferenced", GST_ELEMENT_NAME(element));
+       SAFE_GST_OBJECT_UNREF(element);
+}
+
+static bool __add_elements_to_bin(GstBin *bin, GList *element_list)
 {
        GstElement *element;
        GList *list;
-       int count = 0;
+       GList *added_list = NULL;
 
        RET_VAL_IF(bin == NULL, false, "bin is NULL");
        RET_VAL_IF(element_list == NULL, false, "element_list is NULL");
 
-       for (list = element_list; list; list = g_list_next(list)) {
+       for (list = element_list; list; list = list->next) {
                element = (GstElement *)list->data;
-               RET_VAL_IF(!gst_bin_remove(bin, element), false,
-                       "failed to gst_bin_remove(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
-               count++;
+               if (!gst_bin_add(bin, element)) {
+                       LOG_ERROR("failed to gst_bin_add(), bin[%s], element[%s]", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(element));
+                       __remove_elements_from_bin(bin, added_list);
+                       SAFE_G_LIST_FREE(added_list);
+                       g_list_foreach(list, __foreach_unref_object_cb, NULL); /* rest of elements on the list should be unreferenced */
+                       return false;
+               }
+               APPEND_ELEMENT(added_list, element);
        }
 
-       LOG_DEBUG("%d elements are removed from bin[%s]", count, GST_ELEMENT_NAME(bin));
+       LOG_DEBUG("%d elements are added to bin[%s]", g_list_length(added_list), GST_ELEMENT_NAME(bin));
+
+       SAFE_G_LIST_FREE(added_list);
 
        return true;
 }
@@ -1304,12 +1319,16 @@ static int __build_screensrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list, false)) != WEBRTC_ERROR_NONE)
                goto exit;
 
-       if (!__add_elements_to_bin(source->bin, switch_src_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, switch_src_list)) {
+               SAFE_G_LIST_FREE(switch_src_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__add_elements_to_bin(source->bin, element_list)) {
-               ret = WEBRTC_ERROR_INVALID_OPERATION;
-               goto exit_with_remove_from_bin;
+               __remove_elements_from_bin(source->bin, switch_src_list);
+               SAFE_G_LIST_FREE(switch_src_list);
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
        }
 
        if (!__link_switch_srcs(videoswitch, switch_src_list)) {
@@ -1384,8 +1403,10 @@ static int __build_camerasrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list, false)) != WEBRTC_ERROR_NONE)
                goto exit;
 
-       if (!__add_elements_to_bin(source->bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list)) {
                ret = WEBRTC_ERROR_INVALID_OPERATION;
@@ -1450,8 +1471,10 @@ static int __build_audiosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool us
        if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list, true)) != WEBRTC_ERROR_NONE)
                goto exit;
 
-       if (!__add_elements_to_bin(source->bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list)) {
                ret = WEBRTC_ERROR_INVALID_OPERATION;
@@ -1511,8 +1534,10 @@ static int __build_videotestsrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list, false)) != WEBRTC_ERROR_NONE)
                goto exit;
 
-       if (!__add_elements_to_bin(source->bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list)) {
                ret = WEBRTC_ERROR_INVALID_OPERATION;
@@ -1568,8 +1593,10 @@ static int __build_custom_videosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list, false)) != WEBRTC_ERROR_NONE)
                goto exit;
 
-       if (!__add_elements_to_bin(source->bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list)) {
                ret = WEBRTC_ERROR_INVALID_OPERATION;
@@ -1631,8 +1658,10 @@ static int __build_custom_audiosrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list, true)) != WEBRTC_ERROR_NONE)
                goto exit;
 
-       if (!__add_elements_to_bin(source->bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list)) {
                ret = WEBRTC_ERROR_INVALID_OPERATION;
@@ -1697,8 +1726,10 @@ static int __build_filesrc_bin(webrtc_gst_slot_s *source, media_type_e media_typ
                goto exit;
        APPEND_ELEMENT(element_list, capsfilter);
 
-       if (!__add_elements_to_bin(source->bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list))
                goto exit_with_remove_from_bin;
@@ -1901,8 +1932,10 @@ static int __create_rest_of_elements_for_filesrc_pipeline(webrtc_gst_slot_s *sou
                goto exit;
        APPEND_ELEMENT(element_list, fakesink);
 
-       if (!__add_elements_to_bin(bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list))
                goto exit_with_remove_from_bin;
@@ -2264,19 +2297,22 @@ static int __complete_mediapacketsrc_from_raw_format(webrtc_s *webrtc, webrtc_gs
        source->zerocopy_enabled = __is_hw_encoder_used(webrtc, source->type, source->media_types);
 
        if ((ret = __create_rest_of_elements(webrtc, source, false, &element_list, (source->media_types == MEDIA_TYPE_AUDIO))) != WEBRTC_ERROR_NONE)
-               return ret;
+               goto exit;
 
        if (!(sink_caps = __make_raw_caps_from_media_format(source))) {
                LOG_ERROR("failed to __make_raw_caps_from_media_format()");
-               return WEBRTC_ERROR_INVALID_OPERATION;
+               ret = WEBRTC_ERROR_INVALID_OPERATION;
+               goto exit;
        }
        PRINT_CAPS(sink_caps, "appsrc");
 
        g_object_set(G_OBJECT(appsrc), "caps", sink_caps, NULL);
        gst_caps_unref(sink_caps);
 
-       if (!__add_elements_to_bin(source->bin, element_list))
-               goto exit;
+       if (!__add_elements_to_bin(source->bin, element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        PREPEND_ELEMENT(element_list, appsrc);
        if (!__link_elements(element_list)) {
@@ -3741,8 +3777,10 @@ static int __build_loopback_audiosink(webrtc_gst_slot_s *source, GstElement *lin
        }
        g_object_set(G_OBJECT(audiosink), "sync", FALSE, NULL);
 
-       if (!__add_elements_to_bin(GST_BIN(source->av[AV_IDX_AUDIO].render.pipeline), element_list))
-               goto exit;
+       if (!__add_elements_to_bin(GST_BIN(source->av[AV_IDX_AUDIO].render.pipeline), element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list))
                goto exit_with_remove_from_bin;
@@ -3830,8 +3868,10 @@ static int __build_loopback_videosink(webrtc_gst_slot_s *source, GstElement *lin
                _connect_and_append_signal(&source->signals, (GObject *)videosink, "handoff", G_CALLBACK(_video_stream_decoded_cb), source->display);
        }
 
-       if (!__add_elements_to_bin(GST_BIN(source->av[AV_IDX_VIDEO].render.pipeline), element_list))
-               goto exit;
+       if (!__add_elements_to_bin(GST_BIN(source->av[AV_IDX_VIDEO].render.pipeline), element_list)) {
+               SAFE_G_LIST_FREE(element_list);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
 
        if (!__link_elements(element_list))
                goto exit_with_remove_from_bin;