Revise webrtc_stop() 08/245608/4
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 13 Oct 2020 06:20:33 +0000 (15:20 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 19 Oct 2020 05:52:24 +0000 (14:52 +0900)
The gstreamer pipeline state is changed to NULL when after webrtc_stop().
In this situation, webrtc state is IDLE in which a media source can be added
or removed. This change intends to be sure to release all the resources
inside of the webrtcbin as well as avoid warning message when calling the
gst_bin_remove() within gstreamer READY state.

Release missing sink slots which have been created after finishing
negotiation APIs.

[Version] 0.1.39
[Issue Type] Improvement

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

index 6ee446e38d1ddd63893c81ef0ac50c8f2f522270..2406bdc5968da66fbdf6e7933168419f87b8d094 100644 (file)
@@ -123,13 +123,14 @@ do { \
        } \
 } while (0)
 
-#define MALLOC_AND_INIT_SLOT(x_slot, x_id, x_bin_name) \
+#define MALLOC_AND_INIT_SLOT(x_slot, x_id, x_bin_name, x_webrtcbin) \
 do { \
        x_slot = g_new0(webrtc_gst_slot_s, 1); \
        x_slot->id = x_id; \
        x_slot->bin = gst_bin_new(x_bin_name); \
        x_slot->mlines[MLINES_IDX_AUDIO] = -1; \
        x_slot->mlines[MLINES_IDX_VIDEO] = -1; \
+       x_slot->webrtcbin = x_webrtcbin; \
 } while (0)
 
 #define GENERATE_DOT(x_webrtc, x_fmt, x_arg...) \
@@ -160,6 +161,7 @@ typedef struct _webrtc_gst_slot_s {
        GstElement *bin;
        int media_types;    /* values of media_type_e combined with bitwise 'or' */
        int mlines[2];      /* index 0 for audio, 1 for video */
+       GstElement *webrtcbin;
 } webrtc_gst_slot_s;
 
 typedef struct _webrtc_gst_s {
@@ -227,6 +229,8 @@ GstElement *_create_element_from_registry(element_info_s *elem_info);
 int _add_no_target_ghostpad_to_slot(webrtc_gst_slot_s *slot, gboolean is_src, GstPad **new_pad);
 int _set_ghost_pad_target(GstPad *ghost_pad, GstElement *target_element, gboolean is_src);
 int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad);
+void _sink_slot_destroy_cb(gpointer data);
+void _source_slot_destroy_cb(gpointer data);
 void _generate_dot(webrtc_s *webrtc, const gchar *name);
 
 int _webrtcbin_create_offer(webrtc_s *webrtc, char **offer);
index b2c2ef5e637135cdc41c9339bc949ce2d5afdf96..79f8820642fba3aea514ca406de7f3478b5ccdbb 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.1.38
+Version:    0.1.39
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 3475d6d221990ae34781bc13318b9f56a225c685..0e2637b4c4a9c798a16ba9008911de0adb0fc1d5 100644 (file)
@@ -192,12 +192,14 @@ int webrtc_stop(webrtc_h webrtc)
 
        RET_VAL_WITH_UNLOCK_IF(_webrtc->state == WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should not be IDLE");
 
-       _gst_pipeline_set_state(_webrtc, GST_STATE_READY);
+       _gst_pipeline_set_state(_webrtc, GST_STATE_NULL);
 
        _post_state_in_idle(_webrtc, WEBRTC_STATE_IDLE);
 
        LOG_INFO("webrtc[%p] is stopping", webrtc);
 
+       g_hash_table_remove_all(_webrtc->gst.sink_slots);
+
        g_mutex_unlock(&_webrtc->mutex);
 
        return WEBRTC_ERROR_NONE;
index 1583a7cf65f01aefc23a6502eda3b5a81dfcd1fb..410cd3c19c8cbe0bc4cee235b195a7467bee7d2f 100644 (file)
@@ -273,7 +273,7 @@ static gboolean __idle_cb(gpointer user_data)
 
        __invoke_state_changed_cb(webrtc, old_state, webrtc->state);
 
-       return FALSE;
+       return G_SOURCE_REMOVE;
 }
 
 void _post_state_in_idle(webrtc_s *webrtc, webrtc_state_e new_state)
@@ -377,22 +377,6 @@ GstElement *_create_element_from_registry(element_info_s *elem_info)
        return element;
 }
 
