blob: 9f0b7cf84bcba9e250b6bba4a1365b0b6708833e [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
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +080046#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); \
51 }
xuesong.jiang91391f52021-11-19 15:42:30 +080052#endif
53
54#ifdef GST_OBJECT_UNLOCK
55#undef GST_OBJECT_UNLOCK
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +080056#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); \
61 }
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.jiang7ec9f8f2022-03-14 15:03:04 +080077 PROP_AVSYNC_MODE,
xuesong.jiang62ed50e2022-04-13 16:55:47 +080078 PROP_VIDEO_FRAME_DROP_NUM,
xuesong.jiangd91230d2021-10-20 15:51:10 +080079};
80
xuesong.jiangfa8903d2022-02-11 15:13:05 +080081// #define AML_VIDEO_FORMATS \
82// "{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB, RGB, BGR, " \
83// "RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, " \
84// "YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }"
85#define AML_VIDEO_FORMATS "{ NV21 }"
86
xuesong.jiangd91230d2021-10-20 15:51:10 +080087#define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
xuesong.jiang4a832aa2022-01-06 16:44:26 +080088#define GST_USE_PLAYBIN 1
xuesong.jiange0c6c542022-04-11 16:10:23 +080089#define GST_DEFAULT_AVSYNC_MODE 1 // 0:v master, 1:a master
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +080090
xuesong.jiange0c6c542022-04-11 16:10:23 +080091#define RENDER_DEVICE_NAME "westeros"
xuesong.jiangd91230d2021-10-20 15:51:10 +080092#define USE_DMABUF TRUE
93
xuesong.jiange0c6c542022-04-11 16:10:23 +080094#define DRMBP_EXTRA_BUF_SZIE_FOR_DISPLAY 1
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +080095#define DRMBP_LIMIT_MAX_BUFSIZE_TO_BUFSIZE 1
96#define DRMBP_UNLIMIT_MAX_BUFSIZE 0
xuesong.jiangb3f0f152021-12-23 20:19:08 +080097
xuesong.jiangd91230d2021-10-20 15:51:10 +080098struct _GstAmlVideoSinkPrivate
99{
xuesong.jiangebd18352021-12-28 17:13:22 +0800100 GstBuffer *preroll_buffer;
xuesong.jiange90be372021-10-21 11:29:57 +0800101 gchar *render_device_name;
102 void *render_device_handle;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800103 GstVideoInfo video_info;
104 gboolean video_info_changed;
105 gboolean use_dmabuf;
106 gboolean is_flushing;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800107 gboolean got_eos;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800108 gint mediasync_instanceid;
xuesong.jiang7c724a52021-10-22 17:18:58 +0800109 GstSegment segment;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800110
xuesong.jiangd91230d2021-10-20 15:51:10 +0800111 /* property params */
112 gboolean fullscreen;
113 gboolean mute;
xuesong.jiang1801e172021-10-11 10:56:41 +0800114};
115
116static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE(
117 "sink", GST_PAD_SINK, GST_PAD_ALWAYS,
118 GST_STATIC_CAPS(
119 GST_VIDEO_CAPS_MAKE(AML_VIDEO_FORMATS) ";" GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
120 GST_CAPS_FEATURE_MEMORY_DMABUF, AML_VIDEO_FORMATS)));
121
122GST_DEBUG_CATEGORY(gst_aml_video_sink_debug);
123#define GST_CAT_DEFAULT gst_aml_video_sink_debug
124#define gst_aml_video_sink_parent_class parent_class
xuesong.jiang192316f2021-10-27 14:51:56 +0800125// #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 +0800126G_DEFINE_TYPE_WITH_CODE(GstAmlVideoSink, gst_aml_video_sink,
127 GST_TYPE_VIDEO_SINK, G_ADD_PRIVATE(GstAmlVideoSink));
128
129/* public interface define */
130static void gst_aml_video_sink_get_property(GObject *object, guint prop_id,
131 GValue *value, GParamSpec *pspec);
132static void gst_aml_video_sink_set_property(GObject *object, guint prop_id,
133 const GValue *value,
134 GParamSpec *pspec);
135static void gst_aml_video_sink_finalize(GObject *object);
136static GstStateChangeReturn
137gst_aml_video_sink_change_state(GstElement *element, GstStateChange transition);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800138static gboolean gst_aml_video_sink_propose_allocation(GstBaseSink *bsink, GstQuery *query);
xuesong.jiang1801e172021-10-11 10:56:41 +0800139static GstCaps *gst_aml_video_sink_get_caps(GstBaseSink *bsink,
140 GstCaps *filter);
141static gboolean gst_aml_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800142static gboolean gst_aml_video_sink_show_frame(GstVideoSink *bsink, GstBuffer *buffer);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800143static gboolean gst_aml_video_sink_pad_event(GstPad *pad, GstObject *parent, GstEvent *event);
xuesong.jiang1801e172021-10-11 10:56:41 +0800144
145/* private interface define */
146static void gst_aml_video_sink_reset_private(GstAmlVideoSink *sink);
xuesong.jiang1700bab2021-11-17 17:11:11 +0800147void gst_render_msg_callback(void *userData, RenderMsgType type, void *msg);
148int gst_render_val_callback(void *userData, int key, void *value);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800149static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800150static gboolean gst_get_mediasync_instanceid(GstAmlVideoSink *vsink);
xuesong.jiang16983c92021-12-30 10:57:17 +0800151#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +0800152static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink);
xuesong.jiang16983c92021-12-30 10:57:17 +0800153#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +0800154static gboolean gst_render_set_params(GstVideoSink *vsink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800155static void gst_emit_eos_signal(GstAmlVideoSink *vsink);
156static void gst_wait_eos_signal(GstAmlVideoSink *vsink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800157
158/* public interface definition */
xuesong.jiang7c724a52021-10-22 17:18:58 +0800159static void gst_aml_video_sink_class_init(GstAmlVideoSinkClass *klass)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800160{
161 GObjectClass *gobject_class;
162 GstElementClass *gstelement_class;
163 GstBaseSinkClass *gstbasesink_class;
164 GstVideoSinkClass *gstvideosink_class;
xuesong.jiang1801e172021-10-11 10:56:41 +0800165
xuesong.jiangd91230d2021-10-20 15:51:10 +0800166 gobject_class = (GObjectClass *)klass;
167 gstelement_class = (GstElementClass *)klass;
168 gstbasesink_class = (GstBaseSinkClass *)klass;
169 gstvideosink_class = (GstVideoSinkClass *)klass;
xuesong.jiang1801e172021-10-11 10:56:41 +0800170
xuesong.jiangd91230d2021-10-20 15:51:10 +0800171 gobject_class->set_property = gst_aml_video_sink_set_property;
172 gobject_class->get_property = gst_aml_video_sink_get_property;
173 gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_aml_video_sink_finalize);
xuesong.jiang1801e172021-10-11 10:56:41 +0800174
xuesong.jiangd91230d2021-10-20 15:51:10 +0800175 gst_element_class_add_static_pad_template(gstelement_class, &sink_template);
xuesong.jiang1801e172021-10-11 10:56:41 +0800176
xuesong.jiangd91230d2021-10-20 15:51:10 +0800177 gst_element_class_set_static_metadata(
178 gstelement_class, "aml video sink", "Sink/Video",
179 "Output to video tunnel lib",
180 "Xuesong.Jiang@amlogic.com<Xuesong.Jiang@amlogic.com>");
xuesong.jiang1801e172021-10-11 10:56:41 +0800181
xuesong.jiangd91230d2021-10-20 15:51:10 +0800182 gstelement_class->change_state =
183 GST_DEBUG_FUNCPTR(gst_aml_video_sink_change_state);
xuesong.jiang1801e172021-10-11 10:56:41 +0800184
xuesong.jiangd91230d2021-10-20 15:51:10 +0800185 gstbasesink_class->propose_allocation = GST_DEBUG_FUNCPTR(gst_aml_video_sink_propose_allocation);
186 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR(gst_aml_video_sink_get_caps);
187 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_aml_video_sink_set_caps);
xuesong.jiang1801e172021-10-11 10:56:41 +0800188
xuesong.jiangd91230d2021-10-20 15:51:10 +0800189 gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR(gst_aml_video_sink_show_frame);
xuesong.jiang1801e172021-10-11 10:56:41 +0800190
xuesong.jiangd91230d2021-10-20 15:51:10 +0800191 g_object_class_install_property(
192 gobject_class, PROP_FULLSCREEN,
193 g_param_spec_boolean("fullscreen", "Fullscreen",
194 "Whether the surface should be made fullscreen ",
195 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
xuesong.jiang1801e172021-10-11 10:56:41 +0800196
xuesong.jiangd91230d2021-10-20 15:51:10 +0800197 g_object_class_install_property(
198 gobject_class, PROP_SETMUTE,
199 g_param_spec_boolean("set mute", "set mute params",
200 "Whether set screen mute ",
201 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800202
203 g_object_class_install_property(
204 G_OBJECT_CLASS(klass), PROP_AVSYNC_MODE,
205 g_param_spec_int("avsync-mode", "avsync mode",
206 "Vmaster(0) Amaster(1) PCRmaster(2) IPTV(3) FreeRun(4)",
207 G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE));
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800208
209 g_object_class_install_property (
210 G_OBJECT_CLASS (klass), PROP_VIDEO_FRAME_DROP_NUM,
211 g_param_spec_int ("frames-dropped", "frames-dropped",
212 "number of dropped frames",
213 0, G_MAXINT32, 0, G_PARAM_READABLE));
xuesong.jiang1801e172021-10-11 10:56:41 +0800214}
215
xuesong.jiangd91230d2021-10-20 15:51:10 +0800216static void gst_aml_video_sink_init(GstAmlVideoSink *sink)
217{
218 GstBaseSink *basesink = (GstBaseSink *)sink;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800219
220 /* init eos detect */
221 sink->queued = 0;
222 sink->dequeued = 0;
223 sink->rendered = 0;
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800224 sink->droped = 0;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800225 sink->avsync_mode = GST_DEFAULT_AVSYNC_MODE;
226 g_mutex_init(&sink->eos_lock);
227 g_cond_init(&sink->eos_cond);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800228
xuesong.jiangd91230d2021-10-20 15:51:10 +0800229 gst_pad_set_event_function(basesink->sinkpad, gst_aml_video_sink_pad_event);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800230
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800231 GST_AML_VIDEO_SINK_GET_PRIVATE(sink) = malloc(sizeof(GstAmlVideoSinkPrivate));
xuesong.jiangd91230d2021-10-20 15:51:10 +0800232 gst_aml_video_sink_reset_private(sink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800233
xuesong.jiangd2619562021-12-23 16:38:50 +0800234 gst_base_sink_set_sync(basesink, FALSE);
xuesong.jiang1801e172021-10-11 10:56:41 +0800235}
236
237static void gst_aml_video_sink_get_property(GObject *object, guint prop_id,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800238 GValue *value, GParamSpec *pspec)
239{
240 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
241 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800242
xuesong.jiangd91230d2021-10-20 15:51:10 +0800243 switch (prop_id)
244 {
245 case PROP_FULLSCREEN:
246 GST_OBJECT_LOCK(sink);
247 g_value_set_boolean(value, sink_priv->fullscreen);
248 GST_OBJECT_UNLOCK(sink);
249 break;
250 case PROP_SETMUTE:
251 GST_OBJECT_LOCK(sink);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800252 g_value_set_boolean(value, sink_priv->mute);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800253 GST_OBJECT_UNLOCK(sink);
254 break;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800255 case PROP_AVSYNC_MODE:
256 GST_OBJECT_LOCK(sink);
257 g_value_set_boolean(value, sink->avsync_mode);
258 GST_OBJECT_UNLOCK(sink);
259 break;
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800260 case PROP_VIDEO_FRAME_DROP_NUM:
261 GST_OBJECT_LOCK(sink);
262 g_value_set_int(value, sink->droped);
263 GST_OBJECT_UNLOCK(sink);
264 break;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800265 default:
266 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
267 break;
268 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800269}
270
271static void gst_aml_video_sink_set_property(GObject *object, guint prop_id,
272 const GValue *value,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800273 GParamSpec *pspec)
274{
275 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
276 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800277
xuesong.jiangd91230d2021-10-20 15:51:10 +0800278 switch (prop_id)
279 {
280 case PROP_FULLSCREEN:
281 GST_OBJECT_LOCK(sink);
282 gboolean is_fullscreen = g_value_get_boolean(value);
xuesong.jiange90be372021-10-21 11:29:57 +0800283 if (sink_priv->fullscreen != is_fullscreen)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800284 {
285 sink_priv->fullscreen = is_fullscreen;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800286 // TODO set full screen to tunnel lib
xuesong.jiangd91230d2021-10-20 15:51:10 +0800287 }
288 GST_OBJECT_UNLOCK(sink);
289 break;
290 case PROP_SETMUTE:
291 GST_OBJECT_LOCK(sink);
292 gboolean is_mute = g_value_get_boolean(value);
xuesong.jiange90be372021-10-21 11:29:57 +0800293 if (sink_priv->mute != is_mute)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800294 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800295 sink_priv->mute = is_mute;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800296 // TODO set full screen to tunnel lib
297 }
298 GST_OBJECT_UNLOCK(sink);
299 break;
300 case PROP_AVSYNC_MODE:
301 GST_OBJECT_LOCK(sink);
302 gint mode = g_value_get_int(value);
303 if (mode >= 0)
304 {
305 sink->avsync_mode = mode;
306 GST_WARNING("AV sync mode %d", mode);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800307 }
308 GST_OBJECT_UNLOCK(sink);
309 break;
310 default:
311 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
312 break;
313 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800314}
315
xuesong.jiangd91230d2021-10-20 15:51:10 +0800316static void gst_aml_video_sink_finalize(GObject *object)
317{
318 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
xuesong.jiang1801e172021-10-11 10:56:41 +0800319
xuesong.jiangd91230d2021-10-20 15:51:10 +0800320 GST_DEBUG_OBJECT(sink, "Finalizing aml video sink..");
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800321
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800322 g_mutex_clear(&sink->eos_lock);
323 g_cond_clear(&sink->eos_cond);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800324
xuesong.jiangd91230d2021-10-20 15:51:10 +0800325 gst_aml_video_sink_reset_private(sink);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800326 if (GST_AML_VIDEO_SINK_GET_PRIVATE(sink))
xuesong.jiang5c0d1b82021-11-16 19:30:56 +0800327 free(GST_AML_VIDEO_SINK_GET_PRIVATE(sink));
xuesong.jiangd91230d2021-10-20 15:51:10 +0800328 G_OBJECT_CLASS(parent_class)->finalize(object);
xuesong.jiang1801e172021-10-11 10:56:41 +0800329}
330
331static GstStateChangeReturn
332gst_aml_video_sink_change_state(GstElement *element,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800333 GstStateChange transition)
334{
335 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(element);
336 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800337 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
xuesong.jiang32d78282021-11-18 19:24:15 +0800338 GST_DEBUG_OBJECT(sink, "trace in");
xuesong.jiang1801e172021-10-11 10:56:41 +0800339
xuesong.jiangd91230d2021-10-20 15:51:10 +0800340 GST_OBJECT_LOCK(sink);
341 switch (transition)
342 {
343 case GST_STATE_CHANGE_NULL_TO_READY:
344 {
345 sink_priv->render_device_handle = render_open(sink_priv->render_device_name);
xuesong.jiange90be372021-10-21 11:29:57 +0800346 if (sink_priv->render_device_handle == NULL)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800347 {
348 GST_ERROR_OBJECT(sink, "render lib: open device fail");
349 goto error;
350 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800351 RenderCallback cb = {gst_render_msg_callback, gst_render_val_callback};
352 render_set_callback(sink_priv->render_device_handle, &cb);
353 render_set_user_data(sink_priv->render_device_handle, sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800354
xuesong.jiangd91230d2021-10-20 15:51:10 +0800355 break;
356 }
357 case GST_STATE_CHANGE_READY_TO_PAUSED:
358 {
xuesong.jiang1700bab2021-11-17 17:11:11 +0800359 if (render_connect(sink_priv->render_device_handle) == -1)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800360 {
361 GST_ERROR_OBJECT(sink, "render lib connect device fail");
362 goto error;
363 }
364 break;
365 }
366 default:
367 break;
368 }
369 GST_OBJECT_UNLOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800370
xuesong.jiang1700bab2021-11-17 17:11:11 +0800371 GST_LOG_OBJECT(sink, "amlvideosink deal state change ok, goto basesink state change");
xuesong.jiangd91230d2021-10-20 15:51:10 +0800372 ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
373
374 GST_OBJECT_LOCK(sink);
375 if (ret == GST_STATE_CHANGE_FAILURE)
376 goto error;
377
378 switch (transition)
379 {
380 case GST_STATE_CHANGE_PAUSED_TO_READY:
381 {
382 render_disconnect(sink_priv->render_device_handle);
383 break;
384 }
385 case GST_STATE_CHANGE_READY_TO_NULL:
386 {
xuesong.jiange90be372021-10-21 11:29:57 +0800387 if (sink_priv->render_device_handle)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800388 {
389 render_close(sink_priv->render_device_handle);
390 }
391 gst_aml_video_sink_reset_private(sink);
392
393 break;
394 }
395 default:
396 break;
397 }
398 GST_OBJECT_UNLOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800399 return ret;
400
xuesong.jiangd91230d2021-10-20 15:51:10 +0800401error:
402 GST_OBJECT_UNLOCK(sink);
403 ret = GST_STATE_CHANGE_FAILURE;
404 return ret;
405}
xuesong.jiang1801e172021-10-11 10:56:41 +0800406
xuesong.jiangd91230d2021-10-20 15:51:10 +0800407static gboolean gst_aml_video_sink_propose_allocation(GstBaseSink *bsink, GstQuery *query)
408{
xuesong.jiangeb46f672021-11-19 19:05:56 +0800409 GST_DEBUG_OBJECT(bsink, "trace in");
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800410 // TODO only implement dma case
xuesong.jiangd91230d2021-10-20 15:51:10 +0800411 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(bsink);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800412 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
413
xuesong.jiangd91230d2021-10-20 15:51:10 +0800414 GstCaps *caps;
415 GstBufferPool *pool = NULL;
416 gboolean need_pool;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800417
418 gst_query_parse_allocation(query, &caps, &need_pool);
xuesong.jiangeb46f672021-11-19 19:05:56 +0800419 GST_DEBUG_OBJECT(bsink, "jxsaaa need_pool:%d", need_pool);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800420
421 if (need_pool)
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800422 // TODO 没有考虑secure场景
xuesong.jiang7c724a52021-10-22 17:18:58 +0800423 pool = gst_drm_bufferpool_new(FALSE, GST_DRM_BUFFERPOOL_TYPE_VIDEO_PLANE);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800424
xuesong.jiangb3f0f152021-12-23 20:19:08 +0800425 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 +0800426 if (pool)
427 g_object_unref(pool);
428
429 gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
430
431 return TRUE;
xuesong.jiang1801e172021-10-11 10:56:41 +0800432}
433
434static GstCaps *gst_aml_video_sink_get_caps(GstBaseSink *bsink,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800435 GstCaps *filter)
436{
437 GstAmlVideoSink *sink;
438 GstCaps *caps;
xuesong.jiang1801e172021-10-11 10:56:41 +0800439
xuesong.jiangd91230d2021-10-20 15:51:10 +0800440 sink = GST_AML_VIDEO_SINK(bsink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800441
xuesong.jiangd91230d2021-10-20 15:51:10 +0800442 caps = gst_pad_get_pad_template_caps(GST_VIDEO_SINK_PAD(sink));
443 caps = gst_caps_make_writable(caps);
444 // TODO 这里是需要从template直接取出支持的caps还是要通过tunnel lib拿到caps?
xuesong.jiang1801e172021-10-11 10:56:41 +0800445
xuesong.jiangd91230d2021-10-20 15:51:10 +0800446 if (filter)
447 {
448 GstCaps *intersection;
xuesong.jiang1801e172021-10-11 10:56:41 +0800449
xuesong.jiangd91230d2021-10-20 15:51:10 +0800450 intersection =
451 gst_caps_intersect_full(filter, caps, GST_CAPS_INTERSECT_FIRST);
452 gst_caps_unref(caps);
453 caps = intersection;
454 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800455
xuesong.jiangd91230d2021-10-20 15:51:10 +0800456 return caps;
xuesong.jiang1801e172021-10-11 10:56:41 +0800457}
458
xuesong.jiangd91230d2021-10-20 15:51:10 +0800459static gboolean gst_aml_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps)
460{
461 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(bsink);
462 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800463 // gboolean use_dmabuf;
xuesong.jiang91391f52021-11-19 15:42:30 +0800464 gboolean ret = TRUE;
xuesong.jiang1801e172021-10-11 10:56:41 +0800465
xuesong.jiangd91230d2021-10-20 15:51:10 +0800466 GST_OBJECT_LOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800467
xuesong.jiangd91230d2021-10-20 15:51:10 +0800468 GST_DEBUG_OBJECT(sink, "set caps %" GST_PTR_FORMAT, caps);
xuesong.jiangeb46f672021-11-19 19:05:56 +0800469 // use_dmabuf = gst_caps_features_contains(gst_caps_get_features(caps, 0), GST_CAPS_FEATURE_MEMORY_DMABUF);
470 // if (use_dmabuf == FALSE)
471 // {
472 // GST_ERROR_OBJECT(sink, "not support non dma buffer case");
473 // ret = FALSE;
474 // goto done;
475 // }
xuesong.jiang1801e172021-10-11 10:56:41 +0800476
xuesong.jiangd91230d2021-10-20 15:51:10 +0800477 /* extract info from caps */
478 if (!gst_video_info_from_caps(&sink_priv->video_info, caps))
479 {
480 GST_ERROR_OBJECT(sink, "can't get video info from caps");
xuesong.jiang91391f52021-11-19 15:42:30 +0800481 ret = FALSE;
482 goto done;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800483 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800484
xuesong.jiangd91230d2021-10-20 15:51:10 +0800485 sink_priv->video_info_changed = TRUE;
486
xuesong.jiang91391f52021-11-19 15:42:30 +0800487done:
xuesong.jiangd91230d2021-10-20 15:51:10 +0800488 GST_OBJECT_UNLOCK(sink);
xuesong.jiang91391f52021-11-19 15:42:30 +0800489 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800490}
491
xuesong.jiange90be372021-10-21 11:29:57 +0800492static GstFlowReturn gst_aml_video_sink_show_frame(GstVideoSink *vsink, GstBuffer *buffer)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800493{
xuesong.jiang7c724a52021-10-22 17:18:58 +0800494 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800495 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
496 GstFlowReturn ret = GST_FLOW_OK;
497 RenderBuffer *tunnel_lib_buf_wrap = NULL;
xuesong.jiang1801e172021-10-11 10:56:41 +0800498
xuesong.jiangd91230d2021-10-20 15:51:10 +0800499 GST_OBJECT_LOCK(vsink);
xuesong.jiangebd18352021-12-28 17:13:22 +0800500 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 +0800501
xuesong.jiange90be372021-10-21 11:29:57 +0800502 if (!sink_priv->render_device_handle)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800503 {
504 GST_ERROR_OBJECT(sink, "flow error, render_device_handle == NULL");
505 goto error;
506 }
507
xuesong.jiangebd18352021-12-28 17:13:22 +0800508 if (sink_priv->preroll_buffer && sink_priv->preroll_buffer == buffer)
509 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800510 GST_LOG_OBJECT(sink, "get preroll buffer:%p 2nd time, goto ret", buffer);
xuesong.jiangebd18352021-12-28 17:13:22 +0800511 sink_priv->preroll_buffer = NULL;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800512 goto ret;
xuesong.jiangebd18352021-12-28 17:13:22 +0800513 }
514 if (G_UNLIKELY(((GstBaseSink *)sink)->need_preroll))
515 {
516 GST_LOG_OBJECT(sink, "get preroll buffer 1st time, buf:%p", buffer);
517 sink_priv->preroll_buffer = buffer;
518 }
519
xuesong.jiangd91230d2021-10-20 15:51:10 +0800520 // TODO should call tunnel lib flush func
521 if (sink_priv->is_flushing)
522 {
523 gst_buffer_unref(buffer);
xuesong.jiange90be372021-10-21 11:29:57 +0800524 if (!render_flush(sink_priv->render_device_handle))
xuesong.jiangd91230d2021-10-20 15:51:10 +0800525 {
526 GST_ERROR_OBJECT(sink, "render lib: flush error");
527 goto error;
528 }
529 GST_DEBUG_OBJECT(sink, "in flushing flow, release the buffer directly");
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800530 goto flushing;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800531 }
532
533 if (sink_priv->video_info_changed)
534 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800535 if (gst_render_set_params(vsink) == FALSE)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800536 {
537 GST_ERROR_OBJECT(sink, "render lib: set params fail");
538 goto error;
539 }
540 sink_priv->video_info_changed = FALSE;
541 }
542
xuesong.jiang50a0f932021-11-15 15:18:51 +0800543 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 +0800544 if (!tunnel_lib_buf_wrap)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800545 {
546 GST_ERROR_OBJECT(sink, "render lib: alloc buffer wrap fail");
547 goto error;
548 }
xuesong.jiange90be372021-10-21 11:29:57 +0800549 if (!gst_aml_video_sink_tunnel_buf(sink, buffer, tunnel_lib_buf_wrap))
550 {
551 GST_ERROR_OBJECT(sink, "construc render buffer fail");
552 goto error;
553 }
554
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800555 GST_OBJECT_UNLOCK(vsink);
556
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800557 if (render_display_frame(sink_priv->render_device_handle, tunnel_lib_buf_wrap) == -1)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800558 {
559 GST_ERROR_OBJECT(sink, "render lib: display frame fail");
560 goto error;
561 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800562
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800563 sink->queued++;
xuesong.jiangeb46f672021-11-19 19:05:56 +0800564 GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued ok", buffer);
xuesong.jiang1801e172021-10-11 10:56:41 +0800565 return ret;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800566
xuesong.jiangd91230d2021-10-20 15:51:10 +0800567error:
xuesong.jiangeb46f672021-11-19 19:05:56 +0800568 GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued error", buffer);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800569 ret = GST_FLOW_CUSTOM_ERROR_2;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800570 goto ret;
571flushing:
572 GST_DEBUG_OBJECT(sink, "flushing when buf:%p", buffer);
573 goto ret;
574ret:
575 GST_OBJECT_UNLOCK(vsink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800576 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800577}
578
xuesong.jiang50a0f932021-11-15 15:18:51 +0800579static gboolean gst_aml_video_sink_pad_event(GstPad *pad, GstObject *parent, GstEvent *event)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800580{
581 gboolean result = TRUE;
xuesong.jiang7c724a52021-10-22 17:18:58 +0800582 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(parent);
583 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800584
xuesong.jiangd91230d2021-10-20 15:51:10 +0800585 switch (GST_EVENT_TYPE(event))
586 {
587 case GST_EVENT_FLUSH_START:
588 {
589 GST_INFO_OBJECT(sink, "flush start");
590 GST_OBJECT_LOCK(sink);
591 sink_priv->is_flushing = TRUE;
592 GST_OBJECT_UNLOCK(sink);
593 break;
594 }
595 case GST_EVENT_FLUSH_STOP:
596 {
597 GST_INFO_OBJECT(sink, "flush stop");
xuesong.jiang1801e172021-10-11 10:56:41 +0800598
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800599 gst_wait_eos_signal(sink);
600
xuesong.jiangd91230d2021-10-20 15:51:10 +0800601 GST_OBJECT_LOCK(sink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800602 sink->queued = 0;
603 sink->dequeued = 0;
604 sink->rendered = 0;
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800605 sink->droped = 0;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800606 sink_priv->got_eos = FALSE;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800607 sink_priv->is_flushing = FALSE;
608 GST_OBJECT_UNLOCK(sink);
609 break;
610 }
611 case GST_EVENT_SEGMENT:
612 {
613 GST_OBJECT_LOCK(sink);
614 gst_event_copy_segment(event, &sink_priv->segment);
615 GST_INFO_OBJECT(sink, "configured segment %" GST_SEGMENT_FORMAT, &sink_priv->segment);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800616 // TODO set play rate to tunnel lib, 切换rate这部分是不是只需要audio那边set即可
xuesong.jiangd91230d2021-10-20 15:51:10 +0800617 GST_OBJECT_UNLOCK(sink);
618 break;
619 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800620 case GST_EVENT_EOS:
621 {
622 GST_OBJECT_LOCK(sink);
623 sink_priv->got_eos = TRUE;
624 GST_OBJECT_UNLOCK(sink);
625
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800626 if (sink->queued > sink->rendered + sink->droped)
627 {
628 GST_DEBUG_OBJECCT(sink, "need waitting display render all buf");
629 gst_wait_eos_signal(sink);
630 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800631 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800632 default:
633 {
634 GST_DEBUG_OBJECT(sink, "pass to basesink");
xuesong.jiang7c724a52021-10-22 17:18:58 +0800635 return GST_BASE_SINK_CLASS(parent_class)->event((GstBaseSink *)sink, event);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800636 }
637 }
638 gst_event_unref(event);
639 return result;
xuesong.jiang1801e172021-10-11 10:56:41 +0800640}
641
642/* private interface definition */
xuesong.jiangd91230d2021-10-20 15:51:10 +0800643static void gst_aml_video_sink_reset_private(GstAmlVideoSink *sink)
xuesong.jiang1801e172021-10-11 10:56:41 +0800644{
xuesong.jiangd91230d2021-10-20 15:51:10 +0800645 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
646 memset(sink_priv, 0, sizeof(GstAmlVideoSinkPrivate));
647 sink_priv->render_device_name = RENDER_DEVICE_NAME;
648 sink_priv->use_dmabuf = USE_DMABUF;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800649 sink_priv->mediasync_instanceid = -1;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800650}
651
xuesong.jiang1700bab2021-11-17 17:11:11 +0800652void gst_render_msg_callback(void *userData, RenderMsgType type, void *msg)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800653{
xuesong.jiange90be372021-10-21 11:29:57 +0800654 GstAmlVideoSink *sink = (GstAmlVideoSink *)userData;
655 switch (type)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800656 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800657 case MSG_DISPLAYED_BUFFER:
658 {
659 GST_LOG_OBJECT(sink, "get message: MSG_DISPLAYED_BUFFER from tunnel lib");
660 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
661 RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
662 RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
663 GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
664 if (buffer)
665 {
666 sink->rendered++;
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800667 if ((sink_priv->got_eos || sink_priv->is_flushing) && sink->queued == sink->rendered + sink->droped)
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800668 {
669 gst_emit_eos_signal(sink);
670 }
671 }
672 else
673 {
674 GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_DISPLAYED_BUFFER");
675 }
676
677 GST_DEBUG_OBJECT(sink, "buf out:%p\n\
678 planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d\n\
679 pts:%lld, buf stat | queued:%d, dequeued:%d, rendered:%d",
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800680 buffer,
681 dmabuf->planeCnt, dmabuf->fd[0], dmabuf->fd[1],
682 buffer ? GST_BUFFER_PTS(buffer) : -1, sink->queued, sink->dequeued, sink->rendered);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800683 break;
684 }
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800685 case MSG_DROPED_BUFFER:
686 {
687 GST_LOG_OBJECT(sink, "get message: MSG_DROPED_BUFFER from tunnel lib");
688 sink->droped++;
689 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800690 case MSG_RELEASE_BUFFER:
xuesong.jiangd91230d2021-10-20 15:51:10 +0800691 {
xuesong.jiang3e593432021-11-25 16:10:03 +0800692 GST_LOG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib");
xuesong.jiange90be372021-10-21 11:29:57 +0800693 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800694 RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
695 GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
xuesong.jiange90be372021-10-21 11:29:57 +0800696
697 if (buffer)
698 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800699 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 +0800700 gst_buffer_unref(buffer);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800701 sink->dequeued++;
xuesong.jiange90be372021-10-21 11:29:57 +0800702 }
703 else
704 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800705 GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_RELEASE_BUFFER");
xuesong.jiange90be372021-10-21 11:29:57 +0800706 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800707 render_free_render_buffer_wrap(sink_priv->render_device_handle, tunnel_lib_buf_wrap);
708 break;
709 }
710 case MSG_CONNECTED_FAIL:
711 {
712 GST_ERROR_OBJECT(sink, "tunnel lib: should not send message:%d", type);
713 break;
714 }
715 case MSG_DISCONNECTED_FAIL:
716 {
717 GST_ERROR_OBJECT(sink, "tunnel lib: should not send message:%d", type);
xuesong.jiange90be372021-10-21 11:29:57 +0800718 break;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800719 }
xuesong.jiange90be372021-10-21 11:29:57 +0800720 default:
721 {
722 GST_ERROR_OBJECT(sink, "tunnel lib: error message type");
723 }
724 }
725 return;
726}
727
xuesong.jiang50a0f932021-11-15 15:18:51 +0800728int gst_render_val_callback(void *userData, int key, void *value)
729{
730 GstAmlVideoSink *vsink = (GstAmlVideoSink *)userData;
731 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
xuesong.jiang32d78282021-11-18 19:24:15 +0800732 int *val = (int *)value;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800733 gint ret = 0;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800734 switch (key)
xuesong.jiang50a0f932021-11-15 15:18:51 +0800735 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800736 case KEY_MEDIASYNC_INSTANCE_ID:
xuesong.jiang50a0f932021-11-15 15:18:51 +0800737 {
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800738 if (render_set(sink_priv->render_device_handle, KEY_MEDIASYNC_SYNC_MODE, (void *)&vsink->avsync_mode) == -1)
739 {
740 GST_ERROR_OBJECT(vsink, "tunnel lib: set syncmode error");
741 ret = -1;
742 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800743 if (gst_get_mediasync_instanceid(vsink))
744 {
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800745 *val = sink_priv->mediasync_instanceid;
746 GST_DEBUG_OBJECT(vsink, "get mediasync instance id:%d", *val);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800747 }
748 else
749 {
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800750 GST_ERROR_OBJECT(vsink, "can't get mediasync instance id, use vmaster");
xuesong.jiang50a0f932021-11-15 15:18:51 +0800751 ret = -1;
752 }
753 break;
754 }
755 case KEY_VIDEO_FORMAT:
756 {
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800757 if (sink_priv->video_info.finfo != NULL)
xuesong.jiang32d78282021-11-18 19:24:15 +0800758 {
759 *val = sink_priv->video_info.finfo->format;
760 GST_DEBUG_OBJECT(vsink, "get video format:%d", *val);
761 }
762 else
xuesong.jiang50a0f932021-11-15 15:18:51 +0800763 {
764 GST_ERROR_OBJECT(vsink, "get video format error");
xuesong.jiang32d78282021-11-18 19:24:15 +0800765 *val = GST_VIDEO_FORMAT_UNKNOWN;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800766 ret = -1;
767 }
768 break;
769 }
770 default:
771 {
772 GST_ERROR_OBJECT(vsink, "tunnel lib: error key type");
773 ret = -1;
774 }
775 }
776 return ret;
777}
778
xuesong.jiang7c724a52021-10-22 17:18:58 +0800779static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap)
xuesong.jiange90be372021-10-21 11:29:57 +0800780{
781 // only support dma buf
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800782 RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800783 GstMemory *dma_mem = NULL;
784 GstVideoMeta *vmeta = NULL;
xuesong.jiange90be372021-10-21 11:29:57 +0800785 guint n_mem = 0;
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800786 gboolean ret = TRUE;
xuesong.jiange90be372021-10-21 11:29:57 +0800787
xuesong.jiangeb46f672021-11-19 19:05:56 +0800788 if (gst_buf == NULL || tunnel_lib_buf_wrap == NULL || dmabuf == NULL)
xuesong.jiange90be372021-10-21 11:29:57 +0800789 {
790 GST_ERROR_OBJECT(vsink, "input params error");
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800791 ret = FALSE;
xuesong.jiange90be372021-10-21 11:29:57 +0800792 goto error;
793 }
xuesong.jiang3e593432021-11-25 16:10:03 +0800794 gst_buffer_ref(gst_buf);
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800795 n_mem = gst_buffer_n_memory(gst_buf);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800796 vmeta = gst_buffer_get_video_meta(gst_buf);
797 if (vmeta == NULL)
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800798 {
799 GST_ERROR_OBJECT(vsink, "not found video meta info");
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800800 ret = FALSE;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800801 goto error;
802 }
803 if (n_mem > RENDER_MAX_PLANES || vmeta->n_planes > RENDER_MAX_PLANES || n_mem != vmeta->n_planes)
xuesong.jiange90be372021-10-21 11:29:57 +0800804 {
805 GST_ERROR_OBJECT(vsink, "too many memorys in gst buffer");
806 goto error;
807 }
xuesong.jiangeb46f672021-11-19 19:05:56 +0800808 GST_DEBUG_OBJECT(vsink, "dbg3-0, dmabuf:%p", dmabuf);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800809
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800810 dmabuf->planeCnt = n_mem;
811 dmabuf->width = vmeta->width;
812 dmabuf->height = vmeta->height;
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800813
814 GST_DEBUG_OBJECT(vsink, "dbgjxs, vmeta->width:%d, dmabuf->width:%d", vmeta->width, dmabuf->width);
815
xuesong.jiang7c724a52021-10-22 17:18:58 +0800816 for (guint i = 0; i < n_mem; i++)
xuesong.jiange90be372021-10-21 11:29:57 +0800817 {
818 gint dmafd;
819 gsize size, offset, maxsize;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800820 dma_mem = gst_buffer_peek_memory(gst_buf, i);
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800821 guint mem_idx = 0;
822 guint length = 0;
823 gsize skip = 0;
824
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800825 if (!gst_is_dmabuf_memory(dma_mem))
xuesong.jiange90be372021-10-21 11:29:57 +0800826 {
827 GST_ERROR_OBJECT(vsink, "not support non-dma buf");
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800828 ret = FALSE;
xuesong.jiange90be372021-10-21 11:29:57 +0800829 goto error;
830 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800831 size = gst_memory_get_sizes(dma_mem, &offset, &maxsize);
xuesong.jiang16983c92021-12-30 10:57:17 +0800832 GST_LOG_OBJECT(vsink, "get memory size:%d, offeset:%d, maxsize:%d", size, offset, maxsize);
833
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800834 dmafd = gst_dmabuf_memory_get_fd(dma_mem);
835 dmabuf->handle[i] = 0;
836 dmabuf->fd[i] = dmafd;
837 dmabuf->size[i] = dma_mem->size;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800838 dmabuf->stride[i] = vmeta->stride[i];
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800839 if (gst_buffer_find_memory(gst_buf, vmeta->offset[i], 1, &mem_idx, &length, &skip) && mem_idx == i)
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800840 {
841 dmabuf->offset[i] = dma_mem->offset + skip;
842 GST_DEBUG_OBJECT(vsink, "get skip from buffer:%d, offset[%d]:%d", skip, i, dmabuf->offset[i]);
843 }
844 else
845 {
846 GST_ERROR_OBJECT(vsink, "get skip from buffer error");
847 ret = FALSE;
848 goto error;
849 }
850
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800851 GST_DEBUG_OBJECT(vsink, "dma buffer layer:%d, handle:%d, fd:%d, size:%d, offset:%d, stride:%d",
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800852 i, dmabuf->handle[i], dmabuf->fd[i], dmabuf->size[i], dmabuf->offset[i], dmabuf->stride[i]);
xuesong.jiange90be372021-10-21 11:29:57 +0800853 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800854 tunnel_lib_buf_wrap->flag = BUFFER_FLAG_EXTER_DMA_BUFFER;
xuesong.jiange90be372021-10-21 11:29:57 +0800855 tunnel_lib_buf_wrap->pts = GST_BUFFER_PTS(gst_buf);
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800856 tunnel_lib_buf_wrap->priv = (void *)gst_buf;
xuesong.jiang3e593432021-11-25 16:10:03 +0800857 GST_DEBUG_OBJECT(vsink, "set tunnel lib buf priv:%p from pool:%p", tunnel_lib_buf_wrap->priv, gst_buf->pool);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800858 GST_DEBUG_OBJECT(vsink, "dbg: buf in:%p, planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d",
859 tunnel_lib_buf_wrap->priv,
860 dmabuf->planeCnt,
861 dmabuf->fd[0],
862 dmabuf->fd[1]);
863
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800864 return ret;
xuesong.jiange90be372021-10-21 11:29:57 +0800865
866error:
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800867 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800868}
869
xuesong.jiang50a0f932021-11-15 15:18:51 +0800870static gboolean gst_get_mediasync_instanceid(GstAmlVideoSink *vsink)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800871{
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800872 GST_DEBUG_OBJECT(vsink, "trace in");
xuesong.jiang16983c92021-12-30 10:57:17 +0800873#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +0800874 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
875 GstElement *asink = gst_aml_video_sink_find_audio_sink(vsink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800876 if (!asink)
877 {
878 GST_DEBUG_OBJECT(vsink, "pipeline don't have audio sink element");
879 return FALSE;
880 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800881 GstClock *amlclock = gst_aml_hal_asink_get_clock((GstElement *)asink);
882 gboolean ret = TRUE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800883 if (amlclock)
884 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800885 sink_priv->mediasync_instanceid = gst_aml_clock_get_session_id(amlclock);
886 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);
887 if (sink_priv->mediasync_instanceid == -1)
888 {
889 GST_ERROR_OBJECT(vsink, "audio sink: don't have valid mediasync instance id");
890 ret = FALSE;
891 }
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800892 }
893 else
894 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800895 GST_WARNING_OBJECT(vsink, "no clock: vmaster mode");
896 ret = FALSE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800897 }
xuesong.jiang192316f2021-10-27 14:51:56 +0800898 gst_object_unref(asink);
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800899#else
900 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
901 gboolean ret = TRUE;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800902 FILE *fp;
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800903 fp = fopen("/data/MediaSyncId", "r");
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800904 if (fp == NULL)
905 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800906 GST_ERROR_OBJECT(vsink, "could not open file:/data/MediaSyncId failed");
907 ret = FALSE;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800908 }
909 else
910 {
xuesong.jiang16983c92021-12-30 10:57:17 +0800911 size_t read_size = 0;
912 read_size = fread(&sink_priv->mediasync_instanceid, sizeof(int), 1, fp);
913 if (read_size != sizeof(int))
914 {
915 GST_DEBUG_OBJECT(vsink, "get mediasync instance id read error");
916 }
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800917 fclose(fp);
918 GST_DEBUG_OBJECT(vsink, "get mediasync instance id:0x%x", sink_priv->mediasync_instanceid);
919 }
920#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +0800921 return ret;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800922}
923
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800924static void gst_emit_eos_signal(GstAmlVideoSink *vsink)
925{
926 GST_DEBUG_OBJECT(vsink, "emit eos signal");
927 g_mutex_lock(&vsink->eos_lock);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800928 g_cond_signal(&vsink->eos_cond);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800929 g_mutex_unlock(&vsink->eos_lock);
930}
931
932static void gst_wait_eos_signal(GstAmlVideoSink *vsink)
933{
934 GST_DEBUG_OBJECT(vsink, "waitting eos signal");
935 g_mutex_lock(&vsink->eos_lock);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800936 g_cond_wait(&vsink->eos_cond, &vsink->eos_lock);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800937 g_mutex_unlock(&vsink->eos_lock);
938 GST_DEBUG_OBJECT(vsink, "waitted eos signal");
939}
940
xuesong.jiang16983c92021-12-30 10:57:17 +0800941#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +0800942static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800943{
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800944 GST_DEBUG_OBJECT(sink, "trace in");
xuesong.jiang50a0f932021-11-15 15:18:51 +0800945 GstElement *audioSink = 0;
946 GstElement *pipeline = 0;
947 GstElement *element, *elementPrev = 0;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800948
xuesong.jiang50a0f932021-11-15 15:18:51 +0800949 element = GST_ELEMENT_CAST(sink);
950 do
951 {
952 if (elementPrev)
953 {
954 gst_object_unref(elementPrev);
955 }
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800956 // TODO use this func will ref elment,but when unref these element?
xuesong.jiang50a0f932021-11-15 15:18:51 +0800957 element = GST_ELEMENT_CAST(gst_element_get_parent(element));
958 if (element)
959 {
960 elementPrev = pipeline;
961 pipeline = element;
962 }
963 } while (element != 0);
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800964
xuesong.jiang50a0f932021-11-15 15:18:51 +0800965 if (pipeline)
966 {
967 GstIterator *iterElement = gst_bin_iterate_recurse(GST_BIN(pipeline));
968 if (iterElement)
969 {
970 GValue itemElement = G_VALUE_INIT;
971 while (gst_iterator_next(iterElement, &itemElement) == GST_ITERATOR_OK)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800972 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800973 element = (GstElement *)g_value_get_object(&itemElement);
974 if (element && !GST_IS_BIN(element))
975 {
976 int numSrcPads = 0;
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800977
xuesong.jiang50a0f932021-11-15 15:18:51 +0800978 GstIterator *iterPad = gst_element_iterate_src_pads(element);
979 if (iterPad)
980 {
981 GValue itemPad = G_VALUE_INIT;
982 while (gst_iterator_next(iterPad, &itemPad) == GST_ITERATOR_OK)
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800983 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800984 GstPad *pad = (GstPad *)g_value_get_object(&itemPad);
985 if (pad)
986 {
987 ++numSrcPads;
988 }
989 g_value_reset(&itemPad);
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800990 }
xuesong.jiang50a0f932021-11-15 15:18:51 +0800991 gst_iterator_free(iterPad);
992 }
xuesong.jiangb4c09b52021-10-26 20:18:35 +0800993
xuesong.jiang50a0f932021-11-15 15:18:51 +0800994 if (numSrcPads == 0)
995 {
996 GstElementClass *ec = GST_ELEMENT_GET_CLASS(element);
997 if (ec)
998 {
999 const gchar *meta = gst_element_class_get_metadata(ec, GST_ELEMENT_METADATA_KLASS);
1000 if (meta && strstr(meta, "Sink") && strstr(meta, "Audio"))
1001 {
1002 audioSink = (GstElement *)gst_object_ref(element);
1003 gchar *name = gst_element_get_name(element);
1004 if (name)
1005 {
1006 GST_DEBUG("detected audio sink: name (%s)", name);
1007 g_free(name);
1008 }
1009 g_value_reset(&itemElement);
1010 break;
1011 }
1012 }
1013 }
1014 }
1015 g_value_reset(&itemElement);
1016 }
1017 gst_iterator_free(iterElement);
1018 }
1019
1020 gst_object_unref(pipeline);
1021 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001022 GST_DEBUG_OBJECT(sink, "trace out get audioSink:%p", audioSink);
xuesong.jiang50a0f932021-11-15 15:18:51 +08001023 return audioSink;
1024}
xuesong.jiang16983c92021-12-30 10:57:17 +08001025#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +08001026
1027static gboolean gst_render_set_params(GstVideoSink *vsink)
1028{
1029 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
1030 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
1031 GstVideoInfo *video_info = &(sink_priv->video_info);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001032 int tunnelmode = 1; //1 for tunnel mode; 0 for non-tunnel mode
xuesong.jiang50a0f932021-11-15 15:18:51 +08001033
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001034 // RenderWindowSize window_size = {0, 0, video_info->width, video_info->height};
xuesong.jiang50a0f932021-11-15 15:18:51 +08001035 RenderFrameSize frame_size = {video_info->width, video_info->height};
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001036 GstVideoFormat format = video_info->finfo ? video_info->finfo->format : GST_VIDEO_FORMAT_UNKNOWN;
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001037 // if (render_set(sink_priv->render_device_handle, KEY_WINDOW_SIZE, &window_size) == -1)
1038 // {
1039 // GST_ERROR_OBJECT(vsink, "tunnel lib: set window size error");
1040 // return FALSE;
1041 // }
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001042 if (render_set(sink_priv->render_device_handle, KEY_MEDIASYNC_TUNNEL_MODE, (void *)&tunnelmode) == -1)
1043 {
1044 GST_ERROR_OBJECT(vsink, "tunnel lib: set tunnelmode error");
1045 return FALSE;
1046 }
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001047 if (render_set(sink_priv->render_device_handle, KEY_FRAME_SIZE, &frame_size) == -1)
xuesong.jiang50a0f932021-11-15 15:18:51 +08001048 {
1049 GST_ERROR_OBJECT(vsink, "tunnel lib: set frame size error");
1050 return FALSE;
1051 }
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001052 if (render_set(sink_priv->render_device_handle, KEY_VIDEO_FORMAT, &format) == -1)
xuesong.jiang32d78282021-11-18 19:24:15 +08001053 {
1054 GST_ERROR_OBJECT(vsink, "tunnel lib: set video format error");
1055 return FALSE;
1056 }
1057
xuesong.jiang50a0f932021-11-15 15:18:51 +08001058 return TRUE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001059}
1060
xuesong.jiang1801e172021-10-11 10:56:41 +08001061/* plugin init */
xuesong.jiangd91230d2021-10-20 15:51:10 +08001062static gboolean plugin_init(GstPlugin *plugin)
1063{
xuesong.jiang1700bab2021-11-17 17:11:11 +08001064 GST_DEBUG_CATEGORY_INIT(gst_aml_video_sink_debug, "amlvideosink", 0,
1065 " aml video sink");
xuesong.jiang1801e172021-10-11 10:56:41 +08001066
xuesong.jiangf0ebebe2021-12-24 09:41:15 +08001067 gint rank = 1;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001068 const char *rank_env = getenv("GST_AML_VIDEO_SINK_RANK");
1069 if (rank_env)
1070 {
1071 rank = atoi(rank_env);
1072 }
xuesong.jiangf0ebebe2021-12-24 09:41:15 +08001073
1074 return gst_element_register(plugin, "amlvideosink", rank,
xuesong.jiangd91230d2021-10-20 15:51:10 +08001075 GST_TYPE_AML_VIDEO_SINK);
xuesong.jiang1801e172021-10-11 10:56:41 +08001076}
1077
xuesong.jiang5c0d1b82021-11-16 19:30:56 +08001078#ifndef VERSION
1079#define VERSION "0.1.0"
1080#endif
1081#ifndef PACKAGE
1082#define PACKAGE "aml_package"
1083#endif
1084#ifndef PACKAGE_NAME
1085#define PACKAGE_NAME "aml_media"
1086#endif
1087#ifndef GST_PACKAGE_ORIGIN
1088#define GST_PACKAGE_ORIGIN "http://amlogic.com"
1089#endif
1090// GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, amlvideosink,
1091// "aml Video Sink", plugin_init, VERSION, "LGPL",
1092// "gst-plugin-video-sink", "")
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001093GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
1094 GST_VERSION_MINOR,
1095 amlvideosink,
1096 "Amlogic plugin for video decoding/rendering",
1097 plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)