webrtc_source: Revise assigning payload identifier 57/260357/1
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 24 Jun 2021 00:29:26 +0000 (09:29 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Thu, 24 Jun 2021 00:31:10 +0000 (09:31 +0900)
One media source id can have two audio/video streams.
e.g.)file source

Assigning payload id logic is revised to get it per
each stream all over the webrtc handle.

[Version] 0.2.22
[Issue Type] Improvement

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

index c4c56a174b8c1e5188283b109be850e0387933cb..9d705b8f81adaa29774897e3283e41d30700a09f 100644 (file)
@@ -186,14 +186,14 @@ do { \
                gst_caps_unref(x_elem_info.src_caps); \
 } while (0)
 
-#define MALLOC_AND_INIT_SLOT(x_slot, x_id, x_bin_name, x_webrtcbin) \
+#define MALLOC_AND_INIT_SLOT(x_slot, x_id, x_bin_name, x_webrtc) \
 do { \
        x_slot = g_new0(webrtc_gst_slot_s, 1); \
        x_slot->id = x_id; \
        x_slot->bin = GST_BIN(gst_bin_new(x_bin_name)); \
        x_slot->av[AV_IDX_AUDIO].mline = -1; \
        x_slot->av[AV_IDX_VIDEO].mline = -1; \
-       x_slot->webrtcbin = x_webrtcbin; \
+       x_slot->webrtc = x_webrtc; \
 } while (0)
 
 #define GENERATE_DOT(x_webrtc, x_fmt, x_arg...) \
