webrtc_internal: Add webrtc_null_source_set_media_type() 44/314244/3
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 4 Jul 2024 08:15:37 +0000 (17:15 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 9 Jul 2024 08:10:28 +0000 (17:10 +0900)
If this function is called to the particular null source(recvonly),
then all of available codecs which defined in ini file are set to
the transceiver. Therefore offer or answer description will represents
various codec information via rtpmap attributes.

[Version] 1.1.10
[Issue Type] Internal API

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

index 1ff986e807ddc082a28ca41b134011a5eecdf469..b3b7be9aefda486aa7cfe0b1ba5e30491c96015e 100644 (file)
@@ -468,6 +468,23 @@ int webrtc_media_source_get_transceiver_recv_drop(webrtc_h webrtc, unsigned int
  */
 int webrtc_media_source_get_type(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e *media_type);
 
+/**
+ * @internal
+ * @brief Sets the media type to the null source.
+ * @since_tizen 9.0
+ * @remarks If @a source_id is not a media source of #WEBRTC_MEDIA_SOURCE_TYPE_NULL, this function will return #WEBRTC_ERROR_INVALID_PARAMETER.
+ * @param[in] webrtc      WebRTC handle
+ * @param[in] source_id   The null source id
+ * @param[in] media_type  The media type
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE    Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Add media source of #WEBRTC_MEDIA_SOURCE_TYPE_NULL to @a webrtc to get @a source_id by calling webrtc_add_media_source().
+ */
+int webrtc_null_source_set_media_type(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type);
+
 /**
  * @internal
  * @brief Gets the local session description.
index 0dc8f2534ec5325e88aad96d6cec90daa414cec8..97b322dbcce05ed3ac467a8febd18f22fdd71668 100644 (file)
@@ -604,6 +604,11 @@ typedef struct _webrtc_gst_slot_s {
                unsigned int pt;
                bool pt_set_by_api;
                GHashTable *encodings;
+               struct {
+                       const char *codec;
+                       unsigned int pt;
+               } multiple_codecs[MAX_MLINE_NUM];
+               int num_of_codecs;
                struct {
                        unsigned int track_id;
                        bool need_decoding;
index dcd697cc73e345027ee78df1bed8680cb5066401..f6fa44d3eca891cf6774643226e4111fb4242283 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    1.1.9
+Version:    1.1.10
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 4b319a76f60d7c751117b271a7443214aaaef6db..31e98060cfb60789a3660d993289b63ca33fbbf9 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "webrtc_internal.h"
 #include "webrtc_private.h"
+#include "webrtc_source_private.h"
 
 //LCOV_EXCL_START
 int webrtc_set_ecore_wl_display(webrtc_h webrtc, unsigned int track_id, void *ecore_wl_window)
@@ -375,6 +376,54 @@ int webrtc_media_source_get_type(webrtc_h webrtc, unsigned int source_id, webrtc
        return WEBRTC_ERROR_NONE;
 }
 
+int webrtc_null_source_set_media_type(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type)
+{
+       webrtc_s *_webrtc = (webrtc_s *)webrtc;
+       webrtc_gst_slot_s *source;
+       g_autoptr(GMutexLocker) locker = NULL;
+       int av_idx = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? AV_IDX_AUDIO : AV_IDX_VIDEO;
+       int av_opposite_idx = (av_idx == AV_IDX_AUDIO) ? AV_IDX_VIDEO : AV_IDX_AUDIO;
+       const ini_item_media_source_s *ini_source;
+       int ret;
+       g_autofree gchar *joined_str_codecs = NULL;
+       int i;
+
+       RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+
+       locker = g_mutex_locker_new(&_webrtc->mutex);
+
+       RET_VAL_IF((source = _get_slot_by_id(_webrtc->gst.source_slots, source_id)) == NULL,
+               WEBRTC_ERROR_INVALID_PARAMETER, "could not find source");
+       RET_VAL_IF(source->type != WEBRTC_MEDIA_SOURCE_TYPE_NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source type is not WEBRTC_MEDIA_SOURCE_TYPE_NULL");
+       RET_VAL_IF(source->av[av_idx].codec, WEBRTC_ERROR_INVALID_OPERATION, "codec[%s] was already set", source->av[av_idx].codec);
+       RET_VAL_IF(source->av[av_opposite_idx].codec, WEBRTC_ERROR_INVALID_OPERATION, "codec[%s] was already set", source->av[av_opposite_idx].codec);
+
+       ret = _build_src_check_params_and_get_ini_source(webrtc, source, &ini_source);
+       RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to _build_src_check_params_and_get_ini_source()");
+
+       /* clean up the other side */
+       for (i = 0; i < source->av[av_opposite_idx].num_of_codecs; i++) {
+               source->av[av_opposite_idx].multiple_codecs[i].codec = NULL;
+               source->av[av_opposite_idx].multiple_codecs[i].pt = 0;
+       }
+
+       GStrv codecs = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? ini_source->a_codecs : ini_source->v_codecs;
+       source->av[av_idx].num_of_codecs = g_strv_length(codecs);
+       for (i = 0; i < source->av[av_idx].num_of_codecs; i++) {
+               source->av[av_idx].multiple_codecs[i].codec = codecs[i];
+       }
+
+       source->media_types = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? MEDIA_TYPE_AUDIO : MEDIA_TYPE_VIDEO;
+
+       LOG_INFO("webrtc[%p] source_id[%u] media_type[%d]", _webrtc, source_id, media_type);
+
+       joined_str_codecs = g_strjoinv(" ", codecs);
+       LOG_INFO(" - codecs: %s", joined_str_codecs);
+
+       return WEBRTC_ERROR_NONE;
+}
+
 int webrtc_get_local_description(webrtc_h webrtc, char **description)
 {
        g_autoptr(GMutexLocker) locker = NULL;
index 4898a8897b3f137d2ea4b6543f8440a6b2309b6c..5716abe6cf0d91ec44a458a4e452bf0f412c0067 100644 (file)
@@ -663,6 +663,7 @@ void _source_slot_destroy_cb(gpointer data)
 {
        webrtc_gst_slot_s *source = (webrtc_gst_slot_s *)data;
        int i;
+       int j;
 
        RET_IF(source == NULL, "source is NULL");
 
@@ -695,6 +696,11 @@ void _source_slot_destroy_cb(gpointer data)
                g_hash_table_destroy(source->av[i].encodings);
 
                g_free(source->av[i].payloader_factory_name);
+
+               for (j = 0; j < source->av[i].num_of_codecs; j++) {
+                       if (source->av[i].multiple_codecs[j].pt > 0)
+                               _return_payload_type(source->webrtc, source->av[i].multiple_codecs[j].pt);
+               }
        }
 
        if (source->bin) {
@@ -1171,7 +1177,7 @@ static gboolean __check_codec_is_not_set_cb(gpointer key, gpointer value, gpoint
        if (source->type == GPOINTER_TO_INT(user_data)) {
                LOG_INFO("found media null source[%p, id:%u]", source, source->id);
                for (i = 0; i < AV_IDX_MAX; i++) {
-                       if (source->av[i].codec)
+                       if (source->av[i].codec || source->av[i].num_of_codecs > 0)
                                return FALSE;
                }
                return TRUE;
index cdd4bfbcd915b964c76eeebc798da6e5eeb6376c..fc61ee6b210966e3c5c8c75a0ebb7fcc2c7f9972 100644 (file)
@@ -24,7 +24,6 @@ int _build_src_check_params_and_get_ini_source(webrtc_s *webrtc, webrtc_gst_slot
        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(ini_source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "ini_source is NULL");
-       RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
 
        if (!(*ini_source = _ini_get_source_by_type(&webrtc->ini, source->type))) {
                LOG_ERROR("ini_source is NULL");
index e162b6a95ed59a7e41a40fc5eec9826dc0b2bf67..df4c3006740419dc6a11b0c3baeec8428cb6db1b 100644 (file)
@@ -423,6 +423,70 @@ static int __add_transceiver_for_simulcast(webrtc_gst_slot_s *source, webrtc_med
        return WEBRTC_ERROR_NONE;
 }
 
+int __add_transceiver_with_multiple_codecs(webrtc_gst_slot_s *source, webrtc_media_type_e media_type)
+{
+       int i;
+       GstWebRTCRTPTransceiver *trans;
+       GstCaps *caps = NULL;
+       GstCaps *_caps;
+       int av_idx = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? AV_IDX_AUDIO : AV_IDX_VIDEO;
+       rtp_payload_info_s *payload_info = NULL;
+       int pt;
+
+       ASSERT(source);
+
+       for (i = 0; i < source->av[av_idx].num_of_codecs; i++) {
+               if (!(payload_info = __get_payload_info_by_encoding_name(source->av[av_idx].multiple_codecs[i].codec)))
+                       return WEBRTC_ERROR_INVALID_OPERATION;
+
+               if ((pt = __get_available_payload_type(source->webrtc)) == -1)
+                       return WEBRTC_ERROR_INVALID_OPERATION;
+
+               source->av[av_idx].multiple_codecs[i].pt = pt;
+
+               _caps = gst_caps_new_simple("application/x-rtp",
+                       "media", G_TYPE_STRING, payload_info->media_type,
+                       "encoding-name", G_TYPE_STRING, payload_info->encoding_name,
+                       "clock-rate", G_TYPE_INT, payload_info->clock_rate,
+                       "payload", G_TYPE_INT, pt,
+                       NULL);
+               if (payload_info->codec == WEBRTC_TRANSCEIVER_CODEC_OPUS)
+                       gst_caps_set_simple(_caps,
+                               "encoding-params", G_TYPE_STRING, "2",
+                               NULL);
+               else if (payload_info->codec == WEBRTC_TRANSCEIVER_CODEC_H264)
+                       gst_caps_set_simple(_caps,
+                               "level-asymmetry-allowed", G_TYPE_STRING, "1",
+                               "packetization-mode", G_TYPE_STRING, "1",
+                               "profile-level-id", G_TYPE_STRING, "42e01f",
+                               NULL);
+
+               if (i == 0)
+                       caps = _caps;
+               else
+                       gst_caps_append(caps, _caps);
+       }
+
+       ASSERT(caps);
+       PRINT_CAPS(caps, "transceiver");
+
+       if (!source->av[av_idx].transceiver) {
+               g_signal_emit_by_name(source->webrtc->gst.webrtcbin, "add-transceiver",
+                       GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY, caps, &trans, NULL);
+               gst_object_unref(trans);
+
+       } else {
+               g_object_set(G_OBJECT(source->av[av_idx].transceiver), "codec-preferences", caps, NULL);
+       }
+
+       gst_caps_unref(caps);
+
+       LOG_DEBUG("webrtc[%p] source_id[%u] [%s] transceiver[%p]",
+               source->webrtc, source->id, payload_info->media_type, source->av[av_idx].transceiver);
+
+       return WEBRTC_ERROR_NONE;
+}
+
 int _check_and_add_recvonly_transceiver(webrtc_gst_slot_s *source)
 {
        rtp_payload_info_s *payload_info = NULL;
@@ -433,12 +497,17 @@ int _check_and_add_recvonly_transceiver(webrtc_gst_slot_s *source)
 
        for (i = AV_IDX_AUDIO; i < AV_IDX_MAX; i++) {
                media_type = (i == AV_IDX_AUDIO) ? WEBRTC_MEDIA_TYPE_AUDIO : WEBRTC_MEDIA_TYPE_VIDEO;
-               if (source->av[i].direction == WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY && source->av[i].codec) {
-                       if (g_hash_table_size(source->av[i].encodings) > 0)
-                               __add_transceiver_for_simulcast(source, media_type);
-                       else if (!(payload_info = __get_payload_info_by_encoding_name(source->av[i].codec)))
-                               return WEBRTC_ERROR_INVALID_OPERATION;
-                       _add_transceiver(source, media_type, payload_info);
+               if (source->av[i].direction == WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY) {
+                       if (source->av[i].codec) {
+                               if (g_hash_table_size(source->av[i].encodings) > 0)
+                                       __add_transceiver_for_simulcast(source, media_type);
+                               else if (!(payload_info = __get_payload_info_by_encoding_name(source->av[i].codec)))
+                                       return WEBRTC_ERROR_INVALID_OPERATION;
+                               _add_transceiver(source, media_type, payload_info);
+
+                       } else if (source->av[i].num_of_codecs > 0) {
+                               __add_transceiver_with_multiple_codecs(source, media_type);
+                       }
                }
        }
        return WEBRTC_ERROR_NONE;
@@ -470,8 +539,8 @@ int _add_transceiver(webrtc_gst_slot_s *source, webrtc_media_type_e media_type,
        GstCaps *caps;
        int av_idx = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? AV_IDX_AUDIO : AV_IDX_VIDEO;
 
-       RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
-       RET_VAL_IF(payload_info == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "payload_info is NULL");
+       ASSERT(source);
+       ASSERT(payload_info);
 
        caps = __make_transceiver_caps(payload_info);
        PRINT_CAPS(caps, "transceiver");
@@ -712,13 +781,16 @@ int _set_transceiver_codec(webrtc_s *webrtc, unsigned int source_id, webrtc_medi
 
        /* NOTE: for null source, set media_types here exceptionally. */
        if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_NULL)
-               source->media_types |= (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? MEDIA_TYPE_AUDIO : MEDIA_TYPE_VIDEO;
+               source->media_types = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? MEDIA_TYPE_AUDIO : MEDIA_TYPE_VIDEO;
 
        if ((ret = __validate_codec(webrtc, source, media_type, codec)) != WEBRTC_ERROR_NONE)
                return ret;
 
        source->av[av_idx].codec = payload_info->encoding_name;
 
+       /* clean up multiple codecs */
+       source->av[av_idx].num_of_codecs = 0;
+
        /* FIXME: to utilize 'codec-preferences' of trans object, we need to re-create and re-link elements again */
        LOG_INFO("webrtc[%p] source_id[%u] media_type[%d] codec[%s]", webrtc, source_id, media_type, payload_info->encoding_name);