From: Sangchul Lee Date: Wed, 17 Feb 2021 00:05:49 +0000 (+0900) Subject: webrtc_sink: Revise media packet for encoded frame callback X-Git-Tag: submit/tizen/20210729.023123~128 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=62f849285e0260e8d03d84298d2db15ae141bba9;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_sink: Revise media packet for encoded frame callback The gstbuffer data field is set as external memory pointer of the media packet. The pointer of gstbuffer is set to extra data of the media packet. If the caps of the pad has 'codec_data' field, it is set to the media packet. [Version] 0.1.113 [Issue Type] Improvement Change-Id: Ib361a0a9a2600b262c60486c22f27850a21cc5d0 Signed-off-by: Sangchul Lee --- diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 61f0b87a..42de0987 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.1.112 +Version: 0.1.113 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_sink.c b/src/webrtc_sink.c index 28015a64..5e7a1528 100644 --- a/src/webrtc_sink.c +++ b/src/webrtc_sink.c @@ -17,6 +17,7 @@ #include "webrtc.h" #include "webrtc_private.h" #include +#include #define GST_KLASS_NAME_DEPAYLOADER_RTP "Codec/Depayloader/Network/RTP" @@ -531,6 +532,7 @@ static media_format_h __make_media_format(GstPad *pad) { GstCaps *caps; GstStructure *structure; + gchar *caps_str; const gchar *mime; media_format_h format; media_format_mimetype_e mimetype; @@ -543,26 +545,27 @@ static media_format_h __make_media_format(GstPad *pad) structure = gst_caps_get_structure(caps, 0); mime = gst_structure_get_name(structure); - gchar *caps_str = gst_caps_to_string(caps); - LOG_INFO("%s", caps_str); + caps_str = gst_caps_to_string(caps); + LOG_WARNING("%s", caps_str); g_free(caps_str); - gst_caps_unref(caps); if (__get_media_format_mimetype(mime, &mimetype) != WEBRTC_ERROR_NONE) { + gst_caps_unref(caps); media_format_unref(format); return NULL; } + gst_caps_unref(caps); LOG_INFO("mimetype[0x%x]", mimetype); - if (g_strrstr(mime, "video")) { + if (mimetype & MEDIA_FORMAT_VIDEO) { ret = media_format_set_video_mime(format, mimetype); if (ret != MEDIA_FORMAT_ERROR_NONE) { LOG_ERROR("failed to media_format_set_video_mime()"); media_format_unref(format); return NULL; } - } else if (g_strrstr(mime, "audio")) { + } else if (mimetype & MEDIA_FORMAT_AUDIO) { ret = media_format_set_audio_mime(format, mimetype); if (ret != MEDIA_FORMAT_ERROR_NONE) { LOG_ERROR("failed to media_format_set_audio_mime()"); @@ -581,20 +584,47 @@ static int __media_packet_finalize_cb(media_packet_h packet, int error_code, voi RET_VAL_IF(sink == NULL, MEDIA_PACKET_FINALIZE, "sink is NULL"); - if (media_packet_get_buffer_data_ptr(packet, (void**)&buffer) == MEDIA_PACKET_ERROR_NONE) + if (media_packet_get_extra(packet, (void**)&buffer) == MEDIA_PACKET_ERROR_NONE) gst_buffer_unref(buffer); - else - LOG_ERROR("failed to media_packet_get_buffer_data_ptr()"); LOG_DEBUG("sink[%p], packet[%p], buffer[%p]", sink, packet, buffer); return MEDIA_PACKET_FINALIZE; } +static int __set_codec_data_if_exist(media_packet_h packet, GstPad *pad) +{ + int ret = WEBRTC_ERROR_NONE; + GstCaps *caps; + const GValue *codec_data_value; + + caps = gst_pad_get_current_caps(pad); + + if ((codec_data_value = gst_structure_get_value(gst_caps_get_structure(caps, 0), "codec_data"))) { + GstBuffer *codec_data; + GstMapInfo buff_info; + + codec_data = gst_value_get_buffer(codec_data_value); + gst_buffer_map(codec_data, &buff_info, GST_MAP_READ); + ret = media_packet_set_codec_data(packet, buff_info.data, buff_info.size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOG_ERROR("failed to media_packet_set_codec_data()"); + ret = WEBRTC_ERROR_INVALID_OPERATION; + } + LOG_DEBUG("codec_data[%p, size:%u] is set to the media packet[%p]", buff_info.data, buff_info.size, packet); + gst_buffer_unmap(codec_data, &buff_info); + } + + gst_caps_unref(caps); + + return ret; +} + static media_packet_h __make_media_packet(webrtc_gst_slot_s *sink, GstBuffer *buffer, GstPad *pad) { int ret; - media_packet_h packet; + media_packet_h packet = NULL; + GstMapInfo info = GST_MAP_INFO_INIT; RET_VAL_IF(sink == NULL, NULL, "sink is NULL"); RET_VAL_IF(buffer == NULL, NULL, "buffer is NULL"); @@ -604,12 +634,47 @@ static media_packet_h __make_media_packet(webrtc_gst_slot_s *sink, GstBuffer *bu sink->media_format = __make_media_format(pad); gst_buffer_ref(buffer); - ret = media_packet_create_from_external_memory(sink->media_format, buffer, gst_buffer_get_size(buffer), __media_packet_finalize_cb, sink, &packet); - RET_VAL_IF(ret != MEDIA_PACKET_ERROR_NONE, NULL, "failed to media_packet_create_from_external_memory()"); + + if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) { + LOG_ERROR("failed to gst_buffer_map()"); + goto error; + } + + ret = media_packet_create_from_external_memory(sink->media_format, info.data, gst_buffer_get_size(buffer), __media_packet_finalize_cb, sink, &packet); + gst_buffer_unmap(buffer, &info); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOG_ERROR("failed to media_packet_create_from_external_memory()"); + goto error; + } + + ret |= media_packet_set_pts(packet, GST_BUFFER_PTS(buffer)); + ret |= media_packet_set_dts(packet, GST_BUFFER_DTS(buffer)); + ret |= media_packet_set_duration(packet, GST_BUFFER_DURATION(buffer)); + + /* FIXME: We put the gstbuffer to extra field of media packet. It does not guarantee the validity of the gstbuffer + * after destroying this media packet. Currently, the gstbuffer must be used before destroying the packet. */ + ret |= media_packet_set_extra(packet, (void *)buffer); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOG_ERROR("failed to media_packet_set_*()"); + goto error; + } + + ret = __set_codec_data_if_exist(packet, pad); + if (ret != WEBRTC_ERROR_NONE) + goto error; LOG_DEBUG("sink[%p], packet[%p], buffer[%p]", sink, packet, buffer); return packet; + +error: + if (packet) + media_packet_destroy(packet); + gst_buffer_unref(buffer); + media_format_unref(sink->media_format); + sink->media_format = NULL; + + return NULL; } /* handoff signal handler */