Set a transceiver manually when the source direction is 'recvonly' 74/277774/8
authorhj kim <backto.kim@samsung.com>
Wed, 13 Jul 2022 06:48:05 +0000 (15:48 +0900)
committerhj kim <backto.kim@samsung.com>
Mon, 18 Jul 2022 01:19:31 +0000 (10:19 +0900)
when offer's source direction is 'recvonly', gstreamer webrtc doesn't add media in offer SDP.
then, offerer can't receive media from the peer, so manual setting is needed.
plus, change transceiver setting time of null source from webrtc_media_source_set_transceiver_codec()
to webrtc_start() like other sources.

[Version] 0.3.158
[Issue Type] Bug fix

Change-Id: I072084d0888003975a039304d18a6f2d28b4f4ca

include/webrtc_private.h
include/webrtc_source_private.h
packaging/capi-media-webrtc.spec
src/webrtc.c
src/webrtc_source.c
src/webrtc_source_mediapacket.c

index 8d71172cb0ea35653abe2914397b5f428a30bec0..ad8b5c2752f4d0e79a79947e448fbc5ccf00872c 100644 (file)
@@ -227,6 +227,8 @@ do { \
        x_webrtc->idle_cb_event_source_ids[x_idx] = 0; \
 } while (0)
 
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
 #define GET_AV_IDX(x_is_audio) (x_is_audio) ? AV_IDX_AUDIO : AV_IDX_VIDEO
 #define GET_MEDIA_TYPE_NAME(x_is_audio) (x_is_audio) ? "audio" : "video"
 