-static void __value_destroy_cb(gpointer data)
-{
-       webrtc_gst_slot_s *source  = (webrtc_gst_slot_s *)data;
-
-       RET_IF(data == NULL, "data is NULL");
-
-       LOG_DEBUG("[%s, id:%u, media_types:0x%x, mlines[AUDIO]:%d, mlines[VIDEO]:%d] is removed",
-               GST_ELEMENT_NAME(source->bin), source->id, source->media_types, source->mlines[MLINES_IDX_AUDIO], source->mlines[MLINES_IDX_VIDEO]);
-
-       /* FIXME: do unlink */
-
-       gst_bin_remove(GST_BIN(gst_element_get_parent(source->bin)), source->bin);
-
-       g_free(source);
-}
-
 int _ini_load(webrtc_s *webrtc)
 {
        RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
@@ -485,7 +469,7 @@ static void __disconnect_signal(gpointer data)
 {
        webrtc_signal_s *sig_data = (webrtc_signal_s *)data;
 
-       RET_IF(data == NULL, "data is NULL");
+       RET_IF(sig_data == NULL, "sig_data is NULL");
 
        if (GST_IS_ELEMENT(sig_data->obj)) {
                if (g_signal_handler_is_connected(sig_data->obj, sig_data->signal_id)) {
@@ -877,8 +861,8 @@ int _gst_build_pipeline(webrtc_s *webrtc)
                goto error;
        }
 
-       webrtc->gst.source_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __value_destroy_cb);
-       webrtc->gst.sink_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __value_destroy_cb);
+       webrtc->gst.source_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _source_slot_destroy_cb);
+       webrtc->gst.sink_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _sink_slot_destroy_cb);
 
        return WEBRTC_ERROR_NONE;
 
index 5f07664f7644cbc853b67e9762e8379c49eeabce..fce1ab19d001a8b023aac2fd0d51d978e8975f35 100644 (file)
@@ -202,6 +202,20 @@ static unsigned int __get_id_from_pad_name(const gchar* name)
        return (unsigned int)id;
 }
 
+void _sink_slot_destroy_cb(gpointer data)
+{
+       webrtc_gst_slot_s *sink = (webrtc_gst_slot_s *)data;
+
+       RET_IF(sink == NULL, "sink is NULL");
+
+       LOG_DEBUG("[%s, id:%u, media_types:0x%x] is removed",
+               GST_ELEMENT_NAME(sink->bin), sink->id, sink->media_types);
+
+       gst_bin_remove(GST_BIN(gst_element_get_parent(sink->bin)), sink->bin);
+
+       g_free(sink);
+}
+
 int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad)
 {
        int ret = WEBRTC_ERROR_NONE;
@@ -220,7 +234,7 @@ int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad)
        bin_name = g_strdup_printf("rendering_sink_%u", id);
        decodebin_name = g_strdup_printf("%s_decodebin", bin_name);
 
-       MALLOC_AND_INIT_SLOT(sink, id, bin_name);
+       MALLOC_AND_INIT_SLOT(sink, id, bin_name, webrtc->gst.webrtcbin);
 
        g_free(bin_name);
 
index b1146841ae882d47db50df1e2a7d2171da15dc4a..aae7ecdadf72a02a90cf61a1a1ec7462e6bb13bc 100644 (file)
@@ -441,6 +441,41 @@ static unsigned int __get_unoccupied_id(GHashTable *slots)
        return 0;
 }
 
+static gboolean __foreach_src_pad_cb(GstElement *element, GstPad *pad, gpointer user_data)
+{
+       webrtc_gst_slot_s *source = (webrtc_gst_slot_s *)user_data;
+       GstPad *peer = gst_pad_get_peer(pad);
+
+       RET_VAL_IF(source == NULL, FALSE, "source is NULL");
+       RET_VAL_IF(peer == NULL, TRUE, "peer pad is NULL");
+
+       LOG_DEBUG("about to release request pad[%s]", GST_PAD_NAME(peer));
+
+       gst_element_release_request_pad(source->webrtcbin, peer);
+
+       /* Two unrefing here, one for getting request pad, another one for getting peer pad */
+       gst_object_unref(peer);
+       gst_object_unref(peer);
+
+       return TRUE;
+}
+
+void _source_slot_destroy_cb(gpointer data)
+{
+       webrtc_gst_slot_s *source = (webrtc_gst_slot_s *)data;
+
+       RET_IF(source == NULL, "source is NULL");
+
+       LOG_DEBUG("[%s, id:%u, media_types:0x%x, mlines[AUDIO]:%d, mlines[VIDEO]:%d] is removed",
+               GST_ELEMENT_NAME(source->bin), source->id, source->media_types, source->mlines[MLINES_IDX_AUDIO], source->mlines[MLINES_IDX_VIDEO]);
+
+       gst_element_foreach_src_pad(source->bin, __foreach_src_pad_cb, source);
+
+       gst_bin_remove(GST_BIN(gst_element_get_parent(source->bin)), source->bin);
+
+       g_free(source);
+}
+
 int _add_media_source(webrtc_s *webrtc, webrtc_media_source_type_e type, unsigned int *source_id)
 {
        int ret = WEBRTC_ERROR_NONE;
@@ -461,7 +496,7 @@ int _add_media_source(webrtc_s *webrtc, webrtc_media_source_type_e type, unsigne
 
        bin_name = g_strdup_printf("media_source_%u", id);
 
-       MALLOC_AND_INIT_SLOT(source, id, bin_name);
+       MALLOC_AND_INIT_SLOT(source, id, bin_name, webrtc->gst.webrtcbin);
 
        ret = __build_source_bin(source, type);
        if (ret != WEBRTC_ERROR_NONE) {