blob: 05760b5aaa5a7bd0ed95525458be57ab0a9634a7 [file] [log] [blame]
xuesong.jiang16983c92021-12-30 10:57:17 +08001/* GStreamer
2 * Copyright (C) 2021 <song.zhao@amlogic.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17 * Boston, MA 02110-1335, USA.
18 */
19/**
20 * SECTION:element-gstamlvideosink
21 *
22 * The gstamlvideosink element call render lib to render video
23 *
24 */
25
xuesong.jiang1801e172021-10-11 10:56:41 +080026#ifdef HAVE_CONFIG_H
27#include <config.h>
28#endif
29
xuesong.jiang7c724a52021-10-22 17:18:58 +080030#include <stdbool.h>
xuesong.jiangd91230d2021-10-20 15:51:10 +080031#include <gst/gstdrmbufferpool.h>
xuesong.jiange90be372021-10-21 11:29:57 +080032#include <gst/allocators/gstdmabuf.h>
xuesong.jiang192316f2021-10-27 14:51:56 +080033#include "gstamlvideosink.h"
xuesong.jiang7f613802021-12-15 15:22:44 +080034#include <render_lib.h>
xuesong.jiang192316f2021-10-27 14:51:56 +080035// #ifdef USE_AMLOGIC_MESON
36// #ifdef USE_AMLOGIC_MESON_MSYNC
37// #define INVALID_SESSION_ID (16)
38#include "gstamlclock.h"
39#include "gstamlhalasink_new.h"
xuesong.jiang75ef01c2021-12-09 17:08:52 +080040#include <stdio.h>
xuesong.jiang192316f2021-10-27 14:51:56 +080041// #endif
42// #endif
xuesong.jiang1801e172021-10-11 10:56:41 +080043
xuesong.jiang91391f52021-11-19 15:42:30 +080044#ifdef GST_OBJECT_LOCK
45#undef GST_OBJECT_LOCK
46#define GST_OBJECT_LOCK(obj) \
47{ \
48 GST_DEBUG("dbg basesink ctxt lock | aml | %p | locking", obj); \
49 g_mutex_lock(GST_OBJECT_GET_LOCK(obj)); \
50 GST_DEBUG("dbg basesink ctxt lock | aml | %p | locked", obj); \
xuesong.jiang4a832aa2022-01-06 16:44:26 +080051}
xuesong.jiang91391f52021-11-19 15:42:30 +080052#endif
53
54#ifdef GST_OBJECT_UNLOCK
55#undef GST_OBJECT_UNLOCK
56#define GST_OBJECT_UNLOCK(obj) \
57{ \
58 GST_DEBUG("dbg basesink ctxt lock | aml |%p | unlocking", obj); \
59 g_mutex_unlock(GST_OBJECT_GET_LOCK(obj)); \
60 GST_DEBUG("dbg basesink ctxt lock | aml |%p | unlocked", obj); \
xuesong.jiang4a832aa2022-01-06 16:44:26 +080061}
xuesong.jiang91391f52021-11-19 15:42:30 +080062#endif
63
xuesong.jiang1801e172021-10-11 10:56:41 +080064/* signals */
xuesong.jiangd91230d2021-10-20 15:51:10 +080065enum
66{
67 SIGNAL_0,
68 LAST_SIGNAL
xuesong.jiang1801e172021-10-11 10:56:41 +080069};
70
xuesong.jiangd91230d2021-10-20 15:51:10 +080071/* Properties */
72enum
73{
74 PROP_0,
75 PROP_FULLSCREEN,
76 PROP_SETMUTE,
xuesong.jiang1801e172021-10-11 10:56:41 +080077
xuesong.jiangd91230d2021-10-20 15:51:10 +080078};
79
80#define AML_VIDEO_FORMATS \
81 "{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB, RGB, BGR, " \
82 "RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, " \
83 "YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }"
84#define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
xuesong.jiang4a832aa2022-01-06 16:44:26 +080085#define GST_USE_PLAYBIN 1
xuesong.jiangd91230d2021-10-20 15:51:10 +080086#define RENDER_DEVICE_NAME "wayland"
87#define USE_DMABUF TRUE
88
xuesong.jiang4a832aa2022-01-06 16:44:26 +080089#define DRMBP_EXTRA_BUF_SZIE_FOR_DISPLAY 5
xuesong.jiangb3f0f152021-12-23 20:19:08 +080090#define DRMBP_LIMIT_MAX_BUFSIZE_TO_BUFSIZE 1
91#define DRMBP_UNLIMIT_MAX_BUFSIZE 0
92
xuesong.jiangd91230d2021-10-20 15:51:10 +080093struct _GstAmlVideoSinkPrivate
94{
xuesong.jiangebd18352021-12-28 17:13:22 +080095 GstBuffer *preroll_buffer;
xuesong.jiange90be372021-10-21 11:29:57 +080096 gchar *render_device_name;
97 void *render_device_handle;
xuesong.jiangd91230d2021-10-20 15:51:10 +080098 GstVideoInfo video_info;
99 gboolean video_info_changed;
100 gboolean use_dmabuf;
101 gboolean is_flushing;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800102 gboolean got_eos;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800103 gint mediasync_instanceid;
xuesong.jiang7c724a52021-10-22 17:18:58 +0800104 GstSegment segment;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800105
xuesong.jiangd91230d2021-10-20 15:51:10 +0800106 /* property params */
107 gboolean fullscreen;
108 gboolean mute;
xuesong.jiang1801e172021-10-11 10:56:41 +0800109};
110
111static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE(
112 "sink", GST_PAD_SINK, GST_PAD_ALWAYS,
113 GST_STATIC_CAPS(
114 GST_VIDEO_CAPS_MAKE(AML_VIDEO_FORMATS) ";" GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
115 GST_CAPS_FEATURE_MEMORY_DMABUF, AML_VIDEO_FORMATS)));
116
117GST_DEBUG_CATEGORY(gst_aml_video_sink_debug);
118#define GST_CAT_DEFAULT gst_aml_video_sink_debug
119#define gst_aml_video_sink_parent_class parent_class
xuesong.jiang192316f2021-10-27 14:51:56 +0800120// #define GST_AML_VIDEO_SINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), GST_TYPE_AML_VIDEO_SINK, GstAmlVideoSinkPrivate))
xuesong.jiang1801e172021-10-11 10:56:41 +0800121G_DEFINE_TYPE_WITH_CODE(GstAmlVideoSink, gst_aml_video_sink,
122 GST_TYPE_VIDEO_SINK, G_ADD_PRIVATE(GstAmlVideoSink));
123
124/* public interface define */
125static void gst_aml_video_sink_get_property(GObject *object, guint prop_id,
126 GValue *value, GParamSpec *pspec);
127static void gst_aml_video_sink_set_property(GObject *object, guint prop_id,
128 const GValue *value,
129 GParamSpec *pspec);
130static void gst_aml_video_sink_finalize(GObject *object);
131static GstStateChangeReturn
132gst_aml_video_sink_change_state(GstElement *element, GstStateChange transition);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800133static gboolean gst_aml_video_sink_propose_allocation(GstBaseSink *bsink, GstQuery *query);
xuesong.jiang1801e172021-10-11 10:56:41 +0800134static GstCaps *gst_aml_video_sink_get_caps(GstBaseSink *bsink,
135 GstCaps *filter);
136static gboolean gst_aml_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800137static gboolean gst_aml_video_sink_show_frame(GstVideoSink *bsink, GstBuffer *buffer);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800138static gboolean gst_aml_video_sink_pad_event(GstPad *pad, GstObject *parent, GstEvent *event);
xuesong.jiang1801e172021-10-11 10:56:41 +0800139
140/* private interface define */
141static void gst_aml_video_sink_reset_private(GstAmlVideoSink *sink);
xuesong.jiang1700bab2021-11-17 17:11:11 +0800142void gst_render_msg_callback(void *userData, RenderMsgType type, void *msg);
143int gst_render_val_callback(void *userData, int key, void *value);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800144static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800145static gboolean gst_get_mediasync_instanceid(GstAmlVideoSink *vsink);
xuesong.jiang16983c92021-12-30 10:57:17 +0800146#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +0800147static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink);
xuesong.jiang16983c92021-12-30 10:57:17 +0800148#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +0800149static gboolean gst_render_set_params(GstVideoSink *vsink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800150static void gst_emit_eos_signal(GstAmlVideoSink *vsink);
151static void gst_wait_eos_signal(GstAmlVideoSink *vsink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800152
153/* public interface definition */
xuesong.jiang7c724a52021-10-22 17:18:58 +0800154static void gst_aml_video_sink_class_init(GstAmlVideoSinkClass *klass)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800155{
156 GObjectClass *gobject_class;
157 GstElementClass *gstelement_class;
158 GstBaseSinkClass *gstbasesink_class;
159 GstVideoSinkClass *gstvideosink_class;
xuesong.jiang1801e172021-10-11 10:56:41 +0800160
xuesong.jiangd91230d2021-10-20 15:51:10 +0800161 gobject_class = (GObjectClass *)klass;
162 gstelement_class = (GstElementClass *)klass;
163 gstbasesink_class = (GstBaseSinkClass *)klass;
164 gstvideosink_class = (GstVideoSinkClass *)klass;
xuesong.jiang1801e172021-10-11 10:56:41 +0800165
xuesong.jiangd91230d2021-10-20 15:51:10 +0800166 gobject_class->set_property = gst_aml_video_sink_set_property;
167 gobject_class->get_property = gst_aml_video_sink_get_property;
168 gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_aml_video_sink_finalize);
xuesong.jiang1801e172021-10-11 10:56:41 +0800169
xuesong.jiangd91230d2021-10-20 15:51:10 +0800170 gst_element_class_add_static_pad_template(gstelement_class, &sink_template);
xuesong.jiang1801e172021-10-11 10:56:41 +0800171
xuesong.jiangd91230d2021-10-20 15:51:10 +0800172 gst_element_class_set_static_metadata(
173 gstelement_class, "aml video sink", "Sink/Video",
174 "Output to video tunnel lib",
175 "Xuesong.Jiang@amlogic.com<Xuesong.Jiang@amlogic.com>");
xuesong.jiang1801e172021-10-11 10:56:41 +0800176
xuesong.jiangd91230d2021-10-20 15:51:10 +0800177 gstelement_class->change_state =
178 GST_DEBUG_FUNCPTR(gst_aml_video_sink_change_state);
xuesong.jiang1801e172021-10-11 10:56:41 +0800179
xuesong.jiangd91230d2021-10-20 15:51:10 +0800180 gstbasesink_class->propose_allocation = GST_DEBUG_FUNCPTR(gst_aml_video_sink_propose_allocation);
181 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR(gst_aml_video_sink_get_caps);
182 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_aml_video_sink_set_caps);
xuesong.jiang1801e172021-10-11 10:56:41 +0800183
xuesong.jiangd91230d2021-10-20 15:51:10 +0800184 gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR(gst_aml_video_sink_show_frame);
xuesong.jiang1801e172021-10-11 10:56:41 +0800185
xuesong.jiangd91230d2021-10-20 15:51:10 +0800186 g_object_class_install_property(
187 gobject_class, PROP_FULLSCREEN,
188 g_param_spec_boolean("fullscreen", "Fullscreen",
189 "Whether the surface should be made fullscreen ",
190 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
xuesong.jiang1801e172021-10-11 10:56:41 +0800191
xuesong.jiangd91230d2021-10-20 15:51:10 +0800192 g_object_class_install_property(
193 gobject_class, PROP_SETMUTE,
194 g_param_spec_boolean("set mute", "set mute params",
195 "Whether set screen mute ",
196 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
xuesong.jiang1801e172021-10-11 10:56:41 +0800197}
198
xuesong.jiangd91230d2021-10-20 15:51:10 +0800199static void gst_aml_video_sink_init(GstAmlVideoSink *sink)
200{
201 GstBaseSink *basesink = (GstBaseSink *)sink;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800202
203 /* init eos detect */
204 sink->queued = 0;
205 sink->dequeued = 0;
206 sink->rendered = 0;
207 g_mutex_init (&sink->eos_lock);
208 g_cond_init (&sink->eos_cond);
209
xuesong.jiangd91230d2021-10-20 15:51:10 +0800210 gst_pad_set_event_function(basesink->sinkpad, gst_aml_video_sink_pad_event);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800211
xuesong.jiang5c0d1b82021-11-16 19:30:56 +0800212 GST_AML_VIDEO_SINK_GET_PRIVATE(sink) = malloc (sizeof(GstAmlVideoSinkPrivate));
xuesong.jiangd91230d2021-10-20 15:51:10 +0800213 gst_aml_video_sink_reset_private(sink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800214
xuesong.jiangd2619562021-12-23 16:38:50 +0800215 gst_base_sink_set_sync(basesink, FALSE);
xuesong.jiang1801e172021-10-11 10:56:41 +0800216}
217
218static void gst_aml_video_sink_get_property(GObject *object, guint prop_id,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800219 GValue *value, GParamSpec *pspec)
220{
221 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
222 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800223
xuesong.jiangd91230d2021-10-20 15:51:10 +0800224 switch (prop_id)
225 {
226 case PROP_FULLSCREEN:
227 GST_OBJECT_LOCK(sink);
228 g_value_set_boolean(value, sink_priv->fullscreen);
229 GST_OBJECT_UNLOCK(sink);
230 break;
231 case PROP_SETMUTE:
232 GST_OBJECT_LOCK(sink);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800233 g_value_set_boolean(value, sink_priv->mute);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800234 GST_OBJECT_UNLOCK(sink);
235 break;
236 default:
237 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
238 break;
239 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800240}
241
242static void gst_aml_video_sink_set_property(GObject *object, guint prop_id,
243 const GValue *value,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800244 GParamSpec *pspec)
245{
246 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
247 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800248
xuesong.jiangd91230d2021-10-20 15:51:10 +0800249 switch (prop_id)
250 {
251 case PROP_FULLSCREEN:
252 GST_OBJECT_LOCK(sink);
253 gboolean is_fullscreen = g_value_get_boolean(value);
xuesong.jiange90be372021-10-21 11:29:57 +0800254 if (sink_priv->fullscreen != is_fullscreen)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800255 {
256 sink_priv->fullscreen = is_fullscreen;
257 //TODO set full screen to tunnel lib
258 }
259 GST_OBJECT_UNLOCK(sink);
260 break;
261 case PROP_SETMUTE:
262 GST_OBJECT_LOCK(sink);
263 gboolean is_mute = g_value_get_boolean(value);
xuesong.jiange90be372021-10-21 11:29:57 +0800264 if (sink_priv->mute != is_mute)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800265 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800266 sink_priv->mute = is_mute;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800267 //TODO set full screen to tunnel lib
268 }
269 GST_OBJECT_UNLOCK(sink);
270 break;
271 default:
272 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
273 break;
274 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800275}
276
xuesong.jiangd91230d2021-10-20 15:51:10 +0800277static void gst_aml_video_sink_finalize(GObject *object)
278{
279 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
xuesong.jiang1801e172021-10-11 10:56:41 +0800280
xuesong.jiangd91230d2021-10-20 15:51:10 +0800281 GST_DEBUG_OBJECT(sink, "Finalizing aml video sink..");
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800282
283 g_mutex_clear (&sink->eos_lock);
284 g_cond_clear (&sink->eos_cond);
285
xuesong.jiangd91230d2021-10-20 15:51:10 +0800286 gst_aml_video_sink_reset_private(sink);
xuesong.jiang5c0d1b82021-11-16 19:30:56 +0800287 if(GST_AML_VIDEO_SINK_GET_PRIVATE(sink))
288 free(GST_AML_VIDEO_SINK_GET_PRIVATE(sink));
xuesong.jiangd91230d2021-10-20 15:51:10 +0800289 G_OBJECT_CLASS(parent_class)->finalize(object);
xuesong.jiang1801e172021-10-11 10:56:41 +0800290}
291
292static GstStateChangeReturn
293gst_aml_video_sink_change_state(GstElement *element,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800294 GstStateChange transition)
295{
296 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(element);
297 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800298 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
xuesong.jiang32d78282021-11-18 19:24:15 +0800299 GST_DEBUG_OBJECT(sink, "trace in");
xuesong.jiang1801e172021-10-11 10:56:41 +0800300
xuesong.jiangd91230d2021-10-20 15:51:10 +0800301 GST_OBJECT_LOCK(sink);
302 switch (transition)
303 {
304 case GST_STATE_CHANGE_NULL_TO_READY:
305 {
306 sink_priv->render_device_handle = render_open(sink_priv->render_device_name);
xuesong.jiange90be372021-10-21 11:29:57 +0800307 if (sink_priv->render_device_handle == NULL)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800308 {
309 GST_ERROR_OBJECT(sink, "render lib: open device fail");
310 goto error;
311 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800312 RenderCallback cb = {gst_render_msg_callback, gst_render_val_callback};
313 render_set_callback(sink_priv->render_device_handle, &cb);
314 render_set_user_data(sink_priv->render_device_handle, sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800315
xuesong.jiangd91230d2021-10-20 15:51:10 +0800316 break;
317 }
318 case GST_STATE_CHANGE_READY_TO_PAUSED:
319 {
xuesong.jiang1700bab2021-11-17 17:11:11 +0800320 if (render_connect(sink_priv->render_device_handle) == -1)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800321 {
322 GST_ERROR_OBJECT(sink, "render lib connect device fail");
323 goto error;
324 }
325 break;
326 }
327 default:
328 break;
329 }
330 GST_OBJECT_UNLOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800331
xuesong.jiang1700bab2021-11-17 17:11:11 +0800332 GST_LOG_OBJECT(sink, "amlvideosink deal state change ok, goto basesink state change");
xuesong.jiangd91230d2021-10-20 15:51:10 +0800333 ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
334
335 GST_OBJECT_LOCK(sink);
336 if (ret == GST_STATE_CHANGE_FAILURE)
337 goto error;
338
339 switch (transition)
340 {
341 case GST_STATE_CHANGE_PAUSED_TO_READY:
342 {
343 render_disconnect(sink_priv->render_device_handle);
344 break;
345 }
346 case GST_STATE_CHANGE_READY_TO_NULL:
347 {
xuesong.jiange90be372021-10-21 11:29:57 +0800348 if (sink_priv->render_device_handle)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800349 {
350 render_close(sink_priv->render_device_handle);
351 }
352 gst_aml_video_sink_reset_private(sink);
353
354 break;
355 }
356 default:
357 break;
358 }
359 GST_OBJECT_UNLOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800360 return ret;
361
xuesong.jiangd91230d2021-10-20 15:51:10 +0800362error:
363 GST_OBJECT_UNLOCK(sink);
364 ret = GST_STATE_CHANGE_FAILURE;
365 return ret;
366}
xuesong.jiang1801e172021-10-11 10:56:41 +0800367
xuesong.jiangd91230d2021-10-20 15:51:10 +0800368static gboolean gst_aml_video_sink_propose_allocation(GstBaseSink *bsink, GstQuery *query)
369{
xuesong.jiangeb46f672021-11-19 19:05:56 +0800370 GST_DEBUG_OBJECT(bsink, "trace in");
xuesong.jiangd91230d2021-10-20 15:51:10 +0800371 //TODO only implement dma case
372 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(bsink);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800373 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
374
xuesong.jiangd91230d2021-10-20 15:51:10 +0800375 GstCaps *caps;
376 GstBufferPool *pool = NULL;
377 gboolean need_pool;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800378
379 gst_query_parse_allocation(query, &caps, &need_pool);
xuesong.jiangeb46f672021-11-19 19:05:56 +0800380 GST_DEBUG_OBJECT(bsink, "jxsaaa need_pool:%d", need_pool);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800381
382 if (need_pool)
xuesong.jiang7c724a52021-10-22 17:18:58 +0800383 //TODO 没有考虑secure场景
384 pool = gst_drm_bufferpool_new(FALSE, GST_DRM_BUFFERPOOL_TYPE_VIDEO_PLANE);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800385
xuesong.jiangb3f0f152021-12-23 20:19:08 +0800386 gst_query_add_allocation_pool(query, pool, sink_priv->video_info.size, DRMBP_EXTRA_BUF_SZIE_FOR_DISPLAY, DRMBP_LIMIT_MAX_BUFSIZE_TO_BUFSIZE);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800387 if (pool)
388 g_object_unref(pool);
389
390 gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
391
392 return TRUE;
xuesong.jiang1801e172021-10-11 10:56:41 +0800393}
394
395static GstCaps *gst_aml_video_sink_get_caps(GstBaseSink *bsink,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800396 GstCaps *filter)
397{
398 GstAmlVideoSink *sink;
399 GstCaps *caps;
xuesong.jiang1801e172021-10-11 10:56:41 +0800400
xuesong.jiangd91230d2021-10-20 15:51:10 +0800401 sink = GST_AML_VIDEO_SINK(bsink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800402
xuesong.jiangd91230d2021-10-20 15:51:10 +0800403 caps = gst_pad_get_pad_template_caps(GST_VIDEO_SINK_PAD(sink));
404 caps = gst_caps_make_writable(caps);
405 // TODO 这里是需要从template直接取出支持的caps还是要通过tunnel lib拿到caps?
xuesong.jiang1801e172021-10-11 10:56:41 +0800406
xuesong.jiangd91230d2021-10-20 15:51:10 +0800407 if (filter)
408 {
409 GstCaps *intersection;
xuesong.jiang1801e172021-10-11 10:56:41 +0800410
xuesong.jiangd91230d2021-10-20 15:51:10 +0800411 intersection =
412 gst_caps_intersect_full(filter, caps, GST_CAPS_INTERSECT_FIRST);
413 gst_caps_unref(caps);
414 caps = intersection;
415 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800416
xuesong.jiangd91230d2021-10-20 15:51:10 +0800417 return caps;
xuesong.jiang1801e172021-10-11 10:56:41 +0800418}
419
xuesong.jiangd91230d2021-10-20 15:51:10 +0800420static gboolean gst_aml_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps)
421{
422 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(bsink);
423 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800424 // gboolean use_dmabuf;
xuesong.jiang91391f52021-11-19 15:42:30 +0800425 gboolean ret = TRUE;
xuesong.jiang1801e172021-10-11 10:56:41 +0800426
xuesong.jiangd91230d2021-10-20 15:51:10 +0800427 GST_OBJECT_LOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800428
xuesong.jiangd91230d2021-10-20 15:51:10 +0800429 GST_DEBUG_OBJECT(sink, "set caps %" GST_PTR_FORMAT, caps);
xuesong.jiangeb46f672021-11-19 19:05:56 +0800430 // use_dmabuf = gst_caps_features_contains(gst_caps_get_features(caps, 0), GST_CAPS_FEATURE_MEMORY_DMABUF);
431 // if (use_dmabuf == FALSE)
432 // {
433 // GST_ERROR_OBJECT(sink, "not support non dma buffer case");
434 // ret = FALSE;
435 // goto done;
436 // }
xuesong.jiang1801e172021-10-11 10:56:41 +0800437
xuesong.jiangd91230d2021-10-20 15:51:10 +0800438 /* extract info from caps */
439 if (!gst_video_info_from_caps(&sink_priv->video_info, caps))
440 {
441 GST_ERROR_OBJECT(sink, "can't get video info from caps");
xuesong.jiang91391f52021-11-19 15:42:30 +0800442 ret = FALSE;
443 goto done;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800444 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800445
xuesong.jiangd91230d2021-10-20 15:51:10 +0800446 sink_priv->video_info_changed = TRUE;
447
xuesong.jiang91391f52021-11-19 15:42:30 +0800448done:
xuesong.jiangd91230d2021-10-20 15:51:10 +0800449 GST_OBJECT_UNLOCK(sink);
xuesong.jiang91391f52021-11-19 15:42:30 +0800450 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800451}
452
xuesong.jiange90be372021-10-21 11:29:57 +0800453static GstFlowReturn gst_aml_video_sink_show_frame(GstVideoSink *vsink, GstBuffer *buffer)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800454{
xuesong.jiang7c724a52021-10-22 17:18:58 +0800455 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800456 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
457 GstFlowReturn ret = GST_FLOW_OK;
458 RenderBuffer *tunnel_lib_buf_wrap = NULL;
xuesong.jiang1801e172021-10-11 10:56:41 +0800459
xuesong.jiangd91230d2021-10-20 15:51:10 +0800460 GST_OBJECT_LOCK(vsink);
xuesong.jiangebd18352021-12-28 17:13:22 +0800461 GST_LOG_OBJECT(sink, "revice buffer:%p, from pool:%p, need_preroll:%d", buffer, buffer->pool, ((GstBaseSink *)sink)->need_preroll);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800462
xuesong.jiange90be372021-10-21 11:29:57 +0800463 if (!sink_priv->render_device_handle)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800464 {
465 GST_ERROR_OBJECT(sink, "flow error, render_device_handle == NULL");
466 goto error;
467 }
468
xuesong.jiangebd18352021-12-28 17:13:22 +0800469 if (sink_priv->preroll_buffer && sink_priv->preroll_buffer == buffer)
470 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800471 GST_LOG_OBJECT(sink, "get preroll buffer:%p 2nd time, goto ret", buffer);
xuesong.jiangebd18352021-12-28 17:13:22 +0800472 sink_priv->preroll_buffer = NULL;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800473 goto ret;
xuesong.jiangebd18352021-12-28 17:13:22 +0800474 }
475 if (G_UNLIKELY(((GstBaseSink *)sink)->need_preroll))
476 {
477 GST_LOG_OBJECT(sink, "get preroll buffer 1st time, buf:%p", buffer);
478 sink_priv->preroll_buffer = buffer;
479 }
480
xuesong.jiangd91230d2021-10-20 15:51:10 +0800481 // TODO should call tunnel lib flush func
482 if (sink_priv->is_flushing)
483 {
484 gst_buffer_unref(buffer);
xuesong.jiange90be372021-10-21 11:29:57 +0800485 if (!render_flush(sink_priv->render_device_handle))
xuesong.jiangd91230d2021-10-20 15:51:10 +0800486 {
487 GST_ERROR_OBJECT(sink, "render lib: flush error");
488 goto error;
489 }
490 GST_DEBUG_OBJECT(sink, "in flushing flow, release the buffer directly");
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800491 goto flushing;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800492 }
493
494 if (sink_priv->video_info_changed)
495 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800496 if (gst_render_set_params(vsink) == FALSE)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800497 {
498 GST_ERROR_OBJECT(sink, "render lib: set params fail");
499 goto error;
500 }
501 sink_priv->video_info_changed = FALSE;
502 }
503
xuesong.jiang50a0f932021-11-15 15:18:51 +0800504 tunnel_lib_buf_wrap = render_allocate_render_buffer_wrap(sink_priv->render_device_handle, BUFFER_FLAG_EXTER_DMA_BUFFER, 0);
xuesong.jiange90be372021-10-21 11:29:57 +0800505 if (!tunnel_lib_buf_wrap)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800506 {
507 GST_ERROR_OBJECT(sink, "render lib: alloc buffer wrap fail");
508 goto error;
509 }
xuesong.jiange90be372021-10-21 11:29:57 +0800510 if (!gst_aml_video_sink_tunnel_buf(sink, buffer, tunnel_lib_buf_wrap))
511 {
512 GST_ERROR_OBJECT(sink, "construc render buffer fail");
513 goto error;
514 }
515
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800516 GST_OBJECT_UNLOCK(vsink);
517
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800518 if (render_display_frame(sink_priv->render_device_handle, tunnel_lib_buf_wrap) == -1)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800519 {
520 GST_ERROR_OBJECT(sink, "render lib: display frame fail");
521 goto error;
522 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800523
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800524 sink->queued++;
xuesong.jiangeb46f672021-11-19 19:05:56 +0800525 GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued ok", buffer);
xuesong.jiang1801e172021-10-11 10:56:41 +0800526 return ret;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800527
xuesong.jiangd91230d2021-10-20 15:51:10 +0800528error:
xuesong.jiangeb46f672021-11-19 19:05:56 +0800529 GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued error", buffer);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800530 ret = GST_FLOW_CUSTOM_ERROR_2;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800531 goto ret;
532flushing:
533 GST_DEBUG_OBJECT(sink, "flushing when buf:%p", buffer);
534 goto ret;
535ret:
536 GST_OBJECT_UNLOCK(vsink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800537 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800538}
539
xuesong.jiang50a0f932021-11-15 15:18:51 +0800540static gboolean gst_aml_video_sink_pad_event(GstPad *pad, GstObject *parent, GstEvent *event)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800541{
542 gboolean result = TRUE;
xuesong.jiang7c724a52021-10-22 17:18:58 +0800543 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(parent);
544 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800545
xuesong.jiangd91230d2021-10-20 15:51:10 +0800546 switch (GST_EVENT_TYPE(event))
547 {
548 case GST_EVENT_FLUSH_START:
549 {
550 GST_INFO_OBJECT(sink, "flush start");
551 GST_OBJECT_LOCK(sink);
552 sink_priv->is_flushing = TRUE;
553 GST_OBJECT_UNLOCK(sink);
554 break;
555 }
556 case GST_EVENT_FLUSH_STOP:
557 {
558 GST_INFO_OBJECT(sink, "flush stop");
xuesong.jiang1801e172021-10-11 10:56:41 +0800559
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800560 gst_wait_eos_signal(sink);
561
xuesong.jiangd91230d2021-10-20 15:51:10 +0800562 GST_OBJECT_LOCK(sink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800563 sink->queued = 0;
564 sink->dequeued = 0;
565 sink->rendered = 0;
566 sink_priv->got_eos = FALSE;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800567 sink_priv->is_flushing = FALSE;
568 GST_OBJECT_UNLOCK(sink);
569 break;
570 }
571 case GST_EVENT_SEGMENT:
572 {
573 GST_OBJECT_LOCK(sink);
574 gst_event_copy_segment(event, &sink_priv->segment);
575 GST_INFO_OBJECT(sink, "configured segment %" GST_SEGMENT_FORMAT, &sink_priv->segment);
576 //TODO set play rate to tunnel lib, 切换rate这部分是不是只需要audio那边set即可
577 GST_OBJECT_UNLOCK(sink);
578 break;
579 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800580 case GST_EVENT_EOS:
581 {
582 GST_OBJECT_LOCK(sink);
583 sink_priv->got_eos = TRUE;
584 GST_OBJECT_UNLOCK(sink);
585
586 gst_wait_eos_signal(sink);
587 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800588 default:
589 {
590 GST_DEBUG_OBJECT(sink, "pass to basesink");
xuesong.jiang7c724a52021-10-22 17:18:58 +0800591 return GST_BASE_SINK_CLASS(parent_class)->event((GstBaseSink *)sink, event);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800592 }
593 }
594 gst_event_unref(event);
595 return result;
xuesong.jiang1801e172021-10-11 10:56:41 +0800596}
597
598/* private interface definition */
xuesong.jiangd91230d2021-10-20 15:51:10 +0800599static void gst_aml_video_sink_reset_private(GstAmlVideoSink *sink)
xuesong.jiang1801e172021-10-11 10:56:41 +0800600{
xuesong.jiangd91230d2021-10-20 15:51:10 +0800601 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
602 memset(sink_priv, 0, sizeof(GstAmlVideoSinkPrivate));
603 sink_priv->render_device_name = RENDER_DEVICE_NAME;
604 sink_priv->use_dmabuf = USE_DMABUF;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800605 sink_priv->mediasync_instanceid = -1;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800606}
607
xuesong.jiang1700bab2021-11-17 17:11:11 +0800608void gst_render_msg_callback(void *userData, RenderMsgType type, void *msg)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800609{
xuesong.jiange90be372021-10-21 11:29:57 +0800610 GstAmlVideoSink *sink = (GstAmlVideoSink *)userData;
611 switch (type)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800612 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800613 case MSG_DISPLAYED_BUFFER:
614 {
615 GST_LOG_OBJECT(sink, "get message: MSG_DISPLAYED_BUFFER from tunnel lib");
616 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
617 RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
618 RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
619 GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
620 if (buffer)
621 {
622 sink->rendered++;
623 if ((sink_priv->got_eos || sink_priv->is_flushing) && sink->queued == sink->rendered)
624 {
625 gst_emit_eos_signal(sink);
626 }
627 }
628 else
629 {
630 GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_DISPLAYED_BUFFER");
631 }
632
633 GST_DEBUG_OBJECT(sink, "buf out:%p\n\
634 planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d\n\
635 pts:%lld, buf stat | queued:%d, dequeued:%d, rendered:%d",
636 buffer,
637 dmabuf->planeCnt, dmabuf->fd[0], dmabuf->fd[1],
638 buffer? GST_BUFFER_PTS(buffer):-1, sink->queued, sink->dequeued, sink->rendered);
639 break;
640 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800641 case MSG_RELEASE_BUFFER:
xuesong.jiangd91230d2021-10-20 15:51:10 +0800642 {
xuesong.jiang3e593432021-11-25 16:10:03 +0800643 GST_LOG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib");
xuesong.jiange90be372021-10-21 11:29:57 +0800644 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800645 RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
646 GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
xuesong.jiange90be372021-10-21 11:29:57 +0800647
648 if (buffer)
649 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800650 GST_DEBUG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib, buffer:%p, from pool:%p", buffer, buffer->pool);
xuesong.jiange90be372021-10-21 11:29:57 +0800651 gst_buffer_unref(buffer);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800652 sink->dequeued++;
xuesong.jiange90be372021-10-21 11:29:57 +0800653 }
654 else
655 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800656 GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_RELEASE_BUFFER");
xuesong.jiange90be372021-10-21 11:29:57 +0800657 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800658 render_free_render_buffer_wrap(sink_priv->render_device_handle, tunnel_lib_buf_wrap);
659 break;
660 }
661 case MSG_CONNECTED_FAIL:
662 {
663 GST_ERROR_OBJECT(sink, "tunnel lib: should not send message:%d", type);
664 break;
665 }
666 case MSG_DISCONNECTED_FAIL:
667 {
668 GST_ERROR_OBJECT(sink, "tunnel lib: should not send message:%d", type);
xuesong.jiange90be372021-10-21 11:29:57 +0800669 break;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800670 }
xuesong.jiange90be372021-10-21 11:29:57 +0800671 default:
672 {
673 GST_ERROR_OBJECT(sink, "tunnel lib: error message type");
674 }
675 }
676 return;
677}
678
xuesong.jiang50a0f932021-11-15 15:18:51 +0800679int gst_render_val_callback(void *userData, int key, void *value)
680{
681 GstAmlVideoSink *vsink = (GstAmlVideoSink *)userData;
682 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
xuesong.jiang32d78282021-11-18 19:24:15 +0800683 int *val = (int *)value;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800684 gint ret = 0;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800685 switch (key)
xuesong.jiang50a0f932021-11-15 15:18:51 +0800686 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800687 case KEY_MEDIASYNC_INSTANCE_ID:
xuesong.jiang50a0f932021-11-15 15:18:51 +0800688 {
xuesong.jiangd2619562021-12-23 16:38:50 +0800689 // break;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800690 if (gst_get_mediasync_instanceid(vsink))
691 {
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800692 *val = sink_priv->mediasync_instanceid;
693 GST_DEBUG_OBJECT(vsink, "get mediasync instance id:%d", *val);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800694 }
695 else
696 {
697 GST_ERROR_OBJECT(vsink, "can't get mediasync instance id");
698 ret = -1;
699 }
700 break;
701 }
702 case KEY_VIDEO_FORMAT:
703 {
xuesong.jiang32d78282021-11-18 19:24:15 +0800704 if(sink_priv->video_info.finfo != NULL)
705 {
706 *val = sink_priv->video_info.finfo->format;
707 GST_DEBUG_OBJECT(vsink, "get video format:%d", *val);
708 }
709 else
xuesong.jiang50a0f932021-11-15 15:18:51 +0800710 {
711 GST_ERROR_OBJECT(vsink, "get video format error");
xuesong.jiang32d78282021-11-18 19:24:15 +0800712 *val = GST_VIDEO_FORMAT_UNKNOWN;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800713 ret = -1;
714 }
715 break;
716 }
717 default:
718 {
719 GST_ERROR_OBJECT(vsink, "tunnel lib: error key type");
720 ret = -1;
721 }
722 }
723 return ret;
724}
725
xuesong.jiang7c724a52021-10-22 17:18:58 +0800726static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap)
xuesong.jiange90be372021-10-21 11:29:57 +0800727{
728 // only support dma buf
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800729 RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800730 GstMemory *dma_mem = NULL;
731 GstVideoMeta *vmeta = NULL;
xuesong.jiange90be372021-10-21 11:29:57 +0800732 guint n_mem = 0;
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800733 gboolean ret = TRUE;
xuesong.jiange90be372021-10-21 11:29:57 +0800734
xuesong.jiangeb46f672021-11-19 19:05:56 +0800735 if (gst_buf == NULL || tunnel_lib_buf_wrap == NULL || dmabuf == NULL)
xuesong.jiange90be372021-10-21 11:29:57 +0800736 {
737 GST_ERROR_OBJECT(vsink, "input params error");
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800738 ret = FALSE;
xuesong.jiange90be372021-10-21 11:29:57 +0800739 goto error;
740 }
xuesong.jiang3e593432021-11-25 16:10:03 +0800741 gst_buffer_ref(gst_buf);
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800742 n_mem = gst_buffer_n_memory(gst_buf);
743 vmeta = gst_buffer_get_video_meta (gst_buf);
744 if(vmeta == NULL)
745 {
746 GST_ERROR_OBJECT(vsink, "not found video meta info");
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800747 ret = FALSE;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800748 goto error;
749 }
750 if (n_mem > RENDER_MAX_PLANES || vmeta->n_planes > RENDER_MAX_PLANES || n_mem != vmeta->n_planes)
xuesong.jiange90be372021-10-21 11:29:57 +0800751 {
752 GST_ERROR_OBJECT(vsink, "too many memorys in gst buffer");
753 goto error;
754 }
xuesong.jiangeb46f672021-11-19 19:05:56 +0800755 GST_DEBUG_OBJECT(vsink, "dbg3-0, dmabuf:%p", dmabuf);
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800756
757 dmabuf->planeCnt = n_mem;
758 dmabuf->width = vmeta->width;
759 dmabuf->height = vmeta->height;
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800760
761 GST_DEBUG_OBJECT(vsink, "dbgjxs, vmeta->width:%d, dmabuf->width:%d", vmeta->width, dmabuf->width);
762
xuesong.jiang7c724a52021-10-22 17:18:58 +0800763 for (guint i = 0; i < n_mem; i++)
xuesong.jiange90be372021-10-21 11:29:57 +0800764 {
765 gint dmafd;
766 gsize size, offset, maxsize;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800767 dma_mem = gst_buffer_peek_memory(gst_buf, i);
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800768 guint mem_idx = 0;
769 guint length = 0;
770 gsize skip = 0;
771
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800772 if (!gst_is_dmabuf_memory(dma_mem))
xuesong.jiange90be372021-10-21 11:29:57 +0800773 {
774 GST_ERROR_OBJECT(vsink, "not support non-dma buf");
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800775 ret = FALSE;
xuesong.jiange90be372021-10-21 11:29:57 +0800776 goto error;
777 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800778 size = gst_memory_get_sizes(dma_mem, &offset, &maxsize);
xuesong.jiang16983c92021-12-30 10:57:17 +0800779 GST_LOG_OBJECT(vsink, "get memory size:%d, offeset:%d, maxsize:%d", size, offset, maxsize);
780
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800781 dmafd = gst_dmabuf_memory_get_fd(dma_mem);
782 dmabuf->handle[i] = 0;
783 dmabuf->fd[i] = dmafd;
784 dmabuf->size[i] = dma_mem->size;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800785 dmabuf->stride[i] = vmeta->stride[i];
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800786 if (gst_buffer_find_memory (gst_buf, vmeta->offset[i], 1, &mem_idx, &length, &skip) && mem_idx == i)
787 {
788 dmabuf->offset[i] = dma_mem->offset + skip;
789 GST_DEBUG_OBJECT(vsink, "get skip from buffer:%d, offset[%d]:%d", skip, i, dmabuf->offset[i]);
790 }
791 else
792 {
793 GST_ERROR_OBJECT(vsink, "get skip from buffer error");
794 ret = FALSE;
795 goto error;
796 }
797
798
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800799 GST_DEBUG_OBJECT(vsink, "dma buffer layer:%d, handle:%d, fd:%d, size:%d, offset:%d, stride:%d",
800 i, dmabuf->handle[i], dmabuf->fd[i], dmabuf->size[i], dmabuf->offset[i], dmabuf->stride[i]);
xuesong.jiange90be372021-10-21 11:29:57 +0800801 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800802 tunnel_lib_buf_wrap->flag = BUFFER_FLAG_EXTER_DMA_BUFFER;
xuesong.jiange90be372021-10-21 11:29:57 +0800803 tunnel_lib_buf_wrap->pts = GST_BUFFER_PTS(gst_buf);
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800804 tunnel_lib_buf_wrap->priv = (void *)gst_buf;
xuesong.jiang3e593432021-11-25 16:10:03 +0800805 GST_DEBUG_OBJECT(vsink, "set tunnel lib buf priv:%p from pool:%p", tunnel_lib_buf_wrap->priv, gst_buf->pool);
xuesong.jiangd2619562021-12-23 16:38:50 +0800806 GST_DEBUG_OBJECT(vsink, "dbg: buf in:%p, planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d",
807 tunnel_lib_buf_wrap->priv,
808 dmabuf->planeCnt,
809 dmabuf->fd[0],
810 dmabuf->fd[1]);
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800811
812 return ret;
xuesong.jiange90be372021-10-21 11:29:57 +0800813
814error:
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800815 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800816}
817
xuesong.jiang50a0f932021-11-15 15:18:51 +0800818static gboolean gst_get_mediasync_instanceid(GstAmlVideoSink *vsink)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800819{
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800820 GST_DEBUG_OBJECT(vsink, "trace in");
xuesong.jiang16983c92021-12-30 10:57:17 +0800821#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +0800822 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
823 GstElement *asink = gst_aml_video_sink_find_audio_sink(vsink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800824 if (!asink)
825 {
826 GST_DEBUG_OBJECT(vsink, "pipeline don't have audio sink element");
827 return FALSE;
828 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800829 GstClock *amlclock = gst_aml_hal_asink_get_clock((GstElement *)asink);
830 gboolean ret = TRUE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800831 if (amlclock)
832 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800833 sink_priv->mediasync_instanceid = gst_aml_clock_get_session_id(amlclock);
834 GST_DEBUG_OBJECT(vsink, "get mediasync instance id:%d, from aml audio clock:%p. in aml audio sink:%p", sink_priv->mediasync_instanceid, amlclock, vsink);
835 if (sink_priv->mediasync_instanceid == -1)
836 {
837 GST_ERROR_OBJECT(vsink, "audio sink: don't have valid mediasync instance id");
838 ret = FALSE;
839 }
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800840 }
841 else
842 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800843 GST_WARNING_OBJECT(vsink, "no clock: vmaster mode");
844 ret = FALSE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800845 }
xuesong.jiang192316f2021-10-27 14:51:56 +0800846 gst_object_unref(asink);
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800847#else
848 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
849 gboolean ret = TRUE;
850 FILE * fp;
851 fp = fopen("/data/MediaSyncId", "r");
852 if (fp == NULL) {
853 GST_ERROR_OBJECT(vsink, "could not open file:/data/MediaSyncId failed");
854 ret = FALSE;
855 } else {
xuesong.jiang16983c92021-12-30 10:57:17 +0800856 size_t read_size = 0;
857 read_size = fread(&sink_priv->mediasync_instanceid, sizeof(int), 1, fp);
858 if (read_size != sizeof(int))
859 {
860 GST_DEBUG_OBJECT(vsink, "get mediasync instance id read error");
861 }
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800862 fclose(fp);
863 GST_DEBUG_OBJECT(vsink, "get mediasync instance id:0x%x", sink_priv->mediasync_instanceid);
864 }
865#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +0800866 return ret;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800867}
868
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800869static void gst_emit_eos_signal(GstAmlVideoSink *vsink)
870{
871 GST_DEBUG_OBJECT(vsink, "emit eos signal");
872 g_mutex_lock(&vsink->eos_lock);
873 g_cond_signal (&vsink->eos_cond);
874 g_mutex_unlock(&vsink->eos_lock);
875}
876
877static void gst_wait_eos_signal(GstAmlVideoSink *vsink)
878{
879 GST_DEBUG_OBJECT(vsink, "waitting eos signal");
880 g_mutex_lock(&vsink->eos_lock);
881 g_cond_wait (&vsink->eos_cond, &vsink->eos_lock);
882 g_mutex_unlock(&vsink->eos_lock);
883 GST_DEBUG_OBJECT(vsink, "waitted eos signal");
884}
885
xuesong.jiang16983c92021-12-30 10:57:17 +0800886#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +0800887static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800888{
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800889 GST_DEBUG_OBJECT(sink, "trace in");
xuesong.jiang50a0f932021-11-15 15:18:51 +0800890 GstElement *audioSink = 0;
891 GstElement *pipeline = 0;
892 GstElement *element, *elementPrev = 0;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800893
xuesong.jiang50a0f932021-11-15 15:18:51 +0800894 element = GST_ELEMENT_CAST(sink);
895 do
896 {
897 if (elementPrev)
898 {
899 gst_object_unref(elementPrev);
900 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800901 //TODO use this func will ref elment,but when unref these element?
xuesong.jiang50a0f932021-11-15 15:18:51 +0800902 element = GST_ELEMENT_CAST(gst_element_get_parent(element));
903 if (element)
904 {
905 elementPrev = pipeline;
906 pipeline = element;
907 }
908 } while (element != 0);
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800909
xuesong.jiang50a0f932021-11-15 15:18:51 +0800910 if (pipeline)
911 {
912 GstIterator *iterElement = gst_bin_iterate_recurse(GST_BIN(pipeline));
913 if (iterElement)
914 {
915 GValue itemElement = G_VALUE_INIT;
916 while (gst_iterator_next(iterElement, &itemElement) == GST_ITERATOR_OK)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800917 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800918 element = (GstElement *)g_value_get_object(&itemElement);
919 if (element && !GST_IS_BIN(element))
920 {
921 int numSrcPads = 0;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800922
xuesong.jiang50a0f932021-11-15 15:18:51 +0800923 GstIterator *iterPad = gst_element_iterate_src_pads(element);
924 if (iterPad)
925 {
926 GValue itemPad = G_VALUE_INIT;
927 while (gst_iterator_next(iterPad, &itemPad) == GST_ITERATOR_OK)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800928 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800929 GstPad *pad = (GstPad *)g_value_get_object(&itemPad);
930 if (pad)
931 {
932 ++numSrcPads;
933 }
934 g_value_reset(&itemPad);
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800935 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800936 gst_iterator_free(iterPad);
937 }
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800938
xuesong.jiang50a0f932021-11-15 15:18:51 +0800939 if (numSrcPads == 0)
940 {
941 GstElementClass *ec = GST_ELEMENT_GET_CLASS(element);
942 if (ec)
943 {
944 const gchar *meta = gst_element_class_get_metadata(ec, GST_ELEMENT_METADATA_KLASS);
945 if (meta && strstr(meta, "Sink") && strstr(meta, "Audio"))
946 {
947 audioSink = (GstElement *)gst_object_ref(element);
948 gchar *name = gst_element_get_name(element);
949 if (name)
950 {
951 GST_DEBUG("detected audio sink: name (%s)", name);
952 g_free(name);
953 }
954 g_value_reset(&itemElement);
955 break;
956 }
957 }
958 }
959 }
960 g_value_reset(&itemElement);
961 }
962 gst_iterator_free(iterElement);
963 }
964
965 gst_object_unref(pipeline);
966 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800967 GST_DEBUG_OBJECT(sink, "trace out get audioSink:%p", audioSink);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800968 return audioSink;
969}
xuesong.jiang16983c92021-12-30 10:57:17 +0800970#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +0800971
972static gboolean gst_render_set_params(GstVideoSink *vsink)
973{
974 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
975 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
976 GstVideoInfo *video_info = &(sink_priv->video_info);
977
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800978 // RenderWindowSize window_size = {0, 0, video_info->width, video_info->height};
xuesong.jiang50a0f932021-11-15 15:18:51 +0800979 RenderFrameSize frame_size = {video_info->width, video_info->height};
xuesong.jiang32d78282021-11-18 19:24:15 +0800980 GstVideoFormat format = video_info->finfo? video_info->finfo->format : GST_VIDEO_FORMAT_UNKNOWN;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800981 // if (render_set(sink_priv->render_device_handle, KEY_WINDOW_SIZE, &window_size) == -1)
982 // {
983 // GST_ERROR_OBJECT(vsink, "tunnel lib: set window size error");
984 // return FALSE;
985 // }
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800986 if (render_set(sink_priv->render_device_handle, KEY_FRAME_SIZE, &frame_size) == -1)
xuesong.jiang50a0f932021-11-15 15:18:51 +0800987 {
988 GST_ERROR_OBJECT(vsink, "tunnel lib: set frame size error");
989 return FALSE;
990 }
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800991 if (render_set(sink_priv->render_device_handle, KEY_VIDEO_FORMAT, &format) == -1)
xuesong.jiang32d78282021-11-18 19:24:15 +0800992 {
993 GST_ERROR_OBJECT(vsink, "tunnel lib: set video format error");
994 return FALSE;
995 }
996
xuesong.jiang50a0f932021-11-15 15:18:51 +0800997 return TRUE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800998}
999
xuesong.jiang1801e172021-10-11 10:56:41 +08001000/* plugin init */
xuesong.jiangd91230d2021-10-20 15:51:10 +08001001static gboolean plugin_init(GstPlugin *plugin)
1002{
xuesong.jiang1700bab2021-11-17 17:11:11 +08001003 GST_DEBUG_CATEGORY_INIT(gst_aml_video_sink_debug, "amlvideosink", 0,
1004 " aml video sink");
xuesong.jiang1801e172021-10-11 10:56:41 +08001005
xuesong.jiangf0ebebe2021-12-24 09:41:15 +08001006 gint rank = 1;
1007 const char *rank_env = getenv ("GST_AML_VIDEO_SINK_RANK");
1008 if (rank_env) {
1009 rank = atoi(rank_env);
1010 }
1011
1012 return gst_element_register(plugin, "amlvideosink", rank,
xuesong.jiangd91230d2021-10-20 15:51:10 +08001013 GST_TYPE_AML_VIDEO_SINK);
xuesong.jiang1801e172021-10-11 10:56:41 +08001014}
1015
xuesong.jiang5c0d1b82021-11-16 19:30:56 +08001016#ifndef VERSION
1017#define VERSION "0.1.0"
1018#endif
1019#ifndef PACKAGE
1020#define PACKAGE "aml_package"
1021#endif
1022#ifndef PACKAGE_NAME
1023#define PACKAGE_NAME "aml_media"
1024#endif
1025#ifndef GST_PACKAGE_ORIGIN
1026#define GST_PACKAGE_ORIGIN "http://amlogic.com"
1027#endif
1028// GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, amlvideosink,
1029// "aml Video Sink", plugin_init, VERSION, "LGPL",
1030// "gst-plugin-video-sink", "")
1031GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1032 GST_VERSION_MINOR,
1033 amlvideosink,
1034 "Amlogic plugin for video decoding/rendering",
1035 plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)