support h/w codec 71/319971/1
authorEunhwa Kang <e.kang@samsung.com>
Tue, 10 Sep 2024 11:39:48 +0000 (20:39 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 6 Nov 2024 00:40:03 +0000 (09:40 +0900)
Change-Id: I9f84ec0f744500f0a747ebfa57e33341bc193555

include/webrtc_private.h
src/webrtc_display.c
src/webrtc_sink.c

index 97c9324845fe57954f3672fedbe2dfbf49d141c5..20a9e50d304a59d263da76d589f2bcbce66b502e 100644 (file)
@@ -461,6 +461,7 @@ typedef struct _webrtc_display {
        bool qos;
        webrtc_tbm_s *tbm;
        GstElement *sink_element;
+       bool zerocopy;
 } webrtc_display_s;
 
 typedef struct _webrtc_gst_s {
index 57bed31491c05cb71743d34ba8a00a943f0537ec..ba00d7d21f88304e68be4152c50598a58df0c539 100644 (file)
@@ -21,6 +21,7 @@
 #include <tbm_surface_internal.h>
 #include <media_packet.h>
 #include <media_format.h>
+#include <gst/allocators/gsttizenmemory.h>
 
 #define BUFFER_MAX_PLANE_NUM         4
 
@@ -30,6 +31,7 @@ typedef struct _video_decoded_data_s {
        int height;                            /**< height of video buffer */
        unsigned int timestamp;                /**< timestamp of buffer (msec)*/
        unsigned int length_total;             /**< total length of buffer (in byte)*/
+       void *internal_buffer;
        void *data[BUFFER_MAX_PLANE_NUM];
        void *bo[BUFFER_MAX_PLANE_NUM];        /**< TBM buffer object */
        int stride[BUFFER_MAX_PLANE_NUM];      /**< stride of plane */
@@ -302,6 +304,24 @@ static video_decoded_data_info_s *__get_decoded_data_info_from_pad(GstPad *pad)
        return info;
 }
 
+static void
+__mmplayer_zerocopy_set_stride_elevation_bo(video_decoded_data_info_s *info, GstMemory *mem)
+{
+       unsigned int pitch = 0;
+       unsigned int size = 0;
+       int index = 0;
+       tbm_surface_h surface = gst_tizen_memory_get_surface(mem);
+
+       for (index = 0; index < info->plane_num; index++) {
+               tbm_surface_internal_get_plane_data(surface, index, &size, NULL, &pitch);
+               info->stride[index] = pitch;
+               if (pitch)
+                       info->elevation[index] = size / pitch;
+               else
+                       info->elevation[index] = info->height;
+       }
+}
+
 static bool __swcodec_set_stride_elevation(video_decoded_data_info_s *info)
 {
        RET_VAL_IF(info == NULL, false, "info is NULL");
@@ -480,8 +500,11 @@ static int __media_packet_finalize_cb(media_packet_h m_packet, int error_code, v
                tbm_surface_destroy(ts);
        }
 
-       if (finalize_data->info->bo[0])
+       if (finalize_data->info->internal_buffer) {
+               gst_buffer_unref((GstBuffer *)finalize_data->info->internal_buffer);
+       } else if (finalize_data->info->bo[0]) {  /* sw codec */
                _release_tbm_bo(finalize_data->tbm, finalize_data->info->bo[0]);
+       }
 
        g_free(finalize_data->info);
        g_free(finalize_data);
@@ -632,13 +655,20 @@ static media_packet_h __get_media_packet_from_buffer(webrtc_display_s *display,
        info->length_total = (unsigned int)gst_memory_get_sizes(mem, NULL, NULL);
        info->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> milli sec */
 
-       if (!__swcodec_set_stride_elevation(info) || !__swcodec_set_bo(display, info, mem))
-               goto ERROR;
-
-       ts = __get_tbm_surface(info);
-       if (ts == NULL) {
-               LOG_ERROR("failed to __get_tbm_surface()");
-               goto ERROR;
+       if (display->zerocopy &&
+               gst_is_tizen_memory(mem)) {
+               __mmplayer_zerocopy_set_stride_elevation_bo(info, mem);
+               info->internal_buffer = gst_buffer_ref(buffer);
+               ts = (tbm_surface_h) gst_tizen_memory_get_surface(mem);
+       } else { /* sw codec */
+               if (!__swcodec_set_stride_elevation(info) || !__swcodec_set_bo(display, info, mem))
+                       goto ERROR;
+
+               ts = __get_tbm_surface(info);
+               if (ts == NULL) {
+                       LOG_ERROR("failed to __get_tbm_surface()");
+                       goto ERROR;
+               }
        }
 
        m_packet = __get_media_packet(display->tbm, info, ts);
@@ -651,9 +681,11 @@ static media_packet_h __get_media_packet_from_buffer(webrtc_display_s *display,
 
 ERROR:
        LOG_ERROR("release video data resource");
-
-       if (info->bo[0])
+       if (info->internal_buffer) {
+               gst_buffer_unref (info->internal_buffer);
+       } else if (info->bo[0]) {
                _release_tbm_bo(display->tbm, info->bo[0]);
+       }
        g_free(info);
 
        return NULL;
index c7e23f7970afe374fd7aab9efe30189fa9f165da..b4a984b8230d545b32cc79f81ebfd6c005d46f01 100644 (file)
@@ -109,7 +109,7 @@ static const char *__get_videosink_factory_name(webrtc_display_s *display, webrt
                factory_name = ini->rendering_sink.v_sink_element;
                break;
        case WEBRTC_DISPLAY_TYPE_EVAS:
-               factory_name = DEFAULT_ELEMENT_FAKESINK;
+               factory_name = display->zerocopy ? "mesonvideosink" : DEFAULT_ELEMENT_FAKESINK;
                break;
        default:
                LOG_ERROR_IF_REACHED("invalid type(%d)", display->type);
@@ -150,7 +150,6 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr
 {
        webrtc_gst_slot_s *sink;
        GstElement *videoconvert = NULL;
-       GstElement *capsfilter;
        GstElement *videosink;
        GstElement *link_to;
        GstPad *sink_pad;
@@ -198,6 +197,13 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr
                                "qos", (gboolean)sink->display->qos,
                                NULL);
 
+                       if (sink->display->zerocopy) {
+                               g_object_set(G_OBJECT(videosink),
+                                               "use-drm", TRUE,
+                                               "use-tizen-video-object", FALSE,
+                                               NULL);
+                       }
+
                        /* FIXME: The order of setting property and display is important when 'use-tbm' is true. The reverse does not work */
                        gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(videosink), sink->display->overlay_surface_id);
                        LOG_DEBUG("overlay_surface_id[%d]", sink->display->overlay_surface_id);
@@ -217,7 +223,6 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr
                        }
 
                } else if (sink->display->type == WEBRTC_DISPLAY_TYPE_EVAS) {
-                       GstCaps *caps;
                        g_object_set(G_OBJECT(videosink),
                                "sync", TRUE,
                                "qos", (gboolean)sink->display->qos,
@@ -225,22 +230,27 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr
                                NULL);
                        _connect_and_append_signal(&sink->signals, (GObject *)videosink, "handoff", G_CALLBACK(_video_stream_decoded_cb), sink->display);
 
-                       if (!(capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, NULL)))
-                               goto exit;
-                       PREPEND_ELEMENT(element_list, capsfilter);
-
-                       caps = gst_caps_new_simple(MEDIA_TYPE_VIDEO_RAW,
-                                                       "format", G_TYPE_STRING, webrtc->ini.rendering_sink.evas_native_surface_tbm_format,
-                                                       NULL);
-                       g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
-                       gst_caps_unref(caps);
+                       if (!sink->display->zerocopy) {
+                               GstCaps *caps;
+                               GstElement *capsfilter;
+                               if (!(capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, NULL)))
+                                       goto exit;
+                               PREPEND_ELEMENT(element_list, capsfilter);
+
+                               caps = gst_caps_new_simple(MEDIA_TYPE_VIDEO_RAW,
+                                                               "format", G_TYPE_STRING, webrtc->ini.rendering_sink.evas_native_surface_tbm_format,
+                                                               NULL);
+                               g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
+                               gst_caps_unref(caps);
+                       } else {
+                               g_object_set(G_OBJECT(videosink),
+                                               "convert-mode", 1,
+                                               NULL);
+                       }
                }
 
-               if (sink->av[AV_IDX_VIDEO].render.hw_decoder_used &&
-                       (sink->display->type == WEBRTC_DISPLAY_TYPE_OVERLAY ||
-                       sink->display->type == WEBRTC_DISPLAY_TYPE_ECORE_WL)) {
+               if (sink->av[AV_IDX_VIDEO].render.hw_decoder_used) {
                        link_to = videosink;
-
                } else {
                        if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
                                goto exit;
@@ -487,6 +497,9 @@ static void __decodebin_element_added_cb(GstElement *decodebin, GstElement *elem
                /* send SPS and PPS Insertion Interval every second */
                g_object_set(G_OBJECT(element), "config-interval", 1, NULL);
                _add_probe_to_pad_for_dump(sink, element, _depayloaded_data_probe_cb);
+       } else if (g_strrstr(factory_name, "v4l2")) {
+               LOG_INFO("[%s] set capture-io-mode to dmabuf-import", factory_name);
+               g_object_set(G_OBJECT(element), "capture-io-mode", 5, NULL);
        }
 
        /* all other depayloaders except h264 */
@@ -533,6 +546,7 @@ static void __decodebin_pad_added_cb(GstElement *decodebin, GstPad *new_pad, gpo
                sink->media_types |= MEDIA_TYPE_VIDEO;
                __invoke_track_added_cb(webrtc, GST_ELEMENT_NAME(decodebin), false, true);
                _apply_display(sink->display);
+               sink->display->zerocopy = sink->av[AV_IDX_VIDEO].render.hw_decoder_used;
                ret = __build_videosink(webrtc, decodebin, new_pad);
        }