blob: 4a74f799e208ccee4aa8577f2bc0ab2ee7db677f [file] [log] [blame]
xuesong.jiang16983c92021-12-30 10:57:17 +08001/* GStreamer
xuesong.jiangf6734c62022-04-26 13:46:11 +08002 * Copyright (C) 2022 <xuesong.jiang@amlogic.com>
xuesong.jiang16983c92021-12-30 10:57:17 +08003 *
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.jiangc26425b2022-05-12 20:37:22 +080064#define GST_IMPORT_LGE_PROP 0
65
xuesong.jiang1801e172021-10-11 10:56:41 +080066/* signals */
xuesong.jiangd91230d2021-10-20 15:51:10 +080067enum
68{
69 SIGNAL_0,
70 LAST_SIGNAL
xuesong.jiang1801e172021-10-11 10:56:41 +080071};
72
xuesong.jiangd91230d2021-10-20 15:51:10 +080073/* Properties */
74enum
75{
76 PROP_0,
77 PROP_FULLSCREEN,
78 PROP_SETMUTE,
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +080079 PROP_AVSYNC_MODE,
xuesong.jiang62ed50e2022-04-13 16:55:47 +080080 PROP_VIDEO_FRAME_DROP_NUM,
xuesong.jiang1a9c2822022-04-24 11:35:07 +080081 PROP_WINDOW_SET,
xuesong.jiangc26425b2022-05-12 20:37:22 +080082#if GST_IMPORT_LGE_PROP
83 PROP_LGE_RESOURCE_INFO,
84 PROP_LGE_CURRENT_PTS,
85 PROP_LGE_INTERLEAVING_TYPE,
86 PROP_LGE_APP_TYPE,
87 PROP_LGE_SYNC,
88 PROP_LGE_DISH_TRICK,
89 PROP_LGE_DISH_TRICK_IGNORE_RATE,
90#endif
xuesong.jiangd91230d2021-10-20 15:51:10 +080091};
92
xuesong.jiangfa8903d2022-02-11 15:13:05 +080093// #define AML_VIDEO_FORMATS \
94// "{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB, RGB, BGR, " \
95// "RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, " \
96// "YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }"
97#define AML_VIDEO_FORMATS "{ NV21 }"
98
xuesong.jiangd91230d2021-10-20 15:51:10 +080099#define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800100#define GST_USE_PLAYBIN 1
xuesong.jiange0c6c542022-04-11 16:10:23 +0800101#define GST_DEFAULT_AVSYNC_MODE 1 // 0:v master, 1:a master
xuesong.jiang5d2761f2022-05-05 11:43:21 +0800102#define GST_DUMP_STAT_FILENAME "amlvideosink_buf_stat"
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800103
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800104#if GST_IMPORT_LGE_PROP
105#define RENDER_DEVICE_NAME "videotunnel"
106#else
xuesong.jiange0c6c542022-04-11 16:10:23 +0800107#define RENDER_DEVICE_NAME "westeros"
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800108#endif
xuesong.jiangd91230d2021-10-20 15:51:10 +0800109#define USE_DMABUF TRUE
110
xuesong.jiange0c6c542022-04-11 16:10:23 +0800111#define DRMBP_EXTRA_BUF_SZIE_FOR_DISPLAY 1
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800112#define DRMBP_LIMIT_MAX_BUFSIZE_TO_BUFSIZE 1
113#define DRMBP_UNLIMIT_MAX_BUFSIZE 0
xuesong.jiangb3f0f152021-12-23 20:19:08 +0800114
xuesong.jiang1a9c2822022-04-24 11:35:07 +0800115typedef struct _GstAmlVideoSinkWindowSet
116{
117 gboolean window_change;
118 gint x;
119 gint y;
120 gint w;
121 gint h;
122} GstAmlVideoSinkWindowSet;
123
xuesong.jiangc26425b2022-05-12 20:37:22 +0800124#if GST_IMPORT_LGE_PROP
125typedef struct _GstAmlResourceInfo
126{
127 gchar *coretype;
128 gint videoport;
129 gint audioport;
130 gint maxwidth;
131 gint maxheight;
132 gint mixerport;
133} GstAmlResourceInfo;
134
135typedef struct _GstAmlVideoSinkLgeCtxt
136{
137 GstAmlResourceInfo res_info;
138 guint interleaving_type;
139 gchar *app_type;
140 gboolean sync;
141 gboolean dish_trick;
142 gboolean dish_trick_ignore_rate;
143} GstAmlVideoSinkLgeCtxt;
144#endif
145
xuesong.jiangd91230d2021-10-20 15:51:10 +0800146struct _GstAmlVideoSinkPrivate
147{
xuesong.jiang1a9c2822022-04-24 11:35:07 +0800148 GstAmlVideoSinkWindowSet window_set;
xuesong.jiangebd18352021-12-28 17:13:22 +0800149 GstBuffer *preroll_buffer;
xuesong.jiange90be372021-10-21 11:29:57 +0800150 gchar *render_device_name;
151 void *render_device_handle;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800152 GstVideoInfo video_info;
153 gboolean video_info_changed;
154 gboolean use_dmabuf;
155 gboolean is_flushing;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800156 gboolean got_eos;
xuesong.jiang50a0f932021-11-15 15:18:51 +0800157 gint mediasync_instanceid;
xuesong.jiang7c724a52021-10-22 17:18:58 +0800158 GstSegment segment;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800159
xuesong.jiangd91230d2021-10-20 15:51:10 +0800160 /* property params */
161 gboolean fullscreen;
162 gboolean mute;
xuesong.jiangc26425b2022-05-12 20:37:22 +0800163
164#if GST_IMPORT_LGE_PROP
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800165 GstAmlVideoSinkLgeCtxt lge_ctxt;
xuesong.jiangc26425b2022-05-12 20:37:22 +0800166#endif
xuesong.jiang1801e172021-10-11 10:56:41 +0800167};
168
169static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE(
170 "sink", GST_PAD_SINK, GST_PAD_ALWAYS,
171 GST_STATIC_CAPS(
172 GST_VIDEO_CAPS_MAKE(AML_VIDEO_FORMATS) ";" GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
173 GST_CAPS_FEATURE_MEMORY_DMABUF, AML_VIDEO_FORMATS)));
174
175GST_DEBUG_CATEGORY(gst_aml_video_sink_debug);
176#define GST_CAT_DEFAULT gst_aml_video_sink_debug
177#define gst_aml_video_sink_parent_class parent_class
xuesong.jiang192316f2021-10-27 14:51:56 +0800178// #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 +0800179G_DEFINE_TYPE_WITH_CODE(GstAmlVideoSink, gst_aml_video_sink,
180 GST_TYPE_VIDEO_SINK, G_ADD_PRIVATE(GstAmlVideoSink));
181
182/* public interface define */
183static void gst_aml_video_sink_get_property(GObject *object, guint prop_id,
184 GValue *value, GParamSpec *pspec);
185static void gst_aml_video_sink_set_property(GObject *object, guint prop_id,
186 const GValue *value,
187 GParamSpec *pspec);
188static void gst_aml_video_sink_finalize(GObject *object);
xuesong.jiang69031992022-06-09 19:30:35 +0800189static GstStateChangeReturn gst_aml_video_sink_change_state(GstElement *element, GstStateChange transition);
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800190static gboolean gst_aml_video_sink_query(GstElement *element, GstQuery *query);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800191static gboolean gst_aml_video_sink_propose_allocation(GstBaseSink *bsink, GstQuery *query);
xuesong.jiang1801e172021-10-11 10:56:41 +0800192static GstCaps *gst_aml_video_sink_get_caps(GstBaseSink *bsink,
193 GstCaps *filter);
194static gboolean gst_aml_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800195static gboolean gst_aml_video_sink_show_frame(GstVideoSink *bsink, GstBuffer *buffer);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800196static gboolean gst_aml_video_sink_pad_event(GstPad *pad, GstObject *parent, GstEvent *event);
xuesong.jiang69031992022-06-09 19:30:35 +0800197static gboolean gst_aml_video_sink_send_event(GstElement *element, GstEvent *event);
xuesong.jiang1801e172021-10-11 10:56:41 +0800198
199/* private interface define */
200static void gst_aml_video_sink_reset_private(GstAmlVideoSink *sink);
xuesong.jiang1700bab2021-11-17 17:11:11 +0800201void gst_render_msg_callback(void *userData, RenderMsgType type, void *msg);
202int gst_render_val_callback(void *userData, int key, void *value);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800203static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap);
xuesong.jiang50a0f932021-11-15 15:18:51 +0800204static gboolean gst_get_mediasync_instanceid(GstAmlVideoSink *vsink);
xuesong.jiang16983c92021-12-30 10:57:17 +0800205#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +0800206static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink);
xuesong.jiang16983c92021-12-30 10:57:17 +0800207#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +0800208static gboolean gst_render_set_params(GstVideoSink *vsink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800209static void gst_emit_eos_signal(GstAmlVideoSink *vsink);
210static void gst_wait_eos_signal(GstAmlVideoSink *vsink);
xuesong.jiang5d2761f2022-05-05 11:43:21 +0800211static void gst_aml_video_sink_dump_stat(GstAmlVideoSink *sink, const gchar *file_name);
xuesong.jiang1801e172021-10-11 10:56:41 +0800212
213/* public interface definition */
xuesong.jiang7c724a52021-10-22 17:18:58 +0800214static void gst_aml_video_sink_class_init(GstAmlVideoSinkClass *klass)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800215{
216 GObjectClass *gobject_class;
217 GstElementClass *gstelement_class;
218 GstBaseSinkClass *gstbasesink_class;
219 GstVideoSinkClass *gstvideosink_class;
xuesong.jiang1801e172021-10-11 10:56:41 +0800220
xuesong.jiangd91230d2021-10-20 15:51:10 +0800221 gobject_class = (GObjectClass *)klass;
222 gstelement_class = (GstElementClass *)klass;
223 gstbasesink_class = (GstBaseSinkClass *)klass;
224 gstvideosink_class = (GstVideoSinkClass *)klass;
xuesong.jiang1801e172021-10-11 10:56:41 +0800225
xuesong.jiangd91230d2021-10-20 15:51:10 +0800226 gobject_class->set_property = gst_aml_video_sink_set_property;
227 gobject_class->get_property = gst_aml_video_sink_get_property;
228 gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_aml_video_sink_finalize);
xuesong.jiang1801e172021-10-11 10:56:41 +0800229
xuesong.jiangd91230d2021-10-20 15:51:10 +0800230 gst_element_class_add_static_pad_template(gstelement_class, &sink_template);
xuesong.jiang1801e172021-10-11 10:56:41 +0800231
xuesong.jiangd91230d2021-10-20 15:51:10 +0800232 gst_element_class_set_static_metadata(
233 gstelement_class, "aml video sink", "Sink/Video",
234 "Output to video tunnel lib",
235 "Xuesong.Jiang@amlogic.com<Xuesong.Jiang@amlogic.com>");
xuesong.jiang1801e172021-10-11 10:56:41 +0800236
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800237 gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_aml_video_sink_change_state);
238 gstelement_class->query = GST_DEBUG_FUNCPTR(gst_aml_video_sink_query);
xuesong.jiang69031992022-06-09 19:30:35 +0800239 gstelement_class->send_event = GST_DEBUG_FUNCPTR(gst_aml_video_sink_send_event);
xuesong.jiang1801e172021-10-11 10:56:41 +0800240
xuesong.jiangd91230d2021-10-20 15:51:10 +0800241 gstbasesink_class->propose_allocation = GST_DEBUG_FUNCPTR(gst_aml_video_sink_propose_allocation);
242 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR(gst_aml_video_sink_get_caps);
243 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_aml_video_sink_set_caps);
xuesong.jiang1801e172021-10-11 10:56:41 +0800244
xuesong.jiangd91230d2021-10-20 15:51:10 +0800245 gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR(gst_aml_video_sink_show_frame);
xuesong.jiang1801e172021-10-11 10:56:41 +0800246
xuesong.jiangd91230d2021-10-20 15:51:10 +0800247 g_object_class_install_property(
248 gobject_class, PROP_FULLSCREEN,
249 g_param_spec_boolean("fullscreen", "Fullscreen",
250 "Whether the surface should be made fullscreen ",
251 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
xuesong.jiang1801e172021-10-11 10:56:41 +0800252
xuesong.jiangd91230d2021-10-20 15:51:10 +0800253 g_object_class_install_property(
254 gobject_class, PROP_SETMUTE,
255 g_param_spec_boolean("set mute", "set mute params",
256 "Whether set screen mute ",
257 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800258
259 g_object_class_install_property(
260 G_OBJECT_CLASS(klass), PROP_AVSYNC_MODE,
261 g_param_spec_int("avsync-mode", "avsync mode",
262 "Vmaster(0) Amaster(1) PCRmaster(2) IPTV(3) FreeRun(4)",
263 G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE));
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800264
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800265 g_object_class_install_property(
266 G_OBJECT_CLASS(klass), PROP_VIDEO_FRAME_DROP_NUM,
267 g_param_spec_int("frames-dropped", "frames-dropped",
268 "number of dropped frames",
269 0, G_MAXINT32, 0, G_PARAM_READABLE));
xuesong.jiang1a9c2822022-04-24 11:35:07 +0800270
271 g_object_class_install_property(
272 G_OBJECT_CLASS(klass), PROP_WINDOW_SET,
273 g_param_spec_string("rectangle", "rectangle",
274 "Window Set Format: x,y,width,height",
275 NULL, G_PARAM_WRITABLE));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800276
277#if GST_IMPORT_LGE_PROP
278 g_object_class_install_property(
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800279 G_OBJECT_CLASS(klass), PROP_LGE_RESOURCE_INFO,
xuesong.jiangc26425b2022-05-12 20:37:22 +0800280 g_param_spec_object("resource-info", "resource-info",
281 "After acquisition of H/W resources is completed, allocated resource information must be delivered to the decoder and the sink",
282 GST_TYPE_STRUCTURE,
283 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
284
285 g_object_class_install_property(
286 G_OBJECT_CLASS(klass), PROP_LGE_CURRENT_PTS,
287 g_param_spec_uint64("current-pts", "current pts",
288 "get rendering timing video position",
289 0, G_MAXUINT64,
290 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
291
292 g_object_class_install_property(
293 G_OBJECT_CLASS(klass), PROP_LGE_INTERLEAVING_TYPE,
294 g_param_spec_uint("interleaving-type", "interleaving type",
295 "set 3D type",
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800296 0, G_MAXUINT,
xuesong.jiangc26425b2022-05-12 20:37:22 +0800297 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
298
299 g_object_class_install_property(
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800300 G_OBJECT_CLASS(klass), PROP_LGE_APP_TYPE,
xuesong.jiangc26425b2022-05-12 20:37:22 +0800301 g_param_spec_string("app-type", "app-type",
302 "set application type.",
303 "default_app",
304 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
305
306 g_object_class_install_property(
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800307 G_OBJECT_CLASS(klass), PROP_LGE_SYNC,
xuesong.jiangc26425b2022-05-12 20:37:22 +0800308 g_param_spec_boolean("sync", "sync",
309 "M16, H15, K2L",
310 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
311
312 g_object_class_install_property(
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800313 G_OBJECT_CLASS(klass), PROP_LGE_DISH_TRICK,
xuesong.jiangc26425b2022-05-12 20:37:22 +0800314 g_param_spec_boolean("dish-trick", "dish trick",
315 "H15, M16",
316 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
317
318 g_object_class_install_property(
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800319 G_OBJECT_CLASS(klass), PROP_LGE_DISH_TRICK_IGNORE_RATE,
xuesong.jiangc26425b2022-05-12 20:37:22 +0800320 g_param_spec_boolean("dish-trick-ignore-rate", "dish trick ignore rate",
321 "H15, M16",
322 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
323#endif
xuesong.jiang1801e172021-10-11 10:56:41 +0800324}
325
xuesong.jiangd91230d2021-10-20 15:51:10 +0800326static void gst_aml_video_sink_init(GstAmlVideoSink *sink)
327{
328 GstBaseSink *basesink = (GstBaseSink *)sink;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800329
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800330 sink->last_displayed_buf_pts = 0;
xuesong.jiangaed30942022-06-17 14:27:27 +0800331 sink->last_dec_buf_pts = 0;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800332 /* init eos detect */
333 sink->queued = 0;
334 sink->dequeued = 0;
335 sink->rendered = 0;
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800336 sink->droped = 0;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800337 sink->avsync_mode = GST_DEFAULT_AVSYNC_MODE;
sheng.liuc9f34962022-06-17 21:42:48 +0800338 sink->secure_mode = FALSE;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800339 g_mutex_init(&sink->eos_lock);
340 g_cond_init(&sink->eos_cond);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800341
xuesong.jiangd91230d2021-10-20 15:51:10 +0800342 gst_pad_set_event_function(basesink->sinkpad, gst_aml_video_sink_pad_event);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800343
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800344 GST_AML_VIDEO_SINK_GET_PRIVATE(sink) = malloc(sizeof(GstAmlVideoSinkPrivate));
xuesong.jiangd91230d2021-10-20 15:51:10 +0800345 gst_aml_video_sink_reset_private(sink);
xuesong.jiangd2619562021-12-23 16:38:50 +0800346 gst_base_sink_set_sync(basesink, FALSE);
xuesong.jiangfc27c272022-05-11 17:09:02 +0800347
348 gst_base_sink_set_qos_enabled(basesink, FALSE);
xuesong.jiang1801e172021-10-11 10:56:41 +0800349}
350
351static void gst_aml_video_sink_get_property(GObject *object, guint prop_id,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800352 GValue *value, GParamSpec *pspec)
353{
354 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
355 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800356
xuesong.jiangd91230d2021-10-20 15:51:10 +0800357 switch (prop_id)
358 {
359 case PROP_FULLSCREEN:
360 GST_OBJECT_LOCK(sink);
361 g_value_set_boolean(value, sink_priv->fullscreen);
362 GST_OBJECT_UNLOCK(sink);
363 break;
364 case PROP_SETMUTE:
365 GST_OBJECT_LOCK(sink);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800366 g_value_set_boolean(value, sink_priv->mute);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800367 GST_OBJECT_UNLOCK(sink);
368 break;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800369 case PROP_AVSYNC_MODE:
370 GST_OBJECT_LOCK(sink);
371 g_value_set_boolean(value, sink->avsync_mode);
372 GST_OBJECT_UNLOCK(sink);
373 break;
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800374 case PROP_VIDEO_FRAME_DROP_NUM:
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800375 GST_OBJECT_LOCK(sink);
xuesong.jiang3d6528a2022-06-10 15:51:11 +0800376 GST_DEBUG_OBJECT(sink, "app get frame drop num | queued:%d, dequeued:%d, droped:%d, rendered:%d",
377 sink->queued, sink->dequeued, sink->droped, sink->rendered);
378 if (sink->droped < 10)
379 g_value_set_int(value, 0);
380 else
381 g_value_set_int(value, sink->droped);
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800382 GST_OBJECT_UNLOCK(sink);
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800383 break;
xuesong.jiangc26425b2022-05-12 20:37:22 +0800384#if GST_IMPORT_LGE_PROP
385 case PROP_LGE_CURRENT_PTS:
386 {
387 GST_OBJECT_LOCK(sink);
388 g_value_set_uint64(value, sink->last_displayed_buf_pts);
389 GST_OBJECT_UNLOCK(sink);
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800390 break;
xuesong.jiangc26425b2022-05-12 20:37:22 +0800391 }
392#endif
xuesong.jiangd91230d2021-10-20 15:51:10 +0800393 default:
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800394 // G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800395 break;
396 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800397}
398
399static void gst_aml_video_sink_set_property(GObject *object, guint prop_id,
400 const GValue *value,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800401 GParamSpec *pspec)
402{
403 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
404 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800405
xuesong.jiangd91230d2021-10-20 15:51:10 +0800406 switch (prop_id)
407 {
408 case PROP_FULLSCREEN:
409 GST_OBJECT_LOCK(sink);
410 gboolean is_fullscreen = g_value_get_boolean(value);
xuesong.jiange90be372021-10-21 11:29:57 +0800411 if (sink_priv->fullscreen != is_fullscreen)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800412 {
413 sink_priv->fullscreen = is_fullscreen;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800414 // TODO set full screen to tunnel lib
xuesong.jiangd91230d2021-10-20 15:51:10 +0800415 }
416 GST_OBJECT_UNLOCK(sink);
417 break;
418 case PROP_SETMUTE:
419 GST_OBJECT_LOCK(sink);
420 gboolean is_mute = g_value_get_boolean(value);
xuesong.jiange90be372021-10-21 11:29:57 +0800421 if (sink_priv->mute != is_mute)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800422 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +0800423 sink_priv->mute = is_mute;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800424 // TODO set full screen to tunnel lib
425 }
426 GST_OBJECT_UNLOCK(sink);
427 break;
428 case PROP_AVSYNC_MODE:
429 GST_OBJECT_LOCK(sink);
430 gint mode = g_value_get_int(value);
431 if (mode >= 0)
432 {
433 sink->avsync_mode = mode;
434 GST_WARNING("AV sync mode %d", mode);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800435 }
436 GST_OBJECT_UNLOCK(sink);
437 break;
xuesong.jiang1a9c2822022-04-24 11:35:07 +0800438 case PROP_WINDOW_SET:
439 {
440 const gchar *str = g_value_get_string(value);
441 gchar **parts = g_strsplit(str, ",", 4);
442
443 if (!parts[0] || !parts[1] || !parts[2] || !parts[3])
444 {
445 GST_ERROR("Bad window properties string");
446 }
447 else
448 {
449 int nx, ny, nw, nh;
450 nx = atoi(parts[0]);
451 ny = atoi(parts[1]);
452 nw = atoi(parts[2]);
453 nh = atoi(parts[3]);
454
455 if ((nx != sink_priv->window_set.x) ||
456 (ny != sink_priv->window_set.y) ||
457 (nw != sink_priv->window_set.w) ||
458 (nh != sink_priv->window_set.h))
459 {
460 GST_OBJECT_LOCK(sink);
461 sink_priv->window_set.window_change = true;
462 sink_priv->window_set.x = nx;
463 sink_priv->window_set.y = ny;
464 sink_priv->window_set.w = nw;
465 sink_priv->window_set.h = nh;
466
467 GST_DEBUG("set window rect (%d,%d,%d,%d)\n",
468 sink_priv->window_set.x,
469 sink_priv->window_set.y,
470 sink_priv->window_set.w,
471 sink_priv->window_set.h);
472 GST_OBJECT_UNLOCK(sink);
473 }
474 }
475
476 g_strfreev(parts);
477 break;
478 }
xuesong.jiangc26425b2022-05-12 20:37:22 +0800479#if GST_IMPORT_LGE_PROP
480 case PROP_LGE_RESOURCE_INFO:
481 {
482 GST_OBJECT_LOCK(sink);
483 GstStructure *r_info = g_value_get_object(value);
484 if (r_info)
485 {
486 if (gst_structure_has_field(r_info, "coretype"))
487 {
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800488 if (sink_priv->lge_ctxt.res_info.coretype)
489 {
490 g_free(sink_priv->lge_ctxt.res_info.coretype);
491 sink_priv->lge_ctxt.res_info.coretype = NULL;
492 }
493 sink_priv->lge_ctxt.res_info.coretype = g_strdup(gst_structure_get_string(r_info, "coretype"));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800494 }
495 if (gst_structure_has_field(r_info, "videoport"))
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800496 gst_structure_get_int(r_info, "videoport", &(sink_priv->lge_ctxt.res_info.videoport));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800497 if (gst_structure_has_field(r_info, "audioport"))
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800498 gst_structure_get_int(r_info, "audioport", &(sink_priv->lge_ctxt.res_info.audioport));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800499 if (gst_structure_has_field(r_info, "maxwidth"))
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800500 gst_structure_get_int(r_info, "maxwidth", &(sink_priv->lge_ctxt.res_info.maxwidth));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800501 if (gst_structure_has_field(r_info, "maxheight"))
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800502 gst_structure_get_int(r_info, "maxheight", &(sink_priv->lge_ctxt.res_info.maxheight));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800503 if (gst_structure_has_field(r_info, "mixerport"))
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800504 gst_structure_get_int(r_info, "mixerport", &(sink_priv->lge_ctxt.res_info.mixerport));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800505 }
506 GST_OBJECT_UNLOCK(sink);
507 break;
508 }
509 case PROP_LGE_INTERLEAVING_TYPE:
510 {
511 GST_OBJECT_LOCK(sink);
512 guint interlv_type = g_value_get_uint(value);
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800513 sink_priv->lge_ctxt.interleaving_type = interlv_type;
xuesong.jiangc26425b2022-05-12 20:37:22 +0800514 GST_OBJECT_UNLOCK(sink);
515 break;
516 }
517 case PROP_LGE_APP_TYPE:
518 {
519 GST_OBJECT_LOCK(sink);
520 GST_DEBUG_OBJECT(sink, "LGE up layer set app type");
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800521 if (sink_priv->lge_ctxt.app_type)
522 g_free(sink_priv->lge_ctxt.app_type);
523 sink_priv->lge_ctxt.app_type = g_strdup(g_value_get_string(value));
xuesong.jiangc26425b2022-05-12 20:37:22 +0800524 GST_OBJECT_UNLOCK(sink);
525 break;
526 }
527 case PROP_LGE_SYNC:
528 {
529 GST_OBJECT_LOCK(sink);
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800530 sink_priv->lge_ctxt.sync = g_value_get_boolean(value);
xuesong.jiangc26425b2022-05-12 20:37:22 +0800531 GST_OBJECT_UNLOCK(sink);
532 break;
533 }
534 case PROP_LGE_DISH_TRICK:
535 {
536 GST_OBJECT_LOCK(sink);
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800537 sink_priv->lge_ctxt.dish_trick = g_value_get_boolean(value);
xuesong.jiangc26425b2022-05-12 20:37:22 +0800538 GST_OBJECT_UNLOCK(sink);
539 break;
540 }
541 case PROP_LGE_DISH_TRICK_IGNORE_RATE:
542 {
543 GST_OBJECT_LOCK(sink);
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800544 sink_priv->lge_ctxt.dish_trick_ignore_rate = g_value_get_boolean(value);
xuesong.jiangc26425b2022-05-12 20:37:22 +0800545 GST_OBJECT_UNLOCK(sink);
546 break;
547 }
548#endif
xuesong.jiangd91230d2021-10-20 15:51:10 +0800549 default:
xuesong.jianga52aa5b2022-05-13 16:00:32 +0800550 // G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800551 break;
552 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800553}
554
xuesong.jiangd91230d2021-10-20 15:51:10 +0800555static void gst_aml_video_sink_finalize(GObject *object)
556{
557 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
xuesong.jiang1801e172021-10-11 10:56:41 +0800558
xuesong.jiangd91230d2021-10-20 15:51:10 +0800559 GST_DEBUG_OBJECT(sink, "Finalizing aml video sink..");
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800560
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800561 g_mutex_clear(&sink->eos_lock);
562 g_cond_clear(&sink->eos_cond);
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800563
xuesong.jiangd91230d2021-10-20 15:51:10 +0800564 gst_aml_video_sink_reset_private(sink);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800565 if (GST_AML_VIDEO_SINK_GET_PRIVATE(sink))
xuesong.jiang5c0d1b82021-11-16 19:30:56 +0800566 free(GST_AML_VIDEO_SINK_GET_PRIVATE(sink));
xuesong.jiangd91230d2021-10-20 15:51:10 +0800567 G_OBJECT_CLASS(parent_class)->finalize(object);
xuesong.jiang1801e172021-10-11 10:56:41 +0800568}
569
570static GstStateChangeReturn
571gst_aml_video_sink_change_state(GstElement *element,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800572 GstStateChange transition)
573{
574 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(element);
575 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800576 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
xuesong.jiang9d55c672022-05-09 18:33:03 +0800577 GstState state, next;
578
579 state = (GstState)GST_STATE_TRANSITION_CURRENT(transition);
580 next = GST_STATE_TRANSITION_NEXT(transition);
581 GST_LOG_OBJECT(sink,
xuesong.jiangc26425b2022-05-12 20:37:22 +0800582 "amlvideosink handler tries setting state from %s to %s (%04x)",
583 gst_element_state_get_name(state),
584 gst_element_state_get_name(next), transition);
xuesong.jiang1801e172021-10-11 10:56:41 +0800585
xuesong.jiangd91230d2021-10-20 15:51:10 +0800586 GST_OBJECT_LOCK(sink);
587 switch (transition)
588 {
589 case GST_STATE_CHANGE_NULL_TO_READY:
590 {
591 sink_priv->render_device_handle = render_open(sink_priv->render_device_name);
xuesong.jiange90be372021-10-21 11:29:57 +0800592 if (sink_priv->render_device_handle == NULL)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800593 {
594 GST_ERROR_OBJECT(sink, "render lib: open device fail");
595 goto error;
596 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +0800597 RenderCallback cb = {gst_render_msg_callback, gst_render_val_callback};
598 render_set_callback(sink_priv->render_device_handle, &cb);
599 render_set_user_data(sink_priv->render_device_handle, sink);
xuesong.jiangc26425b2022-05-12 20:37:22 +0800600
xuesong.jiangfc27c272022-05-11 17:09:02 +0800601 GST_DEBUG_OBJECT(sink, "set qos fail");
602 gst_base_sink_set_qos_enabled((GstBaseSink *)sink, FALSE);
xuesong.jiang1801e172021-10-11 10:56:41 +0800603
xuesong.jiangd91230d2021-10-20 15:51:10 +0800604 break;
605 }
606 case GST_STATE_CHANGE_READY_TO_PAUSED:
607 {
xuesong.jiang1700bab2021-11-17 17:11:11 +0800608 if (render_connect(sink_priv->render_device_handle) == -1)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800609 {
610 GST_ERROR_OBJECT(sink, "render lib connect device fail");
611 goto error;
612 }
xuesong.jiang69031992022-06-09 19:30:35 +0800613 if (render_pause(sink_priv->render_device_handle) == -1)
614 {
615 GST_ERROR_OBJECT(sink, "render lib pause device fail when first into paused state");
616 goto error;
617 }
618 break;
619 }
620 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
621 {
622 if (render_resume(sink_priv->render_device_handle) == -1)
623 {
624 GST_ERROR_OBJECT(sink, "render lib resume device fail");
625 goto error;
626 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800627 break;
628 }
629 default:
630 break;
631 }
632 GST_OBJECT_UNLOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800633
xuesong.jiang1700bab2021-11-17 17:11:11 +0800634 GST_LOG_OBJECT(sink, "amlvideosink deal state change ok, goto basesink state change");
xuesong.jiangd91230d2021-10-20 15:51:10 +0800635 ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
636
637 GST_OBJECT_LOCK(sink);
638 if (ret == GST_STATE_CHANGE_FAILURE)
639 goto error;
640
641 switch (transition)
642 {
xuesong.jiang69031992022-06-09 19:30:35 +0800643 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
644 {
645 GstBaseSink *basesink;
646 basesink = GST_BASE_SINK(sink);
647
648 if (render_pause(sink_priv->render_device_handle) == -1)
649 {
650 GST_ERROR_OBJECT(sink, "render lib pause device fail");
651 goto error;
652 }
653
654 // GST_BASE_SINK_PREROLL_LOCK(basesink);
655 // basesink->have_preroll = 1;
656 // GST_BASE_SINK_PREROLL_UNLOCK(basesink);
657 break;
658 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800659 case GST_STATE_CHANGE_PAUSED_TO_READY:
660 {
xuesong.jiangaed30942022-06-17 14:27:27 +0800661 GST_DEBUG_OBJECT(sink, "before disconnect rlib");
662 if (render_disconnect(sink_priv->render_device_handle) == -1)
663 {
664 GST_ERROR_OBJECT(sink, "render lib disconnect device fail");
665 goto error;
666 }
667 GST_DEBUG_OBJECT(sink, "after disconnect rlib");
668 GST_DEBUG_OBJECT(sink, "buf stat | queued:%d, dequeued:%d, droped:%d, rendered:%d",
669 sink->queued, sink->dequeued, sink->droped, sink->rendered);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800670 break;
671 }
672 case GST_STATE_CHANGE_READY_TO_NULL:
673 {
xuesong.jiange90be372021-10-21 11:29:57 +0800674 if (sink_priv->render_device_handle)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800675 {
676 render_close(sink_priv->render_device_handle);
677 }
678 gst_aml_video_sink_reset_private(sink);
679
680 break;
681 }
682 default:
683 break;
684 }
685 GST_OBJECT_UNLOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800686 return ret;
687
xuesong.jiangd91230d2021-10-20 15:51:10 +0800688error:
689 GST_OBJECT_UNLOCK(sink);
690 ret = GST_STATE_CHANGE_FAILURE;
691 return ret;
692}
xuesong.jiang1801e172021-10-11 10:56:41 +0800693
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800694static gboolean gst_aml_video_sink_query(GstElement *element, GstQuery *query)
695{
696 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(element);
697
698 switch (GST_QUERY_TYPE(query))
699 {
700 case GST_QUERY_POSITION:
701 {
702 GstFormat format;
703 gst_query_parse_position(query, &format, NULL);
704 if (GST_FORMAT_BYTES == format)
705 {
706 return GST_ELEMENT_CLASS(parent_class)->query(element, query);
707 }
708 else
709 {
710 GST_OBJECT_LOCK(sink);
711 gint64 position = sink->last_displayed_buf_pts;
xuesong.jiangaed30942022-06-17 14:27:27 +0800712 // gint64 position = sink->last_dec_buf_pts;
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800713 GST_OBJECT_UNLOCK(sink);
714 GST_LOG_OBJECT(sink, "got position: %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
715 gst_query_set_position(query, GST_FORMAT_TIME, position);
716 return TRUE;
717 }
718 break;
719 }
720 default:
721 return GST_ELEMENT_CLASS(parent_class)->query(element, query);
722 }
723}
724
xuesong.jiangd91230d2021-10-20 15:51:10 +0800725static gboolean gst_aml_video_sink_propose_allocation(GstBaseSink *bsink, GstQuery *query)
726{
xuesong.jiangeb46f672021-11-19 19:05:56 +0800727 GST_DEBUG_OBJECT(bsink, "trace in");
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +0800728 // TODO only implement dma case
xuesong.jiangd91230d2021-10-20 15:51:10 +0800729 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(bsink);
xuesong.jiang7c724a52021-10-22 17:18:58 +0800730 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
731
xuesong.jiangd91230d2021-10-20 15:51:10 +0800732 GstCaps *caps;
733 GstBufferPool *pool = NULL;
734 gboolean need_pool;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800735
736 gst_query_parse_allocation(query, &caps, &need_pool);
sheng.liuc9f34962022-06-17 21:42:48 +0800737 GST_DEBUG_OBJECT(bsink, "need_pool: %d, secure_mode: %d", need_pool, sink->secure_mode);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800738
739 if (need_pool)
sheng.liuc9f34962022-06-17 21:42:48 +0800740 pool = gst_drm_bufferpool_new(sink->secure_mode, GST_DRM_BUFFERPOOL_TYPE_VIDEO_PLANE);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800741
xuesong.jiangb3f0f152021-12-23 20:19:08 +0800742 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 +0800743 if (pool)
744 g_object_unref(pool);
745
746 gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
747
748 return TRUE;
xuesong.jiang1801e172021-10-11 10:56:41 +0800749}
750
751static GstCaps *gst_aml_video_sink_get_caps(GstBaseSink *bsink,
xuesong.jiangd91230d2021-10-20 15:51:10 +0800752 GstCaps *filter)
753{
754 GstAmlVideoSink *sink;
755 GstCaps *caps;
xuesong.jiang1801e172021-10-11 10:56:41 +0800756
xuesong.jiangd91230d2021-10-20 15:51:10 +0800757 sink = GST_AML_VIDEO_SINK(bsink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800758
xuesong.jiangd91230d2021-10-20 15:51:10 +0800759 caps = gst_pad_get_pad_template_caps(GST_VIDEO_SINK_PAD(sink));
760 caps = gst_caps_make_writable(caps);
761 // TODO 这里是需要从template直接取出支持的caps还是要通过tunnel lib拿到caps?
xuesong.jiang1801e172021-10-11 10:56:41 +0800762
xuesong.jiangd91230d2021-10-20 15:51:10 +0800763 if (filter)
764 {
765 GstCaps *intersection;
xuesong.jiang1801e172021-10-11 10:56:41 +0800766
xuesong.jiangd91230d2021-10-20 15:51:10 +0800767 intersection =
768 gst_caps_intersect_full(filter, caps, GST_CAPS_INTERSECT_FIRST);
769 gst_caps_unref(caps);
770 caps = intersection;
771 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800772
xuesong.jiangd91230d2021-10-20 15:51:10 +0800773 return caps;
xuesong.jiang1801e172021-10-11 10:56:41 +0800774}
775
xuesong.jiangd91230d2021-10-20 15:51:10 +0800776static gboolean gst_aml_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps)
777{
778 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(bsink);
779 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800780 // gboolean use_dmabuf;
xuesong.jiang91391f52021-11-19 15:42:30 +0800781 gboolean ret = TRUE;
xuesong.jiang1801e172021-10-11 10:56:41 +0800782
xuesong.jiangd91230d2021-10-20 15:51:10 +0800783 GST_OBJECT_LOCK(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800784
xuesong.jiangd91230d2021-10-20 15:51:10 +0800785 GST_DEBUG_OBJECT(sink, "set caps %" GST_PTR_FORMAT, caps);
xuesong.jiangeb46f672021-11-19 19:05:56 +0800786 // use_dmabuf = gst_caps_features_contains(gst_caps_get_features(caps, 0), GST_CAPS_FEATURE_MEMORY_DMABUF);
787 // if (use_dmabuf == FALSE)
788 // {
789 // GST_ERROR_OBJECT(sink, "not support non dma buffer case");
790 // ret = FALSE;
791 // goto done;
792 // }
xuesong.jiang1801e172021-10-11 10:56:41 +0800793
xuesong.jiangd91230d2021-10-20 15:51:10 +0800794 /* extract info from caps */
795 if (!gst_video_info_from_caps(&sink_priv->video_info, caps))
796 {
797 GST_ERROR_OBJECT(sink, "can't get video info from caps");
xuesong.jiang91391f52021-11-19 15:42:30 +0800798 ret = FALSE;
799 goto done;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800800 }
xuesong.jiang1801e172021-10-11 10:56:41 +0800801
xuesong.jiang69031992022-06-09 19:30:35 +0800802 // #if GST_IMPORT_LGE_PROP
803 // GstMessage *message;
804 // GstStructure *s;
805 // s = gst_structure_new("media-info",
806 // "type", "G_TYPE_INT", 1,
807 // "mime-type", G_TYPE_STRING, sink_priv->video_info.finfo->name,
808 // "width", G_TYPE_INT, sink_priv->video_info.width,
809 // "height", "G_TYPE_INT", sink_priv->video_info.height,
810 // NULL);
811 // message = gst_message_new_custom(GST_MESSAGE_APPLICATION, GST_OBJECT(sink), s);
812 // gst_element_post_message(GST_ELEMENT_CAST(sink), message);
813 // #endif
xuesong.jiangc26425b2022-05-12 20:37:22 +0800814
xuesong.jiangd91230d2021-10-20 15:51:10 +0800815 sink_priv->video_info_changed = TRUE;
816
xuesong.jiang91391f52021-11-19 15:42:30 +0800817done:
xuesong.jiangd91230d2021-10-20 15:51:10 +0800818 GST_OBJECT_UNLOCK(sink);
xuesong.jiang91391f52021-11-19 15:42:30 +0800819 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800820}
821
xuesong.jiange90be372021-10-21 11:29:57 +0800822static GstFlowReturn gst_aml_video_sink_show_frame(GstVideoSink *vsink, GstBuffer *buffer)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800823{
xuesong.jiang7c724a52021-10-22 17:18:58 +0800824 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800825 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
826 GstFlowReturn ret = GST_FLOW_OK;
827 RenderBuffer *tunnel_lib_buf_wrap = NULL;
xuesong.jiang1801e172021-10-11 10:56:41 +0800828
xuesong.jiangd91230d2021-10-20 15:51:10 +0800829 GST_OBJECT_LOCK(vsink);
xuesong.jiang103d2922022-04-26 13:37:20 +0800830
xuesong.jiang5d2761f2022-05-05 11:43:21 +0800831 GST_LOG_OBJECT(sink, "revice buffer:%p (start: %" GST_TIME_FORMAT ", end: %" GST_TIME_FORMAT "), from pool:%p, need_preroll:%d",
832 buffer, GST_TIME_ARGS(GST_BUFFER_PTS(buffer)), GST_TIME_ARGS(GST_BUFFER_DURATION(buffer)),
xuesong.jiang103d2922022-04-26 13:37:20 +0800833 buffer->pool, ((GstBaseSink *)sink)->need_preroll);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800834
xuesong.jiangaed30942022-06-17 14:27:27 +0800835 sink->last_dec_buf_pts = GST_BUFFER_PTS(buffer);
836 GST_DEBUG_OBJECT(sink, "set last_dec_buf_pts %" GST_TIME_FORMAT, GST_TIME_ARGS(sink->last_dec_buf_pts));
837
xuesong.jiange90be372021-10-21 11:29:57 +0800838 if (!sink_priv->render_device_handle)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800839 {
840 GST_ERROR_OBJECT(sink, "flow error, render_device_handle == NULL");
841 goto error;
842 }
843
xuesong.jiangebd18352021-12-28 17:13:22 +0800844 if (sink_priv->preroll_buffer && sink_priv->preroll_buffer == buffer)
845 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800846 GST_LOG_OBJECT(sink, "get preroll buffer:%p 2nd time, goto ret", buffer);
xuesong.jiangebd18352021-12-28 17:13:22 +0800847 sink_priv->preroll_buffer = NULL;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800848 goto ret;
xuesong.jiangebd18352021-12-28 17:13:22 +0800849 }
850 if (G_UNLIKELY(((GstBaseSink *)sink)->need_preroll))
851 {
852 GST_LOG_OBJECT(sink, "get preroll buffer 1st time, buf:%p", buffer);
853 sink_priv->preroll_buffer = buffer;
xuesong.jiang69031992022-06-09 19:30:35 +0800854 // goto flushing;
xuesong.jiangebd18352021-12-28 17:13:22 +0800855 }
856
xuesong.jiangd91230d2021-10-20 15:51:10 +0800857 // TODO should call tunnel lib flush func
858 if (sink_priv->is_flushing)
859 {
860 gst_buffer_unref(buffer);
xuesong.jiang103d2922022-04-26 13:37:20 +0800861 if (render_flush(sink_priv->render_device_handle) == 0)
862 {
863 GST_DEBUG_OBJECT(sink, "in flushing flow, release the buffer directly");
864 goto flushing;
865 }
866 else
xuesong.jiangd91230d2021-10-20 15:51:10 +0800867 {
868 GST_ERROR_OBJECT(sink, "render lib: flush error");
869 goto error;
870 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800871 }
872
xuesong.jiang5d2761f2022-05-05 11:43:21 +0800873 if (sink_priv->window_set.window_change)
xuesong.jiang1a9c2822022-04-24 11:35:07 +0800874 {
875 RenderWindowSize window_size = {sink_priv->window_set.x, sink_priv->window_set.y, sink_priv->window_set.w, sink_priv->window_set.h};
876 if (render_set(sink_priv->render_device_handle, KEY_WINDOW_SIZE, &window_size) == -1)
877 {
878 GST_ERROR_OBJECT(vsink, "tunnel lib: set window size error");
879 return FALSE;
880 }
881 sink_priv->window_set.window_change = FALSE;
882 }
883
xuesong.jiangd91230d2021-10-20 15:51:10 +0800884 if (sink_priv->video_info_changed)
885 {
xuesong.jiang50a0f932021-11-15 15:18:51 +0800886 if (gst_render_set_params(vsink) == FALSE)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800887 {
888 GST_ERROR_OBJECT(sink, "render lib: set params fail");
889 goto error;
890 }
891 sink_priv->video_info_changed = FALSE;
892 }
893
xuesong.jiang50a0f932021-11-15 15:18:51 +0800894 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 +0800895 if (!tunnel_lib_buf_wrap)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800896 {
897 GST_ERROR_OBJECT(sink, "render lib: alloc buffer wrap fail");
898 goto error;
899 }
xuesong.jiange90be372021-10-21 11:29:57 +0800900 if (!gst_aml_video_sink_tunnel_buf(sink, buffer, tunnel_lib_buf_wrap))
901 {
902 GST_ERROR_OBJECT(sink, "construc render buffer fail");
903 goto error;
904 }
905
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800906 GST_OBJECT_UNLOCK(vsink);
907
xuesong.jiangf190e2a2021-11-22 20:26:00 +0800908 if (render_display_frame(sink_priv->render_device_handle, tunnel_lib_buf_wrap) == -1)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800909 {
910 GST_ERROR_OBJECT(sink, "render lib: display frame fail");
911 goto error;
912 }
xuesong.jiangd91230d2021-10-20 15:51:10 +0800913
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800914 sink->queued++;
xuesong.jiang5a9096a2022-05-17 14:56:16 +0800915 gst_aml_video_sink_dump_stat(sink, GST_DUMP_STAT_FILENAME);
xuesong.jiang28a82172022-04-28 15:05:46 +0800916 GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued ok, queued:%d", buffer, sink->queued);
xuesong.jiang1801e172021-10-11 10:56:41 +0800917 return ret;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800918
xuesong.jiangd91230d2021-10-20 15:51:10 +0800919error:
xuesong.jiangeb46f672021-11-19 19:05:56 +0800920 GST_DEBUG_OBJECT(sink, "GstBuffer:%p queued error", buffer);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800921 ret = GST_FLOW_CUSTOM_ERROR_2;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800922 goto ret;
923flushing:
924 GST_DEBUG_OBJECT(sink, "flushing when buf:%p", buffer);
925 goto ret;
926ret:
927 GST_OBJECT_UNLOCK(vsink);
xuesong.jiangd91230d2021-10-20 15:51:10 +0800928 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +0800929}
930
xuesong.jiang50a0f932021-11-15 15:18:51 +0800931static gboolean gst_aml_video_sink_pad_event(GstPad *pad, GstObject *parent, GstEvent *event)
xuesong.jiangd91230d2021-10-20 15:51:10 +0800932{
933 gboolean result = TRUE;
xuesong.jiang7c724a52021-10-22 17:18:58 +0800934 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(parent);
935 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang1801e172021-10-11 10:56:41 +0800936
xuesong.jiangd91230d2021-10-20 15:51:10 +0800937 switch (GST_EVENT_TYPE(event))
938 {
939 case GST_EVENT_FLUSH_START:
940 {
941 GST_INFO_OBJECT(sink, "flush start");
942 GST_OBJECT_LOCK(sink);
943 sink_priv->is_flushing = TRUE;
xuesong.jiang5d2761f2022-05-05 11:43:21 +0800944 if (render_flush(sink_priv->render_device_handle) == 0)
xuesong.jiang28a82172022-04-28 15:05:46 +0800945 {
946 GST_INFO_OBJECT(sink, "recv flush start and set render lib flushing succ");
947 }
xuesong.jiangaed30942022-06-17 14:27:27 +0800948 GST_INFO_OBJECT(sink, "flush start done");
xuesong.jiangd91230d2021-10-20 15:51:10 +0800949 GST_OBJECT_UNLOCK(sink);
950 break;
951 }
952 case GST_EVENT_FLUSH_STOP:
953 {
954 GST_INFO_OBJECT(sink, "flush stop");
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800955 GST_DEBUG_OBJECT(sink, "flushing need waitting display render all buf, queued:%d, rendered:%d, droped:%d",
956 sink->queued,
957 sink->rendered,
958 sink->droped);
959 // gst_wait_eos_signal(sink);
960 if (sink->queued > sink->rendered + sink->droped)
961 {
962 gst_wait_eos_signal(sink);
963 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800964
xuesong.jiangd91230d2021-10-20 15:51:10 +0800965 GST_OBJECT_LOCK(sink);
xuesong.jiang28a82172022-04-28 15:05:46 +0800966 GST_INFO_OBJECT(sink, "flush all count num to zero");
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800967 sink->queued = 0;
968 sink->dequeued = 0;
969 sink->rendered = 0;
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800970 sink->droped = 0;
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800971 sink_priv->got_eos = FALSE;
xuesong.jiangd91230d2021-10-20 15:51:10 +0800972 sink_priv->is_flushing = FALSE;
xuesong.jiangaed30942022-06-17 14:27:27 +0800973 GST_INFO_OBJECT(sink, "flush stop done");
xuesong.jiangd91230d2021-10-20 15:51:10 +0800974 GST_OBJECT_UNLOCK(sink);
975 break;
976 }
977 case GST_EVENT_SEGMENT:
978 {
979 GST_OBJECT_LOCK(sink);
980 gst_event_copy_segment(event, &sink_priv->segment);
981 GST_INFO_OBJECT(sink, "configured segment %" GST_SEGMENT_FORMAT, &sink_priv->segment);
xuesong.jiangaed30942022-06-17 14:27:27 +0800982 sink->last_displayed_buf_pts = sink_priv->segment.position;
983 GST_INFO_OBJECT(sink, "update cur pos to %" GST_TIME_FORMAT, GST_TIME_ARGS(sink->last_displayed_buf_pts));
xuesong.jiangd91230d2021-10-20 15:51:10 +0800984 GST_OBJECT_UNLOCK(sink);
985 break;
986 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +0800987 case GST_EVENT_EOS:
988 {
989 GST_OBJECT_LOCK(sink);
990 sink_priv->got_eos = TRUE;
991 GST_OBJECT_UNLOCK(sink);
992
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800993 if (sink->queued > sink->rendered + sink->droped)
994 {
xuesong.jiang9ae8f882022-04-18 20:15:06 +0800995 GST_DEBUG_OBJECT(sink, "need waitting display render all buf, queued:%d, rendered:%d, droped:%d",
996 sink->queued,
997 sink->rendered,
998 sink->droped);
xuesong.jiang62ed50e2022-04-13 16:55:47 +0800999 gst_wait_eos_signal(sink);
1000 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001001 }
sheng.liuc9f34962022-06-17 21:42:48 +08001002 case GST_EVENT_CUSTOM_DOWNSTREAM:
1003 {
1004 if (gst_event_has_name (event, "IS_SVP"))
1005 {
1006 GST_DEBUG_OBJECT(sink, "Got SVP Event");
1007 sink->secure_mode = TRUE;
1008 }
1009 break;
1010 }
xuesong.jiangd91230d2021-10-20 15:51:10 +08001011 default:
1012 {
1013 GST_DEBUG_OBJECT(sink, "pass to basesink");
xuesong.jiang7c724a52021-10-22 17:18:58 +08001014 return GST_BASE_SINK_CLASS(parent_class)->event((GstBaseSink *)sink, event);
xuesong.jiangd91230d2021-10-20 15:51:10 +08001015 }
1016 }
1017 gst_event_unref(event);
1018 return result;
xuesong.jiang1801e172021-10-11 10:56:41 +08001019}
1020
xuesong.jiang69031992022-06-09 19:30:35 +08001021static gboolean gst_aml_video_sink_send_event(GstElement *element, GstEvent *event)
1022{
1023 GstPad *pad = NULL;
1024 GstBaseSink *basesink = GST_BASE_SINK(element);
1025 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(element);
1026 GstAmlVideoSinkClass *sink_class = GST_AML_VIDEO_SINK_GET_CLASS(sink);
1027 GstVideoSinkClass *sink_p_class = parent_class;
1028 GstBaseSinkClass *sink_pp_class = g_type_class_peek_parent(sink_p_class);
1029 gboolean result = TRUE;
1030 GstPadMode mode = GST_PAD_MODE_NONE;
1031
1032 GST_DEBUG_OBJECT(sink, "amlvideosink_class:%p, videosink_class:%p, basesink_class:%p", sink_class, sink_p_class, sink_pp_class);
1033 GST_DEBUG_OBJECT(sink, "handling event %p %" GST_PTR_FORMAT, event, event);
1034
1035 switch (GST_EVENT_TYPE(event))
1036 {
1037 case GST_EVENT_SEEK:
1038 {
1039 GST_OBJECT_LOCK(element);
1040 /* get the pad and the scheduling mode */
1041 pad = gst_object_ref(basesink->sinkpad);
1042 mode = basesink->pad_mode;
1043 GST_OBJECT_UNLOCK(element);
1044
1045 if (mode == GST_PAD_MODE_PUSH)
1046 {
1047 GST_BASE_SINK_PREROLL_LOCK(basesink);
1048 if (GST_BASE_SINK(sink)->need_preroll && GST_BASE_SINK(sink)->have_preroll)
1049 {
1050 GST_DEBUG_OBJECT(sink, "reset preroll when recived seek event");
1051 GST_BASE_SINK(sink)->need_preroll = FALSE;
1052 GST_BASE_SINK(sink)->have_preroll = FALSE;
1053 GST_BASE_SINK_PREROLL_SIGNAL(basesink);
1054 }
1055 GST_BASE_SINK_PREROLL_UNLOCK(basesink);
1056 }
1057
1058 gst_object_unref(pad);
1059 break;
1060 }
1061 default:
1062 break;
1063 }
1064
1065 if (GST_ELEMENT_CLASS(sink_pp_class)->send_event)
1066 {
1067 GST_DEBUG_OBJECT(sink, "use basesink class send event func handle event");
1068 result = GST_ELEMENT_CLASS(sink_pp_class)->send_event(element, event);
1069 }
1070 else
1071 {
1072 GST_ERROR_OBJECT(sink, "can't find basesink send event func");
1073 result = FALSE;
1074 }
1075
1076 GST_DEBUG_OBJECT(sink, "handled event: %d", result);
1077
1078 return result;
1079}
1080
xuesong.jiang1801e172021-10-11 10:56:41 +08001081/* private interface definition */
xuesong.jiangd91230d2021-10-20 15:51:10 +08001082static void gst_aml_video_sink_reset_private(GstAmlVideoSink *sink)
xuesong.jiang1801e172021-10-11 10:56:41 +08001083{
xuesong.jiangd91230d2021-10-20 15:51:10 +08001084 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jianga52aa5b2022-05-13 16:00:32 +08001085#if GST_IMPORT_LGE_PROP
1086 if (sink_priv->lge_ctxt.app_type)
1087 g_free(sink_priv->lge_ctxt.app_type);
1088 if (sink_priv->lge_ctxt.res_info.coretype)
1089 g_free(sink_priv->lge_ctxt.res_info.coretype);
1090#endif
xuesong.jiangd91230d2021-10-20 15:51:10 +08001091 memset(sink_priv, 0, sizeof(GstAmlVideoSinkPrivate));
1092 sink_priv->render_device_name = RENDER_DEVICE_NAME;
1093 sink_priv->use_dmabuf = USE_DMABUF;
xuesong.jiang50a0f932021-11-15 15:18:51 +08001094 sink_priv->mediasync_instanceid = -1;
xuesong.jiangd91230d2021-10-20 15:51:10 +08001095}
1096
xuesong.jiang1700bab2021-11-17 17:11:11 +08001097void gst_render_msg_callback(void *userData, RenderMsgType type, void *msg)
xuesong.jiangd91230d2021-10-20 15:51:10 +08001098{
xuesong.jiange90be372021-10-21 11:29:57 +08001099 GstAmlVideoSink *sink = (GstAmlVideoSink *)userData;
1100 switch (type)
xuesong.jiangd91230d2021-10-20 15:51:10 +08001101 {
xuesong.jiang28a82172022-04-28 15:05:46 +08001102 case MSG_DROPED_BUFFER:
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001103 case MSG_DISPLAYED_BUFFER:
1104 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001105 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
1106 RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
1107 RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
1108 GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
1109 if (buffer)
1110 {
xuesong.jiang9ae8f882022-04-18 20:15:06 +08001111 sink->last_displayed_buf_pts = GST_BUFFER_PTS(buffer);
xuesong.jiang5d2761f2022-05-05 11:43:21 +08001112 if (type == MSG_DROPED_BUFFER)
xuesong.jiang28a82172022-04-28 15:05:46 +08001113 {
1114 GST_LOG_OBJECT(sink, "get message: MSG_DROPED_BUFFER from tunnel lib");
1115 sink->droped++;
1116 }
xuesong.jiang5d2761f2022-05-05 11:43:21 +08001117 else if (type == MSG_DISPLAYED_BUFFER)
xuesong.jiang28a82172022-04-28 15:05:46 +08001118 {
1119 GST_LOG_OBJECT(sink, "get message: MSG_DISPLAYED_BUFFER from tunnel lib");
1120 sink->rendered++;
1121 }
1122
1123 GST_DEBUG_OBJECT(sink, "buf:%p planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d pts:%lld, buf stat | queued:%d, dequeued:%d, droped:%d, rendered:%d",
xuesong.jiang5d2761f2022-05-05 11:43:21 +08001124 buffer,
1125 dmabuf->planeCnt, dmabuf->fd[0], dmabuf->fd[1],
1126 buffer ? GST_BUFFER_PTS(buffer) : -1, sink->queued, sink->dequeued, sink->droped, sink->rendered);
1127 gst_aml_video_sink_dump_stat(sink, GST_DUMP_STAT_FILENAME);
xuesong.jiang62ed50e2022-04-13 16:55:47 +08001128 if ((sink_priv->got_eos || sink_priv->is_flushing) && sink->queued == sink->rendered + sink->droped)
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001129 {
1130 gst_emit_eos_signal(sink);
1131 }
1132 }
1133 else
1134 {
xuesong.jiang28a82172022-04-28 15:05:46 +08001135 GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_DISPLAYED_BUFFER or MSG_DROPED_BUFFER");
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001136 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001137 break;
1138 }
xuesong.jiang50a0f932021-11-15 15:18:51 +08001139 case MSG_RELEASE_BUFFER:
xuesong.jiangd91230d2021-10-20 15:51:10 +08001140 {
xuesong.jiang3e593432021-11-25 16:10:03 +08001141 GST_LOG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib");
xuesong.jiange90be372021-10-21 11:29:57 +08001142 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
xuesong.jiang50a0f932021-11-15 15:18:51 +08001143 RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
1144 GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
xuesong.jiange90be372021-10-21 11:29:57 +08001145
1146 if (buffer)
1147 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001148 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 +08001149 gst_buffer_unref(buffer);
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001150 sink->dequeued++;
xuesong.jiang5d2761f2022-05-05 11:43:21 +08001151 gst_aml_video_sink_dump_stat(sink, GST_DUMP_STAT_FILENAME);
xuesong.jiange90be372021-10-21 11:29:57 +08001152 }
1153 else
1154 {
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001155 GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_RELEASE_BUFFER");
xuesong.jiange90be372021-10-21 11:29:57 +08001156 }
xuesong.jiang50a0f932021-11-15 15:18:51 +08001157 render_free_render_buffer_wrap(sink_priv->render_device_handle, tunnel_lib_buf_wrap);
1158 break;
1159 }
1160 case MSG_CONNECTED_FAIL:
1161 {
1162 GST_ERROR_OBJECT(sink, "tunnel lib: should not send message:%d", type);
1163 break;
1164 }
1165 case MSG_DISCONNECTED_FAIL:
1166 {
1167 GST_ERROR_OBJECT(sink, "tunnel lib: should not send message:%d", type);
xuesong.jiange90be372021-10-21 11:29:57 +08001168 break;
xuesong.jiangd91230d2021-10-20 15:51:10 +08001169 }
xuesong.jiange90be372021-10-21 11:29:57 +08001170 default:
1171 {
1172 GST_ERROR_OBJECT(sink, "tunnel lib: error message type");
1173 }
1174 }
1175 return;
1176}
1177
xuesong.jiang50a0f932021-11-15 15:18:51 +08001178int gst_render_val_callback(void *userData, int key, void *value)
1179{
1180 GstAmlVideoSink *vsink = (GstAmlVideoSink *)userData;
1181 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
xuesong.jiang32d78282021-11-18 19:24:15 +08001182 int *val = (int *)value;
xuesong.jiang50a0f932021-11-15 15:18:51 +08001183 gint ret = 0;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001184 switch (key)
xuesong.jiang50a0f932021-11-15 15:18:51 +08001185 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +08001186 case KEY_MEDIASYNC_INSTANCE_ID:
xuesong.jiang50a0f932021-11-15 15:18:51 +08001187 {
xuesong.jiangfc27c272022-05-11 17:09:02 +08001188 // vsink->avsync_mode = 0;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001189 if (render_set(sink_priv->render_device_handle, KEY_MEDIASYNC_SYNC_MODE, (void *)&vsink->avsync_mode) == -1)
1190 {
1191 GST_ERROR_OBJECT(vsink, "tunnel lib: set syncmode error");
1192 ret = -1;
1193 }
xuesong.jiang50a0f932021-11-15 15:18:51 +08001194 if (gst_get_mediasync_instanceid(vsink))
1195 {
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001196 *val = sink_priv->mediasync_instanceid;
1197 GST_DEBUG_OBJECT(vsink, "get mediasync instance id:%d", *val);
xuesong.jiang50a0f932021-11-15 15:18:51 +08001198 }
1199 else
1200 {
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001201 GST_ERROR_OBJECT(vsink, "can't get mediasync instance id, use vmaster");
xuesong.jiang50a0f932021-11-15 15:18:51 +08001202 ret = -1;
1203 }
1204 break;
1205 }
1206 case KEY_VIDEO_FORMAT:
1207 {
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001208 if (sink_priv->video_info.finfo != NULL)
xuesong.jiang32d78282021-11-18 19:24:15 +08001209 {
1210 *val = sink_priv->video_info.finfo->format;
1211 GST_DEBUG_OBJECT(vsink, "get video format:%d", *val);
1212 }
1213 else
xuesong.jiang50a0f932021-11-15 15:18:51 +08001214 {
1215 GST_ERROR_OBJECT(vsink, "get video format error");
xuesong.jiang32d78282021-11-18 19:24:15 +08001216 *val = GST_VIDEO_FORMAT_UNKNOWN;
xuesong.jiang50a0f932021-11-15 15:18:51 +08001217 ret = -1;
1218 }
1219 break;
1220 }
1221 default:
1222 {
1223 GST_ERROR_OBJECT(vsink, "tunnel lib: error key type");
1224 ret = -1;
1225 }
1226 }
1227 return ret;
1228}
1229
xuesong.jiang7c724a52021-10-22 17:18:58 +08001230static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap)
xuesong.jiange90be372021-10-21 11:29:57 +08001231{
1232 // only support dma buf
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001233 RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001234 GstMemory *dma_mem = NULL;
1235 GstVideoMeta *vmeta = NULL;
xuesong.jiange90be372021-10-21 11:29:57 +08001236 guint n_mem = 0;
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001237 gboolean ret = TRUE;
xuesong.jiange90be372021-10-21 11:29:57 +08001238
xuesong.jiangeb46f672021-11-19 19:05:56 +08001239 if (gst_buf == NULL || tunnel_lib_buf_wrap == NULL || dmabuf == NULL)
xuesong.jiange90be372021-10-21 11:29:57 +08001240 {
1241 GST_ERROR_OBJECT(vsink, "input params error");
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001242 ret = FALSE;
xuesong.jiange90be372021-10-21 11:29:57 +08001243 goto error;
1244 }
xuesong.jiang3e593432021-11-25 16:10:03 +08001245 gst_buffer_ref(gst_buf);
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001246 n_mem = gst_buffer_n_memory(gst_buf);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001247 vmeta = gst_buffer_get_video_meta(gst_buf);
1248 if (vmeta == NULL)
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001249 {
1250 GST_ERROR_OBJECT(vsink, "not found video meta info");
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001251 ret = FALSE;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001252 goto error;
1253 }
1254 if (n_mem > RENDER_MAX_PLANES || vmeta->n_planes > RENDER_MAX_PLANES || n_mem != vmeta->n_planes)
xuesong.jiange90be372021-10-21 11:29:57 +08001255 {
1256 GST_ERROR_OBJECT(vsink, "too many memorys in gst buffer");
1257 goto error;
1258 }
xuesong.jiangeb46f672021-11-19 19:05:56 +08001259 GST_DEBUG_OBJECT(vsink, "dbg3-0, dmabuf:%p", dmabuf);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001260
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001261 dmabuf->planeCnt = n_mem;
1262 dmabuf->width = vmeta->width;
1263 dmabuf->height = vmeta->height;
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001264
1265 GST_DEBUG_OBJECT(vsink, "dbgjxs, vmeta->width:%d, dmabuf->width:%d", vmeta->width, dmabuf->width);
1266
xuesong.jiang7c724a52021-10-22 17:18:58 +08001267 for (guint i = 0; i < n_mem; i++)
xuesong.jiange90be372021-10-21 11:29:57 +08001268 {
1269 gint dmafd;
1270 gsize size, offset, maxsize;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001271 dma_mem = gst_buffer_peek_memory(gst_buf, i);
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001272 guint mem_idx = 0;
1273 guint length = 0;
1274 gsize skip = 0;
1275
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001276 if (!gst_is_dmabuf_memory(dma_mem))
xuesong.jiange90be372021-10-21 11:29:57 +08001277 {
1278 GST_ERROR_OBJECT(vsink, "not support non-dma buf");
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001279 ret = FALSE;
xuesong.jiange90be372021-10-21 11:29:57 +08001280 goto error;
1281 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001282 size = gst_memory_get_sizes(dma_mem, &offset, &maxsize);
xuesong.jiang16983c92021-12-30 10:57:17 +08001283 GST_LOG_OBJECT(vsink, "get memory size:%d, offeset:%d, maxsize:%d", size, offset, maxsize);
1284
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001285 dmafd = gst_dmabuf_memory_get_fd(dma_mem);
1286 dmabuf->handle[i] = 0;
1287 dmabuf->fd[i] = dmafd;
1288 dmabuf->size[i] = dma_mem->size;
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001289 dmabuf->stride[i] = vmeta->stride[i];
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001290 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 +08001291 {
1292 dmabuf->offset[i] = dma_mem->offset + skip;
1293 GST_DEBUG_OBJECT(vsink, "get skip from buffer:%d, offset[%d]:%d", skip, i, dmabuf->offset[i]);
1294 }
1295 else
1296 {
1297 GST_ERROR_OBJECT(vsink, "get skip from buffer error");
1298 ret = FALSE;
1299 goto error;
1300 }
1301
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001302 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 +08001303 i, dmabuf->handle[i], dmabuf->fd[i], dmabuf->size[i], dmabuf->offset[i], dmabuf->stride[i]);
xuesong.jiange90be372021-10-21 11:29:57 +08001304 }
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001305 tunnel_lib_buf_wrap->flag = BUFFER_FLAG_EXTER_DMA_BUFFER;
xuesong.jiange90be372021-10-21 11:29:57 +08001306 tunnel_lib_buf_wrap->pts = GST_BUFFER_PTS(gst_buf);
xuesong.jiang8e8a58a2021-11-15 17:02:41 +08001307 tunnel_lib_buf_wrap->priv = (void *)gst_buf;
xuesong.jianga52aa5b2022-05-13 16:00:32 +08001308 GST_DEBUG_OBJECT(vsink, "set tunnel lib buf priv:%p from pool:%p, pts:%lld", tunnel_lib_buf_wrap->priv, gst_buf->pool, tunnel_lib_buf_wrap->pts);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001309 GST_DEBUG_OBJECT(vsink, "dbg: buf in:%p, planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d",
1310 tunnel_lib_buf_wrap->priv,
1311 dmabuf->planeCnt,
1312 dmabuf->fd[0],
1313 dmabuf->fd[1]);
1314
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001315 return ret;
xuesong.jiange90be372021-10-21 11:29:57 +08001316
1317error:
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001318 return ret;
xuesong.jiang1801e172021-10-11 10:56:41 +08001319}
1320
xuesong.jiang50a0f932021-11-15 15:18:51 +08001321static gboolean gst_get_mediasync_instanceid(GstAmlVideoSink *vsink)
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001322{
xuesong.jiang75ef01c2021-12-09 17:08:52 +08001323 GST_DEBUG_OBJECT(vsink, "trace in");
xuesong.jiang16983c92021-12-30 10:57:17 +08001324#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +08001325 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
1326 GstElement *asink = gst_aml_video_sink_find_audio_sink(vsink);
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001327 if (!asink)
1328 {
1329 GST_DEBUG_OBJECT(vsink, "pipeline don't have audio sink element");
1330 return FALSE;
1331 }
xuesong.jiang50a0f932021-11-15 15:18:51 +08001332 GstClock *amlclock = gst_aml_hal_asink_get_clock((GstElement *)asink);
1333 gboolean ret = TRUE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001334 if (amlclock)
1335 {
xuesong.jiang50a0f932021-11-15 15:18:51 +08001336 sink_priv->mediasync_instanceid = gst_aml_clock_get_session_id(amlclock);
1337 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);
1338 if (sink_priv->mediasync_instanceid == -1)
1339 {
1340 GST_ERROR_OBJECT(vsink, "audio sink: don't have valid mediasync instance id");
1341 ret = FALSE;
1342 }
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001343 }
1344 else
1345 {
xuesong.jiang50a0f932021-11-15 15:18:51 +08001346 GST_WARNING_OBJECT(vsink, "no clock: vmaster mode");
1347 ret = FALSE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001348 }
xuesong.jiang192316f2021-10-27 14:51:56 +08001349 gst_object_unref(asink);
xuesong.jiang75ef01c2021-12-09 17:08:52 +08001350#else
1351 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
1352 gboolean ret = TRUE;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001353 FILE *fp;
xuesong.jiang75ef01c2021-12-09 17:08:52 +08001354 fp = fopen("/data/MediaSyncId", "r");
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001355 if (fp == NULL)
1356 {
xuesong.jiang75ef01c2021-12-09 17:08:52 +08001357 GST_ERROR_OBJECT(vsink, "could not open file:/data/MediaSyncId failed");
1358 ret = FALSE;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001359 }
1360 else
1361 {
xuesong.jiang16983c92021-12-30 10:57:17 +08001362 size_t read_size = 0;
1363 read_size = fread(&sink_priv->mediasync_instanceid, sizeof(int), 1, fp);
1364 if (read_size != sizeof(int))
1365 {
1366 GST_DEBUG_OBJECT(vsink, "get mediasync instance id read error");
1367 }
xuesong.jiang75ef01c2021-12-09 17:08:52 +08001368 fclose(fp);
1369 GST_DEBUG_OBJECT(vsink, "get mediasync instance id:0x%x", sink_priv->mediasync_instanceid);
1370 }
1371#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +08001372 return ret;
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001373}
1374
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001375static void gst_emit_eos_signal(GstAmlVideoSink *vsink)
1376{
1377 GST_DEBUG_OBJECT(vsink, "emit eos signal");
1378 g_mutex_lock(&vsink->eos_lock);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001379 g_cond_signal(&vsink->eos_cond);
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001380 g_mutex_unlock(&vsink->eos_lock);
1381}
1382
1383static void gst_wait_eos_signal(GstAmlVideoSink *vsink)
1384{
1385 GST_DEBUG_OBJECT(vsink, "waitting eos signal");
1386 g_mutex_lock(&vsink->eos_lock);
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001387 g_cond_wait(&vsink->eos_cond, &vsink->eos_lock);
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001388 g_mutex_unlock(&vsink->eos_lock);
1389 GST_DEBUG_OBJECT(vsink, "waitted eos signal");
1390}
1391
xuesong.jiang16983c92021-12-30 10:57:17 +08001392#if GST_USE_PLAYBIN
xuesong.jiang50a0f932021-11-15 15:18:51 +08001393static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink)
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001394{
xuesong.jiang75ef01c2021-12-09 17:08:52 +08001395 GST_DEBUG_OBJECT(sink, "trace in");
xuesong.jiang50a0f932021-11-15 15:18:51 +08001396 GstElement *audioSink = 0;
1397 GstElement *pipeline = 0;
1398 GstElement *element, *elementPrev = 0;
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001399
xuesong.jiang50a0f932021-11-15 15:18:51 +08001400 element = GST_ELEMENT_CAST(sink);
1401 do
1402 {
1403 if (elementPrev)
1404 {
1405 gst_object_unref(elementPrev);
1406 }
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001407 // TODO use this func will ref elment,but when unref these element?
xuesong.jiang50a0f932021-11-15 15:18:51 +08001408 element = GST_ELEMENT_CAST(gst_element_get_parent(element));
1409 if (element)
1410 {
1411 elementPrev = pipeline;
1412 pipeline = element;
1413 }
1414 } while (element != 0);
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001415
xuesong.jiang50a0f932021-11-15 15:18:51 +08001416 if (pipeline)
1417 {
1418 GstIterator *iterElement = gst_bin_iterate_recurse(GST_BIN(pipeline));
1419 if (iterElement)
1420 {
1421 GValue itemElement = G_VALUE_INIT;
1422 while (gst_iterator_next(iterElement, &itemElement) == GST_ITERATOR_OK)
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001423 {
xuesong.jiang50a0f932021-11-15 15:18:51 +08001424 element = (GstElement *)g_value_get_object(&itemElement);
1425 if (element && !GST_IS_BIN(element))
1426 {
1427 int numSrcPads = 0;
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001428
xuesong.jiang50a0f932021-11-15 15:18:51 +08001429 GstIterator *iterPad = gst_element_iterate_src_pads(element);
1430 if (iterPad)
1431 {
1432 GValue itemPad = G_VALUE_INIT;
1433 while (gst_iterator_next(iterPad, &itemPad) == GST_ITERATOR_OK)
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001434 {
xuesong.jiang50a0f932021-11-15 15:18:51 +08001435 GstPad *pad = (GstPad *)g_value_get_object(&itemPad);
1436 if (pad)
1437 {
1438 ++numSrcPads;
1439 }
1440 g_value_reset(&itemPad);
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001441 }
xuesong.jiang50a0f932021-11-15 15:18:51 +08001442 gst_iterator_free(iterPad);
1443 }
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001444
xuesong.jiang50a0f932021-11-15 15:18:51 +08001445 if (numSrcPads == 0)
1446 {
1447 GstElementClass *ec = GST_ELEMENT_GET_CLASS(element);
1448 if (ec)
1449 {
1450 const gchar *meta = gst_element_class_get_metadata(ec, GST_ELEMENT_METADATA_KLASS);
1451 if (meta && strstr(meta, "Sink") && strstr(meta, "Audio"))
1452 {
1453 audioSink = (GstElement *)gst_object_ref(element);
1454 gchar *name = gst_element_get_name(element);
1455 if (name)
1456 {
1457 GST_DEBUG("detected audio sink: name (%s)", name);
1458 g_free(name);
1459 }
1460 g_value_reset(&itemElement);
1461 break;
1462 }
1463 }
1464 }
1465 }
1466 g_value_reset(&itemElement);
1467 }
1468 gst_iterator_free(iterElement);
1469 }
1470
1471 gst_object_unref(pipeline);
1472 }
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001473 GST_DEBUG_OBJECT(sink, "trace out get audioSink:%p", audioSink);
xuesong.jiang50a0f932021-11-15 15:18:51 +08001474 return audioSink;
1475}
xuesong.jiang16983c92021-12-30 10:57:17 +08001476#endif
xuesong.jiang50a0f932021-11-15 15:18:51 +08001477
1478static gboolean gst_render_set_params(GstVideoSink *vsink)
1479{
1480 GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
1481 GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
1482 GstVideoInfo *video_info = &(sink_priv->video_info);
xuesong.jiangbb769f02022-05-17 15:04:40 +08001483 int tunnelmode = 0; // 1 for tunnel mode; 0 for non-tunnel mode
xuesong.jiang50a0f932021-11-15 15:18:51 +08001484
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001485 // RenderWindowSize window_size = {0, 0, video_info->width, video_info->height};
xuesong.jiang50a0f932021-11-15 15:18:51 +08001486 RenderFrameSize frame_size = {video_info->width, video_info->height};
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001487 GstVideoFormat format = video_info->finfo ? video_info->finfo->format : GST_VIDEO_FORMAT_UNKNOWN;
xuesong.jiang4a832aa2022-01-06 16:44:26 +08001488 // if (render_set(sink_priv->render_device_handle, KEY_WINDOW_SIZE, &window_size) == -1)
1489 // {
1490 // GST_ERROR_OBJECT(vsink, "tunnel lib: set window size error");
1491 // return FALSE;
1492 // }
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001493 if (render_set(sink_priv->render_device_handle, KEY_MEDIASYNC_TUNNEL_MODE, (void *)&tunnelmode) == -1)
1494 {
1495 GST_ERROR_OBJECT(vsink, "tunnel lib: set tunnelmode error");
1496 return FALSE;
1497 }
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001498 if (render_set(sink_priv->render_device_handle, KEY_FRAME_SIZE, &frame_size) == -1)
xuesong.jiang50a0f932021-11-15 15:18:51 +08001499 {
1500 GST_ERROR_OBJECT(vsink, "tunnel lib: set frame size error");
1501 return FALSE;
1502 }
xuesong.jiangf190e2a2021-11-22 20:26:00 +08001503 if (render_set(sink_priv->render_device_handle, KEY_VIDEO_FORMAT, &format) == -1)
xuesong.jiang32d78282021-11-18 19:24:15 +08001504 {
1505 GST_ERROR_OBJECT(vsink, "tunnel lib: set video format error");
1506 return FALSE;
1507 }
1508
xuesong.jiang50a0f932021-11-15 15:18:51 +08001509 return TRUE;
xuesong.jiangb4c09b52021-10-26 20:18:35 +08001510}
1511
xuesong.jiang5d2761f2022-05-05 11:43:21 +08001512static void gst_aml_video_sink_dump_stat(GstAmlVideoSink *sink, const gchar *file_name)
1513{
1514 const gchar *dump_dir = NULL;
1515 gchar *full_file_name = NULL;
1516 FILE *out = NULL;
1517
1518 dump_dir = g_getenv("GST_DEBUG_DUMP_AMLVIDEOSINK_STAT_DIR");
1519 if (G_LIKELY(dump_dir == NULL))
1520 return;
1521
1522 if (!file_name)
1523 {
1524 file_name = "unnamed";
1525 }
1526
1527 full_file_name = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s.stat", dump_dir, file_name);
1528
1529 if ((out = fopen(full_file_name, "w")))
1530 {
1531 gchar *stat_info;
1532 stat_info = g_strdup_printf("Q:%d, Dq:%d, Render:%d, Drop:%d\n", sink->queued, sink->dequeued, sink->rendered, sink->droped);
1533 fputs(stat_info, out);
1534 g_free(stat_info);
1535 fclose(out);
1536 GST_INFO("wrote amlvideosink stat to : '%s' succ", full_file_name);
1537 }
1538 else
1539 {
1540 GST_WARNING("Failed to open file '%s' for writing: %s", full_file_name, g_strerror(errno));
1541 }
1542 g_free(full_file_name);
1543}
1544
xuesong.jiang1801e172021-10-11 10:56:41 +08001545/* plugin init */
xuesong.jiangd91230d2021-10-20 15:51:10 +08001546static gboolean plugin_init(GstPlugin *plugin)
1547{
xuesong.jiang1700bab2021-11-17 17:11:11 +08001548 GST_DEBUG_CATEGORY_INIT(gst_aml_video_sink_debug, "amlvideosink", 0,
1549 " aml video sink");
xuesong.jiang1801e172021-10-11 10:56:41 +08001550
xuesong.jiangf0ebebe2021-12-24 09:41:15 +08001551 gint rank = 1;
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001552 const char *rank_env = getenv("GST_AML_VIDEO_SINK_RANK");
1553 if (rank_env)
1554 {
1555 rank = atoi(rank_env);
1556 }
xuesong.jiangf0ebebe2021-12-24 09:41:15 +08001557
1558 return gst_element_register(plugin, "amlvideosink", rank,
xuesong.jiangd91230d2021-10-20 15:51:10 +08001559 GST_TYPE_AML_VIDEO_SINK);
xuesong.jiang1801e172021-10-11 10:56:41 +08001560}
1561
xuesong.jiang5c0d1b82021-11-16 19:30:56 +08001562#ifndef VERSION
1563#define VERSION "0.1.0"
1564#endif
1565#ifndef PACKAGE
1566#define PACKAGE "aml_package"
1567#endif
1568#ifndef PACKAGE_NAME
1569#define PACKAGE_NAME "aml_media"
1570#endif
1571#ifndef GST_PACKAGE_ORIGIN
1572#define GST_PACKAGE_ORIGIN "http://amlogic.com"
1573#endif
1574// GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, amlvideosink,
1575// "aml Video Sink", plugin_init, VERSION, "LGPL",
1576// "gst-plugin-video-sink", "")
xuesong.jiang7ec9f8f2022-03-14 15:03:04 +08001577GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
1578 GST_VERSION_MINOR,
1579 amlvideosink,
1580 "Amlogic plugin for video decoding/rendering",
1581 plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)