@@ -655,7 +657,7 @@ int _set_transceiver_codec(webrtc_s *webrtc, unsigned int source_id, webrtc_medi
 int _get_transceiver_codec(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_transceiver_codec_e *codec);
 void _update_transceivers_fec(webrtc_s *webrtc, bool is_offer);
 int _foreach_supported_transceiver_codec(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_media_source_supported_transceiver_codec_cb callback, void *user_data);
-bool _check_if_transceiver_is_set_to_null_sources(webrtc_s *webrtc);
+bool _check_if_codec_is_set_to_null_sources(webrtc_s *webrtc);
 int _set_pause(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool pause);
 int _get_pause(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool *paused);
 int _set_audio_mute(webrtc_s *webrtc, unsigned int source_id, bool mute);
index 0d6eb566152a536b09e539613ccc829bbeb6c770..48a60cc0cf74757c6a1de1e67b72a2b2d3e1431e 100644 (file)
@@ -78,5 +78,6 @@ GstCaps *_get_caps_from_encoded_audio_media_type(const char *media_type, int cha
 GstCaps *_get_caps_from_encoded_video_media_type(const char *media_type, int width, int height);
 unsigned int _get_available_payload_type(webrtc_s *webrtc);
 GstCaps *_make_rtp_caps(const gchar *media_type, unsigned int payload_type, webrtc_gst_slot_s *source);
+int _set_mediapacketsrc_codec_info(webrtc_s *webrtc, webrtc_gst_slot_s *source, media_format_mimetype_e mime_type);
 
 #endif /* __TIZEN_MEDIA_WEBRTC_SOURCE_COMMON_H__ */
index 69c71377f30423b9c125372b6baed5daac874510..bc591fc3b1a285c44d04efa45dea4385494ac9a0 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.3.157
+Version:    0.3.158
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index aef2e7e47b0ec956266e75c59ce60e95bc25b2f2..8c7fe23d818f683cee0e91a279a3d63bbfb59e09 100644 (file)
@@ -188,7 +188,7 @@ int webrtc_start(webrtc_h webrtc)
        RET_VAL_IF(_webrtc->gst.webrtcbin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "webrtcbin is NULL");
        RET_VAL_IF(!_check_if_format_is_set_to_packet_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "the media format should be set");
        RET_VAL_IF(!_check_if_path_is_set_to_file_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "the media path should be set");
-       RET_VAL_IF(!_check_if_transceiver_is_set_to_null_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "transceiver codec is should be set");
+       RET_VAL_IF(!_check_if_codec_is_set_to_null_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "transceiver codec is should be set");
 
 #ifndef TIZEN_TV
        ret = _acquire_resource_if_needed(_webrtc);
index 731fb2307d9207ff21cce65f263e2bad7a0562f9..0d59ff7852d19a304a7a0174be438b2188425939 100644 (file)
@@ -242,13 +242,17 @@ static GstCaps *__make_default_encoded_caps(webrtc_gst_slot_s *source, webrtc_in
 
        case WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET:
                if (source->media_types == MEDIA_TYPE_AUDIO) {
-                       _media_type = _get_audio_media_type(ini_source->a_codecs[0]);
+                       _media_type = _get_audio_media_type(source->av[AV_IDX_AUDIO].codec);
                        RET_VAL_IF(_media_type == NULL, NULL, "_media_type is NULL");
+
                        caps = _get_caps_from_encoded_audio_media_type(_media_type, ini_source->a_channels, ini_source->a_samplerate);
+
                } else if (source->media_types == MEDIA_TYPE_VIDEO) {
-                       _media_type = _get_video_media_type(ini_source->v_codecs[0]);
+                       _media_type = _get_video_media_type(source->av[AV_IDX_VIDEO].codec);
                        RET_VAL_IF(_media_type == NULL, NULL, "_media_type is NULL");
+
                        caps = _get_caps_from_encoded_video_media_type(_media_type, ini_source->v_width, ini_source->v_height);
+
                } else {
                        LOG_ERROR_IF_REACHED("source->media_types(0x%x)", source->media_types);
                        return NULL;
@@ -1115,6 +1119,44 @@ static int __add_transceiver(webrtc_gst_slot_s *source, webrtc_media_type_e medi
        return WEBRTC_ERROR_NONE;
 }
 
+static rtp_payload_info_s * __get_payload_info(const char *codec)
+{
+       int i = 0;
+       size_t n = 0;
+
+       RET_VAL_IF(codec == NULL, NULL, "codec is NULL");
+
+       n = ARRAY_SIZE(__payload_info);
+
+       for (i = 0; i < (int)n; i++) {
+               if ((__payload_info[i].encoding_name) && !strcasecmp(__payload_info[i].encoding_name, codec))
+                       return &__payload_info[i];
+       }
+
+       LOG_ERROR("could not find payload_info. codec[%s]", codec);
+
+       return NULL;
+}
+
+static void __check_and_add_recvonly_transceiver(webrtc_gst_slot_s *source)
+{
+       rtp_payload_info_s *payload_info = NULL;
+
+       RET_IF(source == NULL, "source is NULL");
+
+       if (source->av[AV_IDX_AUDIO].direction == WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY && source->av[AV_IDX_AUDIO].codec) {
+               payload_info = __get_payload_info(source->av[AV_IDX_AUDIO].codec);
+               if (payload_info)
+                       __add_transceiver(source, WEBRTC_MEDIA_TYPE_AUDIO, payload_info);
+       }
+
+       if (source->av[AV_IDX_VIDEO].direction == WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY && source->av[AV_IDX_VIDEO].codec) {
+               payload_info = __get_payload_info(source->av[AV_IDX_VIDEO].codec);
+               if (payload_info)
+                       __add_transceiver(source, WEBRTC_MEDIA_TYPE_VIDEO, payload_info);
+       }
+}
+
 int _complete_sources(webrtc_s *webrtc)
 {
        int i;
@@ -1124,17 +1166,24 @@ int _complete_sources(webrtc_s *webrtc)
        for (i = 0; i < MAX_SOURCE_NUM; i++) {
                if (!(source = webrtc->gst.sources[i]))
                        continue;
-               if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE ||
-                       source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET ||
-                       source->type == WEBRTC_MEDIA_SOURCE_TYPE_NULL)
-                       continue;
 
                LOG_DEBUG("source[id:%u, type:%d, media_types:0x%x]", source->id, source->type, source->media_types);
 
+               if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE)
+                       continue;
+
+               if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET ||
+                       source->type == WEBRTC_MEDIA_SOURCE_TYPE_NULL) {
+                       goto add_transceiver;
+               }
+
                if (source->media_types == MEDIA_TYPE_AUDIO)
                        __complete_rest_of_audiosrc(webrtc, source);
                else
                        __complete_rest_of_videosrc(webrtc, source);
+
+add_transceiver:
+               __check_and_add_recvonly_transceiver(source);
        }
 
        return WEBRTC_ERROR_NONE;
@@ -1439,6 +1488,8 @@ static GstPadProbeReturn __fakesink_probe_cb(GstPad *pad, GstPadProbeInfo *info,
 
        LOG_INFO("setting caps for [%s appsrc] successfully", (av_idx == AV_IDX_AUDIO) ? "audio" : "video");
        PRINT_CAPS(caps, "appsrc");
+
+       source->av[av_idx].codec = gst_structure_get_string(gst_caps_get_structure(caps, 0), "encoding-name");
        gst_caps_unref(caps);
 
        source->filesrc_av[av_idx].sink_pad = pad;
@@ -2143,6 +2194,7 @@ static int __add_null_source(webrtc_s *webrtc, unsigned int *source_id)
        }
 
        *source_id = source->id;
+       webrtc->gst.sources[*source_id - 1] = source;
 
        LOG_INFO("added a source slot[%p, id:%u]", source, source->id);
 
@@ -2457,9 +2509,6 @@ int _set_transceiver_codec(webrtc_s *webrtc, unsigned int source_id, webrtc_medi
 
                if((ret = __set_payload_type(webrtc, source, av_idx, payload_info->gst_media_type)) != WEBRTC_ERROR_NONE)
                        return ret;
-
-               if((ret = __add_transceiver(source, media_type, payload_info)) != WEBRTC_ERROR_NONE)
-                       return ret;
        }
 
        /* FIXME: to utilize 'codec-preferences' of trans object, we need to re-create and re-link elements again */
@@ -2798,6 +2847,8 @@ int _set_media_format(webrtc_s *webrtc, unsigned int source_id, media_format_h f
 
        media_format_ref(format);
        source->media_format = format;
+       if((ret = _set_mediapacketsrc_codec_info(webrtc, source, mime_type)) != WEBRTC_ERROR_NONE)
+               goto error;
 
        if ((mime_type & MEDIA_FORMAT_RAW) &&
                !(mime_type == MEDIA_FORMAT_PCMU || mime_type == MEDIA_FORMAT_PCMA)) /* FIXME: media_format.h defined PCMU/PCMA as a raw format, it's a bug. */
@@ -2850,7 +2901,7 @@ bool _check_if_format_is_set_to_packet_sources(webrtc_s *webrtc)
        return true;
 }
 
-static gboolean __check_transceiver_is_not_set_cb(gpointer key, gpointer value, gpointer user_data)
+static gboolean __check_codec_is_not_set_cb(gpointer key, gpointer value, gpointer user_data)
 {
        const webrtc_gst_slot_s *source = (webrtc_gst_slot_s *)value;
        int i;
@@ -2858,7 +2909,7 @@ static gboolean __check_transceiver_is_not_set_cb(gpointer key, gpointer value,
        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].transceiver)
+                       if (source->av[i].codec)
                                return FALSE;
                }
                return TRUE;
@@ -2866,15 +2917,15 @@ static gboolean __check_transceiver_is_not_set_cb(gpointer key, gpointer value,
        return FALSE;
 }
 
-bool _check_if_transceiver_is_set_to_null_sources(webrtc_s *webrtc)
+bool _check_if_codec_is_set_to_null_sources(webrtc_s *webrtc)
 {
        const webrtc_gst_slot_s *source;
 
        RET_VAL_IF(webrtc == NULL, false, "webrtc is NULL");
 
-       source = g_hash_table_find(webrtc->gst.source_slots, __check_transceiver_is_not_set_cb, GINT_TO_POINTER(WEBRTC_MEDIA_SOURCE_TYPE_NULL));
+       source = g_hash_table_find(webrtc->gst.source_slots, __check_codec_is_not_set_cb, GINT_TO_POINTER(WEBRTC_MEDIA_SOURCE_TYPE_NULL));
        if (source) {
-               LOG_ERROR("transceiver is not set to the media null source[%u]", source->id);
+               LOG_ERROR("codec is not set to the media null source[%u]", source->id);
                LOG_ERROR("please use webrtc_media_source_set_transceiver_codec()");
                return false;
        }
index ef0941989339fde5a46e5c5743fd567efdcc14e1..79b46038da3121807dc46ed151895dbb761296ba 100644 (file)
@@ -270,7 +270,7 @@ static GstCaps *__make_encoded_caps_from_media_format(webrtc_gst_slot_s *source,
                        RET_VAL_IF(media_format_get_audio_info(source->media_format, &mime_type, &channels, &samplerate, NULL, NULL) != MEDIA_FORMAT_ERROR_NONE,
                                NULL, "failed to media_format_get_audio_info()");
 
-                       _media_type = _get_audio_media_type(_get_audio_format_name(mime_type));
+                       _media_type = _get_audio_media_type(source->av[AV_IDX_AUDIO].codec);
                        RET_VAL_IF(_media_type == NULL, NULL, "media_type is NULL");
 
                        caps = _get_caps_from_encoded_audio_media_type(_media_type, channels, samplerate);
@@ -285,7 +285,7 @@ static GstCaps *__make_encoded_caps_from_media_format(webrtc_gst_slot_s *source,
                        RET_VAL_IF(media_format_get_video_frame_rate(source->media_format, &framerate) != MEDIA_FORMAT_ERROR_NONE,
                                NULL, "failed to media_format_get_video_frame_rate()");
 
-                       _media_type = _get_video_media_type(_get_video_format_name(mime_type, source->zerocopy_enabled));
+                       _media_type = _get_video_media_type(source->av[AV_IDX_VIDEO].codec);
                        RET_VAL_IF(_media_type == NULL, NULL, "media_type is NULL");
 
                        caps = _get_caps_from_encoded_video_media_type(_media_type, width, height);
@@ -636,3 +636,36 @@ exit:
        return ret;
 }
 //LCOV_EXCL_STOP
+
+int _set_mediapacketsrc_codec_info(webrtc_s *webrtc, webrtc_gst_slot_s *source, media_format_mimetype_e mime_type)
+{
+       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(source->media_format == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "media_format is NULL");
+       RET_VAL_IF(((source->media_types != MEDIA_TYPE_AUDIO) && (source->media_types != MEDIA_TYPE_VIDEO)),
+                               WEBRTC_ERROR_INVALID_PARAMETER, "invalid media_types [%d]", source->media_types);
+
+       if ((mime_type & MEDIA_FORMAT_RAW) &&
+               !(mime_type == MEDIA_FORMAT_PCMU || mime_type == MEDIA_FORMAT_PCMA)) { /* FIXME: media_format.h defined PCMU/PCMA as a raw format, it's a bug. */
+
+               const ini_item_media_source_s *ini_source = _ini_get_source_by_type(&webrtc->ini, source->type);
+               if (ini_source == NULL)
+                       ini_source = &(webrtc->ini.media_source);
+
+               if (source->media_types == MEDIA_TYPE_AUDIO)
+                       source->av[AV_IDX_AUDIO].codec = ini_source->a_codecs[0];
+               else
+                       source->av[AV_IDX_VIDEO].codec = ini_source->v_codecs[0];
+
+       } else {
+               if (source->media_types == MEDIA_TYPE_AUDIO)
+                       source->av[AV_IDX_AUDIO].codec = _get_audio_format_name(mime_type);
+               else
+                       source->av[AV_IDX_VIDEO].codec = _get_video_format_name(mime_type, source->zerocopy_enabled);
+
+       }
+
+       LOG_DEBUG("%s codec info [%s]", (source->media_types == MEDIA_TYPE_AUDIO) ? "audio" : "video", source->av[GET_AV_IDX_BY_TYPE(source->media_types)].codec);
+
+       return WEBRTC_ERROR_NONE;
+}