Add more members to the slot structure for source/sink 41/244541/6
authorSangchul Lee <sc11.lee@samsung.com>
Mon, 21 Sep 2020 10:44:46 +0000 (19:44 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Thu, 8 Oct 2020 06:10:19 +0000 (15:10 +0900)
The mline value is got from the transceiver object via
on-new-transceiver callback. It will be used to find the
tranceiver object to modify the direction.

[Version] 0.1.30
[Issue Type] Improvement

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

index 68e66c53ac2b9382e76171ea56300b1d67c03587..0f7f4a937d5601c4babfce29fdaf9c4a033ec5c0 100644 (file)
@@ -112,9 +112,19 @@ typedef struct _webrtc_ini_s {
        gchar **gst_args;
 } webrtc_ini_s;
 
+typedef enum {
+       MEDIA_TYPE_AUDIO = 0x01,
+       MEDIA_TYPE_VIDEO = 0x02,
+} media_type_e;
+
+#define MLINES_IDX_AUDIO 0
+#define MLINES_IDX_VIDEO 1
+
 typedef struct _webrtc_gst_slot_s {
        unsigned int id;
        GstElement *bin;
+       int media_types;    /* values of media_type_e combined with bitwise 'or' */
+       int mlines[2];      /* index 0 for audio, 1 for video */
 } webrtc_gst_slot_s;
 
 typedef struct _webrtc_gst_s {
index 9320deceeecf9c7b173cf91e722a2f02e2cd4c37..e078c181842a711d318ded731d63cd8bd484a055 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.1.29
+Version:    0.1.30
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 34225b106672a2a948577d3e0c3ed4508a8bb4c2..0c1b427276f8a90ee0125eca2496b4c0f883dc39 100644 (file)
@@ -100,6 +100,15 @@ do { \
        } \
 } while (0)
 
+#define MALLOC_AND_INIT_SLOT(x_slot, x_id, x_bin_name) \
+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; \
+} while (0)
+
 #define GENERATE_DOT(x_webrtc, x_fmt, x_arg...) \
 do { \
        gchar *dot_name; \
@@ -421,7 +430,8 @@ static void __value_destroy_cb(gpointer data)
 
        RET_IF(data == NULL, "data is NULL");
 
-       LOG_DEBUG("[%s, id:%u] is removed", GST_ELEMENT_NAME(source->bin), source->id);
+       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 */
 
@@ -527,7 +537,7 @@ static void __disconnect_signal(gpointer data)
        if (GST_IS_ELEMENT(sig_data->obj)) {
                if (g_signal_handler_is_connected(sig_data->obj, sig_data->signal_id)) {
                        g_signal_handler_disconnect(sig_data->obj, sig_data->signal_id);
-                       LOG_DEBUG("signal with id[%lu] is disconnected from object [%s].", sig_data->signal_id, GST_OBJECT_NAME(sig_data->obj));
+                       LOG_DEBUG("signal with id[%lu] is disconnected from object [%s]", sig_data->signal_id, GST_OBJECT_NAME(sig_data->obj));
                }
        }
 
@@ -757,6 +767,8 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr
        RET_VAL_IF(sink == NULL, WEBRTC_ERROR_INVALID_OPERATION, "could not find an item by [%s] in sink slots", GST_ELEMENT_NAME(decodebin));
        RET_VAL_IF(sink->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
+       sink->media_types |= MEDIA_TYPE_VIDEO;
+
        if (!(videoconvert = __create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL))) {
                LOG_ERROR("failed to create videoconvert");
                return WEBRTC_ERROR_INVALID_OPERATION;
@@ -802,6 +814,8 @@ static int __build_audiosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr
        RET_VAL_IF(sink == NULL, WEBRTC_ERROR_INVALID_OPERATION, "could not find an item by [%s] in sink slots", GST_ELEMENT_NAME(decodebin));
        RET_VAL_IF(sink->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
+       sink->media_types |= MEDIA_TYPE_AUDIO;
+
        if (!(audioconvert = __create_element(DEFAULT_ELEMENT_AUDIOCONVERT, NULL))) {
                LOG_ERROR("failed to create audioconvert");
                return WEBRTC_ERROR_INVALID_OPERATION;
@@ -1000,9 +1014,8 @@ static 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);
 
-       sink = g_new0(webrtc_gst_slot_s, 1);
-       sink->id = id;
-       sink->bin = gst_bin_new(bin_name);
+       MALLOC_AND_INIT_SLOT(sink, id, bin_name);
+
        g_free(bin_name);
 
        decodebin = __create_element("decodebin", decodebin_name);
@@ -1083,6 +1096,36 @@ static void __webrtcbin_no_more_pads_cb(GstElement *webrtcbin, gpointer user_dat
        LOG_DEBUG_LEAVE();
 }
 
+static void __webrtcbin_on_new_transceiver_cb(GstElement *webrtcbin, GstWebRTCRTPTransceiver *transceiver, gpointer user_data)
+{
+       webrtc_s *webrtc = (webrtc_s *)user_data;
+       GHashTableIter iter;
+       gpointer key, value;
+       webrtc_gst_slot_s *source;
+       int i;
+
+       RET_IF(webrtcbin == NULL, "webrtcbin is NULL");
+       RET_IF(transceiver == NULL, "transceiver is NULL");
+       RET_IF(webrtc == NULL, "webrtc is NULL");
+
+       LOG_INFO("new transceiver[%p, mline:%u, mid:%s, direction:%d], user_data[%p]",
+               transceiver, transceiver->mline, transceiver->mid, transceiver->direction, user_data);
+
+       g_hash_table_iter_init(&iter, webrtc->gst.source_slots);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               source = (webrtc_gst_slot_s*)value;
+               for (i = MLINES_IDX_AUDIO; i <= MLINES_IDX_VIDEO; i++) {
+                       if (!(source->media_types & (i == MLINES_IDX_AUDIO ? MEDIA_TYPE_AUDIO : MEDIA_TYPE_VIDEO)))
+                               continue;
+                       if (source->mlines[i] == -1) {
+                               source->mlines[i] = transceiver->mline;
+                               LOG_DEBUG("source[%s, id:%u, mline:%d for %s]",
+                                       (gchar*)key, source->id, source->mlines[i], i == MLINES_IDX_AUDIO ? "AUDIO" : "VIDEO");
+                       }
+               }
+       }
+}
+
 int _gst_build_pipeline(webrtc_s *webrtc)
 {
        RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
@@ -1112,6 +1155,7 @@ int _gst_build_pipeline(webrtc_s *webrtc)
        __connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "notify::ice-connection-state", G_CALLBACK(__webrtcbin_ice_connection_state_cb), webrtc);
        __connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "pad-added", G_CALLBACK(__webrtcbin_pad_added_cb), webrtc);
        __connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "no-more-pads", G_CALLBACK(__webrtcbin_no_more_pads_cb), webrtc);