@@ -218,6 +218,7 @@ do { \
 #define MEDIA_TYPE_VIDEO_JPEG           "image/jpeg"
 
 #define WEBRTC_DISPLAY_TYPE_ECORE_WL    2
+#define PAYLOAD_ID_NUM                  32 /* 96 ~ 127 */
 
 #define SIGNALING_MESSAGE_PREFIX_CONNECTED           "CONNECTED"
 #define SIGNALING_MESSAGE_PREFIX_REQUEST_SESSION     "REQUEST_SESSION"
@@ -372,6 +373,7 @@ typedef struct _webrtc_s {
        GCond desc_cond;
 
        webrtc_gst_s gst;
+       bool payload_ids[PAYLOAD_ID_NUM];
 
        gchar *stun_server_url;
        GList *turn_server_urls;
@@ -416,7 +418,7 @@ typedef struct _webrtc_s {
 typedef struct _webrtc_gst_slot_s {
        unsigned int id;
        GstBin *bin;
-       GstElement *webrtcbin;
+       webrtc_s *webrtc;
        GList *signals;
 
        webrtc_media_source_type_e type;
@@ -426,6 +428,7 @@ typedef struct _webrtc_gst_slot_s {
                GstPad *src_pad;
                gulong src_pad_probe_id;
                bool pause;
+               unsigned int payload_id;
        } av[AV_IDX_MAX];
        struct {
                int width;
@@ -436,7 +439,6 @@ typedef struct _webrtc_gst_slot_s {
        GstAllocator *allocator;
        webrtc_callbacks_s buffer_state_changed_cb;
        webrtc_callbacks_s *encoded_frame_cb;
-       webrtc_s *webrtc;
        gulong probe_id;
        bool video_muted;
 
index f9c9c2e12198909b8d4a060d89c4846e932a2f17..58d13445f229bfacda3e5ab738fa6fcf784195bb 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.2.21
+Version:    0.2.22
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index b8eb833071a29c41d5d2368e029787eedd663761..2f17068adfa19fbfb60f0dee7d6bf6935f2f97af 100644 (file)
@@ -451,7 +451,7 @@ int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad)
        bin_name = g_strdup_printf("rendering_%u", ++id);
        track_name = g_strdup_printf("track_%u", id);
 
-       MALLOC_AND_INIT_SLOT(sink, id, bin_name, webrtc->gst.webrtcbin);
+       MALLOC_AND_INIT_SLOT(sink, id, bin_name, webrtc);
 
        g_free(bin_name);
 
@@ -777,12 +777,10 @@ int _add_forwarding_sink_bin(webrtc_s *webrtc, GstPad *src_pad, bool is_video)
        bin_name = g_strdup_printf("forwarding_%u", ++id);
        track_name = g_strdup_printf("track_%u", id);
 
-       MALLOC_AND_INIT_SLOT(sink, id, bin_name, webrtc->gst.webrtcbin);
+       MALLOC_AND_INIT_SLOT(sink, id, bin_name, webrtc);
 
        g_free(bin_name);
 
-       sink->webrtc = webrtc;
-
        CREATE_ELEMENT_FROM_REGISTRY(elem_info, GST_KLASS_NAME_DEPAYLOADER_RTP, gst_pad_get_current_caps(src_pad), NULL, depayloader);
        if (!depayloader)
                goto error_before_insert;
index 7de1848e0fd763df1e836c6b92b0f9c04cc15ec3..338876a3de296893eaa73d9c0da392072376a52a 100644 (file)
@@ -503,7 +503,7 @@ static GstCaps *__make_encoded_caps_from_media_format(webrtc_gst_slot_s *source,
        return caps;
 }
 
-static GstCaps *__make_rtp_caps(const gchar *media_type, unsigned int id)
+static GstCaps *__make_rtp_caps(const gchar *media_type, unsigned int payload_id)
 {
        GstCaps *caps;
        bool is_video;
@@ -514,7 +514,7 @@ static GstCaps *__make_rtp_caps(const gchar *media_type, unsigned int id)
 
        caps = gst_caps_new_simple("application/x-rtp",
                                "media", G_TYPE_STRING, is_video ? "video" : "audio",
-                               "payload", G_TYPE_INT, id + 95, NULL);
+                               "payload", G_TYPE_INT, payload_id, NULL);
 
        PRINT_CAPS(caps, "RTP");
 
@@ -605,6 +605,31 @@ static bool __is_encoded_format_supported(webrtc_media_source_type_e type, webrt
        return ini_source->v_encoded_fmt_support;
 }
 
+static unsigned int __get_available_payload_id(webrtc_s *webrtc)
+{
+       int i;
+
+       RET_VAL_IF(webrtc == NULL, 0, "webrtc is NULL");
+
+       for (i = 0; i < PAYLOAD_ID_NUM; i++) {
+               if (!webrtc->payload_ids[i]) {
+                       webrtc->payload_ids[i] = true;
+                       LOG_DEBUG("found available payload id[%d]", i + 96);
+                       return i + 96;
+               }
+       }
+       LOG_ERROR("could not assign payload id");
+       return 0;
+}
+
+static void __return_payload_id(webrtc_s *webrtc, unsigned int payload_id)
+{
+       RET_IF(webrtc == NULL, "webrtc is NULL");
+       RET_IF(payload_id < 96 || payload_id > 127, "invalid payload_id(%u)", payload_id);
+
+       webrtc->payload_ids[payload_id - 96] = false;
+}
+
 static int __create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool need_capsfilter, GList **element_list)
 {
        GstElement *capsfilter = NULL;
@@ -617,16 +642,15 @@ static int __create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source
        const gchar *encoder_klass_name;
        gchar *media_type = NULL;
        gchar *encoder_name = NULL;
+       unsigned int payload_id;
 
        RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
        RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
        RET_VAL_IF(element_list == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "element_list is NULL");
 
        if (need_capsfilter) {
-               if (!(capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_FIRST_CAPSFILTER))) {
-                       LOG_ERROR("failed to create capsfilter");
+               if (!(capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_FIRST_CAPSFILTER)))
                        return WEBRTC_ERROR_INVALID_OPERATION;
-               }
 
                if (__is_encoded_format_supported(source->type, &webrtc->ini)) {
                        if ((sink_caps = __make_default_encoded_caps(source, &webrtc->ini, NULL))) {
@@ -687,17 +711,23 @@ skip_encoder:
        }
 
        if (!(queue = _create_element(DEFAULT_ELEMENT_QUEUE, NULL))) {
-               LOG_ERROR("failed to create queue");
                g_free(media_type);
                return WEBRTC_ERROR_INVALID_OPERATION;
        }
 
        if (!(capsfilter2 = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_RTP_CAPSFILTER))) {
-               LOG_ERROR("failed to create capsfilter");
                g_free(media_type);
                return WEBRTC_ERROR_INVALID_OPERATION;
        }
-       if ((sink_caps = __make_rtp_caps(media_type, source->id))) {
+
+       payload_id = __get_available_payload_id(webrtc);
+       if (payload_id == 0) {
+               g_free(media_type);
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
+       source->av[source->media_types == MEDIA_TYPE_VIDEO ? AV_IDX_VIDEO : AV_IDX_AUDIO].payload_id = payload_id;
+
+       if ((sink_caps = __make_rtp_caps(media_type, payload_id))) {
                g_object_set(G_OBJECT(capsfilter2), "caps", sink_caps, NULL);
                gst_caps_unref(sink_caps);
        }
@@ -736,13 +766,11 @@ static int __create_rest_of_elements_for_encoded_format(webrtc_s *webrtc, webrtc
        }
 
        if (!(*queue = _create_element(DEFAULT_ELEMENT_QUEUE, NULL))) {
-               LOG_ERROR("failed to create queue");
                g_free(media_type);
                return WEBRTC_ERROR_INVALID_OPERATION;
        }
 
        if (!(*capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, NULL))) {
-               LOG_ERROR("failed to create capsfilter");
                g_free(media_type);
                return WEBRTC_ERROR_INVALID_OPERATION;
        }
@@ -1294,10 +1322,8 @@ static int __build_mediapacketsrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
        RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
-       if (!(appsrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET), NULL))) {
-               LOG_ERROR("failed to create appsrc");
+       if (!(appsrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET), NULL)))
                return WEBRTC_ERROR_INVALID_OPERATION;
-       }
 
        g_object_set(G_OBJECT(appsrc), "is-live", TRUE, "do-timestamp", TRUE, "format", GST_FORMAT_TIME, NULL);
 
@@ -1502,11 +1528,12 @@ static gboolean __foreach_src_pad_cb(GstElement *element, GstPad *pad, gpointer
        GstPad *peer = gst_pad_get_peer(pad);
 
        RET_VAL_IF(source == NULL, FALSE, "source is NULL");
+       RET_VAL_IF(source->webrtc == NULL, FALSE, "webrtc 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);
+       gst_element_release_request_pad(source->webrtc->gst.webrtcbin, peer);
 
        /* Two unrefing here, one for getting request pad, another one for getting peer pad */
        gst_object_unref(peer);
@@ -1532,6 +1559,8 @@ void _source_slot_destroy_cb(gpointer data)
                        gst_pad_remove_probe(source->av[i].src_pad, source->av[i].src_pad_probe_id);
                        source->av[i].src_pad_probe_id = 0;
                }
+               if (source->av[i].payload_id > 0)
+                       __return_payload_id(source->webrtc, source->av[i].payload_id);
        }
 
        gst_bin_remove(GST_BIN(gst_element_get_parent(source->bin)), GST_ELEMENT(source->bin));
@@ -1602,7 +1631,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, webrtc->gst.webrtcbin);
+       MALLOC_AND_INIT_SLOT(source, id, bin_name, webrtc);
        source->type = type;
 
        ret = __build_source_bin(webrtc, source);