blob: c2fdffe070ac60ed4eee6cebd548dee49fb94e52 [file] [log] [blame]
xuesong.jiangae1548e2022-05-06 16:38:46 +08001/* GStreamer
2 * Copyright (C) 2022 <xuesong.jiang@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#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <errno.h>
27#include <unistd.h>
28#include <string.h>
29
30#include "gstamlv4l2object.h"
31#include "gstamlv4l2videodec.h"
32
33#include <string.h>
34#include <gst/gst-i18n-plugin.h>
35#include <gst/allocators/gstdmabuf.h>
36
37GST_DEBUG_CATEGORY_STATIC(gst_aml_v4l2_video_dec_debug);
38#define GST_CAT_DEFAULT gst_aml_v4l2_video_dec_debug
zengliang.lidcd41462024-06-19 16:05:12 +080039#define GST_AML_V4L2_CC_IMPORT_QUARK gst_aml_v4l2_buffer_pool_cc_import_quark ()
40
hanghang.luo36df2852022-08-24 15:02:27 +080041#ifndef ABSDIFF
42#define ABSDIFF(a,b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
43#endif
44
xuesong.jiang61ea8012022-05-12 15:38:17 +080045#if GST_IMPORT_LGE_PROP
46typedef struct _GstAmlResourceInfo
47{
48 gchar *coretype;
49 gint videoport;
50 gint audioport;
51 gint maxwidth;
52 gint maxheight;
53 gint mixerport;
54} GstAmlResourceInfo;
55
56struct _GstAmlV4l2VideoDecLgeCtxt
57{
58 GstAmlResourceInfo res_info;
59 guint64 dec_size;
60 guint64 undec_size;
61 gchar *app_type;
62 gboolean clip_mode;
63};
64#endif
65
xuesong.jiangae1548e2022-05-06 16:38:46 +080066typedef struct
67{
bo.xiao857b8682024-09-12 16:40:32 +080068 gchar *device;
69 GstCaps *sink_caps;
70 GstCaps *src_caps;
71 const gchar *longname;
72 const gchar *description;
xuesong.jiangae1548e2022-05-06 16:38:46 +080073} GstAmlV4l2VideoDecCData;
74
75enum
76{
bo.xiao857b8682024-09-12 16:40:32 +080077 PROP_0,
78 V4L2_STD_OBJECT_PROPS,
xuesong.jiang61ea8012022-05-12 15:38:17 +080079#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +080080 LGE_RESOURCE_INFO,
81 LGE_DECODE_SIZE,
82 LGE_UNDECODE_SIZE,
83 LGE_APP_TYPE,
84 LGE_CLIP_MODE
xuesong.jiang61ea8012022-05-12 15:38:17 +080085#endif
xuesong.jiangae1548e2022-05-06 16:38:46 +080086};
87
xuesong.jiang406ee302023-06-28 03:45:22 +000088enum
89{
90 SIGNAL_DECODED_PTS,
le.han7e9c27d2024-08-08 08:10:46 +000091 SIGNAL_DECODED_ERROR_PTS,
xuesong.jiang406ee302023-06-28 03:45:22 +000092 MAX_SIGNAL
93};
94
95static guint g_signals[MAX_SIGNAL]= {0};
96
xuesong.jiangae1548e2022-05-06 16:38:46 +080097#define gst_aml_v4l2_video_dec_parent_class parent_class
98G_DEFINE_ABSTRACT_TYPE(GstAmlV4l2VideoDec, gst_aml_v4l2_video_dec,
bo.xiao857b8682024-09-12 16:40:32 +080099 GST_AML_TYPE_VIDEO_DECODER);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800100
le.han02c38f02024-08-16 02:35:36 +0000101static GstFlowReturn gst_aml_v4l2_video_dec_finish(GstAmlVideoDecoder *decoder);
xuesong.jiang61ea8012022-05-12 15:38:17 +0800102#if GST_IMPORT_LGE_PROP
103static void gst_aml_v4l2_video_dec_install_lge_properties_helper(GObjectClass *gobject_class);
104#endif
le.han44125c32024-09-03 07:55:57 +0000105static GstClockTime gst_aml_v4l2_video_dec_calc_output_buffer_pts(GstAmlVideoDecoder *decoder);
106static GstClockTime gst_aml_v4l2_video_dec_calc_duration(GstAmlVideoDecoder *decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800107
108static void
109gst_aml_v4l2_video_dec_set_property(GObject *object,
bo.xiao857b8682024-09-12 16:40:32 +0800110 guint prop_id, const GValue * value, GParamSpec * pspec)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800111{
bo.xiao857b8682024-09-12 16:40:32 +0800112 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(object);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800113
bo.xiao857b8682024-09-12 16:40:32 +0800114 switch (prop_id)
115 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800116 case PROP_CAPTURE_IO_MODE:
xuesong.jiangae1548e2022-05-06 16:38:46 +0800117 case PROP_DUMP_FRAME_LOCATION:
zengliang.lidcd41462024-06-19 16:05:12 +0800118 case PROP_CC_DATA:
bo.xiao857b8682024-09-12 16:40:32 +0800119 if (!gst_aml_v4l2_object_set_property_helper(self->v4l2capture,
120 prop_id, value, pspec))
121 {
122 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
123 }
124 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800125#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +0800126 case LGE_RESOURCE_INFO:
127 {
128 GST_DEBUG_OBJECT(self, "LGE up layer set res info");
129 GstStructure *r_info = g_value_get_object(value);
130 if (r_info)
131 {
132 if (gst_structure_has_field(r_info, "coretype"))
133 {
134 if (self->lge_ctxt->res_info.coretype)
135 g_free(self->lge_ctxt->res_info.coretype);
136 self->lge_ctxt->res_info.coretype = g_strdup(gst_structure_get_string(r_info, "coretype"));
137 }
138 if (gst_structure_has_field(r_info, "videoport"))
139 gst_structure_get_int(r_info, "videoport", &(self->lge_ctxt->res_info.videoport));
140 if (gst_structure_has_field(r_info, "audioport"))
141 gst_structure_get_int(r_info, "audioport", &(self->lge_ctxt->res_info.audioport));
142 if (gst_structure_has_field(r_info, "maxwidth"))
143 gst_structure_get_int(r_info, "maxwidth", &(self->lge_ctxt->res_info.maxwidth));
144 if (gst_structure_has_field(r_info, "maxheight"))
145 gst_structure_get_int(r_info, "maxheight", &(self->lge_ctxt->res_info.maxheight));
146 if (gst_structure_has_field(r_info, "mixerport"))
147 gst_structure_get_int(r_info, "mixerport", &(self->lge_ctxt->res_info.mixerport));
148 }
149 break;
150 }
151 case LGE_APP_TYPE:
152 {
153 GST_DEBUG_OBJECT(self, "LGE up layer set app type");
154 if (self->lge_ctxt->app_type)
155 g_free(self->lge_ctxt->app_type);
156 self->lge_ctxt->app_type = g_strdup(g_value_get_string(value));
157 break;
158 }
159 case LGE_CLIP_MODE:
160 {
161 GST_DEBUG_OBJECT(self, "LGE up layer set clip mode");
162 self->lge_ctxt->clip_mode = g_strdup(g_value_get_boolean(value));
163 break;
164 }
xuesong.jiang61ea8012022-05-12 15:38:17 +0800165#endif
bo.xiao857b8682024-09-12 16:40:32 +0800166 /* By default, only set on output */
xuesong.jiangae1548e2022-05-06 16:38:46 +0800167 default:
bo.xiao857b8682024-09-12 16:40:32 +0800168 if (!gst_aml_v4l2_object_set_property_helper (self->v4l2output,
169 prop_id, value, pspec))
170 {
171 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
172 }
173 break;
174 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800175}
176
177static void
178gst_aml_v4l2_video_dec_get_property(GObject *object,
179 guint prop_id, GValue *value, GParamSpec *pspec)
180{
bo.xiao857b8682024-09-12 16:40:32 +0800181 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(object);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800182
bo.xiao857b8682024-09-12 16:40:32 +0800183 switch (prop_id)
184 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800185 case PROP_CAPTURE_IO_MODE:
zengliang.lidcd41462024-06-19 16:05:12 +0800186 case PROP_CC_DATA:
fei.dengaf682762024-06-24 19:06:03 +0800187 case PROP_DECODING_ERROR_FRAMES:
bo.xiao857b8682024-09-12 16:40:32 +0800188 if (!gst_aml_v4l2_object_get_property_helper (self->v4l2capture,
189 prop_id, value, pspec))
190 {
191 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
192 }
193 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800194#if GST_IMPORT_LGE_PROP
195 case LGE_DECODE_SIZE:
196 {
bo.xiao857b8682024-09-12 16:40:32 +0800197 GST_DEBUG_OBJECT(self, "LGE up layer get dec size");
198 self->lge_ctxt->dec_size = -1;
199 g_value_set_int(value, self->lge_ctxt->dec_size);
200 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800201 }
202 case LGE_UNDECODE_SIZE:
203 {
bo.xiao857b8682024-09-12 16:40:32 +0800204 GST_DEBUG_OBJECT(self, "LGE up layer get undec size");
205 self->lge_ctxt->undec_size = -1;
206 g_value_set_int(value, self->lge_ctxt->undec_size);
207 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800208 }
209#endif
210
bo.xiao857b8682024-09-12 16:40:32 +0800211 /* By default read from output */
212 default:
213 if (!gst_aml_v4l2_object_get_property_helper (self->v4l2output,
214 prop_id, value, pspec))
215 {
216 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800217 }
bo.xiao857b8682024-09-12 16:40:32 +0800218 break;
219 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800220}
221
222static gboolean
le.han02c38f02024-08-16 02:35:36 +0000223gst_aml_v4l2_video_dec_open(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800224{
bo.xiao857b8682024-09-12 16:40:32 +0800225 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
226 GstCaps *codec_caps;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800227
bo.xiao857b8682024-09-12 16:40:32 +0800228 GST_DEBUG_OBJECT (self, "Opening");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800229
bo.xiao857b8682024-09-12 16:40:32 +0800230 if (!gst_aml_v4l2_object_open (self->v4l2output))
xuesong.jiangae1548e2022-05-06 16:38:46 +0800231 goto failure;
232
bo.xiao857b8682024-09-12 16:40:32 +0800233 if (!gst_aml_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
234 goto failure;
235
236 codec_caps = gst_pad_get_pad_template_caps (decoder->sinkpad);
237 self->probed_sinkcaps = gst_aml_v4l2_object_probe_caps (self->v4l2output,
238 codec_caps);
239 gst_caps_unref (codec_caps);
240
241 if (gst_caps_is_empty (self->probed_sinkcaps))
242 goto no_encoded_format;
243
244 return TRUE;
245
246no_encoded_format:
247 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
248 (_("Decoder on device %s has no supported input format"),
249 self->v4l2output->videodev), (NULL));
250 goto failure;
251
xuesong.jiangae1548e2022-05-06 16:38:46 +0800252failure:
bo.xiao857b8682024-09-12 16:40:32 +0800253 if (GST_AML_V4L2_IS_OPEN (self->v4l2output))
254 gst_aml_v4l2_object_close (self->v4l2output);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800255
bo.xiao857b8682024-09-12 16:40:32 +0800256 if (GST_AML_V4L2_IS_OPEN (self->v4l2capture))
257 gst_aml_v4l2_object_close (self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800258
bo.xiao857b8682024-09-12 16:40:32 +0800259 gst_caps_replace (&self->probed_srccaps, NULL);
260 gst_caps_replace (&self->probed_sinkcaps, NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800261
bo.xiao857b8682024-09-12 16:40:32 +0800262 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800263}
264
265static gboolean
le.han02c38f02024-08-16 02:35:36 +0000266gst_aml_v4l2_video_dec_close(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800267{
bo.xiao857b8682024-09-12 16:40:32 +0800268 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800269
bo.xiao857b8682024-09-12 16:40:32 +0800270 GST_DEBUG_OBJECT (self, "Closing");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800271
bo.xiao857b8682024-09-12 16:40:32 +0800272 gst_aml_v4l2_object_close(self->v4l2output);
273 gst_aml_v4l2_object_close(self->v4l2capture);
274 gst_caps_replace (&self->probed_srccaps, NULL);
275 gst_caps_replace (&self->probed_sinkcaps, NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800276
bo.xiao857b8682024-09-12 16:40:32 +0800277 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800278}
279
280static gboolean
le.han02c38f02024-08-16 02:35:36 +0000281gst_aml_v4l2_video_dec_start(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800282{
bo.xiao857b8682024-09-12 16:40:32 +0800283 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800284
bo.xiao857b8682024-09-12 16:40:32 +0800285 GST_DEBUG_OBJECT (self, "Starting");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800286
bo.xiao857b8682024-09-12 16:40:32 +0800287 gst_aml_v4l2_object_flush_start (self->v4l2output);
288 g_atomic_int_set (&self->active, TRUE);
289 self->output_flow = GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800290
bo.xiao857b8682024-09-12 16:40:32 +0800291 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800292}
293
294static gboolean
le.han02c38f02024-08-16 02:35:36 +0000295gst_aml_v4l2_video_dec_stop(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800296{
bo.xiao857b8682024-09-12 16:40:32 +0800297 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800298
bo.xiao857b8682024-09-12 16:40:32 +0800299 GST_DEBUG_OBJECT (self, "Stopping");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800300
bo.xiao857b8682024-09-12 16:40:32 +0800301 gst_aml_v4l2_object_flush_start (self->v4l2output);
302 gst_aml_v4l2_object_flush_start (self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800303
bo.xiao857b8682024-09-12 16:40:32 +0800304 /* Wait for capture thread to stop */
305 gst_pad_stop_task (decoder->srcpad);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800306
bo.xiao857b8682024-09-12 16:40:32 +0800307 GST_AML_VIDEO_DECODER_STREAM_LOCK(decoder);
308 self->output_flow = GST_FLOW_OK;
309 GST_AML_VIDEO_DECODER_STREAM_UNLOCK(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800310
bo.xiao857b8682024-09-12 16:40:32 +0800311 /* Should have been flushed already */
312 g_assert (g_atomic_int_get (&self->active) == FALSE);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800313
bo.xiao857b8682024-09-12 16:40:32 +0800314 gst_aml_v4l2_object_stop(self->v4l2output);
315 gst_aml_v4l2_object_stop(self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800316
bo.xiao857b8682024-09-12 16:40:32 +0800317 if (self->input_state)
318 {
319 gst_aml_video_codec_state_unref(self->input_state);
320 self->input_state = NULL;
321 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800322
bo.xiao857b8682024-09-12 16:40:32 +0800323 GST_DEBUG_OBJECT (self, "Stopped");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800324
bo.xiao857b8682024-09-12 16:40:32 +0800325 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800326}
327
328static gboolean
le.han02c38f02024-08-16 02:35:36 +0000329gst_aml_v4l2_video_dec_codec_chg(GstAmlVideoDecoder *decoder,
330 GstAmlVideoCodecState *state)
hanghang.luo8e1225b2023-10-10 08:54:28 +0000331{
bo.xiao857b8682024-09-12 16:40:32 +0800332 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
333 GstStructure *s_old = NULL;
334 GstStructure *s_new = NULL;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000335
bo.xiao857b8682024-09-12 16:40:32 +0800336 // first play, must set foramt;
337 if (!self->input_state)
338 return TRUE;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000339
bo.xiao857b8682024-09-12 16:40:32 +0800340 if (self->input_state->caps)
341 s_old = gst_caps_get_structure(self->input_state->caps,0);
342 if (state->caps)
343 s_new = gst_caps_get_structure(state->caps,0);
hanghang.luo8e1225b2023-10-10 08:54:28 +0000344
bo.xiao857b8682024-09-12 16:40:32 +0800345 if (s_new && s_old && strcmp(gst_structure_get_name(s_new),gst_structure_get_name(s_old)))
346 return TRUE;
347 return FALSE;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000348}
349
350static gboolean
le.han02c38f02024-08-16 02:35:36 +0000351gst_aml_v4l2_video_dec_res_chg(GstAmlVideoDecoder *decoder,
352 GstAmlVideoCodecState *state)
hanghang.luo8e1225b2023-10-10 08:54:28 +0000353{
bo.xiao857b8682024-09-12 16:40:32 +0800354 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
355 gboolean ret = FALSE;
356 gint width_new = -1,height_new = -1,width_old = -1,height_old = -1;
357 GstStructure *s_old = NULL;
358 GstStructure *s_new = NULL;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000359
bo.xiao857b8682024-09-12 16:40:32 +0800360 // first play, must set foramt;
361 if (!self->input_state)
362 {
363 ret = TRUE;
364 goto done;
365 }
hanghang.luo8e1225b2023-10-10 08:54:28 +0000366
bo.xiao857b8682024-09-12 16:40:32 +0800367 if (self->input_state->caps)
368 s_old = gst_caps_get_structure(self->input_state->caps,0);
369 if (state->caps)
370 s_new = gst_caps_get_structure(state->caps,0);
hanghang.luo8e1225b2023-10-10 08:54:28 +0000371
bo.xiao857b8682024-09-12 16:40:32 +0800372 if (s_new && gst_structure_has_field(s_new,"width") && gst_structure_has_field(s_new,"height"))
373 {
374 gst_structure_get_int(s_new,"width",&width_new);
375 gst_structure_get_int(s_new,"height",&height_new);
376 }
377 if (s_old && gst_structure_has_field(s_old,"width") && gst_structure_has_field(s_old,"height"))
378 {
379 gst_structure_get_int(s_old,"width",&width_old);
380 gst_structure_get_int(s_old,"height",&height_old);
381 }
hanghang.luo8e1225b2023-10-10 08:54:28 +0000382
bo.xiao857b8682024-09-12 16:40:32 +0800383 if (width_new != width_old || height_new != height_old)
384 ret = TRUE;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000385
386done:
bo.xiao857b8682024-09-12 16:40:32 +0800387 GST_DEBUG_OBJECT(self, "ret is %d",ret);
388 return ret;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000389}
390
391static gboolean
le.han02c38f02024-08-16 02:35:36 +0000392gst_aml_v4l2_video_dec_set_format(GstAmlVideoDecoder *decoder,
393 GstAmlVideoCodecState *state)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800394{
bo.xiao857b8682024-09-12 16:40:32 +0800395 GstAmlV4l2Error error = GST_AML_V4L2_ERROR_INIT;
396 gboolean ret = TRUE;
397 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
398 GstCaps *caps;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800399
bo.xiao857b8682024-09-12 16:40:32 +0800400 GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
401 if (self->input_state)
402 {
403 if (gst_aml_v4l2_video_dec_res_chg(decoder,state) || gst_aml_v4l2_video_dec_codec_chg(decoder,state))
404 GST_DEBUG_OBJECT(self, "resolution or codec changed");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800405 else
bo.xiao857b8682024-09-12 16:40:32 +0800406 goto done;
407 }
408
409 GstCapsFeatures *const features = gst_caps_get_features(state->caps, 0);
410 GstStructure *s = gst_caps_get_structure(state->caps,0);
411 if (s && gst_structure_has_field(s,"format"))
412 {
413 if (!strcmp("XVID",gst_structure_get_string(s,"format")))
414 {
415 GST_DEBUG_OBJECT(self, "This is a DIVX file, cannot support");
416 ret = FALSE;
417 goto done;
418 }
419 }
420
421 if (gst_caps_features_contains(features, GST_CAPS_FEATURE_MEMORY_DMABUF))
422 self->v4l2output->req_mode = GST_V4L2_IO_DMABUF_IMPORT;
423
424 if (self->input_state)
425 {
426 if (gst_aml_v4l2_object_caps_equal(self->v4l2output, state->caps))
427 {
428 GST_DEBUG_OBJECT (self, "Compatible caps");
429 goto done;
430 }
431
432 gst_aml_v4l2_video_dec_finish (decoder);
433 gst_aml_v4l2_object_stop (self->v4l2output);
434
435 gst_aml_video_codec_state_unref(self->input_state);
436 self->input_state = NULL;
437
438 /* The renegotiation flow don't blend with the base class flow. To properly
439 * stop the capture pool, if the buffers can't be orphaned, we need to
440 * reclaim our buffers, which will happend through the allocation query.
441 * The allocation query is triggered by gst_aml_video_decoder_negotiate() which
442 * requires the output caps to be set, but we can't know this information
443 * as we rely on the decoder, which requires the capture queue to be
444 * stopped.
445 *
446 * To workaround this issue, we simply run an allocation query with the
447 * old negotiated caps in order to drain/reclaim our buffers. That breaks
448 * the complexity and should not have much impact in performance since the
449 * following allocation query will happen on a drained pipeline and won't
450 * block. */
451 if (self->v4l2capture->pool &&
452 !gst_aml_v4l2_buffer_pool_orphan(&self->v4l2capture->pool))
453 {
454 GstCaps *caps = gst_pad_get_current_caps (decoder->srcpad);
455 if (caps)
456 {
457 GstQuery *query = gst_query_new_allocation (caps, FALSE);
458 gst_pad_peer_query (decoder->srcpad, query);
459 gst_query_unref (query);
460 gst_caps_unref (caps);
461 }
462 }
463
464 gst_aml_v4l2_object_stop (self->v4l2capture);
465 self->output_flow = GST_FLOW_OK;
466 }
467 if ((ret = gst_aml_v4l2_set_drm_mode(self->v4l2output)) == FALSE)
468 {
469 GST_ERROR_OBJECT(self, "config output drm mode error");
470 goto done;
471 }
472
473 if ((ret = gst_aml_v4l2_set_stream_mode(self->v4l2output)) == FALSE)
474 {
475 GST_ERROR_OBJECT(self, "config output stream mode error");
476 goto done;
477 }
478
479 if (!gst_aml_v4l2_object_set_format (self->v4l2output, state->caps, &error))
480 {
481 GST_ERROR_OBJECT(self, "set format error");
482 goto done;
483 }
484
485 // MUST: aml v4l2 drive request set I frame after VIDIOC_S_FMT.
486 if ((ret = gst_aml_v4l2_set_I_frame_mode(self->v4l2output)) == FALSE)
487 {
488 GST_ERROR_OBJECT(self, "config I frame mode error");
489 goto done;
490 }
491
492 gst_caps_replace (&self->probed_srccaps, NULL);
493 self->probed_srccaps = gst_aml_v4l2_object_probe_caps (self->v4l2capture,
494 gst_aml_v4l2_object_get_raw_caps ());
495
496 if (gst_caps_is_empty (self->probed_srccaps))
497 goto no_raw_format;
498
499 caps = gst_caps_copy(self->probed_srccaps);
500 gst_caps_set_features_simple(caps, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
501 gst_caps_append(self->probed_srccaps, caps);
502 if (ret)
503 self->input_state = gst_aml_video_codec_state_ref (state);
504 else
505 gst_aml_v4l2_error (self, &error);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800506
507done:
bo.xiao857b8682024-09-12 16:40:32 +0800508 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800509
510no_raw_format:
bo.xiao857b8682024-09-12 16:40:32 +0800511 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
512 (_("Decoder on device %s has no supported output format"),
513 self->v4l2output->videodev), (NULL));
514 return GST_FLOW_ERROR;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800515}
516
517static gboolean
le.han02c38f02024-08-16 02:35:36 +0000518gst_aml_v4l2_video_dec_flush(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800519{
bo.xiao857b8682024-09-12 16:40:32 +0800520 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800521
bo.xiao857b8682024-09-12 16:40:32 +0800522 GST_DEBUG_OBJECT(self, "Flushed");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800523
bo.xiao857b8682024-09-12 16:40:32 +0800524 /* Ensure the processing thread has stopped for the reverse playback
525 * discount case */
526 if (gst_pad_get_task_state (decoder->srcpad) == GST_TASK_STARTED)
527 {
528 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800529
bo.xiao857b8682024-09-12 16:40:32 +0800530 gst_aml_v4l2_object_flush_start (self->v4l2output);
531 gst_aml_v4l2_object_flush_start (self->v4l2capture);
532 gst_pad_stop_task (decoder->srcpad);
533 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
534 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800535
bo.xiao857b8682024-09-12 16:40:32 +0800536 self->output_flow = GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800537
bo.xiao857b8682024-09-12 16:40:32 +0800538 gst_aml_v4l2_object_flush_stop (self->v4l2output);
539 gst_aml_v4l2_object_flush_stop (self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800540
bo.xiao857b8682024-09-12 16:40:32 +0800541 if (self->v4l2output->pool)
542 gst_aml_v4l2_buffer_pool_flush (self->v4l2output->pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800543
bo.xiao857b8682024-09-12 16:40:32 +0800544 /* gst_aml_v4l2_buffer_pool_flush() calls streamon the capture pool and must be
545 * called after gst_aml_v4l2_object_flush_stop() stopped flushing the buffer
546 * pool. */
547 if (self->v4l2capture->pool)
548 gst_aml_v4l2_buffer_pool_flush (self->v4l2capture->pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800549
bo.xiao857b8682024-09-12 16:40:32 +0800550 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800551}
552
553static gboolean
le.han02c38f02024-08-16 02:35:36 +0000554gst_aml_v4l2_video_dec_negotiate(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800555{
bo.xiao857b8682024-09-12 16:40:32 +0800556 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800557
bo.xiao857b8682024-09-12 16:40:32 +0800558 if (TRUE == self->v4l2output->is_svp)
559 {
560 GstStructure *s;
561 GstEvent *event;
xuesong.jiang681d3602022-06-24 21:23:35 +0800562
bo.xiao857b8682024-09-12 16:40:32 +0800563 s = gst_structure_new_empty ("IS_SVP");
564 event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, s);
565 GST_DEBUG_OBJECT(self, "before Send SVP Event :%p", event);
566 gst_pad_push_event (decoder->srcpad, event);
567 GST_DEBUG_OBJECT(self, "after Send SVP Event :%p", event);
568 }
xuesong.jiang681d3602022-06-24 21:23:35 +0800569
bo.xiao857b8682024-09-12 16:40:32 +0800570 /* We don't allow renegotiation without carefull disabling the pool */
571 if (self->v4l2capture->pool &&
572 gst_buffer_pool_is_active(GST_BUFFER_POOL(self->v4l2capture->pool)))
573 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800574
bo.xiao857b8682024-09-12 16:40:32 +0800575 return GST_AML_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800576}
577
578static gboolean
579gst_aml_v4l2_decoder_cmd(GstAmlV4l2Object *v4l2object, guint cmd, guint flags)
580{
bo.xiao857b8682024-09-12 16:40:32 +0800581 struct v4l2_decoder_cmd dcmd = { 0, };
xuesong.jiangae1548e2022-05-06 16:38:46 +0800582
bo.xiao857b8682024-09-12 16:40:32 +0800583 GST_DEBUG_OBJECT (v4l2object->element,
584 "sending v4l2 decoder command %u with flags %u", cmd, flags);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800585
bo.xiao857b8682024-09-12 16:40:32 +0800586 if (!GST_AML_V4L2_IS_OPEN (v4l2object))
587 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800588
bo.xiao857b8682024-09-12 16:40:32 +0800589 dcmd.cmd = cmd;
590 dcmd.flags = flags;
591 if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_DECODER_CMD, &dcmd) < 0)
592 goto dcmd_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800593
bo.xiao857b8682024-09-12 16:40:32 +0800594 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800595
596dcmd_failed:
bo.xiao857b8682024-09-12 16:40:32 +0800597 if (errno == ENOTTY)
598 {
599 GST_INFO_OBJECT (v4l2object->element,
600 "Failed to send decoder command %u with flags %u for '%s'. (%s)",
601 cmd, flags, v4l2object->videodev, g_strerror (errno));
602 }
603 else
604 {
605 GST_ERROR_OBJECT (v4l2object->element,
606 "Failed to send decoder command %u with flags %u for '%s'. (%s)",
607 cmd, flags, v4l2object->videodev, g_strerror (errno));
608 }
609 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800610}
611
612static GstFlowReturn
le.han02c38f02024-08-16 02:35:36 +0000613gst_aml_v4l2_video_dec_finish(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800614{
bo.xiao857b8682024-09-12 16:40:32 +0800615 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
616 GstFlowReturn ret = GST_FLOW_OK;
617 GstBuffer *buffer;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800618
bo.xiao857b8682024-09-12 16:40:32 +0800619 if (gst_pad_get_task_state (decoder->srcpad) != GST_TASK_STARTED)
620 goto done;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800621
bo.xiao857b8682024-09-12 16:40:32 +0800622 GST_DEBUG_OBJECT (self, "Finishing decoding");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800623
bo.xiao857b8682024-09-12 16:40:32 +0800624 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800625
bo.xiao857b8682024-09-12 16:40:32 +0800626 if (gst_aml_v4l2_decoder_cmd (self->v4l2output, V4L2_DEC_CMD_STOP, 0))
627 {
628 GstTask *task = decoder->srcpad->task;
629
630 /* If the decoder stop command succeeded, just wait until processing is
631 * finished */
632 GST_DEBUG_OBJECT (self, "Waiting for decoder stop");
633 GST_OBJECT_LOCK (task);
634 while (GST_TASK_STATE (task) == GST_TASK_STARTED)
635 GST_TASK_WAIT (task);
636 GST_OBJECT_UNLOCK (task);
637
638 ret = GST_FLOW_FLUSHING;
639 }
640 else
641 {
642 /* otherwise keep queuing empty buffers until the processing thread has
643 * stopped, _pool_process() will return FLUSHING when that happened */
644 while (ret == GST_FLOW_OK)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800645 {
bo.xiao857b8682024-09-12 16:40:32 +0800646 GST_DEBUG_OBJECT(self, "queue empty output buf");
647 buffer = gst_buffer_new ();
648 ret =
649 gst_aml_v4l2_buffer_pool_process(GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &buffer);
650 gst_buffer_unref (buffer);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800651 }
bo.xiao857b8682024-09-12 16:40:32 +0800652 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800653
bo.xiao857b8682024-09-12 16:40:32 +0800654 /* and ensure the processing thread has stopped in case another error
655 * occurred. */
656 gst_aml_v4l2_object_flush_start (self->v4l2capture);
657 gst_pad_stop_task (decoder->srcpad);
658 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800659
bo.xiao857b8682024-09-12 16:40:32 +0800660 if (ret == GST_FLOW_FLUSHING)
661 ret = self->output_flow;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800662
bo.xiao857b8682024-09-12 16:40:32 +0800663 /*if V4L2_DEC_CMD_STOP called,indicate decoder will stop.
664 should reset need_wait_event=true to wait source change event*/
665 self->v4l2capture->need_wait_event = TRUE;
666 GST_DEBUG_OBJECT (decoder, "Done draining buffers");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800667
bo.xiao857b8682024-09-12 16:40:32 +0800668 /* TODO Shall we cleanup any reffed frame to workaround broken decoders ? */
xuesong.jiangae1548e2022-05-06 16:38:46 +0800669
670done:
bo.xiao857b8682024-09-12 16:40:32 +0800671 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800672}
673
674static GstFlowReturn
le.han02c38f02024-08-16 02:35:36 +0000675gst_aml_v4l2_video_dec_drain(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800676{
677 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
678
bo.xiao857b8682024-09-12 16:40:32 +0800679 GST_DEBUG_OBJECT (self, "Draining...");
680 gst_aml_v4l2_video_dec_finish (decoder);
681 gst_aml_v4l2_video_dec_flush (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800682
bo.xiao857b8682024-09-12 16:40:32 +0800683 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800684}
685
le.han02c38f02024-08-16 02:35:36 +0000686static GstAmlVideoCodecFrame *
687gst_aml_v4l2_video_dec_get_right_frame_for_frame_mode(GstAmlVideoDecoder *decoder, GstClockTime pts)
fei.dengbee20862022-06-14 14:59:48 +0800688{
bo.xiao857b8682024-09-12 16:40:32 +0800689 GstAmlVideoCodecFrame *frame = NULL;
690 GList *frames, *l;
691 gint count = 0;
fei.dengbee20862022-06-14 14:59:48 +0800692
bo.xiao857b8682024-09-12 16:40:32 +0800693 GST_LOG_OBJECT (decoder, "trace in with pts: %" GST_TIME_FORMAT, GST_TIME_ARGS(pts));
xuesong.jiange24aef92023-06-16 06:39:10 +0000694
bo.xiao857b8682024-09-12 16:40:32 +0800695 frames = gst_aml_video_decoder_get_frames(decoder);
fei.dengbee20862022-06-14 14:59:48 +0800696
bo.xiao857b8682024-09-12 16:40:32 +0800697 for (l = frames; l != NULL; l = l->next)
698 {
699 GstAmlVideoCodecFrame *f = l->data;
fei.denge9458472023-04-18 02:05:48 +0000700
bo.xiao857b8682024-09-12 16:40:32 +0800701 if (GST_CLOCK_TIME_IS_VALID(pts) && (ABSDIFF(f->pts,pts)) < 1000) {
702 frame = f;
703 }
704 count++;
705 }
fei.dengbee20862022-06-14 14:59:48 +0800706
bo.xiao857b8682024-09-12 16:40:32 +0800707 if (!frame)
708 {
709 for (l = frames; l != NULL; l = l->next)
710 {
711 GstAmlVideoCodecFrame *f = l->data;
712 if (!GST_CLOCK_TIME_IS_VALID(f->pts))
713 {
714 frame = f;
715 GST_DEBUG("The pts of the expected output frame is invalid");
716 break;
717 }
718 }
719 }
zengliang.liddee2da2023-07-14 07:27:05 +0000720
bo.xiao857b8682024-09-12 16:40:32 +0800721 if (frame)
722 {
723 GST_LOG_OBJECT(decoder,
724 "frame %p is %d %" GST_TIME_FORMAT " and %d frames left",
725 frame, frame->system_frame_number, GST_TIME_ARGS(frame->pts), count - 1);
726 gst_aml_video_codec_frame_ref(frame);
727 }
728 else
729 {
730 GST_LOG_OBJECT(decoder,
731 "buffer %" GST_TIME_FORMAT " unmatch, create new frame", GST_TIME_ARGS(pts));
732 frame = gst_aml_video_decoder_v4l2_new_frame (decoder);
733 }
fei.dengbee20862022-06-14 14:59:48 +0800734
bo.xiao857b8682024-09-12 16:40:32 +0800735 g_list_free_full(frames, (GDestroyNotify)gst_aml_video_codec_frame_unref);
fei.dengbee20862022-06-14 14:59:48 +0800736
bo.xiao857b8682024-09-12 16:40:32 +0800737 return frame;
fei.dengbee20862022-06-14 14:59:48 +0800738}
739
le.han02c38f02024-08-16 02:35:36 +0000740static GstAmlVideoCodecFrame *
741gst_aml_v4l2_video_dec_get_right_frame_for_stream_mode(GstAmlVideoDecoder *decoder, GstClockTime pts)
xuesong.jiange24aef92023-06-16 06:39:10 +0000742{
bo.xiao857b8682024-09-12 16:40:32 +0800743 GstAmlVideoCodecFrame *frame = NULL;
744 GList *frames, *l;
745 guint frames_len = 0;
746 GST_LOG_OBJECT (decoder, "trace in with pts: %" GST_TIME_FORMAT, GST_TIME_ARGS(pts));
xuesong.jiange24aef92023-06-16 06:39:10 +0000747
bo.xiao857b8682024-09-12 16:40:32 +0800748 if (!(frames = gst_aml_video_decoder_get_frames(decoder)))
749 goto done;
hanghang.luo4486d7d2024-07-24 10:06:35 +0800750
bo.xiao857b8682024-09-12 16:40:32 +0800751 frames_len = g_list_length(frames);
752 GST_LOG_OBJECT (decoder, "got frames list len:%d", frames_len);
xuesong.jiange24aef92023-06-16 06:39:10 +0000753
bo.xiao857b8682024-09-12 16:40:32 +0800754 for (l = frames; l != NULL; l = l->next)
755 {
756 GstAmlVideoCodecFrame *f = l->data;
xuesong.jiange24aef92023-06-16 06:39:10 +0000757
bo.xiao857b8682024-09-12 16:40:32 +0800758 if (GST_CLOCK_TIME_IS_VALID(pts) && (ABSDIFF(f->pts, pts)) < 1000)
759 {
760 /* found the right frame */
761 GST_LOG_OBJECT(decoder,
762 "found frame %" GST_TIME_FORMAT "with pts %" GST_TIME_FORMAT,
763 GST_TIME_ARGS(f->pts), GST_TIME_ARGS(pts));
764 frame = f;
765 break;
766 }
767 else if(GST_CLOCK_TIME_IS_VALID(pts) && (f->pts < pts))
768 {
769 GST_LOG_OBJECT(decoder,
770 "stream mode drop frame %d %" GST_TIME_FORMAT,
771 f->system_frame_number, GST_TIME_ARGS(f->pts));
xuesong.jiange24aef92023-06-16 06:39:10 +0000772
bo.xiao857b8682024-09-12 16:40:32 +0800773 gst_aml_video_codec_frame_ref(f);
774 // gst_aml_video_decoder_drop_frame(decoder, f);
775 gst_aml_video_decoder_release_frame(decoder, f);
776 }
777 else
778 {
779 GST_LOG_OBJECT (decoder, "dbg");
780 }
781 }
xuesong.jiange24aef92023-06-16 06:39:10 +0000782
bo.xiao857b8682024-09-12 16:40:32 +0800783 if (frame)
784 {
785 guint l_len = 0;
786 l = gst_aml_video_decoder_get_frames(decoder);
787 l_len = g_list_length(l);
788 g_list_free_full(l, (GDestroyNotify)gst_aml_video_codec_frame_unref);
xuesong.jiange24aef92023-06-16 06:39:10 +0000789
bo.xiao857b8682024-09-12 16:40:32 +0800790 GST_LOG_OBJECT(decoder,
791 "frame %p is %d %" GST_TIME_FORMAT " and %d frames left",
792 frame, frame->system_frame_number, GST_TIME_ARGS(frame->pts), l_len);
793 gst_aml_video_codec_frame_ref(frame);
794 }
xuesong.jiange24aef92023-06-16 06:39:10 +0000795
bo.xiao857b8682024-09-12 16:40:32 +0800796 g_list_free_full(frames, (GDestroyNotify)gst_aml_video_codec_frame_unref);
xuesong.jiange24aef92023-06-16 06:39:10 +0000797
hanghang.luo4486d7d2024-07-24 10:06:35 +0800798done:
bo.xiao857b8682024-09-12 16:40:32 +0800799 return frame;
xuesong.jiange24aef92023-06-16 06:39:10 +0000800}
801
le.han02c38f02024-08-16 02:35:36 +0000802static GstAmlVideoCodecFrame *
803gst_aml_v4l2_video_dec_get_right_frame(GstAmlVideoDecoder *decoder, GstClockTime pts)
xuesong.jiange24aef92023-06-16 06:39:10 +0000804{
bo.xiao857b8682024-09-12 16:40:32 +0800805 GstAmlV4l2VideoDec *self = (GstAmlV4l2VideoDec *)decoder;
806 if (self->v4l2output->stream_mode)
807 return gst_aml_v4l2_video_dec_get_right_frame_for_stream_mode(decoder, pts);
808 else
809 return gst_aml_v4l2_video_dec_get_right_frame_for_frame_mode(decoder, pts);
xuesong.jiange24aef92023-06-16 06:39:10 +0000810}
811
xuesong.jiangae1548e2022-05-06 16:38:46 +0800812static gboolean
813gst_aml_v4l2_video_remove_padding(GstCapsFeatures *features,
814 GstStructure *structure, gpointer user_data)
815{
bo.xiao857b8682024-09-12 16:40:32 +0800816 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(user_data);
817 GstVideoAlignment *align = &self->v4l2capture->align;
818 GstVideoInfo *info = &self->v4l2capture->info;
819 int width, height;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800820
bo.xiao857b8682024-09-12 16:40:32 +0800821 if (!gst_structure_get_int(structure, "width", &width))
822 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800823
bo.xiao857b8682024-09-12 16:40:32 +0800824 if (!gst_structure_get_int(structure, "height", &height))
825 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800826
bo.xiao857b8682024-09-12 16:40:32 +0800827 if (align->padding_left != 0 || align->padding_top != 0 ||
828 height != info->height + align->padding_bottom)
829 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800830
bo.xiao857b8682024-09-12 16:40:32 +0800831 if (height == info->height + align->padding_bottom)
832 {
833 /* Some drivers may round up width to the padded with */
834 if (width == info->width + align->padding_right)
835 gst_structure_set(structure,
836 "width", G_TYPE_INT, width - align->padding_right,
837 "height", G_TYPE_INT, height - align->padding_bottom, NULL);
838 /* Some drivers may keep visible width and only round up bytesperline */
839 else if (width == info->width)
840 gst_structure_set(structure,
841 "height", G_TYPE_INT, height - align->padding_bottom, NULL);
842 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800843
bo.xiao857b8682024-09-12 16:40:32 +0800844 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800845}
846
847static void
sheng.liubcf036c2022-06-21 15:55:42 +0800848gst_v4l2_drop_event (GstAmlV4l2Object * v4l2object)
sheng.liub56bbc52022-06-21 11:02:33 +0800849{
850 struct v4l2_event evt;
851 gint ret;
852
853 memset (&evt, 0x00, sizeof (struct v4l2_event));
854 ret = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_DQEVENT, &evt);
855 if (ret < 0)
856 {
857 GST_DEBUG_OBJECT (v4l2object, "dqevent failed");
858 return;
859 }
860
861 switch (evt.type)
862 {
863 case V4L2_EVENT_SOURCE_CHANGE:
864 GST_DEBUG_OBJECT (v4l2object, "Drop GST_V4L2_FLOW_SOURCE_CHANGE");
865 break;
866 case V4L2_EVENT_EOS:
867 GST_DEBUG_OBJECT (v4l2object, "Drop GST_V4L2_FLOW_LAST_BUFFER");
868 break;
869 default:
870 break;
871 }
872
873 return;
874}
875
876static void
le.han02c38f02024-08-16 02:35:36 +0000877gst_aml_v4l2_video_dec_set_output_status(GstAmlVideoDecoder *decoder,GstVideoInfo info)
hanghang.luo2eec4892023-07-18 06:44:42 +0000878{
bo.xiao857b8682024-09-12 16:40:32 +0800879 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
880 GstAmlVideoCodecState *output_state;
881 struct v4l2_selection sel;
882 struct v4l2_rect *r = NULL;
883 GstStructure *s;
884 gint width = 0;
885 gint height = 0;
886 GST_DEBUG("%d %d",info.width, info.height);
887 output_state = gst_aml_video_decoder_set_output_state(decoder,
888 info.finfo->format, info.width, info.height, self->input_state);
889 memset(&sel, 0, sizeof(struct v4l2_selection));
890 sel.type = self->v4l2capture->type;
891 sel.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
892 if (self->v4l2capture->ioctl(self->v4l2capture->video_fd, VIDIOC_G_SELECTION, &sel) >= 0)
893 {
894 r = &sel.r;
895 width = (r->width/2)*2;
896 height = (r->height/2)*2;
897 GST_DEBUG_OBJECT(self, "w:%d h:%d ",width,height);
898 }
899 else
900 GST_DEBUG_OBJECT(self, "iotcl error");
901 if (output_state)
902 {
903 output_state->info.interlace_mode = info.interlace_mode;
904 output_state->allocation_caps =gst_video_info_to_caps(&info);
905 output_state->caps =gst_video_info_to_caps(&info);
906 s = gst_caps_get_structure(output_state->caps, 0);
907 if (s)
hanghang.luo9b60a3c2023-08-01 16:01:47 +0000908 {
bo.xiao857b8682024-09-12 16:40:32 +0800909 gst_structure_set(s,"src_width",G_TYPE_INT,width,NULL);
910 gst_structure_set(s,"src_height",G_TYPE_INT,height,NULL);
911 gst_structure_set(s,"width",G_TYPE_INT,info.width,NULL);
912 gst_structure_set(s,"height",G_TYPE_INT,info.height,NULL);
913 GST_DEBUG_OBJECT(self, "output_state->caps: %" GST_PTR_FORMAT, output_state->caps);
914 gst_aml_video_codec_state_unref(output_state);
hanghang.luo9b60a3c2023-08-01 16:01:47 +0000915 }
bo.xiao857b8682024-09-12 16:40:32 +0800916 }
hanghang.luo2eec4892023-07-18 06:44:42 +0000917}
918
zengliang.lidcd41462024-06-19 16:05:12 +0800919static GQuark
920gst_aml_v4l2_buffer_pool_cc_import_quark (void)
921{
922 static GQuark quark = 0;
923
924 if (quark == 0)
925 quark = g_quark_from_string ("GstAmlV4l2BufferPoolCcUsePtrData");
926
927 return quark;
928}
929
930static gboolean
le.han02c38f02024-08-16 02:35:36 +0000931foreach_cc_buffer_list_match_pts_func(GList *list , GstAmlVideoCodecFrame *frame)
zengliang.lidcd41462024-06-19 16:05:12 +0800932{
bo.xiao857b8682024-09-12 16:40:32 +0800933 GList *l;
934 if (g_list_length (list) > 0)
935 {
936 for (l = list; l != NULL; l = l->next)
zengliang.lidcd41462024-06-19 16:05:12 +0800937 {
bo.xiao857b8682024-09-12 16:40:32 +0800938 GstBuffer *cc_buffer = l->data;
939 if (GST_BUFFER_TIMESTAMP (frame->output_buffer) == GST_BUFFER_TIMESTAMP (cc_buffer))
940 {
941 gst_mini_object_set_qdata (GST_MINI_OBJECT (frame->output_buffer), GST_AML_V4L2_CC_IMPORT_QUARK,
942 gst_buffer_ref(cc_buffer), (GDestroyNotify) gst_buffer_unref);
943 #if 0
944 //Debug code:dump cc data
945 GstMapInfo gst_map;
946 gst_buffer_map(cc_buffer,&gst_map,GST_MAP_READ);
947 int fd=open("/data/test/cc1.data",O_RDWR |O_CREAT|O_APPEND,0777);
948 if (gst_map.size>0)
949 write(fd,gst_map.data,gst_map.size);
950 close(fd);
951 gst_buffer_unmap(cc_buffer,&gst_map);
952 #endif
953 GST_DEBUG("match success");
954 return TRUE;
955 }
956 else
957 {
958 GST_DEBUG("match fail");
959 }
zengliang.lidcd41462024-06-19 16:05:12 +0800960 }
bo.xiao857b8682024-09-12 16:40:32 +0800961 GST_WARNING("no match frame in the bufferlist");
962 }
963 else
964 {
965 GST_WARNING("list is null,can not foreach");
966 }
967 return FALSE;
zengliang.lidcd41462024-06-19 16:05:12 +0800968}
969
bo.xiao8e3054d2024-07-31 17:13:57 +0800970static GstClockTime
le.han44125c32024-09-03 07:55:57 +0000971gst_aml_v4l2_video_dec_calc_output_buffer_pts(GstAmlVideoDecoder *decoder)
bo.xiao8e3054d2024-07-31 17:13:57 +0800972{
bo.xiao857b8682024-09-12 16:40:32 +0800973 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
974 GstClockTime pts = GST_CLOCK_TIME_NONE;
bo.xiao8e3054d2024-07-31 17:13:57 +0800975
bo.xiao857b8682024-09-12 16:40:32 +0800976 if (GST_CLOCK_TIME_IS_VALID (self->last_out_pts) && GST_CLOCK_TIME_IS_VALID(self->frame_duration)) {
977 pts = self->last_out_pts + self->frame_duration;
978 GST_LOG_OBJECT (decoder,
979 "calculate PTS %" GST_TIME_FORMAT " by duration: %" GST_TIME_FORMAT,
980 GST_TIME_ARGS (pts), GST_TIME_ARGS (self->frame_duration));
981 }
982 else
983 {
984 pts = 0;
985 GST_INFO_OBJECT (decoder,"Set PTS=0");
986 }
987 return pts;
bo.xiao8e3054d2024-07-31 17:13:57 +0800988}
989
990static GstClockTime
le.han44125c32024-09-03 07:55:57 +0000991gst_aml_v4l2_video_dec_calc_duration(GstAmlVideoDecoder *decoder)
bo.xiao8e3054d2024-07-31 17:13:57 +0800992{
993 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
994 GstClockTime duration = GST_CLOCK_TIME_NONE;
995 gint fps_n, fps_d;
996 fps_n = gst_value_get_fraction_numerator(self->v4l2capture->fps);
997 fps_d = gst_value_get_fraction_denominator(self->v4l2capture->fps);
998
999 if (fps_n != 0 && fps_d != 0)
1000 {
1001 duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n);
1002
1003 if (self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
1004 {
1005 duration = duration / 2;
1006 }
1007 }
1008
1009 GST_INFO_OBJECT (decoder,"framerate(fps_d: %d, fps_n: %d) -> frame_duration = %" GST_TIME_FORMAT, fps_d, fps_n, GST_TIME_ARGS(duration));
1010
1011 return duration;
1012}
1013
hanghang.luo2eec4892023-07-18 06:44:42 +00001014static void
le.han02c38f02024-08-16 02:35:36 +00001015gst_aml_v4l2_video_dec_loop(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001016{
bo.xiao857b8682024-09-12 16:40:32 +08001017 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
1018 GstAmlV4l2BufferPool *v4l2_pool;
1019 GstAmlV4l2Error error = GST_AML_V4L2_ERROR_INIT;
1020 GstBufferPool *pool;
1021 GstAmlVideoCodecFrame *frame;
1022 GstBuffer *buffer = NULL;
1023 GstFlowReturn ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001024
bo.xiao857b8682024-09-12 16:40:32 +08001025 if (G_UNLIKELY (!GST_AML_V4L2_IS_ACTIVE (self->v4l2capture)))
1026 {
1027 GstVideoInfo info;
1028 GstCaps *acquired_caps, *available_caps, *caps, *filter;
1029 GstStructure *st;
1030 GST_DEBUG_OBJECT(self, "waitting source change event");
1031 /* Wait until received SOURCE_CHANGE event to get right video format */
1032 while (self->v4l2capture->can_wait_event && self->v4l2capture->need_wait_event)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001033 {
bo.xiao857b8682024-09-12 16:40:32 +08001034 ret = gst_aml_v4l2_object_dqevent (self->v4l2capture);
1035 if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
1036 {
1037 //let flush start event blocked until capture buffer pool actived
1038 self->is_res_chg = TRUE;
1039 GST_DEBUG_OBJECT (self, "Received source change event");
1040 break;
1041 }
1042 else if (ret == GST_AML_V4L2_FLOW_LAST_BUFFER)
1043 {
1044 GST_DEBUG_OBJECT (self, "Received eos event");
1045 goto beach;
1046 }
1047 else if (ret != GST_FLOW_OK)
1048 {
1049 GST_ERROR_OBJECT (self, "dqevent error");
1050 goto beach;
1051 }
1052 }
1053 self->v4l2capture->need_wait_event = FALSE;
1054
1055 if (TRUE == self->v4l2output->is_svp)
1056 {
1057 GstPad *peer;
1058 GstStructure *s;
1059 GstEvent *event;
1060
1061 peer = gst_pad_get_peer (decoder->srcpad);
1062 if (peer)
1063 {
1064 s = gst_structure_new_empty ("IS_SVP");
1065 if (s)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001066 {
bo.xiao857b8682024-09-12 16:40:32 +08001067 event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
1068 gst_pad_send_event (peer, event);
1069 GST_DEBUG_OBJECT(self, "Send SVP Event");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001070 }
bo.xiao857b8682024-09-12 16:40:32 +08001071 gst_object_unref (peer);
1072 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001073 }
1074
bo.xiao857b8682024-09-12 16:40:32 +08001075 if (self->v4l2capture->need_drop_event)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001076 {
bo.xiao857b8682024-09-12 16:40:32 +08001077 // drop V4L2_EVENT_SOURCE_CHANGE
1078 gst_v4l2_drop_event(self->v4l2capture);
1079 self->v4l2capture->need_drop_event = FALSE;
bo.xiao8e3054d2024-07-31 17:13:57 +08001080 }
1081
bo.xiao857b8682024-09-12 16:40:32 +08001082 if (!gst_aml_v4l2_object_acquire_format (self->v4l2capture, &info))
1083 goto not_negotiated;
1084
1085 /* Create caps from the acquired format, remove the format field */
1086 acquired_caps = gst_video_info_to_caps (&info);
1087 GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
1088 st = gst_caps_get_structure (acquired_caps, 0);
1089 gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site", NULL);
1090
1091 /* Probe currently available pixel formats */
1092 available_caps = gst_caps_copy (self->probed_srccaps);
1093 GST_DEBUG_OBJECT (self, "Available caps: %" GST_PTR_FORMAT, available_caps);
1094
1095 /* Replace coded size with visible size, we want to negotiate visible size
1096 * with downstream, not coded size. */
1097 gst_caps_map_in_place (available_caps, gst_aml_v4l2_video_remove_padding, self);
1098
1099 filter = gst_caps_intersect_full (available_caps, acquired_caps, GST_CAPS_INTERSECT_FIRST);
1100 caps = gst_caps_copy(filter);
1101 gst_caps_set_features_simple(caps, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
1102 gst_caps_append(filter, caps);
1103
1104 GST_DEBUG_OBJECT (self, "Filtered caps: %" GST_PTR_FORMAT, filter);
1105 gst_caps_unref (acquired_caps);
1106 gst_caps_unref (available_caps);
1107 caps = gst_pad_peer_query_caps (decoder->srcpad, filter);
1108 gst_caps_unref (filter);
1109
1110 GST_DEBUG_OBJECT (self, "Possible decoded caps: %" GST_PTR_FORMAT, caps);
1111 if (gst_caps_is_empty (caps))
bo.xiao8e3054d2024-07-31 17:13:57 +08001112 {
bo.xiao857b8682024-09-12 16:40:32 +08001113 gst_caps_unref (caps);
1114 goto not_negotiated;
bo.xiao8e3054d2024-07-31 17:13:57 +08001115 }
1116
bo.xiao857b8682024-09-12 16:40:32 +08001117 /* Fixate pixel format */
1118 caps = gst_caps_fixate (caps);
bo.xiao8e3054d2024-07-31 17:13:57 +08001119
bo.xiao857b8682024-09-12 16:40:32 +08001120 GST_DEBUG_OBJECT (self, "Chosen decoded caps: %" GST_PTR_FORMAT, caps);
zengliang.lidcd41462024-06-19 16:05:12 +08001121
bo.xiao857b8682024-09-12 16:40:32 +08001122 /* Try to set negotiated format, on success replace acquired format */
1123 if (gst_aml_v4l2_object_set_format (self->v4l2capture, caps, &error))
1124 gst_video_info_from_caps (&info, caps);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001125 else
bo.xiao857b8682024-09-12 16:40:32 +08001126 gst_aml_v4l2_clear_error (&error);
1127 gst_caps_unref (caps);
1128 gst_aml_v4l2_video_dec_set_output_status(decoder,info);
1129 if (!gst_aml_video_decoder_negotiate (decoder))
xuesong.jiangae1548e2022-05-06 16:38:46 +08001130 {
bo.xiao857b8682024-09-12 16:40:32 +08001131 if (GST_PAD_IS_FLUSHING (decoder->srcpad))
1132 goto flushing;
1133 else
1134 goto not_negotiated;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001135 }
1136
bo.xiao857b8682024-09-12 16:40:32 +08001137 /* Ensure our internal pool is activated */
1138 if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
1139 TRUE))
1140 goto activate_failed;
1141
1142 //cal duration when got resolution event
1143 self->frame_duration = gst_aml_v4l2_video_dec_calc_duration(decoder);
1144
1145 g_mutex_lock(&self->res_chg_lock);
1146 GST_LOG_OBJECT(decoder, "signal resolution changed");
1147 self->is_res_chg = FALSE;
1148 g_cond_signal(&self->res_chg_cond);
1149 g_mutex_unlock(&self->res_chg_lock);
1150 }
1151
1152 GST_LOG_OBJECT (decoder, "Allocate output buffer");
1153 v4l2_pool = GST_AML_V4L2_BUFFER_POOL(self->v4l2capture->pool);
1154
1155 self->output_flow = GST_FLOW_OK;
1156 do
1157 {
1158 /* We cannot use the base class allotate helper since it taking the internal
1159 * stream lock. we know that the acquire may need to poll until more frames
1160 * comes in and holding this lock would prevent that.
1161 */
1162 pool = gst_aml_video_decoder_get_buffer_pool (decoder);
1163
1164 /* Pool may be NULL if we started going to READY state */
1165 if (pool == NULL)
1166 {
1167 GST_WARNING_OBJECT(decoder, "gst_aml_video_decoder_get_buffer_pool goto beach");
1168 ret = GST_FLOW_FLUSHING;
1169 goto beach;
1170 }
1171
1172 ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
1173
1174 g_object_unref (pool);
1175
1176 if (ret == GST_FLOW_OK && GST_BUFFER_FLAG_IS_SET(buffer,GST_AML_V4L2_BUFFER_FLAG_LAST_EMPTY)) {
1177 GST_LOG_OBJECT(decoder, "Get GST_AML_V4L2_FLOW_LAST_BUFFER");
1178 self->v4l2capture->need_drop_event = TRUE;
1179 gst_aml_v4l2_buffer_pool_process(v4l2_pool, &buffer);
1180 if (self->is_res_chg) {
1181 //we must release last buffer
1182 gst_buffer_unref(buffer);
1183 //if resolution changed event received,we should set need_drop_event to false
1184 self->v4l2capture->need_drop_event = FALSE;
1185 gst_aml_v4l2_object_stop(self->v4l2capture);
fei.deng2a06e042023-10-10 03:09:45 +00001186 //unblock flush start event
1187 g_mutex_lock(&self->res_chg_lock);
1188 self->is_res_chg = FALSE;
1189 g_cond_signal(&self->res_chg_cond);
1190 g_mutex_unlock(&self->res_chg_lock);
bo.xiao857b8682024-09-12 16:40:32 +08001191 return;
1192 } else {
1193 goto beach;
1194 }
fei.deng2a06e042023-10-10 03:09:45 +00001195 }
bo.xiao857b8682024-09-12 16:40:32 +08001196
1197 if (ret == GST_AML_V4L2_FLOW_CC_DATA)
1198 {
1199 GST_DEBUG_OBJECT(decoder, "already got cc data, just continue.");
1200 continue;
1201 }
1202
1203 if (ret == GST_AML_V4L2_FLOW_UNKNOWN_EVENT)
1204 {
1205 GST_DEBUG_OBJECT(decoder, "unknow event, just continue.");
1206 continue;
1207 }
1208
1209 if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
1210 {
1211 GST_LOG_OBJECT(decoder, "Get GST_AML_V4L2_FLOW_SOURCE_CHANGE");
1212
1213 g_mutex_lock (&self->res_chg_lock);
1214 self->is_res_chg = TRUE;
1215 g_mutex_unlock (&self->res_chg_lock);
1216 return;
1217 }
1218
1219 //decoding error happened
1220 if (ret == GST_AML_V4L2_FLOW_DECODING_ERROR)
1221 {
1222 GST_DEBUG("send error pts:%llu - %" GST_TIME_FORMAT, v4l2_pool->obj->error_frame_pts, GST_TIME_ARGS(v4l2_pool->obj->error_frame_pts));
1223 g_signal_emit (self, g_signals[SIGNAL_DECODED_ERROR_PTS], 0, v4l2_pool->obj->error_frame_pts, NULL);
1224 g_signal_emit (self, g_signals[SIGNAL_DECODED_PTS], 0, v4l2_pool->obj->error_frame_pts);
1225 continue;
1226 }
1227
1228 if (ret != GST_FLOW_OK) {
1229 GST_WARNING_OBJECT(decoder, "gst_buffer_pool_acquire_buffer goto beach ret:%d",ret);
1230 goto beach;
1231 }
1232
1233 GST_LOG_OBJECT(decoder, "Process output buffer (switching flow outstanding num:%d)", self->v4l2capture->outstanding_buf_num);
1234 ret = gst_aml_v4l2_buffer_pool_process(v4l2_pool, &buffer);
1235
1236 GST_DEBUG_OBJECT(decoder, "decoded pts:%lld - %" GST_TIME_FORMAT, GST_BUFFER_PTS(buffer), GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));
1237 g_signal_emit (self, g_signals[SIGNAL_DECODED_PTS], 0, GST_BUFFER_PTS(buffer));
1238
1239 if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
1240 {
1241 gst_aml_v4l2_object_stop (self->v4l2capture);
1242 return;
1243 }
1244
1245 } while ((ret == GST_AML_V4L2_FLOW_CORRUPTED_BUFFER) ||
1246 (ret == GST_AML_V4L2_FLOW_CC_DATA) ||
1247 (ret == GST_AML_V4L2_FLOW_UNKNOWN_EVENT) ||
1248 (ret == GST_AML_V4L2_FLOW_DECODING_ERROR));
1249
1250 if (ret != GST_FLOW_OK)
1251 goto beach;
1252
1253 if (!GST_BUFFER_PTS_IS_VALID (buffer)
1254 || (GST_BUFFER_TIMESTAMP(buffer) == 0 && self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED))
1255 {
1256 GST_BUFFER_TIMESTAMP(buffer) = gst_aml_v4l2_video_dec_calc_output_buffer_pts(decoder);
1257 }
1258
1259 if (self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
1260 {
1261 GST_BUFFER_DURATION(buffer) = self->frame_duration; // got at resolution event.
1262 GST_BUFFER_FLAG_UNSET(buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1263 }
1264
1265 frame = gst_aml_v4l2_video_dec_get_right_frame(decoder, GST_BUFFER_TIMESTAMP (buffer));
1266 if (frame)
1267 {
1268 self->last_out_pts = GST_BUFFER_TIMESTAMP(buffer);
1269 frame->output_buffer = buffer;
1270 frame->pts = GST_BUFFER_TIMESTAMP(buffer);
1271 frame->duration = GST_BUFFER_DURATION(buffer);
1272
1273 buffer = NULL;
1274
1275 if (self->v4l2capture->enable_cc_data)
1276 {
1277 if (foreach_cc_buffer_list_match_pts_func(v4l2_pool->cc_buffer_list, frame))
1278 {
1279 GST_DEBUG("cc buffer and frame bind success");
1280 GstBuffer *cc_buffer = gst_mini_object_get_qdata (GST_MINI_OBJECT (frame->output_buffer),
1281 GST_AML_V4L2_CC_IMPORT_QUARK);
1282 #if 0
1283 //Debug code:dump cc data
1284 GstMapInfo gst_map;
1285 gst_buffer_map(cc_buffer,&gst_map,GST_MAP_READ);
1286 int fd=open("/data/test/cc2.data",O_RDWR |O_CREAT|O_APPEND,0777);
1287 if (gst_map.size>0)
1288 write(fd,gst_map.data,gst_map.size);
1289 close(fd);
1290 gst_buffer_unmap(cc_buffer,&gst_map);
1291 #endif
1292 v4l2_pool->cc_buffer_list = g_list_remove(v4l2_pool->cc_buffer_list,cc_buffer);
1293 gst_buffer_unref(cc_buffer);
1294 }
1295 else
1296 {
1297 GST_WARNING("bufferlist is empty or no match frame in the bufferlist");
1298 }
1299 }
1300 ret = gst_aml_video_decoder_finish_frame (decoder, frame);
1301
1302 if (ret != GST_FLOW_OK)
1303 goto beach;
1304 }
1305 else
1306 {
1307 GST_WARNING_OBJECT(decoder, "Unmatch buffer, should be push, need refine");
1308 //gst_pad_push (decoder->srcpad, buffer);
1309 gst_buffer_unref (buffer);
1310 }
1311
1312 return;
1313 /* ERRORS */
1314not_negotiated:
1315 {
1316 GST_ERROR_OBJECT (self, "not negotiated");
1317 ret = GST_FLOW_NOT_NEGOTIATED;
1318 goto beach;
1319 }
1320activate_failed:
1321 {
1322 GST_ERROR_OBJECT (self, "Buffer pool activation failed");
1323 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
1324 (_("Failed to allocate required memory.")),
1325 ("Buffer pool activation failed"));
1326 ret = GST_FLOW_ERROR;
1327 goto beach;
1328 }
1329flushing:
1330 {
1331 ret = GST_FLOW_FLUSHING;
1332 goto beach;
1333 }
1334beach:
1335 GST_DEBUG_OBJECT (decoder, "Leaving output thread: %s",
1336 gst_flow_get_name (ret));
1337 if (self->is_res_chg) {
1338 //unblock flush start event
1339 g_mutex_lock(&self->res_chg_lock);
1340 self->is_res_chg = FALSE;
1341 g_cond_signal(&self->res_chg_cond);
1342 g_mutex_unlock(&self->res_chg_lock);
1343 }
1344 gst_buffer_replace (&buffer, NULL);
1345 self->output_flow = ret;
1346 gst_aml_v4l2_object_flush_start (self->v4l2output);
1347 gst_pad_pause_task (decoder->srcpad);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001348}
1349
1350static GstFlowReturn
bo.xiao857b8682024-09-12 16:40:32 +08001351gst_aml_v4l2_video_dec_handle_frame (GstAmlVideoDecoder * decoder,
1352 GstAmlVideoCodecFrame * frame)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001353{
bo.xiao857b8682024-09-12 16:40:32 +08001354 GstAmlV4l2Error error = GST_AML_V4L2_ERROR_INIT;
1355 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
1356 GstBufferPool *pool = GST_BUFFER_POOL(self->v4l2output->pool);
1357 GstFlowReturn ret = GST_FLOW_OK;
1358 gboolean processed = FALSE;
1359 GstBuffer *tmp;
1360 GstTaskState task_state;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001361
bo.xiao857b8682024-09-12 16:40:32 +08001362 GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001363
bo.xiao857b8682024-09-12 16:40:32 +08001364 if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
1365 goto flushing;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001366
bo.xiao857b8682024-09-12 16:40:32 +08001367 if (G_UNLIKELY(!GST_CLOCK_TIME_IS_VALID(self->frame_duration)))
1368 self->frame_duration = frame->duration;
le.han44125c32024-09-03 07:55:57 +00001369
bo.xiao857b8682024-09-12 16:40:32 +08001370 if (G_UNLIKELY (!GST_AML_V4L2_IS_ACTIVE (self->v4l2output)))
1371 {
1372 if (!self->input_state)
1373 goto not_negotiated;
1374 if (!gst_aml_v4l2_object_set_format (self->v4l2output, self->input_state->caps,
1375 &error))
1376 goto not_negotiated;
1377 }
1378
1379 if (G_UNLIKELY (!GST_AML_V4L2_IS_ACTIVE (self->v4l2capture)))
1380 {
1381 GstBuffer *codec_data;
1382 GstCapsFeatures *features = NULL;
1383
1384 features = gst_caps_get_features(self->input_state->caps, 0);
1385 if (features && gst_caps_features_contains(features, GST_CAPS_FEATURE_MEMORY_DMABUF) && self->v4l2output->secure_es)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001386 {
bo.xiao857b8682024-09-12 16:40:32 +08001387 GST_DEBUG_OBJECT(self, "Is SVP");
1388 //TODO:need rm is_svp flag and just using secure_es flag
1389 self->v4l2output->is_svp = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001390 }
1391
bo.xiao857b8682024-09-12 16:40:32 +08001392 GST_DEBUG_OBJECT (self, "Sending header");
1393
1394 codec_data = self->input_state->codec_data;
1395
1396 /* We are running in byte-stream mode, so we don't know the headers, but
1397 * we need to send something, otherwise the decoder will refuse to
1398 * initialize.
1399 */
1400 if (codec_data)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001401 {
bo.xiao857b8682024-09-12 16:40:32 +08001402 gst_buffer_ref (codec_data);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001403 }
1404 else
1405 {
bo.xiao857b8682024-09-12 16:40:32 +08001406 codec_data = gst_buffer_ref (frame->input_buffer);
1407 processed = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001408 }
1409
bo.xiao857b8682024-09-12 16:40:32 +08001410 /* Ensure input internal pool is active */
1411 if (!gst_buffer_pool_is_active (pool))
1412 {
1413 GstStructure *config = gst_buffer_pool_get_config (pool);
1414 // guint min = MAX(self->v4l2output->min_buffers, GST_AML_V4L2_MIN_BUFFERS);
1415 // guint max = VIDEO_MAX_FRAME;
1416 // gst_buffer_pool_config_set_params (config, self->input_state->caps,
1417 // self->v4l2output->info.size, min, max);
1418 gst_buffer_pool_config_set_params(config, self->input_state->caps, self->v4l2output->info.size, self->v4l2output->min_buffers, self->v4l2output->min_buffers);
1419
1420 /* There is no reason to refuse this config */
1421 if (!gst_buffer_pool_set_config (pool, config))
1422 goto activate_failed;
1423 GST_DEBUG_OBJECT(self, "setting output pool config to %" GST_PTR_FORMAT, config);
1424
1425 if (!gst_buffer_pool_set_active (pool, TRUE))
1426 goto activate_failed;
1427 }
1428
1429 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
1430 ret =
1431 gst_aml_v4l2_buffer_pool_process(GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &codec_data);
1432 self->codec_data_inject = TRUE;
1433 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
1434
1435 gst_buffer_unref (codec_data);
1436
1437 /* For decoders G_FMT returns coded size, G_SELECTION returns visible size
1438 * in the compose rectangle. gst_aml_v4l2_object_acquire_format() checks both
1439 * and returns the visible size as with/height and the coded size as
1440 * padding. */
1441 }
1442
1443 task_state = gst_pad_get_task_state (GST_AML_VIDEO_DECODER_SRC_PAD (self));
1444 if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED)
1445 {
1446 /* It's possible that the processing thread stopped due to an error */
1447 if (self->output_flow != GST_FLOW_OK &&
1448 self->output_flow != GST_FLOW_FLUSHING)
1449 {
1450 GST_DEBUG_OBJECT (self, "Processing loop stopped with error, leaving");
1451 ret = self->output_flow;
1452 goto drop;
1453 }
1454
1455 GST_DEBUG_OBJECT (self, "Starting decoding thread");
1456
1457 /* Start the processing task, when it quits, the task will disable input
1458 * processing to unlock input if draining, or prevent potential block */
1459 self->output_flow = GST_FLOW_FLUSHING;
1460 /*reset poll and need_drop_event before start decoding loop thread*/
1461 self->v4l2capture->need_drop_event = FALSE;
1462 gst_poll_set_flushing(self->v4l2capture->poll, FALSE);
1463 if (!gst_pad_start_task(decoder->srcpad,
1464 (GstTaskFunction) gst_aml_v4l2_video_dec_loop, self, NULL))
1465 goto start_task_failed;
1466 }
1467
1468 if (!processed)
1469 {
1470 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
1471 if (!self->codec_data_inject && self->input_state->codec_data)
1472 {
1473 ret = gst_aml_v4l2_buffer_pool_process
1474 (GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &self->input_state->codec_data);
1475 self->codec_data_inject = TRUE;
1476 if (ret != GST_FLOW_OK)
1477 goto send_codec_failed;
1478 }
1479 ret =
1480 gst_aml_v4l2_buffer_pool_process(GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &frame->input_buffer);
1481 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
1482
1483 if (ret == GST_FLOW_FLUSHING)
1484 {
1485 if (gst_pad_get_task_state (GST_AML_VIDEO_DECODER_SRC_PAD (self)) !=
1486 GST_TASK_STARTED)
1487 ret = self->output_flow;
1488 goto drop;
1489 }
1490 else if (ret != GST_FLOW_OK)
1491 {
1492 goto process_failed;
1493 }
1494 }
1495
1496 /* No need to keep input around */
1497 tmp = frame->input_buffer;
1498 frame->input_buffer = gst_buffer_new ();
1499 gst_buffer_copy_into (frame->input_buffer, tmp,
1500 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
1501 GST_BUFFER_COPY_META, 0, 0);
1502 gst_buffer_unref (tmp);
1503
1504 gst_aml_video_codec_frame_unref (frame);
1505 return ret;
1506
1507 /* ERRORS */
1508send_codec_failed:
1509 GST_ERROR_OBJECT(self, "send codec_date fialed.ret is %d",ret);
1510 goto drop;
1511not_negotiated:
1512 {
1513 GST_ERROR_OBJECT (self, "not negotiated");
1514 ret = GST_FLOW_NOT_NEGOTIATED;
1515 gst_aml_v4l2_error (self, &error);
1516 goto drop;
1517 }
1518activate_failed:
1519 {
1520 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
1521 (_("Failed to allocate required memory.")),
1522 ("Buffer pool activation failed"));
1523 ret = GST_FLOW_ERROR;
1524 goto drop;
1525 }
1526flushing:
1527 {
1528 ret = GST_FLOW_FLUSHING;
1529 goto drop;
1530 }
1531
1532start_task_failed:
1533 {
1534 GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
1535 (_("Failed to start decoding thread.")), (NULL));
1536 ret = GST_FLOW_ERROR;
1537 goto drop;
1538 }
1539process_failed:
1540 {
1541 GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
1542 (_("Failed to process frame.")),
1543 ("Maybe be due to not enough memory or failing driver"));
1544 ret = GST_FLOW_ERROR;
1545 goto drop;
1546 }
1547drop:
1548 {
1549 gst_aml_video_decoder_drop_frame (decoder, frame);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001550 return ret;
bo.xiao857b8682024-09-12 16:40:32 +08001551 }
1552}
1553
1554static gboolean
1555gst_aml_v4l2_video_dec_decide_allocation (GstAmlVideoDecoder * decoder,
1556 GstQuery * query)
1557{
1558 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
1559 GstClockTime latency;
1560 gboolean ret = FALSE;
1561
1562 if (gst_aml_v4l2_object_decide_allocation (self->v4l2capture, query))
1563 ret = GST_AML_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder, query);
1564
1565 if (GST_CLOCK_TIME_IS_VALID (self->v4l2capture->duration))
1566 {
1567 latency = self->v4l2capture->min_buffers * self->v4l2capture->duration;
1568 GST_DEBUG_OBJECT (self, "Setting latency: %" GST_TIME_FORMAT " (%"
1569 G_GUINT32_FORMAT " * %" G_GUINT64_FORMAT, GST_TIME_ARGS (latency),
1570 self->v4l2capture->min_buffers, self->v4l2capture->duration);
1571 gst_aml_video_decoder_set_latency (decoder, latency, latency);
1572 }
1573 else
1574 {
1575 GST_WARNING_OBJECT (self, "Duration invalid, not setting latency");
1576 }
1577
1578 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001579}
1580
1581static gboolean
le.han02c38f02024-08-16 02:35:36 +00001582gst_aml_v4l2_video_dec_src_query(GstAmlVideoDecoder *decoder, GstQuery *query)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001583{
bo.xiao857b8682024-09-12 16:40:32 +08001584 gboolean ret = TRUE;
1585 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001586
bo.xiao857b8682024-09-12 16:40:32 +08001587 switch (GST_QUERY_TYPE (query))
1588 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001589 case GST_QUERY_CAPS:
1590 {
bo.xiao857b8682024-09-12 16:40:32 +08001591 GstCaps *filter, *result = NULL;
1592 GstPad *pad = GST_AML_VIDEO_DECODER_SRC_PAD (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001593
bo.xiao857b8682024-09-12 16:40:32 +08001594 gst_query_parse_caps (query, &filter);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001595
bo.xiao857b8682024-09-12 16:40:32 +08001596 if (self->probed_srccaps)
1597 result = gst_caps_ref (self->probed_srccaps);
1598 else
1599 result = gst_pad_get_pad_template_caps (pad);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001600
bo.xiao857b8682024-09-12 16:40:32 +08001601 if (filter)
1602 {
1603 GstCaps *tmp = result;
1604 result =
1605 gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
1606 gst_caps_unref (tmp);
1607 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001608
bo.xiao857b8682024-09-12 16:40:32 +08001609 GST_DEBUG_OBJECT (self, "Returning src caps %" GST_PTR_FORMAT, result);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001610
bo.xiao857b8682024-09-12 16:40:32 +08001611 gst_query_set_caps_result (query, result);
1612 gst_caps_unref (result);
1613 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001614 }
1615
1616 default:
bo.xiao857b8682024-09-12 16:40:32 +08001617 ret = GST_AML_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query);
1618 break;
1619 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001620
bo.xiao857b8682024-09-12 16:40:32 +08001621 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001622}
1623
1624static GstCaps *
le.han02c38f02024-08-16 02:35:36 +00001625gst_aml_v4l2_video_dec_sink_getcaps(GstAmlVideoDecoder *decoder, GstCaps *filter)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001626{
bo.xiao857b8682024-09-12 16:40:32 +08001627 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
1628 GstCaps *result;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001629
bo.xiao857b8682024-09-12 16:40:32 +08001630 result = gst_aml_video_decoder_proxy_getcaps (decoder, self->probed_sinkcaps,
1631 filter);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001632
bo.xiao857b8682024-09-12 16:40:32 +08001633 GST_DEBUG_OBJECT (self, "Returning sink caps %" GST_PTR_FORMAT, result);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001634
bo.xiao857b8682024-09-12 16:40:32 +08001635 return result;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001636}
1637
1638static gboolean
bo.xiao857b8682024-09-12 16:40:32 +08001639gst_aml_v4l2_video_dec_sink_event (GstAmlVideoDecoder *decoder, GstEvent *event)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001640{
bo.xiao857b8682024-09-12 16:40:32 +08001641 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
1642 gboolean ret;
1643 GstEventType type = GST_EVENT_TYPE (event);
1644 GST_DEBUG_OBJECT (self, "received event %p %" GST_PTR_FORMAT, event, event);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001645
bo.xiao857b8682024-09-12 16:40:32 +08001646 switch (type)
1647 {
xuesong.jiang406ee302023-06-28 03:45:22 +00001648 case GST_EVENT_STREAM_START:
1649 {
bo.xiao857b8682024-09-12 16:40:32 +08001650 GstStructure *s;
1651 GstEvent *event;
1652 s = gst_structure_new("private_signal", "obj_ptr", G_TYPE_POINTER, self, "sig_name", G_TYPE_STRING, "decoded-pts", NULL);
1653 event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
1654 GST_DEBUG_OBJECT(self, "before Send private_signal Event :%p", event);
1655 gst_pad_push_event (decoder->sinkpad, event);
1656 GST_DEBUG_OBJECT(self, "after Send private_signal Event :%p", event);
1657 break;
xuesong.jiang406ee302023-06-28 03:45:22 +00001658 }
zengliang.li51f54b62023-10-10 12:14:49 +00001659 case GST_EVENT_CAPS:
1660 {
bo.xiao857b8682024-09-12 16:40:32 +08001661 GstCaps *caps;
1662 GstStructure *structure;
1663 gint num, denom;
zengliang.li51f54b62023-10-10 12:14:49 +00001664
bo.xiao857b8682024-09-12 16:40:32 +08001665 gst_event_parse_caps (event, &caps);
bo.xiao34e36202024-07-17 16:04:01 +08001666
bo.xiao857b8682024-09-12 16:40:32 +08001667 structure= gst_caps_get_structure(caps, 0);
1668 if ( gst_structure_has_field(structure, "parsed") )
1669 {
1670 gboolean parsed = TRUE;
1671 if ( gst_structure_get_boolean( structure, "parsed", &parsed ) )
zengliang.li51f54b62023-10-10 12:14:49 +00001672 {
bo.xiao857b8682024-09-12 16:40:32 +08001673 self->v4l2output->stream_mode = !parsed;
1674 GST_DEBUG("frame parsed:%d, set stream_mode to %d", parsed, self->v4l2output->stream_mode);
1675 }
1676 }
1677
1678 if ( gst_structure_has_field(structure, "secure") )
1679 {
1680 gboolean is_secure = FALSE;
1681 if ( gst_structure_get_boolean( structure, "secure", &is_secure ) )
1682 {
1683 self->v4l2output->secure_es = is_secure;
1684 GST_DEBUG("is secure es:%d", self->v4l2output->secure_es);
1685 }
1686 }
1687 else
1688 {
1689 GstCapsFeatures *const features = gst_caps_get_features(caps, 0);
1690 if (features && gst_caps_features_contains(features, GST_CAPS_FEATURE_MEMORY_DMABUF))
1691 {
1692 self->v4l2output->secure_es = TRUE;
1693 GST_DEBUG("If there is no secure field in caps, consider dma es is secure");
1694 }
1695 }
1696
1697 if ( gst_structure_get_fraction( structure, "framerate", &num, &denom ) )
1698 {
1699 if ( denom == 0 ) denom= 1;
1700
1701 if (self->v4l2capture->fps)
1702 {
1703 g_value_unset(self->v4l2capture->fps);
1704 g_free(self->v4l2capture->fps);
zengliang.li51f54b62023-10-10 12:14:49 +00001705 }
sheng.liu641aa422023-12-26 07:05:59 +00001706
bo.xiao857b8682024-09-12 16:40:32 +08001707 self->v4l2capture->fps = g_new0(GValue, 1);
1708 g_value_init(self->v4l2capture->fps, GST_TYPE_FRACTION);
1709 gst_value_set_fraction(self->v4l2capture->fps, num, denom);
1710
1711 GST_DEBUG_OBJECT(self, "get framerate ratio %d:%d", num, denom);
1712 }
1713
1714 if (( gst_structure_get_fraction( structure, "pixel-aspect-ratio", &num, &denom ) ) &&
1715 ( !self->v4l2capture->have_set_par ) )
1716 {
1717 if ( (num <= 0) || (denom <= 0) )
xuesong.jiang26749f32024-07-24 09:40:47 +08001718 {
bo.xiao857b8682024-09-12 16:40:32 +08001719 num= denom= 1;
xuesong.jiang578add22024-07-25 15:11:30 +08001720 }
xuesong.jiang26749f32024-07-24 09:40:47 +08001721
bo.xiao857b8682024-09-12 16:40:32 +08001722 if ( self->v4l2capture->par )
sheng.liudb26f7d2024-01-22 11:24:23 +00001723 {
bo.xiao857b8682024-09-12 16:40:32 +08001724 g_value_unset(self->v4l2capture->par);
1725 g_free(self->v4l2capture->par);
sheng.liudb26f7d2024-01-22 11:24:23 +00001726 }
1727
bo.xiao857b8682024-09-12 16:40:32 +08001728 self->v4l2capture->par = g_new0(GValue, 1);
1729 g_value_init(self->v4l2capture->par, GST_TYPE_FRACTION);
1730 gst_value_set_fraction(self->v4l2capture->par, num, denom);
1731 GST_DEBUG_OBJECT(self, "get pixel aspect ratio %d:%d", num, denom);
1732 }
1733 break;
zengliang.li51f54b62023-10-10 12:14:49 +00001734 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001735 case GST_EVENT_FLUSH_START:
bo.xiao857b8682024-09-12 16:40:32 +08001736 GST_DEBUG_OBJECT (self, "flush start");
xuesong.jiangc5dac0f2023-02-01 14:42:24 +08001737
bo.xiao857b8682024-09-12 16:40:32 +08001738 g_mutex_lock (&self->res_chg_lock);
1739 while (self->is_res_chg)
1740 {
1741 GST_LOG_OBJECT(decoder, "wait resolution change finish");
1742 g_cond_wait(&self->res_chg_cond, &self->res_chg_lock);
1743 }
1744 g_mutex_unlock (&self->res_chg_lock);
xuesong.jiangc5dac0f2023-02-01 14:42:24 +08001745
bo.xiao857b8682024-09-12 16:40:32 +08001746 self->last_out_pts = GST_CLOCK_TIME_NONE;
1747 gst_aml_v4l2_object_flush_start (self->v4l2output);
1748 gst_aml_v4l2_object_flush_start (self->v4l2capture);
1749 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001750 default:
bo.xiao857b8682024-09-12 16:40:32 +08001751 break;
1752 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001753
bo.xiao857b8682024-09-12 16:40:32 +08001754 ret = GST_AML_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001755
bo.xiao857b8682024-09-12 16:40:32 +08001756 switch (type)
1757 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001758 case GST_EVENT_FLUSH_START:
bo.xiao857b8682024-09-12 16:40:32 +08001759 /* The processing thread should stop now, wait for it */
1760 gst_pad_stop_task (decoder->srcpad);
1761 self->codec_data_inject = FALSE;
1762 GST_DEBUG_OBJECT (self, "flush start done");
1763 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001764 default:
bo.xiao857b8682024-09-12 16:40:32 +08001765 break;
1766 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001767
bo.xiao857b8682024-09-12 16:40:32 +08001768 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001769}
1770
1771static GstStateChangeReturn
bo.xiao857b8682024-09-12 16:40:32 +08001772gst_aml_v4l2_video_dec_change_state (GstElement * element,
1773 GstStateChange transition)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001774{
bo.xiao857b8682024-09-12 16:40:32 +08001775 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(element);
1776 GstAmlVideoDecoder *decoder = GST_AML_VIDEO_DECODER(element);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001777
bo.xiao857b8682024-09-12 16:40:32 +08001778 GST_DEBUG_OBJECT(element, "change state from %s to %s",
1779 gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
1780 gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
bo.xiao8e3054d2024-07-31 17:13:57 +08001781
bo.xiao857b8682024-09-12 16:40:32 +08001782 if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
1783 {
1784 g_atomic_int_set (&self->active, FALSE);
1785 gst_aml_v4l2_object_flush_start (self->v4l2output);
1786 gst_aml_v4l2_object_flush_start (self->v4l2capture);
1787 gst_pad_stop_task (decoder->srcpad);
1788 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001789
bo.xiao857b8682024-09-12 16:40:32 +08001790 return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001791}
1792
1793static void
bo.xiao857b8682024-09-12 16:40:32 +08001794gst_aml_v4l2_video_dec_dispose (GObject * object)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001795{
bo.xiao857b8682024-09-12 16:40:32 +08001796 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001797
bo.xiao857b8682024-09-12 16:40:32 +08001798 gst_caps_replace (&self->probed_sinkcaps, NULL);
1799 gst_caps_replace (&self->probed_srccaps, NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001800
bo.xiao857b8682024-09-12 16:40:32 +08001801 G_OBJECT_CLASS (parent_class)->dispose (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001802}
1803
1804static void
bo.xiao857b8682024-09-12 16:40:32 +08001805gst_aml_v4l2_video_dec_finalize (GObject * object)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001806{
bo.xiao857b8682024-09-12 16:40:32 +08001807 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001808
bo.xiao857b8682024-09-12 16:40:32 +08001809 gst_aml_v4l2_object_destroy (self->v4l2capture);
1810 gst_aml_v4l2_object_destroy (self->v4l2output);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001811
bo.xiao857b8682024-09-12 16:40:32 +08001812 g_mutex_clear(&self->res_chg_lock);
1813 g_cond_clear(&self->res_chg_cond);
xuesong.jiangc5dac0f2023-02-01 14:42:24 +08001814
xuesong.jiang61ea8012022-05-12 15:38:17 +08001815#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +08001816 if (self->lge_ctxt)
1817 {
1818 if (self->lge_ctxt->app_type)
1819 g_free(self->lge_ctxt->app_type);
1820 if (self->lge_ctxt->res_info.coretype)
1821 g_free(self->lge_ctxt->res_info.coretype);
1822 free(self->lge_ctxt);
1823 }
xuesong.jiang61ea8012022-05-12 15:38:17 +08001824
1825#endif
1826
bo.xiao857b8682024-09-12 16:40:32 +08001827 G_OBJECT_CLASS (parent_class)->finalize (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001828}
1829
1830static void
bo.xiao857b8682024-09-12 16:40:32 +08001831gst_aml_v4l2_video_dec_init (GstAmlV4l2VideoDec * self)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001832{
bo.xiao857b8682024-09-12 16:40:32 +08001833 /* V4L2 object are created in subinstance_init */
1834 self->last_out_pts = GST_CLOCK_TIME_NONE;
1835 self->frame_duration = GST_CLOCK_TIME_NONE;
1836 self->is_secure_path = FALSE;
1837 self->is_res_chg = FALSE;
1838 self->codec_data_inject = FALSE;
1839 g_mutex_init(&self->res_chg_lock);
1840 g_cond_init(&self->res_chg_cond);
xuesong.jiang61ea8012022-05-12 15:38:17 +08001841#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +08001842 self->lge_ctxt = malloc(sizeof(GstAmlV4l2VideoDecLgeCtxt));
1843 memset(self->lge_ctxt, 0, sizeof(GstAmlV4l2VideoDecLgeCtxt));
xuesong.jiang61ea8012022-05-12 15:38:17 +08001844#endif
xuesong.jiangae1548e2022-05-06 16:38:46 +08001845}
1846
1847static void
bo.xiao857b8682024-09-12 16:40:32 +08001848gst_aml_v4l2_video_dec_subinstance_init (GTypeInstance * instance, gpointer g_class)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001849{
bo.xiao857b8682024-09-12 16:40:32 +08001850 GstAmlV4l2VideoDecClass *klass = GST_AML_V4L2_VIDEO_DEC_CLASS (g_class);
1851 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (instance);
1852 GstAmlVideoDecoder *decoder = GST_AML_VIDEO_DECODER (instance);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001853
bo.xiao857b8682024-09-12 16:40:32 +08001854 gst_aml_video_decoder_set_packetized (decoder, TRUE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001855
bo.xiao857b8682024-09-12 16:40:32 +08001856 self->v4l2output = gst_aml_v4l2_object_new (GST_ELEMENT (self),
1857 GST_OBJECT (GST_AML_VIDEO_DECODER_SINK_PAD (self)),
1858 V4L2_BUF_TYPE_VIDEO_OUTPUT, klass->default_device,
1859 gst_aml_v4l2_get_output, gst_aml_v4l2_set_output, NULL);
1860 self->v4l2output->no_initial_format = TRUE;
1861 self->v4l2output->keep_aspect = FALSE;
1862 self->v4l2output->is_svp = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001863
bo.xiao857b8682024-09-12 16:40:32 +08001864 self->v4l2capture = gst_aml_v4l2_object_new (GST_ELEMENT (self),
1865 GST_OBJECT (GST_AML_VIDEO_DECODER_SRC_PAD (self)),
1866 V4L2_BUF_TYPE_VIDEO_CAPTURE, klass->default_device,
1867 gst_aml_v4l2_get_input, gst_aml_v4l2_set_input, NULL);
1868 self->v4l2capture->need_wait_event = TRUE;
1869 self->v4l2capture->need_drop_event = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001870}
1871
1872static void
bo.xiao857b8682024-09-12 16:40:32 +08001873gst_aml_v4l2_video_dec_class_init (GstAmlV4l2VideoDecClass * klass)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001874{
bo.xiao857b8682024-09-12 16:40:32 +08001875 GstElementClass *element_class;
1876 GObjectClass *gobject_class;
1877 GstAmlVideoDecoderClass *video_decoder_class;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001878
bo.xiao857b8682024-09-12 16:40:32 +08001879 parent_class = g_type_class_peek_parent (klass);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001880
bo.xiao857b8682024-09-12 16:40:32 +08001881 element_class = (GstElementClass *) klass;
1882 gobject_class = (GObjectClass *) klass;
1883 video_decoder_class = (GstAmlVideoDecoderClass *) klass;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001884
bo.xiao857b8682024-09-12 16:40:32 +08001885 GST_DEBUG_CATEGORY_INIT (gst_aml_v4l2_video_dec_debug, "amlv4l2videodec", 0,
1886 "AML V4L2 Video Decoder");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001887
bo.xiao857b8682024-09-12 16:40:32 +08001888 gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_dispose);
1889 gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_finalize);
1890 gobject_class->set_property =
1891 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_set_property);
1892 gobject_class->get_property =
1893 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_get_property);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001894
bo.xiao857b8682024-09-12 16:40:32 +08001895 video_decoder_class->open = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_open);
1896 video_decoder_class->close = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_close);
1897 video_decoder_class->start = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_start);
1898 video_decoder_class->stop = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_stop);
1899 video_decoder_class->finish = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_finish);
1900 video_decoder_class->flush = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_flush);
1901 video_decoder_class->drain = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_drain);
1902 video_decoder_class->set_format =
1903 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_set_format);
1904 video_decoder_class->negotiate =
1905 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_negotiate);
1906 video_decoder_class->decide_allocation =
1907 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_decide_allocation);
1908 /* FIXME propose_allocation or not ? */
1909 video_decoder_class->handle_frame =
1910 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_handle_frame);
1911 video_decoder_class->getcaps =
1912 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_sink_getcaps);
1913 video_decoder_class->src_query =
1914 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_src_query);
1915 video_decoder_class->sink_event =
1916 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_sink_event);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001917
bo.xiao857b8682024-09-12 16:40:32 +08001918 element_class->change_state =
1919 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_change_state);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001920
xuesong.jiang406ee302023-06-28 03:45:22 +00001921 g_signals[SIGNAL_DECODED_PTS] = g_signal_new ("decoded-pts",
bo.xiao857b8682024-09-12 16:40:32 +08001922 G_TYPE_FROM_CLASS(GST_ELEMENT_CLASS(klass)),
1923 G_SIGNAL_RUN_LAST,
1924 0, /* class offset */
1925 NULL, /* accumulator */
1926 NULL, /* accu data */
1927 g_cclosure_marshal_generic,
1928 G_TYPE_NONE,
1929 1,
1930 G_TYPE_UINT64);
1931 g_signals[SIGNAL_DECODED_ERROR_PTS] = g_signal_new ("decoded-error-pts",
1932 G_TYPE_FROM_CLASS(GST_ELEMENT_CLASS(klass)),
1933 G_SIGNAL_RUN_LAST,
1934 0, /* class offset */
1935 NULL, /* accumulator */
1936 NULL, /* accu data */
1937 g_cclosure_marshal_generic,
1938 G_TYPE_NONE,
1939 1,
1940 G_TYPE_UINT64);
xuesong.jiang406ee302023-06-28 03:45:22 +00001941
bo.xiao857b8682024-09-12 16:40:32 +08001942 gst_aml_v4l2_object_install_m2m_properties_helper (gobject_class);
xuesong.jiang61ea8012022-05-12 15:38:17 +08001943#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +08001944 gst_aml_v4l2_video_dec_install_lge_properties_helper(gobject_class);
xuesong.jiang61ea8012022-05-12 15:38:17 +08001945#endif
xuesong.jiangae1548e2022-05-06 16:38:46 +08001946}
1947
1948static void
bo.xiao857b8682024-09-12 16:40:32 +08001949gst_aml_v4l2_video_dec_subclass_init (gpointer g_class, gpointer data)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001950{
bo.xiao857b8682024-09-12 16:40:32 +08001951 GstAmlV4l2VideoDecClass *klass = GST_AML_V4L2_VIDEO_DEC_CLASS (g_class);
1952 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1953 GstAmlV4l2VideoDecCData *cdata = data;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001954
bo.xiao857b8682024-09-12 16:40:32 +08001955 klass->default_device = cdata->device;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001956
bo.xiao857b8682024-09-12 16:40:32 +08001957 /* Note: gst_pad_template_new() take the floating ref from the caps */
1958 gst_element_class_add_pad_template (element_class,
1959 gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
1960 cdata->sink_caps));
1961 gst_element_class_add_pad_template (element_class,
1962 gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
1963 cdata->src_caps));
xuesong.jiangae1548e2022-05-06 16:38:46 +08001964
bo.xiao857b8682024-09-12 16:40:32 +08001965 gst_element_class_set_metadata (element_class, cdata->longname,
1966 "Codec/Decoder/Video/Hardware", cdata->description,
1967 "Xuesong Jiang <Xuesong.Jiang@amlogic.com>");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001968
bo.xiao857b8682024-09-12 16:40:32 +08001969 gst_caps_unref (cdata->sink_caps);
1970 gst_caps_unref (cdata->src_caps);
1971 g_free (cdata);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001972}
1973
1974/* Probing functions */
1975gboolean
bo.xiao857b8682024-09-12 16:40:32 +08001976gst_aml_v4l2_is_video_dec (GstCaps * sink_caps, GstCaps * src_caps)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001977{
bo.xiao857b8682024-09-12 16:40:32 +08001978 gboolean ret = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001979
bo.xiao857b8682024-09-12 16:40:32 +08001980 if (gst_caps_is_subset (sink_caps, gst_aml_v4l2_object_get_codec_caps ())
1981 && gst_caps_is_subset (src_caps, gst_aml_v4l2_object_get_raw_caps ()))
1982 ret = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001983
bo.xiao857b8682024-09-12 16:40:32 +08001984 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001985}
1986
1987static gchar *
bo.xiao857b8682024-09-12 16:40:32 +08001988gst_aml_v4l2_video_dec_set_metadata (GstStructure * s, GstAmlV4l2VideoDecCData * cdata,
1989 const gchar * basename)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001990{
bo.xiao857b8682024-09-12 16:40:32 +08001991 gchar *codec_name = NULL;
1992 gchar *type_name = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001993
bo.xiao857b8682024-09-12 16:40:32 +08001994#define SET_META(codec) \
1995G_STMT_START { \
1996 cdata->longname = "AML V4L2 " codec " Decoder"; \
1997 cdata->description = "Decodes " codec " streams via V4L2 API"; \
1998 codec_name = g_ascii_strdown (codec, -1); \
1999} G_STMT_END
xuesong.jiangae1548e2022-05-06 16:38:46 +08002000
bo.xiao857b8682024-09-12 16:40:32 +08002001 if (gst_structure_has_name(s, "video/mjpeg"))
2002 {
2003 SET_META("MJPEG");
2004 }
2005 else if (gst_structure_has_name (s, "video/mpeg"))
2006 {
2007 //include mpeg1, mpeg2, mpeg4
2008 SET_META("MPEG4");
2009 }
2010 else if (gst_structure_has_name (s, "video/x-h263"))
2011 {
2012 SET_META ("H263");
2013 }
2014 else if (gst_structure_has_name (s, "video/x-fwht"))
2015 {
2016 SET_META ("FWHT");
2017 }
2018 else if (gst_structure_has_name (s, "video/x-h264"))
2019 {
2020 SET_META ("H264");
2021 }
2022 else if (gst_structure_has_name (s, "video/x-h265"))
2023 {
2024 SET_META ("H265");
2025 }
2026 else if (gst_structure_has_name (s, "video/x-wmv"))
2027 {
2028 SET_META ("VC1");
2029 }
2030 else if (gst_structure_has_name (s, "video/x-vp8"))
2031 {
2032 SET_META ("VP8");
2033 }
2034 else if (gst_structure_has_name (s, "video/x-vp9"))
2035 {
2036 SET_META ("VP9");
2037 }
2038 else if (gst_structure_has_name(s, "video/x-av1"))
2039 {
2040 SET_META("AV1");
2041 }
2042 else if (gst_structure_has_name(s, "video/x-avs"))
2043 {
2044 SET_META("AVS");
2045 }
2046 else if (gst_structure_has_name(s, "video/x-avs2"))
2047 {
2048 SET_META("AVS2");
2049 }
2050 else if (gst_structure_has_name(s, "video/x-avs3"))
2051 {
2052 SET_META("AVS3");
2053 }
2054 else if (gst_structure_has_name (s, "video/x-bayer"))
2055 {
2056 SET_META ("BAYER");
2057 }
2058 else if (gst_structure_has_name (s, "video/x-sonix"))
2059 {
2060 SET_META ("SONIX");
2061 }
2062 else if (gst_structure_has_name (s, "video/x-pwc1"))
2063 {
2064 SET_META ("PWC1");
2065 }
2066 else if (gst_structure_has_name (s, "video/x-pwc2"))
2067 {
2068 SET_META ("PWC2");
2069 }
2070 else
2071 {
2072 /* This code should be kept on sync with the exposed CODEC type of format
2073 * from gstamlv4l2object.c. This warning will only occur in case we forget
2074 * to also add a format here. */
2075 gchar *s_str = gst_structure_to_string (s);
2076 g_warning ("Missing fixed name mapping for caps '%s', this is a GStreamer "
2077 "bug, please report at https://bugs.gnome.org", s_str);
2078 g_free (s_str);
2079 }
2080
2081 if (codec_name)
2082 {
2083 type_name = g_strdup_printf ("amlv4l2%sdec", codec_name);
2084 if (g_type_from_name (type_name) != 0)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002085 {
bo.xiao857b8682024-09-12 16:40:32 +08002086 g_free (type_name);
2087 type_name = g_strdup_printf ("amlv4l2%s%sdec", basename, codec_name);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002088 }
2089
bo.xiao857b8682024-09-12 16:40:32 +08002090 g_free (codec_name);
2091 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002092
bo.xiao857b8682024-09-12 16:40:32 +08002093 return type_name;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002094#undef SET_META
2095}
2096
bo.xiao857b8682024-09-12 16:40:32 +08002097void
2098gst_aml_v4l2_video_dec_register(GstPlugin *plugin, const gchar *basename,
xuesong.jiangae1548e2022-05-06 16:38:46 +08002099 const gchar *device_path, GstCaps *sink_caps, GstCaps *src_caps)
2100{
bo.xiao857b8682024-09-12 16:40:32 +08002101 gint i;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002102
bo.xiao857b8682024-09-12 16:40:32 +08002103 for (i = 0; i < gst_caps_get_size (sink_caps); i++)
2104 {
2105 GstAmlV4l2VideoDecCData *cdata;
2106 GstStructure *s;
2107 GTypeQuery type_query;
2108 GTypeInfo type_info = { 0, };
2109 GType type, subtype;
2110 gchar *type_name;
2111
2112 s = gst_caps_get_structure (sink_caps, i);
2113
2114 cdata = g_new0 (GstAmlV4l2VideoDecCData, 1);
2115 cdata->device = g_strdup (device_path);
2116 cdata->sink_caps = gst_caps_new_empty ();
2117 gst_caps_append_structure (cdata->sink_caps, gst_structure_copy (s));
2118 gst_caps_append_structure (cdata->sink_caps, gst_structure_copy (s));
2119 gst_caps_set_features(cdata->sink_caps, 0, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
2120 cdata->src_caps = gst_caps_copy(src_caps);
2121 gst_caps_set_features_simple(cdata->src_caps, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
2122 gst_caps_append(cdata->src_caps, gst_caps_copy (src_caps));
2123 type_name = gst_aml_v4l2_video_dec_set_metadata (s, cdata, basename);
2124
2125 /* Skip over if we hit an unmapped type */
2126 if (!type_name)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002127 {
bo.xiao857b8682024-09-12 16:40:32 +08002128 g_free (cdata);
2129 continue;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002130 }
bo.xiao857b8682024-09-12 16:40:32 +08002131
2132 type = gst_aml_v4l2_video_dec_get_type ();
2133 g_type_query (type, &type_query);
2134 memset (&type_info, 0, sizeof (type_info));
2135 type_info.class_size = type_query.class_size;
2136 type_info.instance_size = type_query.instance_size;
2137 type_info.class_init = gst_aml_v4l2_video_dec_subclass_init;
2138 type_info.class_data = cdata;
2139 type_info.instance_init = gst_aml_v4l2_video_dec_subinstance_init;
2140
2141 subtype = g_type_register_static (type, type_name, &type_info, 0);
2142 if (!gst_element_register (plugin, type_name, GST_RANK_PRIMARY + 1,
2143 subtype))
2144 GST_WARNING ("Failed to register plugin '%s'", type_name);
2145
2146 g_free (type_name);
2147 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002148}
xuesong.jiang61ea8012022-05-12 15:38:17 +08002149
2150#if GST_IMPORT_LGE_PROP
2151static void gst_aml_v4l2_video_dec_install_lge_properties_helper(GObjectClass *gobject_class)
2152{
2153 g_object_class_install_property(gobject_class, LGE_RESOURCE_INFO,
2154 g_param_spec_object("resource-info", "resource-info",
2155 "After acquisition of H/W resources is completed, allocated resource information must be delivered to the decoder and the sink",
2156 GST_TYPE_STRUCTURE,
2157 G_PARAM_READABLE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
2158
2159 g_object_class_install_property(gobject_class, LGE_DECODE_SIZE,
2160 g_param_spec_uint64("decoded-size", "decoded-size",
2161 "The total amount of decoder element's decoded video es after constructing pipeline or flushing pipeline update unit is byte.",
2162 0, G_MAXUINT64,
2163 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2164
2165 g_object_class_install_property(gobject_class, LGE_UNDECODE_SIZE,
2166 g_param_spec_uint64("undecoded-size", "undecoded-size",
2167 "video decoder element's total undecoded data update unit is byte.",
2168 0, G_MAXUINT64,
2169 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2170
2171 g_object_class_install_property(gobject_class, LGE_APP_TYPE,
2172 g_param_spec_string("app-type", "app-type",
2173 "set application type.",
2174 "default_app",
2175 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2176
2177 g_object_class_install_property(gobject_class, LGE_CLIP_MODE,
2178 g_param_spec_boolean("clip-mode", "clip-mode",
2179 "When seeking, Content is moving faster for a while to skip frames.",
2180 FALSE,
2181 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2182}
2183#endif