+       __connect_and_append_signal(&webrtc->signals, webrtc->gst.webrtcbin, "on-new-transceiver", G_CALLBACK(__webrtcbin_on_new_transceiver_cb), webrtc);
 
        if (!gst_bin_add(GST_BIN(webrtc->gst.pipeline), webrtc->gst.webrtcbin)) {
                LOG_ERROR("failed to gst_bin_add(), [%s] -> [%s] pipeline", GST_ELEMENT_NAME(webrtc->gst.webrtcbin), GST_ELEMENT_NAME(webrtc->gst.pipeline));
@@ -1379,6 +1423,8 @@ static int __build_camerasrc(webrtc_gst_slot_s *source, GstPad *ghost_src_pad)
        RET_VAL_IF(ghost_src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "ghost_src_pad is NULL");
        RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
+       source->media_types |= MEDIA_TYPE_VIDEO;
+
        /* FIXME: get factory name from ini */
        if (!(camerasrc = __create_element(DEFAULT_ELEMENT_CAMERASRC, NULL))) {
                LOG_ERROR("failed to create camerasrc");
@@ -1412,6 +1458,8 @@ static int __build_audiosrc(webrtc_gst_slot_s *source, GstPad *ghost_src_pad)
        RET_VAL_IF(ghost_src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "ghost_src_pad is NULL");
        RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
+       source->media_types |= MEDIA_TYPE_AUDIO;
+
        if (!(audiosrc = __create_element(DEFAULT_ELEMENT_AUDIOSRC, NULL))) {
                LOG_ERROR("failed to create audiosrc");
                return WEBRTC_ERROR_INVALID_OPERATION;
@@ -1443,6 +1491,8 @@ static int __build_videotestsrc(webrtc_gst_slot_s *source, GstPad *ghost_src_pad
        RET_VAL_IF(ghost_src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "ghost_src_pad is NULL");
        RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
+       source->media_types |= MEDIA_TYPE_VIDEO;
+
        if (!(videotestsrc = __create_element(DEFAULT_ELEMENT_VIDEOTESTSRC, NULL))) {
                LOG_ERROR("failed to create videotestsrc");
                return WEBRTC_ERROR_INVALID_OPERATION;
@@ -1475,6 +1525,8 @@ static int __build_audiotestsrc(webrtc_gst_slot_s *source, GstPad *ghost_src_pad
        RET_VAL_IF(ghost_src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "ghost_src_pad is NULL");
        RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
+       source->media_types |= MEDIA_TYPE_AUDIO;
+
        if (!(audiotestsrc = __create_element(DEFAULT_ELEMENT_AUDIOTESTSRC, NULL))) {
                LOG_ERROR("failed to create audiotestsrc");
                return WEBRTC_ERROR_INVALID_OPERATION;
@@ -1568,45 +1620,45 @@ int _add_media_source(webrtc_s *webrtc, webrtc_media_source_type_e type, unsigne
        RET_VAL_IF(id == 0, WEBRTC_ERROR_INVALID_OPERATION, "source_slots are full");
 
        bin_name = g_strdup_printf("media_source_%u", id);
-       source = g_new0(webrtc_gst_slot_s, 1);
-       source->id = id;
-       source->bin = gst_bin_new(bin_name);
+
+       MALLOC_AND_INIT_SLOT(source, id, bin_name);
 
        ret = __build_source_bin(source, type);
        if (ret != WEBRTC_ERROR_NONE) {
                LOG_ERROR("failed to __build_source_bin()");
-               goto error_before_insert;
+               goto error;
        }
 
        if (!gst_bin_add(GST_BIN(webrtc->gst.pipeline), source->bin)) {
                LOG_ERROR("failed to gst_bin_add(), [%s] -> [%s] pipeline", GST_ELEMENT_NAME(source->bin), GST_ELEMENT_NAME(webrtc->gst.pipeline));
-               goto error_before_insert;
+               goto error;
+       }
+
+       /* The gst_element_get_request_pad() of webrtcbin will trigger the transciever callback. To update the mline value of
+        * new transceiver object to the source structure in the callback, hash table inserting should be preceded. */
+       if (!g_hash_table_insert(webrtc->gst.source_slots, bin_name, (gpointer)source)) {
+               LOG_ERROR("should not be reached here, bin_name[%s] already exist, source id[%u] will be removed", bin_name, source->id);
+               g_hash_table_remove(webrtc->gst.source_slots, bin_name);
+               return WEBRTC_ERROR_INVALID_OPERATION;
        }
 
        if (!(webrtc_sinkpad = gst_element_get_request_pad(webrtc->gst.webrtcbin, "sink_%u"))) {
                LOG_ERROR("failed to gst_element_get_request_pad()");
-               goto error_before_insert;
+               goto error_after_insert;
        }
        if (!(webrtc_sinkpad_name = gst_pad_get_name(webrtc_sinkpad))) {
                LOG_ERROR("failed to gst_pad_get_name()");
-               goto error_before_insert;
+               goto error_after_insert;
        }
        bin_srcpad_name = g_strdup_printf("src_%u", id);
        if (!gst_element_link_pads(source->bin, bin_srcpad_name, webrtc->gst.webrtcbin, webrtc_sinkpad_name)) {
                LOG_ERROR("failed to link pads, [%s:%s] - [%s:%s]",
                        GST_ELEMENT_NAME(source->bin), bin_srcpad_name, GST_ELEMENT_NAME(webrtc->gst.webrtcbin), webrtc_sinkpad_name);
-               goto error_before_insert;
+               goto error_after_insert;
        }
        LOG_DEBUG("link pads successfully, [%s:%s] - [%s:%s]",
                GST_ELEMENT_NAME(source->bin), bin_srcpad_name, GST_ELEMENT_NAME(webrtc->gst.webrtcbin), webrtc_sinkpad_name);
 
-       if (!g_hash_table_insert(webrtc->gst.source_slots, bin_name, (gpointer)source)) {
-               LOG_ERROR("should not be reached here, bin_name[%s] already exist, source id[%u] will be removed", bin_name, source->id);
-               g_hash_table_remove(webrtc->gst.source_slots, bin_name);
-               g_free(bin_srcpad_name);
-               return WEBRTC_ERROR_INVALID_OPERATION;
-       }
-
        *source_id = id;
 
        LOG_INFO("added a source slot[%p, id:%u]", source, source->id);
@@ -1615,9 +1667,14 @@ int _add_media_source(webrtc_s *webrtc, webrtc_media_source_type_e type, unsigne
 
        return WEBRTC_ERROR_NONE;
 
-error_before_insert:
-       g_free(bin_name);
+error_after_insert:
+       g_hash_table_remove(webrtc->gst.source_slots, bin_name);
        g_free(bin_srcpad_name);
+
+       return WEBRTC_ERROR_INVALID_OPERATION;
+
+error:
+       g_free(bin_name);
        g_free(source);
 
        return WEBRTC_ERROR_INVALID_OPERATION;