blob: 74a66e0eed8c51594b0cd11f816746debc389e72 [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.jiang0223de52024-09-13 15:33:10 +0800107static GstFlowReturn gst_aml_v4l2_video_dec_clip_and_push_frame (GstAmlVideoDecoder * decoder, GstAmlVideoCodecFrame * frame);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800108
109static void
110gst_aml_v4l2_video_dec_set_property(GObject *object,
bo.xiao857b8682024-09-12 16:40:32 +0800111 guint prop_id, const GValue * value, GParamSpec * pspec)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800112{
bo.xiao857b8682024-09-12 16:40:32 +0800113 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(object);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800114
bo.xiao857b8682024-09-12 16:40:32 +0800115 switch (prop_id)
116 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800117 case PROP_CAPTURE_IO_MODE:
xuesong.jiangae1548e2022-05-06 16:38:46 +0800118 case PROP_DUMP_FRAME_LOCATION:
zengliang.lidcd41462024-06-19 16:05:12 +0800119 case PROP_CC_DATA:
bo.xiao857b8682024-09-12 16:40:32 +0800120 if (!gst_aml_v4l2_object_set_property_helper(self->v4l2capture,
121 prop_id, value, pspec))
122 {
123 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124 }
125 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800126#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +0800127 case LGE_RESOURCE_INFO:
128 {
129 GST_DEBUG_OBJECT(self, "LGE up layer set res info");
130 GstStructure *r_info = g_value_get_object(value);
131 if (r_info)
132 {
133 if (gst_structure_has_field(r_info, "coretype"))
134 {
135 if (self->lge_ctxt->res_info.coretype)
136 g_free(self->lge_ctxt->res_info.coretype);
137 self->lge_ctxt->res_info.coretype = g_strdup(gst_structure_get_string(r_info, "coretype"));
138 }
139 if (gst_structure_has_field(r_info, "videoport"))
140 gst_structure_get_int(r_info, "videoport", &(self->lge_ctxt->res_info.videoport));
141 if (gst_structure_has_field(r_info, "audioport"))
142 gst_structure_get_int(r_info, "audioport", &(self->lge_ctxt->res_info.audioport));
143 if (gst_structure_has_field(r_info, "maxwidth"))
144 gst_structure_get_int(r_info, "maxwidth", &(self->lge_ctxt->res_info.maxwidth));
145 if (gst_structure_has_field(r_info, "maxheight"))
146 gst_structure_get_int(r_info, "maxheight", &(self->lge_ctxt->res_info.maxheight));
147 if (gst_structure_has_field(r_info, "mixerport"))
148 gst_structure_get_int(r_info, "mixerport", &(self->lge_ctxt->res_info.mixerport));
149 }
150 break;
151 }
152 case LGE_APP_TYPE:
153 {
154 GST_DEBUG_OBJECT(self, "LGE up layer set app type");
155 if (self->lge_ctxt->app_type)
156 g_free(self->lge_ctxt->app_type);
157 self->lge_ctxt->app_type = g_strdup(g_value_get_string(value));
158 break;
159 }
160 case LGE_CLIP_MODE:
161 {
162 GST_DEBUG_OBJECT(self, "LGE up layer set clip mode");
163 self->lge_ctxt->clip_mode = g_strdup(g_value_get_boolean(value));
164 break;
165 }
xuesong.jiang61ea8012022-05-12 15:38:17 +0800166#endif
bo.xiao857b8682024-09-12 16:40:32 +0800167 /* By default, only set on output */
xuesong.jiangae1548e2022-05-06 16:38:46 +0800168 default:
bo.xiao857b8682024-09-12 16:40:32 +0800169 if (!gst_aml_v4l2_object_set_property_helper (self->v4l2output,
170 prop_id, value, pspec))
171 {
172 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
173 }
174 break;
175 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800176}
177
178static void
179gst_aml_v4l2_video_dec_get_property(GObject *object,
180 guint prop_id, GValue *value, GParamSpec *pspec)
181{
bo.xiao857b8682024-09-12 16:40:32 +0800182 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(object);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800183
bo.xiao857b8682024-09-12 16:40:32 +0800184 switch (prop_id)
185 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800186 case PROP_CAPTURE_IO_MODE:
zengliang.lidcd41462024-06-19 16:05:12 +0800187 case PROP_CC_DATA:
fei.dengaf682762024-06-24 19:06:03 +0800188 case PROP_DECODING_ERROR_FRAMES:
bo.xiao857b8682024-09-12 16:40:32 +0800189 if (!gst_aml_v4l2_object_get_property_helper (self->v4l2capture,
190 prop_id, value, pspec))
191 {
192 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
193 }
194 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800195#if GST_IMPORT_LGE_PROP
196 case LGE_DECODE_SIZE:
197 {
bo.xiao857b8682024-09-12 16:40:32 +0800198 GST_DEBUG_OBJECT(self, "LGE up layer get dec size");
199 self->lge_ctxt->dec_size = -1;
200 g_value_set_int(value, self->lge_ctxt->dec_size);
201 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800202 }
203 case LGE_UNDECODE_SIZE:
204 {
bo.xiao857b8682024-09-12 16:40:32 +0800205 GST_DEBUG_OBJECT(self, "LGE up layer get undec size");
206 self->lge_ctxt->undec_size = -1;
207 g_value_set_int(value, self->lge_ctxt->undec_size);
208 break;
xuesong.jiang61ea8012022-05-12 15:38:17 +0800209 }
210#endif
211
bo.xiao857b8682024-09-12 16:40:32 +0800212 /* By default read from output */
213 default:
214 if (!gst_aml_v4l2_object_get_property_helper (self->v4l2output,
215 prop_id, value, pspec))
216 {
217 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800218 }
bo.xiao857b8682024-09-12 16:40:32 +0800219 break;
220 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800221}
222
223static gboolean
le.han02c38f02024-08-16 02:35:36 +0000224gst_aml_v4l2_video_dec_open(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800225{
bo.xiao857b8682024-09-12 16:40:32 +0800226 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
227 GstCaps *codec_caps;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800228
bo.xiao857b8682024-09-12 16:40:32 +0800229 GST_DEBUG_OBJECT (self, "Opening");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800230
bo.xiao857b8682024-09-12 16:40:32 +0800231 if (!gst_aml_v4l2_object_open (self->v4l2output))
xuesong.jiangae1548e2022-05-06 16:38:46 +0800232 goto failure;
233
bo.xiao857b8682024-09-12 16:40:32 +0800234 if (!gst_aml_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
235 goto failure;
236
237 codec_caps = gst_pad_get_pad_template_caps (decoder->sinkpad);
238 self->probed_sinkcaps = gst_aml_v4l2_object_probe_caps (self->v4l2output,
239 codec_caps);
240 gst_caps_unref (codec_caps);
241
242 if (gst_caps_is_empty (self->probed_sinkcaps))
243 goto no_encoded_format;
244
245 return TRUE;
246
247no_encoded_format:
248 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
249 (_("Decoder on device %s has no supported input format"),
250 self->v4l2output->videodev), (NULL));
251 goto failure;
252
xuesong.jiangae1548e2022-05-06 16:38:46 +0800253failure:
bo.xiao857b8682024-09-12 16:40:32 +0800254 if (GST_AML_V4L2_IS_OPEN (self->v4l2output))
255 gst_aml_v4l2_object_close (self->v4l2output);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800256
bo.xiao857b8682024-09-12 16:40:32 +0800257 if (GST_AML_V4L2_IS_OPEN (self->v4l2capture))
258 gst_aml_v4l2_object_close (self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800259
bo.xiao857b8682024-09-12 16:40:32 +0800260 gst_caps_replace (&self->probed_srccaps, NULL);
261 gst_caps_replace (&self->probed_sinkcaps, NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800262
bo.xiao857b8682024-09-12 16:40:32 +0800263 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800264}
265
266static gboolean
le.han02c38f02024-08-16 02:35:36 +0000267gst_aml_v4l2_video_dec_close(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800268{
bo.xiao857b8682024-09-12 16:40:32 +0800269 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800270
bo.xiao857b8682024-09-12 16:40:32 +0800271 GST_DEBUG_OBJECT (self, "Closing");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800272
bo.xiao857b8682024-09-12 16:40:32 +0800273 gst_aml_v4l2_object_close(self->v4l2output);
274 gst_aml_v4l2_object_close(self->v4l2capture);
275 gst_caps_replace (&self->probed_srccaps, NULL);
276 gst_caps_replace (&self->probed_sinkcaps, NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800277
bo.xiao857b8682024-09-12 16:40:32 +0800278 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800279}
280
281static gboolean
le.han02c38f02024-08-16 02:35:36 +0000282gst_aml_v4l2_video_dec_start(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800283{
bo.xiao857b8682024-09-12 16:40:32 +0800284 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800285
bo.xiao857b8682024-09-12 16:40:32 +0800286 GST_DEBUG_OBJECT (self, "Starting");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800287
bo.xiao857b8682024-09-12 16:40:32 +0800288 gst_aml_v4l2_object_flush_start (self->v4l2output);
289 g_atomic_int_set (&self->active, TRUE);
290 self->output_flow = GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800291
bo.xiao857b8682024-09-12 16:40:32 +0800292 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800293}
294
295static gboolean
le.han02c38f02024-08-16 02:35:36 +0000296gst_aml_v4l2_video_dec_stop(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800297{
bo.xiao857b8682024-09-12 16:40:32 +0800298 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800299
bo.xiao857b8682024-09-12 16:40:32 +0800300 GST_DEBUG_OBJECT (self, "Stopping");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800301
bo.xiao857b8682024-09-12 16:40:32 +0800302 gst_aml_v4l2_object_flush_start (self->v4l2output);
303 gst_aml_v4l2_object_flush_start (self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800304
bo.xiao857b8682024-09-12 16:40:32 +0800305 /* Wait for capture thread to stop */
306 gst_pad_stop_task (decoder->srcpad);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800307
bo.xiao857b8682024-09-12 16:40:32 +0800308 GST_AML_VIDEO_DECODER_STREAM_LOCK(decoder);
309 self->output_flow = GST_FLOW_OK;
310 GST_AML_VIDEO_DECODER_STREAM_UNLOCK(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800311
bo.xiao857b8682024-09-12 16:40:32 +0800312 /* Should have been flushed already */
313 g_assert (g_atomic_int_get (&self->active) == FALSE);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800314
bo.xiao857b8682024-09-12 16:40:32 +0800315 gst_aml_v4l2_object_stop(self->v4l2output);
316 gst_aml_v4l2_object_stop(self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800317
bo.xiao857b8682024-09-12 16:40:32 +0800318 if (self->input_state)
319 {
320 gst_aml_video_codec_state_unref(self->input_state);
321 self->input_state = NULL;
322 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800323
bo.xiao857b8682024-09-12 16:40:32 +0800324 GST_DEBUG_OBJECT (self, "Stopped");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800325
bo.xiao857b8682024-09-12 16:40:32 +0800326 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800327}
328
329static gboolean
le.han02c38f02024-08-16 02:35:36 +0000330gst_aml_v4l2_video_dec_codec_chg(GstAmlVideoDecoder *decoder,
331 GstAmlVideoCodecState *state)
hanghang.luo8e1225b2023-10-10 08:54:28 +0000332{
bo.xiao857b8682024-09-12 16:40:32 +0800333 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
334 GstStructure *s_old = NULL;
335 GstStructure *s_new = NULL;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000336
bo.xiao857b8682024-09-12 16:40:32 +0800337 // first play, must set foramt;
338 if (!self->input_state)
339 return TRUE;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000340
bo.xiao857b8682024-09-12 16:40:32 +0800341 if (self->input_state->caps)
342 s_old = gst_caps_get_structure(self->input_state->caps,0);
343 if (state->caps)
344 s_new = gst_caps_get_structure(state->caps,0);
hanghang.luo8e1225b2023-10-10 08:54:28 +0000345
bo.xiao857b8682024-09-12 16:40:32 +0800346 if (s_new && s_old && strcmp(gst_structure_get_name(s_new),gst_structure_get_name(s_old)))
347 return TRUE;
348 return FALSE;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000349}
350
351static gboolean
le.han02c38f02024-08-16 02:35:36 +0000352gst_aml_v4l2_video_dec_res_chg(GstAmlVideoDecoder *decoder,
353 GstAmlVideoCodecState *state)
hanghang.luo8e1225b2023-10-10 08:54:28 +0000354{
bo.xiao857b8682024-09-12 16:40:32 +0800355 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
356 gboolean ret = FALSE;
357 gint width_new = -1,height_new = -1,width_old = -1,height_old = -1;
358 GstStructure *s_old = NULL;
359 GstStructure *s_new = NULL;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000360
bo.xiao857b8682024-09-12 16:40:32 +0800361 // first play, must set foramt;
362 if (!self->input_state)
363 {
364 ret = TRUE;
365 goto done;
366 }
hanghang.luo8e1225b2023-10-10 08:54:28 +0000367
bo.xiao857b8682024-09-12 16:40:32 +0800368 if (self->input_state->caps)
369 s_old = gst_caps_get_structure(self->input_state->caps,0);
370 if (state->caps)
371 s_new = gst_caps_get_structure(state->caps,0);
hanghang.luo8e1225b2023-10-10 08:54:28 +0000372
bo.xiao857b8682024-09-12 16:40:32 +0800373 if (s_new && gst_structure_has_field(s_new,"width") && gst_structure_has_field(s_new,"height"))
374 {
375 gst_structure_get_int(s_new,"width",&width_new);
376 gst_structure_get_int(s_new,"height",&height_new);
377 }
378 if (s_old && gst_structure_has_field(s_old,"width") && gst_structure_has_field(s_old,"height"))
379 {
380 gst_structure_get_int(s_old,"width",&width_old);
381 gst_structure_get_int(s_old,"height",&height_old);
382 }
hanghang.luo8e1225b2023-10-10 08:54:28 +0000383
bo.xiao857b8682024-09-12 16:40:32 +0800384 if (width_new != width_old || height_new != height_old)
385 ret = TRUE;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000386
387done:
bo.xiao857b8682024-09-12 16:40:32 +0800388 GST_DEBUG_OBJECT(self, "ret is %d",ret);
389 return ret;
hanghang.luo8e1225b2023-10-10 08:54:28 +0000390}
391
392static gboolean
le.han02c38f02024-08-16 02:35:36 +0000393gst_aml_v4l2_video_dec_set_format(GstAmlVideoDecoder *decoder,
394 GstAmlVideoCodecState *state)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800395{
bo.xiao857b8682024-09-12 16:40:32 +0800396 GstAmlV4l2Error error = GST_AML_V4L2_ERROR_INIT;
397 gboolean ret = TRUE;
398 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
399 GstCaps *caps;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800400
bo.xiao857b8682024-09-12 16:40:32 +0800401 GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
402 if (self->input_state)
403 {
404 if (gst_aml_v4l2_video_dec_res_chg(decoder,state) || gst_aml_v4l2_video_dec_codec_chg(decoder,state))
405 GST_DEBUG_OBJECT(self, "resolution or codec changed");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800406 else
bo.xiao857b8682024-09-12 16:40:32 +0800407 goto done;
408 }
409
410 GstCapsFeatures *const features = gst_caps_get_features(state->caps, 0);
411 GstStructure *s = gst_caps_get_structure(state->caps,0);
412 if (s && gst_structure_has_field(s,"format"))
413 {
414 if (!strcmp("XVID",gst_structure_get_string(s,"format")))
415 {
416 GST_DEBUG_OBJECT(self, "This is a DIVX file, cannot support");
417 ret = FALSE;
418 goto done;
419 }
420 }
421
422 if (gst_caps_features_contains(features, GST_CAPS_FEATURE_MEMORY_DMABUF))
423 self->v4l2output->req_mode = GST_V4L2_IO_DMABUF_IMPORT;
424
425 if (self->input_state)
426 {
427 if (gst_aml_v4l2_object_caps_equal(self->v4l2output, state->caps))
428 {
429 GST_DEBUG_OBJECT (self, "Compatible caps");
430 goto done;
431 }
432
433 gst_aml_v4l2_video_dec_finish (decoder);
434 gst_aml_v4l2_object_stop (self->v4l2output);
435
436 gst_aml_video_codec_state_unref(self->input_state);
437 self->input_state = NULL;
438
439 /* The renegotiation flow don't blend with the base class flow. To properly
440 * stop the capture pool, if the buffers can't be orphaned, we need to
441 * reclaim our buffers, which will happend through the allocation query.
442 * The allocation query is triggered by gst_aml_video_decoder_negotiate() which
443 * requires the output caps to be set, but we can't know this information
444 * as we rely on the decoder, which requires the capture queue to be
445 * stopped.
446 *
447 * To workaround this issue, we simply run an allocation query with the
448 * old negotiated caps in order to drain/reclaim our buffers. That breaks
449 * the complexity and should not have much impact in performance since the
450 * following allocation query will happen on a drained pipeline and won't
451 * block. */
452 if (self->v4l2capture->pool &&
453 !gst_aml_v4l2_buffer_pool_orphan(&self->v4l2capture->pool))
454 {
455 GstCaps *caps = gst_pad_get_current_caps (decoder->srcpad);
456 if (caps)
457 {
458 GstQuery *query = gst_query_new_allocation (caps, FALSE);
459 gst_pad_peer_query (decoder->srcpad, query);
460 gst_query_unref (query);
461 gst_caps_unref (caps);
462 }
463 }
464
465 gst_aml_v4l2_object_stop (self->v4l2capture);
466 self->output_flow = GST_FLOW_OK;
467 }
468 if ((ret = gst_aml_v4l2_set_drm_mode(self->v4l2output)) == FALSE)
469 {
470 GST_ERROR_OBJECT(self, "config output drm mode error");
471 goto done;
472 }
473
474 if ((ret = gst_aml_v4l2_set_stream_mode(self->v4l2output)) == FALSE)
475 {
476 GST_ERROR_OBJECT(self, "config output stream mode error");
477 goto done;
478 }
479
480 if (!gst_aml_v4l2_object_set_format (self->v4l2output, state->caps, &error))
481 {
482 GST_ERROR_OBJECT(self, "set format error");
483 goto done;
484 }
485
486 // MUST: aml v4l2 drive request set I frame after VIDIOC_S_FMT.
487 if ((ret = gst_aml_v4l2_set_I_frame_mode(self->v4l2output)) == FALSE)
488 {
489 GST_ERROR_OBJECT(self, "config I frame mode error");
490 goto done;
491 }
492
493 gst_caps_replace (&self->probed_srccaps, NULL);
494 self->probed_srccaps = gst_aml_v4l2_object_probe_caps (self->v4l2capture,
495 gst_aml_v4l2_object_get_raw_caps ());
496
497 if (gst_caps_is_empty (self->probed_srccaps))
498 goto no_raw_format;
499
500 caps = gst_caps_copy(self->probed_srccaps);
501 gst_caps_set_features_simple(caps, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
502 gst_caps_append(self->probed_srccaps, caps);
503 if (ret)
504 self->input_state = gst_aml_video_codec_state_ref (state);
505 else
506 gst_aml_v4l2_error (self, &error);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800507
508done:
bo.xiao857b8682024-09-12 16:40:32 +0800509 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800510
511no_raw_format:
bo.xiao857b8682024-09-12 16:40:32 +0800512 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
513 (_("Decoder on device %s has no supported output format"),
514 self->v4l2output->videodev), (NULL));
515 return GST_FLOW_ERROR;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800516}
517
518static gboolean
le.han02c38f02024-08-16 02:35:36 +0000519gst_aml_v4l2_video_dec_flush(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800520{
bo.xiao857b8682024-09-12 16:40:32 +0800521 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800522
bo.xiao857b8682024-09-12 16:40:32 +0800523 GST_DEBUG_OBJECT(self, "Flushed");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800524
bo.xiao857b8682024-09-12 16:40:32 +0800525 /* Ensure the processing thread has stopped for the reverse playback
526 * discount case */
527 if (gst_pad_get_task_state (decoder->srcpad) == GST_TASK_STARTED)
528 {
529 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800530
bo.xiao857b8682024-09-12 16:40:32 +0800531 gst_aml_v4l2_object_flush_start (self->v4l2output);
532 gst_aml_v4l2_object_flush_start (self->v4l2capture);
533 gst_pad_stop_task (decoder->srcpad);
534 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
535 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800536
bo.xiao857b8682024-09-12 16:40:32 +0800537 self->output_flow = GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800538
bo.xiao857b8682024-09-12 16:40:32 +0800539 gst_aml_v4l2_object_flush_stop (self->v4l2output);
540 gst_aml_v4l2_object_flush_stop (self->v4l2capture);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800541
bo.xiao857b8682024-09-12 16:40:32 +0800542 if (self->v4l2output->pool)
543 gst_aml_v4l2_buffer_pool_flush (self->v4l2output->pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800544
bo.xiao857b8682024-09-12 16:40:32 +0800545 /* gst_aml_v4l2_buffer_pool_flush() calls streamon the capture pool and must be
546 * called after gst_aml_v4l2_object_flush_stop() stopped flushing the buffer
547 * pool. */
548 if (self->v4l2capture->pool)
549 gst_aml_v4l2_buffer_pool_flush (self->v4l2capture->pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800550
bo.xiao857b8682024-09-12 16:40:32 +0800551 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800552}
553
554static gboolean
le.han02c38f02024-08-16 02:35:36 +0000555gst_aml_v4l2_video_dec_negotiate(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800556{
bo.xiao857b8682024-09-12 16:40:32 +0800557 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800558
xuesong.jiang0223de52024-09-13 15:33:10 +0800559 if (TRUE == decoder->svp)
bo.xiao857b8682024-09-12 16:40:32 +0800560 {
561 GstStructure *s;
562 GstEvent *event;
xuesong.jiang681d3602022-06-24 21:23:35 +0800563
bo.xiao857b8682024-09-12 16:40:32 +0800564 s = gst_structure_new_empty ("IS_SVP");
565 event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, s);
566 GST_DEBUG_OBJECT(self, "before Send SVP Event :%p", event);
567 gst_pad_push_event (decoder->srcpad, event);
568 GST_DEBUG_OBJECT(self, "after Send SVP Event :%p", event);
569 }
xuesong.jiang681d3602022-06-24 21:23:35 +0800570
bo.xiao857b8682024-09-12 16:40:32 +0800571 /* We don't allow renegotiation without carefull disabling the pool */
572 if (self->v4l2capture->pool &&
573 gst_buffer_pool_is_active(GST_BUFFER_POOL(self->v4l2capture->pool)))
574 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800575
bo.xiao857b8682024-09-12 16:40:32 +0800576 return GST_AML_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800577}
578
579static gboolean
580gst_aml_v4l2_decoder_cmd(GstAmlV4l2Object *v4l2object, guint cmd, guint flags)
581{
bo.xiao857b8682024-09-12 16:40:32 +0800582 struct v4l2_decoder_cmd dcmd = { 0, };
xuesong.jiangae1548e2022-05-06 16:38:46 +0800583
bo.xiao857b8682024-09-12 16:40:32 +0800584 GST_DEBUG_OBJECT (v4l2object->element,
585 "sending v4l2 decoder command %u with flags %u", cmd, flags);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800586
bo.xiao857b8682024-09-12 16:40:32 +0800587 if (!GST_AML_V4L2_IS_OPEN (v4l2object))
588 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800589
bo.xiao857b8682024-09-12 16:40:32 +0800590 dcmd.cmd = cmd;
591 dcmd.flags = flags;
592 if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_DECODER_CMD, &dcmd) < 0)
593 goto dcmd_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800594
bo.xiao857b8682024-09-12 16:40:32 +0800595 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800596
597dcmd_failed:
bo.xiao857b8682024-09-12 16:40:32 +0800598 if (errno == ENOTTY)
599 {
600 GST_INFO_OBJECT (v4l2object->element,
601 "Failed to send decoder command %u with flags %u for '%s'. (%s)",
602 cmd, flags, v4l2object->videodev, g_strerror (errno));
603 }
604 else
605 {
606 GST_ERROR_OBJECT (v4l2object->element,
607 "Failed to send decoder command %u with flags %u for '%s'. (%s)",
608 cmd, flags, v4l2object->videodev, g_strerror (errno));
609 }
610 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800611}
612
613static GstFlowReturn
le.han02c38f02024-08-16 02:35:36 +0000614gst_aml_v4l2_video_dec_finish(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800615{
bo.xiao857b8682024-09-12 16:40:32 +0800616 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
617 GstFlowReturn ret = GST_FLOW_OK;
618 GstBuffer *buffer;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800619
bo.xiao857b8682024-09-12 16:40:32 +0800620 if (gst_pad_get_task_state (decoder->srcpad) != GST_TASK_STARTED)
621 goto done;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800622
bo.xiao857b8682024-09-12 16:40:32 +0800623 GST_DEBUG_OBJECT (self, "Finishing decoding");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800624
bo.xiao857b8682024-09-12 16:40:32 +0800625 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800626
bo.xiao857b8682024-09-12 16:40:32 +0800627 if (gst_aml_v4l2_decoder_cmd (self->v4l2output, V4L2_DEC_CMD_STOP, 0))
628 {
629 GstTask *task = decoder->srcpad->task;
630
631 /* If the decoder stop command succeeded, just wait until processing is
632 * finished */
633 GST_DEBUG_OBJECT (self, "Waiting for decoder stop");
634 GST_OBJECT_LOCK (task);
635 while (GST_TASK_STATE (task) == GST_TASK_STARTED)
636 GST_TASK_WAIT (task);
637 GST_OBJECT_UNLOCK (task);
638
639 ret = GST_FLOW_FLUSHING;
640 }
641 else
642 {
643 /* otherwise keep queuing empty buffers until the processing thread has
644 * stopped, _pool_process() will return FLUSHING when that happened */
645 while (ret == GST_FLOW_OK)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800646 {
bo.xiao857b8682024-09-12 16:40:32 +0800647 GST_DEBUG_OBJECT(self, "queue empty output buf");
648 buffer = gst_buffer_new ();
649 ret =
650 gst_aml_v4l2_buffer_pool_process(GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &buffer);
651 gst_buffer_unref (buffer);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800652 }
bo.xiao857b8682024-09-12 16:40:32 +0800653 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800654
bo.xiao857b8682024-09-12 16:40:32 +0800655 /* and ensure the processing thread has stopped in case another error
656 * occurred. */
657 gst_aml_v4l2_object_flush_start (self->v4l2capture);
658 gst_pad_stop_task (decoder->srcpad);
659 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800660
bo.xiao857b8682024-09-12 16:40:32 +0800661 if (ret == GST_FLOW_FLUSHING)
662 ret = self->output_flow;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800663
bo.xiao857b8682024-09-12 16:40:32 +0800664 /*if V4L2_DEC_CMD_STOP called,indicate decoder will stop.
665 should reset need_wait_event=true to wait source change event*/
666 self->v4l2capture->need_wait_event = TRUE;
667 GST_DEBUG_OBJECT (decoder, "Done draining buffers");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800668
bo.xiao857b8682024-09-12 16:40:32 +0800669 /* TODO Shall we cleanup any reffed frame to workaround broken decoders ? */
xuesong.jiangae1548e2022-05-06 16:38:46 +0800670
671done:
bo.xiao857b8682024-09-12 16:40:32 +0800672 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800673}
674
675static GstFlowReturn
le.han02c38f02024-08-16 02:35:36 +0000676gst_aml_v4l2_video_dec_drain(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800677{
678 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
679
bo.xiao857b8682024-09-12 16:40:32 +0800680 GST_DEBUG_OBJECT (self, "Draining...");
681 gst_aml_v4l2_video_dec_finish (decoder);
682 gst_aml_v4l2_video_dec_flush (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800683
bo.xiao857b8682024-09-12 16:40:32 +0800684 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800685}
686
le.han02c38f02024-08-16 02:35:36 +0000687static GstAmlVideoCodecFrame *
688gst_aml_v4l2_video_dec_get_right_frame_for_frame_mode(GstAmlVideoDecoder *decoder, GstClockTime pts)
fei.dengbee20862022-06-14 14:59:48 +0800689{
bo.xiao857b8682024-09-12 16:40:32 +0800690 GstAmlVideoCodecFrame *frame = NULL;
691 GList *frames, *l;
692 gint count = 0;
fei.dengbee20862022-06-14 14:59:48 +0800693
bo.xiao857b8682024-09-12 16:40:32 +0800694 GST_LOG_OBJECT (decoder, "trace in with pts: %" GST_TIME_FORMAT, GST_TIME_ARGS(pts));
xuesong.jiange24aef92023-06-16 06:39:10 +0000695
bo.xiao857b8682024-09-12 16:40:32 +0800696 frames = gst_aml_video_decoder_get_frames(decoder);
fei.dengbee20862022-06-14 14:59:48 +0800697
bo.xiao857b8682024-09-12 16:40:32 +0800698 for (l = frames; l != NULL; l = l->next)
699 {
700 GstAmlVideoCodecFrame *f = l->data;
fei.denge9458472023-04-18 02:05:48 +0000701
bo.xiao857b8682024-09-12 16:40:32 +0800702 if (GST_CLOCK_TIME_IS_VALID(pts) && (ABSDIFF(f->pts,pts)) < 1000) {
703 frame = f;
704 }
705 count++;
706 }
fei.dengbee20862022-06-14 14:59:48 +0800707
bo.xiao857b8682024-09-12 16:40:32 +0800708 if (!frame)
709 {
710 for (l = frames; l != NULL; l = l->next)
711 {
712 GstAmlVideoCodecFrame *f = l->data;
713 if (!GST_CLOCK_TIME_IS_VALID(f->pts))
714 {
715 frame = f;
716 GST_DEBUG("The pts of the expected output frame is invalid");
717 break;
718 }
719 }
720 }
zengliang.liddee2da2023-07-14 07:27:05 +0000721
bo.xiao857b8682024-09-12 16:40:32 +0800722 if (frame)
723 {
724 GST_LOG_OBJECT(decoder,
725 "frame %p is %d %" GST_TIME_FORMAT " and %d frames left",
726 frame, frame->system_frame_number, GST_TIME_ARGS(frame->pts), count - 1);
727 gst_aml_video_codec_frame_ref(frame);
728 }
729 else
730 {
731 GST_LOG_OBJECT(decoder,
732 "buffer %" GST_TIME_FORMAT " unmatch, create new frame", GST_TIME_ARGS(pts));
733 frame = gst_aml_video_decoder_v4l2_new_frame (decoder);
734 }
fei.dengbee20862022-06-14 14:59:48 +0800735
bo.xiao857b8682024-09-12 16:40:32 +0800736 g_list_free_full(frames, (GDestroyNotify)gst_aml_video_codec_frame_unref);
fei.dengbee20862022-06-14 14:59:48 +0800737
bo.xiao857b8682024-09-12 16:40:32 +0800738 return frame;
fei.dengbee20862022-06-14 14:59:48 +0800739}
740
le.han02c38f02024-08-16 02:35:36 +0000741static GstAmlVideoCodecFrame *
742gst_aml_v4l2_video_dec_get_right_frame_for_stream_mode(GstAmlVideoDecoder *decoder, GstClockTime pts)
xuesong.jiange24aef92023-06-16 06:39:10 +0000743{
bo.xiao857b8682024-09-12 16:40:32 +0800744 GstAmlVideoCodecFrame *frame = NULL;
745 GList *frames, *l;
746 guint frames_len = 0;
747 GST_LOG_OBJECT (decoder, "trace in with pts: %" GST_TIME_FORMAT, GST_TIME_ARGS(pts));
xuesong.jiange24aef92023-06-16 06:39:10 +0000748
bo.xiao857b8682024-09-12 16:40:32 +0800749 if (!(frames = gst_aml_video_decoder_get_frames(decoder)))
750 goto done;
hanghang.luo4486d7d2024-07-24 10:06:35 +0800751
bo.xiao857b8682024-09-12 16:40:32 +0800752 frames_len = g_list_length(frames);
753 GST_LOG_OBJECT (decoder, "got frames list len:%d", frames_len);
xuesong.jiange24aef92023-06-16 06:39:10 +0000754
bo.xiao857b8682024-09-12 16:40:32 +0800755 for (l = frames; l != NULL; l = l->next)
756 {
757 GstAmlVideoCodecFrame *f = l->data;
xuesong.jiange24aef92023-06-16 06:39:10 +0000758
bo.xiao857b8682024-09-12 16:40:32 +0800759 if (GST_CLOCK_TIME_IS_VALID(pts) && (ABSDIFF(f->pts, pts)) < 1000)
760 {
761 /* found the right frame */
762 GST_LOG_OBJECT(decoder,
763 "found frame %" GST_TIME_FORMAT "with pts %" GST_TIME_FORMAT,
764 GST_TIME_ARGS(f->pts), GST_TIME_ARGS(pts));
765 frame = f;
766 break;
767 }
768 else if(GST_CLOCK_TIME_IS_VALID(pts) && (f->pts < pts))
769 {
770 GST_LOG_OBJECT(decoder,
771 "stream mode drop frame %d %" GST_TIME_FORMAT,
772 f->system_frame_number, GST_TIME_ARGS(f->pts));
xuesong.jiange24aef92023-06-16 06:39:10 +0000773
bo.xiao857b8682024-09-12 16:40:32 +0800774 gst_aml_video_codec_frame_ref(f);
775 // gst_aml_video_decoder_drop_frame(decoder, f);
776 gst_aml_video_decoder_release_frame(decoder, f);
777 }
778 else
779 {
780 GST_LOG_OBJECT (decoder, "dbg");
781 }
782 }
xuesong.jiange24aef92023-06-16 06:39:10 +0000783
bo.xiao857b8682024-09-12 16:40:32 +0800784 if (frame)
785 {
786 guint l_len = 0;
787 l = gst_aml_video_decoder_get_frames(decoder);
788 l_len = g_list_length(l);
789 g_list_free_full(l, (GDestroyNotify)gst_aml_video_codec_frame_unref);
xuesong.jiange24aef92023-06-16 06:39:10 +0000790
bo.xiao857b8682024-09-12 16:40:32 +0800791 GST_LOG_OBJECT(decoder,
792 "frame %p is %d %" GST_TIME_FORMAT " and %d frames left",
793 frame, frame->system_frame_number, GST_TIME_ARGS(frame->pts), l_len);
794 gst_aml_video_codec_frame_ref(frame);
795 }
xuesong.jiange24aef92023-06-16 06:39:10 +0000796
bo.xiao857b8682024-09-12 16:40:32 +0800797 g_list_free_full(frames, (GDestroyNotify)gst_aml_video_codec_frame_unref);
xuesong.jiange24aef92023-06-16 06:39:10 +0000798
hanghang.luo4486d7d2024-07-24 10:06:35 +0800799done:
bo.xiao857b8682024-09-12 16:40:32 +0800800 return frame;
xuesong.jiange24aef92023-06-16 06:39:10 +0000801}
802
le.han02c38f02024-08-16 02:35:36 +0000803static GstAmlVideoCodecFrame *
804gst_aml_v4l2_video_dec_get_right_frame(GstAmlVideoDecoder *decoder, GstClockTime pts)
xuesong.jiange24aef92023-06-16 06:39:10 +0000805{
bo.xiao857b8682024-09-12 16:40:32 +0800806 GstAmlV4l2VideoDec *self = (GstAmlV4l2VideoDec *)decoder;
807 if (self->v4l2output->stream_mode)
808 return gst_aml_v4l2_video_dec_get_right_frame_for_stream_mode(decoder, pts);
809 else
810 return gst_aml_v4l2_video_dec_get_right_frame_for_frame_mode(decoder, pts);
xuesong.jiange24aef92023-06-16 06:39:10 +0000811}
812
xuesong.jiangae1548e2022-05-06 16:38:46 +0800813static gboolean
814gst_aml_v4l2_video_remove_padding(GstCapsFeatures *features,
815 GstStructure *structure, gpointer user_data)
816{
bo.xiao857b8682024-09-12 16:40:32 +0800817 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(user_data);
818 GstVideoAlignment *align = &self->v4l2capture->align;
819 GstVideoInfo *info = &self->v4l2capture->info;
820 int width, height;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800821
bo.xiao857b8682024-09-12 16:40:32 +0800822 if (!gst_structure_get_int(structure, "width", &width))
823 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800824
bo.xiao857b8682024-09-12 16:40:32 +0800825 if (!gst_structure_get_int(structure, "height", &height))
826 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800827
bo.xiao857b8682024-09-12 16:40:32 +0800828 if (align->padding_left != 0 || align->padding_top != 0 ||
829 height != info->height + align->padding_bottom)
830 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800831
bo.xiao857b8682024-09-12 16:40:32 +0800832 if (height == info->height + align->padding_bottom)
833 {
834 /* Some drivers may round up width to the padded with */
835 if (width == info->width + align->padding_right)
836 gst_structure_set(structure,
837 "width", G_TYPE_INT, width - align->padding_right,
838 "height", G_TYPE_INT, height - align->padding_bottom, NULL);
839 /* Some drivers may keep visible width and only round up bytesperline */
840 else if (width == info->width)
841 gst_structure_set(structure,
842 "height", G_TYPE_INT, height - align->padding_bottom, NULL);
843 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800844
bo.xiao857b8682024-09-12 16:40:32 +0800845 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800846}
847
848static void
sheng.liubcf036c2022-06-21 15:55:42 +0800849gst_v4l2_drop_event (GstAmlV4l2Object * v4l2object)
sheng.liub56bbc52022-06-21 11:02:33 +0800850{
851 struct v4l2_event evt;
852 gint ret;
853
854 memset (&evt, 0x00, sizeof (struct v4l2_event));
855 ret = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_DQEVENT, &evt);
856 if (ret < 0)
857 {
858 GST_DEBUG_OBJECT (v4l2object, "dqevent failed");
859 return;
860 }
861
862 switch (evt.type)
863 {
864 case V4L2_EVENT_SOURCE_CHANGE:
865 GST_DEBUG_OBJECT (v4l2object, "Drop GST_V4L2_FLOW_SOURCE_CHANGE");
866 break;
867 case V4L2_EVENT_EOS:
868 GST_DEBUG_OBJECT (v4l2object, "Drop GST_V4L2_FLOW_LAST_BUFFER");
869 break;
870 default:
871 break;
872 }
873
874 return;
875}
876
877static void
le.han02c38f02024-08-16 02:35:36 +0000878gst_aml_v4l2_video_dec_set_output_status(GstAmlVideoDecoder *decoder,GstVideoInfo info)
hanghang.luo2eec4892023-07-18 06:44:42 +0000879{
bo.xiao857b8682024-09-12 16:40:32 +0800880 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
881 GstAmlVideoCodecState *output_state;
882 struct v4l2_selection sel;
883 struct v4l2_rect *r = NULL;
884 GstStructure *s;
885 gint width = 0;
886 gint height = 0;
887 GST_DEBUG("%d %d",info.width, info.height);
888 output_state = gst_aml_video_decoder_set_output_state(decoder,
889 info.finfo->format, info.width, info.height, self->input_state);
890 memset(&sel, 0, sizeof(struct v4l2_selection));
891 sel.type = self->v4l2capture->type;
le.han3b118242024-09-29 06:32:02 +0000892 sel.target = V4L2_SEL_TGT_CROP_DEFAULT;
bo.xiao857b8682024-09-12 16:40:32 +0800893 if (self->v4l2capture->ioctl(self->v4l2capture->video_fd, VIDIOC_G_SELECTION, &sel) >= 0)
894 {
895 r = &sel.r;
896 width = (r->width/2)*2;
897 height = (r->height/2)*2;
898 GST_DEBUG_OBJECT(self, "w:%d h:%d ",width,height);
899 }
900 else
901 GST_DEBUG_OBJECT(self, "iotcl error");
902 if (output_state)
903 {
904 output_state->info.interlace_mode = info.interlace_mode;
905 output_state->allocation_caps =gst_video_info_to_caps(&info);
906 output_state->caps =gst_video_info_to_caps(&info);
907 s = gst_caps_get_structure(output_state->caps, 0);
908 if (s)
hanghang.luo9b60a3c2023-08-01 16:01:47 +0000909 {
bo.xiao857b8682024-09-12 16:40:32 +0800910 gst_structure_set(s,"src_width",G_TYPE_INT,width,NULL);
911 gst_structure_set(s,"src_height",G_TYPE_INT,height,NULL);
912 gst_structure_set(s,"width",G_TYPE_INT,info.width,NULL);
913 gst_structure_set(s,"height",G_TYPE_INT,info.height,NULL);
le.han3b118242024-09-29 06:32:02 +0000914 gst_structure_set(s,"dw_mode",G_TYPE_INT,self->v4l2output->dw_mode,NULL);
915 gst_structure_set(s,"stride",G_TYPE_INT,self->v4l2output->stride,NULL);
bo.xiao857b8682024-09-12 16:40:32 +0800916 GST_DEBUG_OBJECT(self, "output_state->caps: %" GST_PTR_FORMAT, output_state->caps);
917 gst_aml_video_codec_state_unref(output_state);
hanghang.luo9b60a3c2023-08-01 16:01:47 +0000918 }
bo.xiao857b8682024-09-12 16:40:32 +0800919 }
hanghang.luo2eec4892023-07-18 06:44:42 +0000920}
921
zengliang.lidcd41462024-06-19 16:05:12 +0800922static GQuark
923gst_aml_v4l2_buffer_pool_cc_import_quark (void)
924{
925 static GQuark quark = 0;
926
927 if (quark == 0)
928 quark = g_quark_from_string ("GstAmlV4l2BufferPoolCcUsePtrData");
929
930 return quark;
931}
932
933static gboolean
le.han02c38f02024-08-16 02:35:36 +0000934foreach_cc_buffer_list_match_pts_func(GList *list , GstAmlVideoCodecFrame *frame)
zengliang.lidcd41462024-06-19 16:05:12 +0800935{
bo.xiao857b8682024-09-12 16:40:32 +0800936 GList *l;
937 if (g_list_length (list) > 0)
938 {
939 for (l = list; l != NULL; l = l->next)
zengliang.lidcd41462024-06-19 16:05:12 +0800940 {
bo.xiao857b8682024-09-12 16:40:32 +0800941 GstBuffer *cc_buffer = l->data;
942 if (GST_BUFFER_TIMESTAMP (frame->output_buffer) == GST_BUFFER_TIMESTAMP (cc_buffer))
943 {
944 gst_mini_object_set_qdata (GST_MINI_OBJECT (frame->output_buffer), GST_AML_V4L2_CC_IMPORT_QUARK,
945 gst_buffer_ref(cc_buffer), (GDestroyNotify) gst_buffer_unref);
946 #if 0
947 //Debug code:dump cc data
948 GstMapInfo gst_map;
949 gst_buffer_map(cc_buffer,&gst_map,GST_MAP_READ);
950 int fd=open("/data/test/cc1.data",O_RDWR |O_CREAT|O_APPEND,0777);
951 if (gst_map.size>0)
952 write(fd,gst_map.data,gst_map.size);
953 close(fd);
954 gst_buffer_unmap(cc_buffer,&gst_map);
955 #endif
956 GST_DEBUG("match success");
957 return TRUE;
958 }
959 else
960 {
961 GST_DEBUG("match fail");
962 }
zengliang.lidcd41462024-06-19 16:05:12 +0800963 }
bo.xiao857b8682024-09-12 16:40:32 +0800964 GST_WARNING("no match frame in the bufferlist");
965 }
966 else
967 {
968 GST_WARNING("list is null,can not foreach");
969 }
970 return FALSE;
zengliang.lidcd41462024-06-19 16:05:12 +0800971}
972
bo.xiao8e3054d2024-07-31 17:13:57 +0800973static GstClockTime
le.han44125c32024-09-03 07:55:57 +0000974gst_aml_v4l2_video_dec_calc_output_buffer_pts(GstAmlVideoDecoder *decoder)
bo.xiao8e3054d2024-07-31 17:13:57 +0800975{
bo.xiao857b8682024-09-12 16:40:32 +0800976 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
977 GstClockTime pts = GST_CLOCK_TIME_NONE;
bo.xiao8e3054d2024-07-31 17:13:57 +0800978
bo.xiao857b8682024-09-12 16:40:32 +0800979 if (GST_CLOCK_TIME_IS_VALID (self->last_out_pts) && GST_CLOCK_TIME_IS_VALID(self->frame_duration)) {
980 pts = self->last_out_pts + self->frame_duration;
981 GST_LOG_OBJECT (decoder,
982 "calculate PTS %" GST_TIME_FORMAT " by duration: %" GST_TIME_FORMAT,
983 GST_TIME_ARGS (pts), GST_TIME_ARGS (self->frame_duration));
984 }
985 else
986 {
987 pts = 0;
988 GST_INFO_OBJECT (decoder,"Set PTS=0");
989 }
990 return pts;
bo.xiao8e3054d2024-07-31 17:13:57 +0800991}
992
993static GstClockTime
le.han44125c32024-09-03 07:55:57 +0000994gst_aml_v4l2_video_dec_calc_duration(GstAmlVideoDecoder *decoder)
bo.xiao8e3054d2024-07-31 17:13:57 +0800995{
996 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
997 GstClockTime duration = GST_CLOCK_TIME_NONE;
998 gint fps_n, fps_d;
999 fps_n = gst_value_get_fraction_numerator(self->v4l2capture->fps);
1000 fps_d = gst_value_get_fraction_denominator(self->v4l2capture->fps);
1001
1002 if (fps_n != 0 && fps_d != 0)
1003 {
1004 duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n);
1005
1006 if (self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
1007 {
1008 duration = duration / 2;
1009 }
1010 }
1011
1012 GST_INFO_OBJECT (decoder,"framerate(fps_d: %d, fps_n: %d) -> frame_duration = %" GST_TIME_FORMAT, fps_d, fps_n, GST_TIME_ARGS(duration));
1013
1014 return duration;
1015}
1016
xuesong.jiang0223de52024-09-13 15:33:10 +08001017static GstFlowReturn
1018gst_aml_v4l2_video_dec_clip_and_push_frame (GstAmlVideoDecoder * decoder, GstAmlVideoCodecFrame * frame)
1019{
1020 GstFlowReturn ret = GST_FLOW_OK;
1021 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
1022 gboolean drop = FALSE;
1023
1024 if ((decoder->input_segment.rate > 0 && GST_CLOCK_TIME_NONE == decoder->input_segment.start) ||
1025 (decoder->input_segment.rate < 0 && GST_CLOCK_TIME_NONE == decoder->input_segment.stop))
1026 {
1027 GST_DEBUG_OBJECT(self, "don't do clip when we have no input segment");
1028 goto done;
1029 }
1030
1031 if (decoder->input_segment.rate > 0)
1032 {
1033 GstClockTime duration = 0;
1034
1035 if (GST_CLOCK_TIME_NONE != frame->duration)
1036 duration = frame->duration;
1037
1038 if ((frame->pts + duration) < decoder->input_segment.start)
1039 {
1040 GST_DEBUG_OBJECT(self, "drop frame with pts(dur %" GST_TIME_FORMAT ") %" GST_TIME_FORMAT " < start %" GST_TIME_FORMAT,
1041 GST_TIME_ARGS(frame->pts), GST_TIME_ARGS(frame->duration), GST_TIME_ARGS(decoder->input_segment.start));
1042 drop = TRUE;
1043 goto done;
1044 }
1045 }
1046 else if (decoder->input_segment.rate < 0)
1047 {
1048 if (frame->pts > decoder->input_segment.stop)
1049 {
1050 GST_DEBUG_OBJECT(self, "drop frame with pts(dur %" GST_TIME_FORMAT ") %" GST_TIME_FORMAT " > stop %" GST_TIME_FORMAT,
1051 GST_TIME_ARGS(frame->pts), GST_TIME_ARGS(frame->duration), GST_TIME_ARGS(decoder->input_segment.stop));
1052 drop = TRUE;
1053 goto done;
1054 }
1055 }
1056
1057done:
1058 if (G_LIKELY (!drop))
1059 ret = gst_aml_video_decoder_finish_frame(decoder, frame);
1060 else
1061 ret = gst_aml_video_decoder_drop_frame(decoder, frame);
1062 return ret;
1063}
1064
hanghang.luo2eec4892023-07-18 06:44:42 +00001065static void
le.han02c38f02024-08-16 02:35:36 +00001066gst_aml_v4l2_video_dec_loop(GstAmlVideoDecoder *decoder)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001067{
bo.xiao857b8682024-09-12 16:40:32 +08001068 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
1069 GstAmlV4l2BufferPool *v4l2_pool;
1070 GstAmlV4l2Error error = GST_AML_V4L2_ERROR_INIT;
1071 GstBufferPool *pool;
1072 GstAmlVideoCodecFrame *frame;
1073 GstBuffer *buffer = NULL;
1074 GstFlowReturn ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001075
bo.xiao857b8682024-09-12 16:40:32 +08001076 if (G_UNLIKELY (!GST_AML_V4L2_IS_ACTIVE (self->v4l2capture)))
1077 {
1078 GstVideoInfo info;
1079 GstCaps *acquired_caps, *available_caps, *caps, *filter;
1080 GstStructure *st;
1081 GST_DEBUG_OBJECT(self, "waitting source change event");
1082 /* Wait until received SOURCE_CHANGE event to get right video format */
1083 while (self->v4l2capture->can_wait_event && self->v4l2capture->need_wait_event)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001084 {
bo.xiao857b8682024-09-12 16:40:32 +08001085 ret = gst_aml_v4l2_object_dqevent (self->v4l2capture);
1086 if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
1087 {
1088 //let flush start event blocked until capture buffer pool actived
1089 self->is_res_chg = TRUE;
1090 GST_DEBUG_OBJECT (self, "Received source change event");
1091 break;
1092 }
1093 else if (ret == GST_AML_V4L2_FLOW_LAST_BUFFER)
1094 {
1095 GST_DEBUG_OBJECT (self, "Received eos event");
1096 goto beach;
1097 }
1098 else if (ret != GST_FLOW_OK)
1099 {
1100 GST_ERROR_OBJECT (self, "dqevent error");
1101 goto beach;
1102 }
1103 }
1104 self->v4l2capture->need_wait_event = FALSE;
1105
xuesong.jiang0223de52024-09-13 15:33:10 +08001106 if (TRUE == decoder->svp)
bo.xiao857b8682024-09-12 16:40:32 +08001107 {
1108 GstPad *peer;
1109 GstStructure *s;
1110 GstEvent *event;
1111
1112 peer = gst_pad_get_peer (decoder->srcpad);
1113 if (peer)
1114 {
1115 s = gst_structure_new_empty ("IS_SVP");
1116 if (s)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001117 {
bo.xiao857b8682024-09-12 16:40:32 +08001118 event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
1119 gst_pad_send_event (peer, event);
1120 GST_DEBUG_OBJECT(self, "Send SVP Event");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001121 }
bo.xiao857b8682024-09-12 16:40:32 +08001122 gst_object_unref (peer);
1123 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001124 }
1125
bo.xiao857b8682024-09-12 16:40:32 +08001126 if (self->v4l2capture->need_drop_event)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001127 {
bo.xiao857b8682024-09-12 16:40:32 +08001128 // drop V4L2_EVENT_SOURCE_CHANGE
1129 gst_v4l2_drop_event(self->v4l2capture);
1130 self->v4l2capture->need_drop_event = FALSE;
bo.xiao8e3054d2024-07-31 17:13:57 +08001131 }
1132
bo.xiao857b8682024-09-12 16:40:32 +08001133 if (!gst_aml_v4l2_object_acquire_format (self->v4l2capture, &info))
1134 goto not_negotiated;
1135
1136 /* Create caps from the acquired format, remove the format field */
1137 acquired_caps = gst_video_info_to_caps (&info);
1138 GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
1139 st = gst_caps_get_structure (acquired_caps, 0);
1140 gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site", NULL);
1141
1142 /* Probe currently available pixel formats */
1143 available_caps = gst_caps_copy (self->probed_srccaps);
1144 GST_DEBUG_OBJECT (self, "Available caps: %" GST_PTR_FORMAT, available_caps);
1145
1146 /* Replace coded size with visible size, we want to negotiate visible size
1147 * with downstream, not coded size. */
1148 gst_caps_map_in_place (available_caps, gst_aml_v4l2_video_remove_padding, self);
1149
1150 filter = gst_caps_intersect_full (available_caps, acquired_caps, GST_CAPS_INTERSECT_FIRST);
1151 caps = gst_caps_copy(filter);
1152 gst_caps_set_features_simple(caps, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
1153 gst_caps_append(filter, caps);
1154
1155 GST_DEBUG_OBJECT (self, "Filtered caps: %" GST_PTR_FORMAT, filter);
1156 gst_caps_unref (acquired_caps);
1157 gst_caps_unref (available_caps);
1158 caps = gst_pad_peer_query_caps (decoder->srcpad, filter);
1159 gst_caps_unref (filter);
1160
1161 GST_DEBUG_OBJECT (self, "Possible decoded caps: %" GST_PTR_FORMAT, caps);
1162 if (gst_caps_is_empty (caps))
bo.xiao8e3054d2024-07-31 17:13:57 +08001163 {
bo.xiao857b8682024-09-12 16:40:32 +08001164 gst_caps_unref (caps);
1165 goto not_negotiated;
bo.xiao8e3054d2024-07-31 17:13:57 +08001166 }
1167
bo.xiao857b8682024-09-12 16:40:32 +08001168 /* Fixate pixel format */
1169 caps = gst_caps_fixate (caps);
bo.xiao8e3054d2024-07-31 17:13:57 +08001170
bo.xiao857b8682024-09-12 16:40:32 +08001171 GST_DEBUG_OBJECT (self, "Chosen decoded caps: %" GST_PTR_FORMAT, caps);
zengliang.lidcd41462024-06-19 16:05:12 +08001172
bo.xiao857b8682024-09-12 16:40:32 +08001173 /* Try to set negotiated format, on success replace acquired format */
1174 if (gst_aml_v4l2_object_set_format (self->v4l2capture, caps, &error))
1175 gst_video_info_from_caps (&info, caps);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001176 else
bo.xiao857b8682024-09-12 16:40:32 +08001177 gst_aml_v4l2_clear_error (&error);
1178 gst_caps_unref (caps);
1179 gst_aml_v4l2_video_dec_set_output_status(decoder,info);
1180 if (!gst_aml_video_decoder_negotiate (decoder))
xuesong.jiangae1548e2022-05-06 16:38:46 +08001181 {
bo.xiao857b8682024-09-12 16:40:32 +08001182 if (GST_PAD_IS_FLUSHING (decoder->srcpad))
1183 goto flushing;
1184 else
1185 goto not_negotiated;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001186 }
1187
bo.xiao857b8682024-09-12 16:40:32 +08001188 /* Ensure our internal pool is activated */
1189 if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
1190 TRUE))
1191 goto activate_failed;
1192
1193 //cal duration when got resolution event
1194 self->frame_duration = gst_aml_v4l2_video_dec_calc_duration(decoder);
1195
1196 g_mutex_lock(&self->res_chg_lock);
1197 GST_LOG_OBJECT(decoder, "signal resolution changed");
1198 self->is_res_chg = FALSE;
1199 g_cond_signal(&self->res_chg_cond);
1200 g_mutex_unlock(&self->res_chg_lock);
1201 }
1202
1203 GST_LOG_OBJECT (decoder, "Allocate output buffer");
1204 v4l2_pool = GST_AML_V4L2_BUFFER_POOL(self->v4l2capture->pool);
1205
1206 self->output_flow = GST_FLOW_OK;
1207 do
1208 {
1209 /* We cannot use the base class allotate helper since it taking the internal
1210 * stream lock. we know that the acquire may need to poll until more frames
1211 * comes in and holding this lock would prevent that.
1212 */
1213 pool = gst_aml_video_decoder_get_buffer_pool (decoder);
1214
1215 /* Pool may be NULL if we started going to READY state */
1216 if (pool == NULL)
1217 {
1218 GST_WARNING_OBJECT(decoder, "gst_aml_video_decoder_get_buffer_pool goto beach");
1219 ret = GST_FLOW_FLUSHING;
1220 goto beach;
1221 }
1222
1223 ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
1224
1225 g_object_unref (pool);
1226
1227 if (ret == GST_FLOW_OK && GST_BUFFER_FLAG_IS_SET(buffer,GST_AML_V4L2_BUFFER_FLAG_LAST_EMPTY)) {
1228 GST_LOG_OBJECT(decoder, "Get GST_AML_V4L2_FLOW_LAST_BUFFER");
1229 self->v4l2capture->need_drop_event = TRUE;
1230 gst_aml_v4l2_buffer_pool_process(v4l2_pool, &buffer);
1231 if (self->is_res_chg) {
1232 //we must release last buffer
1233 gst_buffer_unref(buffer);
1234 //if resolution changed event received,we should set need_drop_event to false
1235 self->v4l2capture->need_drop_event = FALSE;
1236 gst_aml_v4l2_object_stop(self->v4l2capture);
fei.deng2a06e042023-10-10 03:09:45 +00001237 //unblock flush start event
1238 g_mutex_lock(&self->res_chg_lock);
1239 self->is_res_chg = FALSE;
1240 g_cond_signal(&self->res_chg_cond);
1241 g_mutex_unlock(&self->res_chg_lock);
bo.xiao857b8682024-09-12 16:40:32 +08001242 return;
1243 } else {
1244 goto beach;
1245 }
fei.deng2a06e042023-10-10 03:09:45 +00001246 }
bo.xiao857b8682024-09-12 16:40:32 +08001247
1248 if (ret == GST_AML_V4L2_FLOW_CC_DATA)
1249 {
1250 GST_DEBUG_OBJECT(decoder, "already got cc data, just continue.");
1251 continue;
1252 }
1253
1254 if (ret == GST_AML_V4L2_FLOW_UNKNOWN_EVENT)
1255 {
1256 GST_DEBUG_OBJECT(decoder, "unknow event, just continue.");
1257 continue;
1258 }
1259
1260 if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
1261 {
1262 GST_LOG_OBJECT(decoder, "Get GST_AML_V4L2_FLOW_SOURCE_CHANGE");
1263
1264 g_mutex_lock (&self->res_chg_lock);
1265 self->is_res_chg = TRUE;
1266 g_mutex_unlock (&self->res_chg_lock);
1267 return;
1268 }
1269
1270 //decoding error happened
1271 if (ret == GST_AML_V4L2_FLOW_DECODING_ERROR)
1272 {
1273 GST_DEBUG("send error pts:%llu - %" GST_TIME_FORMAT, v4l2_pool->obj->error_frame_pts, GST_TIME_ARGS(v4l2_pool->obj->error_frame_pts));
1274 g_signal_emit (self, g_signals[SIGNAL_DECODED_ERROR_PTS], 0, v4l2_pool->obj->error_frame_pts, NULL);
1275 g_signal_emit (self, g_signals[SIGNAL_DECODED_PTS], 0, v4l2_pool->obj->error_frame_pts);
1276 continue;
1277 }
1278
1279 if (ret != GST_FLOW_OK) {
1280 GST_WARNING_OBJECT(decoder, "gst_buffer_pool_acquire_buffer goto beach ret:%d",ret);
1281 goto beach;
1282 }
1283
1284 GST_LOG_OBJECT(decoder, "Process output buffer (switching flow outstanding num:%d)", self->v4l2capture->outstanding_buf_num);
1285 ret = gst_aml_v4l2_buffer_pool_process(v4l2_pool, &buffer);
1286
1287 GST_DEBUG_OBJECT(decoder, "decoded pts:%lld - %" GST_TIME_FORMAT, GST_BUFFER_PTS(buffer), GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));
1288 g_signal_emit (self, g_signals[SIGNAL_DECODED_PTS], 0, GST_BUFFER_PTS(buffer));
1289
1290 if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
1291 {
1292 gst_aml_v4l2_object_stop (self->v4l2capture);
1293 return;
1294 }
1295
1296 } while ((ret == GST_AML_V4L2_FLOW_CORRUPTED_BUFFER) ||
1297 (ret == GST_AML_V4L2_FLOW_CC_DATA) ||
1298 (ret == GST_AML_V4L2_FLOW_UNKNOWN_EVENT) ||
1299 (ret == GST_AML_V4L2_FLOW_DECODING_ERROR));
1300
1301 if (ret != GST_FLOW_OK)
1302 goto beach;
1303
1304 if (!GST_BUFFER_PTS_IS_VALID (buffer)
1305 || (GST_BUFFER_TIMESTAMP(buffer) == 0 && self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED))
1306 {
1307 GST_BUFFER_TIMESTAMP(buffer) = gst_aml_v4l2_video_dec_calc_output_buffer_pts(decoder);
1308 }
1309
1310 if (self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
1311 {
1312 GST_BUFFER_DURATION(buffer) = self->frame_duration; // got at resolution event.
1313 GST_BUFFER_FLAG_UNSET(buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1314 }
1315
1316 frame = gst_aml_v4l2_video_dec_get_right_frame(decoder, GST_BUFFER_TIMESTAMP (buffer));
1317 if (frame)
1318 {
1319 self->last_out_pts = GST_BUFFER_TIMESTAMP(buffer);
1320 frame->output_buffer = buffer;
1321 frame->pts = GST_BUFFER_TIMESTAMP(buffer);
1322 frame->duration = GST_BUFFER_DURATION(buffer);
1323
1324 buffer = NULL;
1325
1326 if (self->v4l2capture->enable_cc_data)
1327 {
1328 if (foreach_cc_buffer_list_match_pts_func(v4l2_pool->cc_buffer_list, frame))
1329 {
1330 GST_DEBUG("cc buffer and frame bind success");
1331 GstBuffer *cc_buffer = gst_mini_object_get_qdata (GST_MINI_OBJECT (frame->output_buffer),
1332 GST_AML_V4L2_CC_IMPORT_QUARK);
1333 #if 0
1334 //Debug code:dump cc data
1335 GstMapInfo gst_map;
1336 gst_buffer_map(cc_buffer,&gst_map,GST_MAP_READ);
1337 int fd=open("/data/test/cc2.data",O_RDWR |O_CREAT|O_APPEND,0777);
1338 if (gst_map.size>0)
1339 write(fd,gst_map.data,gst_map.size);
1340 close(fd);
1341 gst_buffer_unmap(cc_buffer,&gst_map);
1342 #endif
1343 v4l2_pool->cc_buffer_list = g_list_remove(v4l2_pool->cc_buffer_list,cc_buffer);
1344 gst_buffer_unref(cc_buffer);
1345 }
1346 else
1347 {
1348 GST_WARNING("bufferlist is empty or no match frame in the bufferlist");
1349 }
1350 }
xuesong.jiang0223de52024-09-13 15:33:10 +08001351
1352 ret = gst_aml_v4l2_video_dec_clip_and_push_frame(decoder, frame);
bo.xiao857b8682024-09-12 16:40:32 +08001353
1354 if (ret != GST_FLOW_OK)
1355 goto beach;
1356 }
1357 else
1358 {
1359 GST_WARNING_OBJECT(decoder, "Unmatch buffer, should be push, need refine");
1360 //gst_pad_push (decoder->srcpad, buffer);
1361 gst_buffer_unref (buffer);
1362 }
1363
1364 return;
1365 /* ERRORS */
1366not_negotiated:
1367 {
1368 GST_ERROR_OBJECT (self, "not negotiated");
1369 ret = GST_FLOW_NOT_NEGOTIATED;
1370 goto beach;
1371 }
1372activate_failed:
1373 {
1374 GST_ERROR_OBJECT (self, "Buffer pool activation failed");
1375 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
1376 (_("Failed to allocate required memory.")),
1377 ("Buffer pool activation failed"));
1378 ret = GST_FLOW_ERROR;
1379 goto beach;
1380 }
1381flushing:
1382 {
1383 ret = GST_FLOW_FLUSHING;
1384 goto beach;
1385 }
1386beach:
1387 GST_DEBUG_OBJECT (decoder, "Leaving output thread: %s",
1388 gst_flow_get_name (ret));
1389 if (self->is_res_chg) {
1390 //unblock flush start event
1391 g_mutex_lock(&self->res_chg_lock);
1392 self->is_res_chg = FALSE;
1393 g_cond_signal(&self->res_chg_cond);
1394 g_mutex_unlock(&self->res_chg_lock);
1395 }
1396 gst_buffer_replace (&buffer, NULL);
1397 self->output_flow = ret;
1398 gst_aml_v4l2_object_flush_start (self->v4l2output);
1399 gst_pad_pause_task (decoder->srcpad);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001400}
1401
1402static GstFlowReturn
bo.xiao857b8682024-09-12 16:40:32 +08001403gst_aml_v4l2_video_dec_handle_frame (GstAmlVideoDecoder * decoder,
1404 GstAmlVideoCodecFrame * frame)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001405{
bo.xiao857b8682024-09-12 16:40:32 +08001406 GstAmlV4l2Error error = GST_AML_V4L2_ERROR_INIT;
1407 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
1408 GstBufferPool *pool = GST_BUFFER_POOL(self->v4l2output->pool);
1409 GstFlowReturn ret = GST_FLOW_OK;
1410 gboolean processed = FALSE;
1411 GstBuffer *tmp;
1412 GstTaskState task_state;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001413
bo.xiao857b8682024-09-12 16:40:32 +08001414 GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001415
bo.xiao857b8682024-09-12 16:40:32 +08001416 if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
1417 goto flushing;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001418
bo.xiao857b8682024-09-12 16:40:32 +08001419 if (G_UNLIKELY(!GST_CLOCK_TIME_IS_VALID(self->frame_duration)))
1420 self->frame_duration = frame->duration;
le.han44125c32024-09-03 07:55:57 +00001421
bo.xiao857b8682024-09-12 16:40:32 +08001422 if (G_UNLIKELY (!GST_AML_V4L2_IS_ACTIVE (self->v4l2output)))
1423 {
1424 if (!self->input_state)
1425 goto not_negotiated;
1426 if (!gst_aml_v4l2_object_set_format (self->v4l2output, self->input_state->caps,
1427 &error))
1428 goto not_negotiated;
1429 }
1430
1431 if (G_UNLIKELY (!GST_AML_V4L2_IS_ACTIVE (self->v4l2capture)))
1432 {
1433 GstBuffer *codec_data;
1434 GstCapsFeatures *features = NULL;
1435
1436 features = gst_caps_get_features(self->input_state->caps, 0);
1437 if (features && gst_caps_features_contains(features, GST_CAPS_FEATURE_MEMORY_DMABUF) && self->v4l2output->secure_es)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001438 {
bo.xiao857b8682024-09-12 16:40:32 +08001439 GST_DEBUG_OBJECT(self, "Is SVP");
xuesong.jiang0223de52024-09-13 15:33:10 +08001440 decoder->svp = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001441 }
1442
bo.xiao857b8682024-09-12 16:40:32 +08001443 GST_DEBUG_OBJECT (self, "Sending header");
1444
1445 codec_data = self->input_state->codec_data;
1446
1447 /* We are running in byte-stream mode, so we don't know the headers, but
1448 * we need to send something, otherwise the decoder will refuse to
1449 * initialize.
1450 */
1451 if (codec_data)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001452 {
bo.xiao857b8682024-09-12 16:40:32 +08001453 gst_buffer_ref (codec_data);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001454 }
1455 else
1456 {
bo.xiao857b8682024-09-12 16:40:32 +08001457 codec_data = gst_buffer_ref (frame->input_buffer);
1458 processed = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001459 }
1460
bo.xiao857b8682024-09-12 16:40:32 +08001461 /* Ensure input internal pool is active */
1462 if (!gst_buffer_pool_is_active (pool))
1463 {
1464 GstStructure *config = gst_buffer_pool_get_config (pool);
1465 // guint min = MAX(self->v4l2output->min_buffers, GST_AML_V4L2_MIN_BUFFERS);
1466 // guint max = VIDEO_MAX_FRAME;
1467 // gst_buffer_pool_config_set_params (config, self->input_state->caps,
1468 // self->v4l2output->info.size, min, max);
1469 gst_buffer_pool_config_set_params(config, self->input_state->caps, self->v4l2output->info.size, self->v4l2output->min_buffers, self->v4l2output->min_buffers);
1470
1471 /* There is no reason to refuse this config */
1472 if (!gst_buffer_pool_set_config (pool, config))
1473 goto activate_failed;
1474 GST_DEBUG_OBJECT(self, "setting output pool config to %" GST_PTR_FORMAT, config);
1475
1476 if (!gst_buffer_pool_set_active (pool, TRUE))
1477 goto activate_failed;
1478 }
1479
1480 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
1481 ret =
1482 gst_aml_v4l2_buffer_pool_process(GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &codec_data);
1483 self->codec_data_inject = TRUE;
1484 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
1485
1486 gst_buffer_unref (codec_data);
1487
1488 /* For decoders G_FMT returns coded size, G_SELECTION returns visible size
1489 * in the compose rectangle. gst_aml_v4l2_object_acquire_format() checks both
1490 * and returns the visible size as with/height and the coded size as
1491 * padding. */
1492 }
1493
1494 task_state = gst_pad_get_task_state (GST_AML_VIDEO_DECODER_SRC_PAD (self));
1495 if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED)
1496 {
1497 /* It's possible that the processing thread stopped due to an error */
1498 if (self->output_flow != GST_FLOW_OK &&
1499 self->output_flow != GST_FLOW_FLUSHING)
1500 {
1501 GST_DEBUG_OBJECT (self, "Processing loop stopped with error, leaving");
1502 ret = self->output_flow;
1503 goto drop;
1504 }
1505
1506 GST_DEBUG_OBJECT (self, "Starting decoding thread");
1507
1508 /* Start the processing task, when it quits, the task will disable input
1509 * processing to unlock input if draining, or prevent potential block */
1510 self->output_flow = GST_FLOW_FLUSHING;
1511 /*reset poll and need_drop_event before start decoding loop thread*/
1512 self->v4l2capture->need_drop_event = FALSE;
1513 gst_poll_set_flushing(self->v4l2capture->poll, FALSE);
1514 if (!gst_pad_start_task(decoder->srcpad,
1515 (GstTaskFunction) gst_aml_v4l2_video_dec_loop, self, NULL))
1516 goto start_task_failed;
1517 }
1518
1519 if (!processed)
1520 {
1521 GST_AML_VIDEO_DECODER_STREAM_UNLOCK (decoder);
1522 if (!self->codec_data_inject && self->input_state->codec_data)
1523 {
le.han935e7aa2024-09-13 01:50:36 +00001524 if (!self->v4l2output->secure_es)
1525 {
1526 GstBuffer *buffer_input = gst_buffer_new();
1527 gst_buffer_copy_into (buffer_input, self->input_state->codec_data,
1528 GST_BUFFER_COPY_MEMORY, 0, -1);
1529 gst_buffer_copy_into (buffer_input, frame->input_buffer,
1530 GST_BUFFER_COPY_MEMORY, 0, -1);
1531 gst_buffer_unref(frame->input_buffer);
1532 frame->input_buffer = buffer_input;
1533 GST_BUFFER_PTS(frame->input_buffer) = frame->pts;
1534 self->codec_data_inject = TRUE;
1535 }
1536 else
1537 {
1538 ret = gst_aml_v4l2_buffer_pool_process
1539 (GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &self->input_state->codec_data);
1540 self->codec_data_inject = TRUE;
1541 if (ret != GST_FLOW_OK)
1542 goto send_codec_failed;
1543 }
bo.xiao857b8682024-09-12 16:40:32 +08001544 }
1545 ret =
1546 gst_aml_v4l2_buffer_pool_process(GST_AML_V4L2_BUFFER_POOL(self->v4l2output->pool), &frame->input_buffer);
1547 GST_AML_VIDEO_DECODER_STREAM_LOCK (decoder);
1548
1549 if (ret == GST_FLOW_FLUSHING)
1550 {
1551 if (gst_pad_get_task_state (GST_AML_VIDEO_DECODER_SRC_PAD (self)) !=
1552 GST_TASK_STARTED)
1553 ret = self->output_flow;
1554 goto drop;
1555 }
1556 else if (ret != GST_FLOW_OK)
1557 {
1558 goto process_failed;
1559 }
1560 }
1561
1562 /* No need to keep input around */
1563 tmp = frame->input_buffer;
1564 frame->input_buffer = gst_buffer_new ();
1565 gst_buffer_copy_into (frame->input_buffer, tmp,
1566 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
1567 GST_BUFFER_COPY_META, 0, 0);
1568 gst_buffer_unref (tmp);
1569
1570 gst_aml_video_codec_frame_unref (frame);
1571 return ret;
1572
1573 /* ERRORS */
1574send_codec_failed:
1575 GST_ERROR_OBJECT(self, "send codec_date fialed.ret is %d",ret);
1576 goto drop;
1577not_negotiated:
1578 {
1579 GST_ERROR_OBJECT (self, "not negotiated");
1580 ret = GST_FLOW_NOT_NEGOTIATED;
1581 gst_aml_v4l2_error (self, &error);
1582 goto drop;
1583 }
1584activate_failed:
1585 {
1586 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
1587 (_("Failed to allocate required memory.")),
1588 ("Buffer pool activation failed"));
1589 ret = GST_FLOW_ERROR;
1590 goto drop;
1591 }
1592flushing:
1593 {
1594 ret = GST_FLOW_FLUSHING;
1595 goto drop;
1596 }
1597
1598start_task_failed:
1599 {
1600 GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
1601 (_("Failed to start decoding thread.")), (NULL));
1602 ret = GST_FLOW_ERROR;
1603 goto drop;
1604 }
1605process_failed:
1606 {
1607 GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
1608 (_("Failed to process frame.")),
1609 ("Maybe be due to not enough memory or failing driver"));
1610 ret = GST_FLOW_ERROR;
1611 goto drop;
1612 }
1613drop:
1614 {
1615 gst_aml_video_decoder_drop_frame (decoder, frame);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001616 return ret;
bo.xiao857b8682024-09-12 16:40:32 +08001617 }
1618}
1619
1620static gboolean
1621gst_aml_v4l2_video_dec_decide_allocation (GstAmlVideoDecoder * decoder,
1622 GstQuery * query)
1623{
1624 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
1625 GstClockTime latency;
1626 gboolean ret = FALSE;
1627
1628 if (gst_aml_v4l2_object_decide_allocation (self->v4l2capture, query))
1629 ret = GST_AML_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder, query);
1630
1631 if (GST_CLOCK_TIME_IS_VALID (self->v4l2capture->duration))
1632 {
1633 latency = self->v4l2capture->min_buffers * self->v4l2capture->duration;
1634 GST_DEBUG_OBJECT (self, "Setting latency: %" GST_TIME_FORMAT " (%"
1635 G_GUINT32_FORMAT " * %" G_GUINT64_FORMAT, GST_TIME_ARGS (latency),
1636 self->v4l2capture->min_buffers, self->v4l2capture->duration);
1637 gst_aml_video_decoder_set_latency (decoder, latency, latency);
1638 }
1639 else
1640 {
1641 GST_WARNING_OBJECT (self, "Duration invalid, not setting latency");
1642 }
1643
1644 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001645}
1646
1647static gboolean
le.han02c38f02024-08-16 02:35:36 +00001648gst_aml_v4l2_video_dec_src_query(GstAmlVideoDecoder *decoder, GstQuery *query)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001649{
bo.xiao857b8682024-09-12 16:40:32 +08001650 gboolean ret = TRUE;
1651 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001652
bo.xiao857b8682024-09-12 16:40:32 +08001653 switch (GST_QUERY_TYPE (query))
1654 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001655 case GST_QUERY_CAPS:
1656 {
bo.xiao857b8682024-09-12 16:40:32 +08001657 GstCaps *filter, *result = NULL;
1658 GstPad *pad = GST_AML_VIDEO_DECODER_SRC_PAD (decoder);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001659
bo.xiao857b8682024-09-12 16:40:32 +08001660 gst_query_parse_caps (query, &filter);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001661
bo.xiao857b8682024-09-12 16:40:32 +08001662 if (self->probed_srccaps)
1663 result = gst_caps_ref (self->probed_srccaps);
1664 else
1665 result = gst_pad_get_pad_template_caps (pad);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001666
bo.xiao857b8682024-09-12 16:40:32 +08001667 if (filter)
1668 {
1669 GstCaps *tmp = result;
1670 result =
1671 gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
1672 gst_caps_unref (tmp);
1673 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001674
bo.xiao857b8682024-09-12 16:40:32 +08001675 GST_DEBUG_OBJECT (self, "Returning src caps %" GST_PTR_FORMAT, result);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001676
bo.xiao857b8682024-09-12 16:40:32 +08001677 gst_query_set_caps_result (query, result);
1678 gst_caps_unref (result);
1679 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001680 }
1681
1682 default:
bo.xiao857b8682024-09-12 16:40:32 +08001683 ret = GST_AML_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query);
1684 break;
1685 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001686
bo.xiao857b8682024-09-12 16:40:32 +08001687 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001688}
1689
1690static GstCaps *
le.han02c38f02024-08-16 02:35:36 +00001691gst_aml_v4l2_video_dec_sink_getcaps(GstAmlVideoDecoder *decoder, GstCaps *filter)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001692{
bo.xiao857b8682024-09-12 16:40:32 +08001693 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
1694 GstCaps *result;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001695
bo.xiao857b8682024-09-12 16:40:32 +08001696 result = gst_aml_video_decoder_proxy_getcaps (decoder, self->probed_sinkcaps,
1697 filter);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001698
bo.xiao857b8682024-09-12 16:40:32 +08001699 GST_DEBUG_OBJECT (self, "Returning sink caps %" GST_PTR_FORMAT, result);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001700
bo.xiao857b8682024-09-12 16:40:32 +08001701 return result;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001702}
1703
1704static gboolean
bo.xiao857b8682024-09-12 16:40:32 +08001705gst_aml_v4l2_video_dec_sink_event (GstAmlVideoDecoder *decoder, GstEvent *event)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001706{
bo.xiao857b8682024-09-12 16:40:32 +08001707 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (decoder);
1708 gboolean ret;
1709 GstEventType type = GST_EVENT_TYPE (event);
1710 GST_DEBUG_OBJECT (self, "received event %p %" GST_PTR_FORMAT, event, event);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001711
bo.xiao857b8682024-09-12 16:40:32 +08001712 switch (type)
1713 {
xuesong.jiang406ee302023-06-28 03:45:22 +00001714 case GST_EVENT_STREAM_START:
1715 {
bo.xiao857b8682024-09-12 16:40:32 +08001716 GstStructure *s;
1717 GstEvent *event;
1718 s = gst_structure_new("private_signal", "obj_ptr", G_TYPE_POINTER, self, "sig_name", G_TYPE_STRING, "decoded-pts", NULL);
1719 event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
1720 GST_DEBUG_OBJECT(self, "before Send private_signal Event :%p", event);
1721 gst_pad_push_event (decoder->sinkpad, event);
1722 GST_DEBUG_OBJECT(self, "after Send private_signal Event :%p", event);
1723 break;
xuesong.jiang406ee302023-06-28 03:45:22 +00001724 }
zengliang.li51f54b62023-10-10 12:14:49 +00001725 case GST_EVENT_CAPS:
1726 {
bo.xiao857b8682024-09-12 16:40:32 +08001727 GstCaps *caps;
1728 GstStructure *structure;
1729 gint num, denom;
zengliang.li51f54b62023-10-10 12:14:49 +00001730
bo.xiao857b8682024-09-12 16:40:32 +08001731 gst_event_parse_caps (event, &caps);
bo.xiao34e36202024-07-17 16:04:01 +08001732
bo.xiao857b8682024-09-12 16:40:32 +08001733 structure= gst_caps_get_structure(caps, 0);
1734 if ( gst_structure_has_field(structure, "parsed") )
1735 {
1736 gboolean parsed = TRUE;
1737 if ( gst_structure_get_boolean( structure, "parsed", &parsed ) )
zengliang.li51f54b62023-10-10 12:14:49 +00001738 {
bo.xiao857b8682024-09-12 16:40:32 +08001739 self->v4l2output->stream_mode = !parsed;
1740 GST_DEBUG("frame parsed:%d, set stream_mode to %d", parsed, self->v4l2output->stream_mode);
1741 }
1742 }
1743
1744 if ( gst_structure_has_field(structure, "secure") )
1745 {
1746 gboolean is_secure = FALSE;
1747 if ( gst_structure_get_boolean( structure, "secure", &is_secure ) )
1748 {
1749 self->v4l2output->secure_es = is_secure;
1750 GST_DEBUG("is secure es:%d", self->v4l2output->secure_es);
1751 }
1752 }
1753 else
1754 {
1755 GstCapsFeatures *const features = gst_caps_get_features(caps, 0);
1756 if (features && gst_caps_features_contains(features, GST_CAPS_FEATURE_MEMORY_DMABUF))
1757 {
1758 self->v4l2output->secure_es = TRUE;
1759 GST_DEBUG("If there is no secure field in caps, consider dma es is secure");
1760 }
1761 }
1762
1763 if ( gst_structure_get_fraction( structure, "framerate", &num, &denom ) )
1764 {
1765 if ( denom == 0 ) denom= 1;
1766
1767 if (self->v4l2capture->fps)
1768 {
1769 g_value_unset(self->v4l2capture->fps);
1770 g_free(self->v4l2capture->fps);
zengliang.li51f54b62023-10-10 12:14:49 +00001771 }
sheng.liu641aa422023-12-26 07:05:59 +00001772
bo.xiao857b8682024-09-12 16:40:32 +08001773 self->v4l2capture->fps = g_new0(GValue, 1);
1774 g_value_init(self->v4l2capture->fps, GST_TYPE_FRACTION);
1775 gst_value_set_fraction(self->v4l2capture->fps, num, denom);
1776
1777 GST_DEBUG_OBJECT(self, "get framerate ratio %d:%d", num, denom);
1778 }
1779
1780 if (( gst_structure_get_fraction( structure, "pixel-aspect-ratio", &num, &denom ) ) &&
1781 ( !self->v4l2capture->have_set_par ) )
1782 {
1783 if ( (num <= 0) || (denom <= 0) )
xuesong.jiang26749f32024-07-24 09:40:47 +08001784 {
bo.xiao857b8682024-09-12 16:40:32 +08001785 num= denom= 1;
xuesong.jiang578add22024-07-25 15:11:30 +08001786 }
xuesong.jiang26749f32024-07-24 09:40:47 +08001787
bo.xiao857b8682024-09-12 16:40:32 +08001788 if ( self->v4l2capture->par )
sheng.liudb26f7d2024-01-22 11:24:23 +00001789 {
bo.xiao857b8682024-09-12 16:40:32 +08001790 g_value_unset(self->v4l2capture->par);
1791 g_free(self->v4l2capture->par);
sheng.liudb26f7d2024-01-22 11:24:23 +00001792 }
1793
bo.xiao857b8682024-09-12 16:40:32 +08001794 self->v4l2capture->par = g_new0(GValue, 1);
1795 g_value_init(self->v4l2capture->par, GST_TYPE_FRACTION);
1796 gst_value_set_fraction(self->v4l2capture->par, num, denom);
1797 GST_DEBUG_OBJECT(self, "get pixel aspect ratio %d:%d", num, denom);
1798 }
1799 break;
zengliang.li51f54b62023-10-10 12:14:49 +00001800 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001801 case GST_EVENT_FLUSH_START:
bo.xiao857b8682024-09-12 16:40:32 +08001802 GST_DEBUG_OBJECT (self, "flush start");
xuesong.jiangc5dac0f2023-02-01 14:42:24 +08001803
bo.xiao857b8682024-09-12 16:40:32 +08001804 g_mutex_lock (&self->res_chg_lock);
1805 while (self->is_res_chg)
1806 {
1807 GST_LOG_OBJECT(decoder, "wait resolution change finish");
1808 g_cond_wait(&self->res_chg_cond, &self->res_chg_lock);
1809 }
1810 g_mutex_unlock (&self->res_chg_lock);
xuesong.jiangc5dac0f2023-02-01 14:42:24 +08001811
bo.xiao857b8682024-09-12 16:40:32 +08001812 self->last_out_pts = GST_CLOCK_TIME_NONE;
1813 gst_aml_v4l2_object_flush_start (self->v4l2output);
1814 gst_aml_v4l2_object_flush_start (self->v4l2capture);
1815 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001816 default:
bo.xiao857b8682024-09-12 16:40:32 +08001817 break;
1818 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001819
bo.xiao857b8682024-09-12 16:40:32 +08001820 ret = GST_AML_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001821
bo.xiao857b8682024-09-12 16:40:32 +08001822 switch (type)
1823 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001824 case GST_EVENT_FLUSH_START:
bo.xiao857b8682024-09-12 16:40:32 +08001825 /* The processing thread should stop now, wait for it */
1826 gst_pad_stop_task (decoder->srcpad);
1827 self->codec_data_inject = FALSE;
1828 GST_DEBUG_OBJECT (self, "flush start done");
1829 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001830 default:
bo.xiao857b8682024-09-12 16:40:32 +08001831 break;
1832 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001833
bo.xiao857b8682024-09-12 16:40:32 +08001834 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001835}
1836
1837static GstStateChangeReturn
bo.xiao857b8682024-09-12 16:40:32 +08001838gst_aml_v4l2_video_dec_change_state (GstElement * element,
1839 GstStateChange transition)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001840{
bo.xiao857b8682024-09-12 16:40:32 +08001841 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(element);
1842 GstAmlVideoDecoder *decoder = GST_AML_VIDEO_DECODER(element);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001843
bo.xiao857b8682024-09-12 16:40:32 +08001844 GST_DEBUG_OBJECT(element, "change state from %s to %s",
1845 gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
1846 gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
bo.xiao8e3054d2024-07-31 17:13:57 +08001847
bo.xiao857b8682024-09-12 16:40:32 +08001848 if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
1849 {
1850 g_atomic_int_set (&self->active, FALSE);
1851 gst_aml_v4l2_object_flush_start (self->v4l2output);
1852 gst_aml_v4l2_object_flush_start (self->v4l2capture);
1853 gst_pad_stop_task (decoder->srcpad);
1854 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001855
bo.xiao857b8682024-09-12 16:40:32 +08001856 return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001857}
1858
1859static void
bo.xiao857b8682024-09-12 16:40:32 +08001860gst_aml_v4l2_video_dec_dispose (GObject * object)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001861{
bo.xiao857b8682024-09-12 16:40:32 +08001862 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001863
bo.xiao857b8682024-09-12 16:40:32 +08001864 gst_caps_replace (&self->probed_sinkcaps, NULL);
1865 gst_caps_replace (&self->probed_srccaps, NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001866
bo.xiao857b8682024-09-12 16:40:32 +08001867 G_OBJECT_CLASS (parent_class)->dispose (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001868}
1869
1870static void
bo.xiao857b8682024-09-12 16:40:32 +08001871gst_aml_v4l2_video_dec_finalize (GObject * object)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001872{
bo.xiao857b8682024-09-12 16:40:32 +08001873 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001874
bo.xiao857b8682024-09-12 16:40:32 +08001875 gst_aml_v4l2_object_destroy (self->v4l2capture);
1876 gst_aml_v4l2_object_destroy (self->v4l2output);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001877
bo.xiao857b8682024-09-12 16:40:32 +08001878 g_mutex_clear(&self->res_chg_lock);
1879 g_cond_clear(&self->res_chg_cond);
xuesong.jiangc5dac0f2023-02-01 14:42:24 +08001880
xuesong.jiang61ea8012022-05-12 15:38:17 +08001881#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +08001882 if (self->lge_ctxt)
1883 {
1884 if (self->lge_ctxt->app_type)
1885 g_free(self->lge_ctxt->app_type);
1886 if (self->lge_ctxt->res_info.coretype)
1887 g_free(self->lge_ctxt->res_info.coretype);
1888 free(self->lge_ctxt);
1889 }
xuesong.jiang61ea8012022-05-12 15:38:17 +08001890
1891#endif
1892
bo.xiao857b8682024-09-12 16:40:32 +08001893 G_OBJECT_CLASS (parent_class)->finalize (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001894}
1895
1896static void
bo.xiao857b8682024-09-12 16:40:32 +08001897gst_aml_v4l2_video_dec_init (GstAmlV4l2VideoDec * self)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001898{
bo.xiao857b8682024-09-12 16:40:32 +08001899 /* V4L2 object are created in subinstance_init */
1900 self->last_out_pts = GST_CLOCK_TIME_NONE;
1901 self->frame_duration = GST_CLOCK_TIME_NONE;
1902 self->is_secure_path = FALSE;
1903 self->is_res_chg = FALSE;
1904 self->codec_data_inject = FALSE;
1905 g_mutex_init(&self->res_chg_lock);
1906 g_cond_init(&self->res_chg_cond);
xuesong.jiang61ea8012022-05-12 15:38:17 +08001907#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +08001908 self->lge_ctxt = malloc(sizeof(GstAmlV4l2VideoDecLgeCtxt));
1909 memset(self->lge_ctxt, 0, sizeof(GstAmlV4l2VideoDecLgeCtxt));
xuesong.jiang61ea8012022-05-12 15:38:17 +08001910#endif
xuesong.jiangae1548e2022-05-06 16:38:46 +08001911}
1912
1913static void
bo.xiao857b8682024-09-12 16:40:32 +08001914gst_aml_v4l2_video_dec_subinstance_init (GTypeInstance * instance, gpointer g_class)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001915{
bo.xiao857b8682024-09-12 16:40:32 +08001916 GstAmlV4l2VideoDecClass *klass = GST_AML_V4L2_VIDEO_DEC_CLASS (g_class);
1917 GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC (instance);
1918 GstAmlVideoDecoder *decoder = GST_AML_VIDEO_DECODER (instance);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001919
bo.xiao857b8682024-09-12 16:40:32 +08001920 gst_aml_video_decoder_set_packetized (decoder, TRUE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001921
bo.xiao857b8682024-09-12 16:40:32 +08001922 self->v4l2output = gst_aml_v4l2_object_new (GST_ELEMENT (self),
1923 GST_OBJECT (GST_AML_VIDEO_DECODER_SINK_PAD (self)),
1924 V4L2_BUF_TYPE_VIDEO_OUTPUT, klass->default_device,
1925 gst_aml_v4l2_get_output, gst_aml_v4l2_set_output, NULL);
1926 self->v4l2output->no_initial_format = TRUE;
1927 self->v4l2output->keep_aspect = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001928
bo.xiao857b8682024-09-12 16:40:32 +08001929 self->v4l2capture = gst_aml_v4l2_object_new (GST_ELEMENT (self),
1930 GST_OBJECT (GST_AML_VIDEO_DECODER_SRC_PAD (self)),
1931 V4L2_BUF_TYPE_VIDEO_CAPTURE, klass->default_device,
1932 gst_aml_v4l2_get_input, gst_aml_v4l2_set_input, NULL);
1933 self->v4l2capture->need_wait_event = TRUE;
1934 self->v4l2capture->need_drop_event = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001935}
1936
1937static void
bo.xiao857b8682024-09-12 16:40:32 +08001938gst_aml_v4l2_video_dec_class_init (GstAmlV4l2VideoDecClass * klass)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001939{
bo.xiao857b8682024-09-12 16:40:32 +08001940 GstElementClass *element_class;
1941 GObjectClass *gobject_class;
1942 GstAmlVideoDecoderClass *video_decoder_class;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001943
bo.xiao857b8682024-09-12 16:40:32 +08001944 parent_class = g_type_class_peek_parent (klass);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001945
bo.xiao857b8682024-09-12 16:40:32 +08001946 element_class = (GstElementClass *) klass;
1947 gobject_class = (GObjectClass *) klass;
1948 video_decoder_class = (GstAmlVideoDecoderClass *) klass;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001949
bo.xiao857b8682024-09-12 16:40:32 +08001950 GST_DEBUG_CATEGORY_INIT (gst_aml_v4l2_video_dec_debug, "amlv4l2videodec", 0,
1951 "AML V4L2 Video Decoder");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001952
bo.xiao857b8682024-09-12 16:40:32 +08001953 gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_dispose);
1954 gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_finalize);
1955 gobject_class->set_property =
1956 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_set_property);
1957 gobject_class->get_property =
1958 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_get_property);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001959
bo.xiao857b8682024-09-12 16:40:32 +08001960 video_decoder_class->open = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_open);
1961 video_decoder_class->close = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_close);
1962 video_decoder_class->start = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_start);
1963 video_decoder_class->stop = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_stop);
1964 video_decoder_class->finish = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_finish);
1965 video_decoder_class->flush = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_flush);
1966 video_decoder_class->drain = GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_drain);
1967 video_decoder_class->set_format =
1968 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_set_format);
1969 video_decoder_class->negotiate =
1970 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_negotiate);
1971 video_decoder_class->decide_allocation =
1972 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_decide_allocation);
1973 /* FIXME propose_allocation or not ? */
1974 video_decoder_class->handle_frame =
1975 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_handle_frame);
1976 video_decoder_class->getcaps =
1977 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_sink_getcaps);
1978 video_decoder_class->src_query =
1979 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_src_query);
1980 video_decoder_class->sink_event =
1981 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_sink_event);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001982
bo.xiao857b8682024-09-12 16:40:32 +08001983 element_class->change_state =
1984 GST_DEBUG_FUNCPTR(gst_aml_v4l2_video_dec_change_state);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001985
xuesong.jiang406ee302023-06-28 03:45:22 +00001986 g_signals[SIGNAL_DECODED_PTS] = g_signal_new ("decoded-pts",
bo.xiao857b8682024-09-12 16:40:32 +08001987 G_TYPE_FROM_CLASS(GST_ELEMENT_CLASS(klass)),
1988 G_SIGNAL_RUN_LAST,
1989 0, /* class offset */
1990 NULL, /* accumulator */
1991 NULL, /* accu data */
1992 g_cclosure_marshal_generic,
1993 G_TYPE_NONE,
1994 1,
1995 G_TYPE_UINT64);
1996 g_signals[SIGNAL_DECODED_ERROR_PTS] = g_signal_new ("decoded-error-pts",
1997 G_TYPE_FROM_CLASS(GST_ELEMENT_CLASS(klass)),
1998 G_SIGNAL_RUN_LAST,
1999 0, /* class offset */
2000 NULL, /* accumulator */
2001 NULL, /* accu data */
2002 g_cclosure_marshal_generic,
2003 G_TYPE_NONE,
2004 1,
2005 G_TYPE_UINT64);
xuesong.jiang406ee302023-06-28 03:45:22 +00002006
bo.xiao857b8682024-09-12 16:40:32 +08002007 gst_aml_v4l2_object_install_m2m_properties_helper (gobject_class);
xuesong.jiang61ea8012022-05-12 15:38:17 +08002008#if GST_IMPORT_LGE_PROP
bo.xiao857b8682024-09-12 16:40:32 +08002009 gst_aml_v4l2_video_dec_install_lge_properties_helper(gobject_class);
xuesong.jiang61ea8012022-05-12 15:38:17 +08002010#endif
xuesong.jiangae1548e2022-05-06 16:38:46 +08002011}
2012
2013static void
bo.xiao857b8682024-09-12 16:40:32 +08002014gst_aml_v4l2_video_dec_subclass_init (gpointer g_class, gpointer data)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002015{
bo.xiao857b8682024-09-12 16:40:32 +08002016 GstAmlV4l2VideoDecClass *klass = GST_AML_V4L2_VIDEO_DEC_CLASS (g_class);
2017 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
2018 GstAmlV4l2VideoDecCData *cdata = data;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002019
bo.xiao857b8682024-09-12 16:40:32 +08002020 klass->default_device = cdata->device;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002021
bo.xiao857b8682024-09-12 16:40:32 +08002022 /* Note: gst_pad_template_new() take the floating ref from the caps */
2023 gst_element_class_add_pad_template (element_class,
2024 gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
2025 cdata->sink_caps));
2026 gst_element_class_add_pad_template (element_class,
2027 gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
2028 cdata->src_caps));
xuesong.jiangae1548e2022-05-06 16:38:46 +08002029
bo.xiao857b8682024-09-12 16:40:32 +08002030 gst_element_class_set_metadata (element_class, cdata->longname,
2031 "Codec/Decoder/Video/Hardware", cdata->description,
2032 "Xuesong Jiang <Xuesong.Jiang@amlogic.com>");
xuesong.jiangae1548e2022-05-06 16:38:46 +08002033
bo.xiao857b8682024-09-12 16:40:32 +08002034 gst_caps_unref (cdata->sink_caps);
2035 gst_caps_unref (cdata->src_caps);
2036 g_free (cdata);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002037}
2038
2039/* Probing functions */
2040gboolean
bo.xiao857b8682024-09-12 16:40:32 +08002041gst_aml_v4l2_is_video_dec (GstCaps * sink_caps, GstCaps * src_caps)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002042{
bo.xiao857b8682024-09-12 16:40:32 +08002043 gboolean ret = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002044
bo.xiao857b8682024-09-12 16:40:32 +08002045 if (gst_caps_is_subset (sink_caps, gst_aml_v4l2_object_get_codec_caps ())
2046 && gst_caps_is_subset (src_caps, gst_aml_v4l2_object_get_raw_caps ()))
2047 ret = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002048
bo.xiao857b8682024-09-12 16:40:32 +08002049 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002050}
2051
2052static gchar *
bo.xiao857b8682024-09-12 16:40:32 +08002053gst_aml_v4l2_video_dec_set_metadata (GstStructure * s, GstAmlV4l2VideoDecCData * cdata,
2054 const gchar * basename)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002055{
bo.xiao857b8682024-09-12 16:40:32 +08002056 gchar *codec_name = NULL;
2057 gchar *type_name = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002058
bo.xiao857b8682024-09-12 16:40:32 +08002059#define SET_META(codec) \
2060G_STMT_START { \
2061 cdata->longname = "AML V4L2 " codec " Decoder"; \
2062 cdata->description = "Decodes " codec " streams via V4L2 API"; \
2063 codec_name = g_ascii_strdown (codec, -1); \
2064} G_STMT_END
xuesong.jiangae1548e2022-05-06 16:38:46 +08002065
bo.xiao857b8682024-09-12 16:40:32 +08002066 if (gst_structure_has_name(s, "video/mjpeg"))
2067 {
2068 SET_META("MJPEG");
2069 }
2070 else if (gst_structure_has_name (s, "video/mpeg"))
2071 {
2072 //include mpeg1, mpeg2, mpeg4
2073 SET_META("MPEG4");
2074 }
2075 else if (gst_structure_has_name (s, "video/x-h263"))
2076 {
2077 SET_META ("H263");
2078 }
2079 else if (gst_structure_has_name (s, "video/x-fwht"))
2080 {
2081 SET_META ("FWHT");
2082 }
2083 else if (gst_structure_has_name (s, "video/x-h264"))
2084 {
2085 SET_META ("H264");
2086 }
2087 else if (gst_structure_has_name (s, "video/x-h265"))
2088 {
2089 SET_META ("H265");
2090 }
2091 else if (gst_structure_has_name (s, "video/x-wmv"))
2092 {
2093 SET_META ("VC1");
2094 }
2095 else if (gst_structure_has_name (s, "video/x-vp8"))
2096 {
2097 SET_META ("VP8");
2098 }
2099 else if (gst_structure_has_name (s, "video/x-vp9"))
2100 {
2101 SET_META ("VP9");
2102 }
2103 else if (gst_structure_has_name(s, "video/x-av1"))
2104 {
2105 SET_META("AV1");
2106 }
2107 else if (gst_structure_has_name(s, "video/x-avs"))
2108 {
2109 SET_META("AVS");
2110 }
2111 else if (gst_structure_has_name(s, "video/x-avs2"))
2112 {
2113 SET_META("AVS2");
2114 }
2115 else if (gst_structure_has_name(s, "video/x-avs3"))
2116 {
2117 SET_META("AVS3");
2118 }
2119 else if (gst_structure_has_name (s, "video/x-bayer"))
2120 {
2121 SET_META ("BAYER");
2122 }
2123 else if (gst_structure_has_name (s, "video/x-sonix"))
2124 {
2125 SET_META ("SONIX");
2126 }
2127 else if (gst_structure_has_name (s, "video/x-pwc1"))
2128 {
2129 SET_META ("PWC1");
2130 }
2131 else if (gst_structure_has_name (s, "video/x-pwc2"))
2132 {
2133 SET_META ("PWC2");
2134 }
2135 else
2136 {
2137 /* This code should be kept on sync with the exposed CODEC type of format
2138 * from gstamlv4l2object.c. This warning will only occur in case we forget
2139 * to also add a format here. */
2140 gchar *s_str = gst_structure_to_string (s);
2141 g_warning ("Missing fixed name mapping for caps '%s', this is a GStreamer "
2142 "bug, please report at https://bugs.gnome.org", s_str);
2143 g_free (s_str);
2144 }
2145
2146 if (codec_name)
2147 {
2148 type_name = g_strdup_printf ("amlv4l2%sdec", codec_name);
2149 if (g_type_from_name (type_name) != 0)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002150 {
bo.xiao857b8682024-09-12 16:40:32 +08002151 g_free (type_name);
2152 type_name = g_strdup_printf ("amlv4l2%s%sdec", basename, codec_name);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002153 }
2154
bo.xiao857b8682024-09-12 16:40:32 +08002155 g_free (codec_name);
2156 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002157
bo.xiao857b8682024-09-12 16:40:32 +08002158 return type_name;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002159#undef SET_META
2160}
2161
bo.xiao857b8682024-09-12 16:40:32 +08002162void
2163gst_aml_v4l2_video_dec_register(GstPlugin *plugin, const gchar *basename,
xuesong.jiangae1548e2022-05-06 16:38:46 +08002164 const gchar *device_path, GstCaps *sink_caps, GstCaps *src_caps)
2165{
bo.xiao857b8682024-09-12 16:40:32 +08002166 gint i;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002167
bo.xiao857b8682024-09-12 16:40:32 +08002168 for (i = 0; i < gst_caps_get_size (sink_caps); i++)
2169 {
2170 GstAmlV4l2VideoDecCData *cdata;
2171 GstStructure *s;
2172 GTypeQuery type_query;
2173 GTypeInfo type_info = { 0, };
2174 GType type, subtype;
2175 gchar *type_name;
2176
2177 s = gst_caps_get_structure (sink_caps, i);
2178
2179 cdata = g_new0 (GstAmlV4l2VideoDecCData, 1);
2180 cdata->device = g_strdup (device_path);
2181 cdata->sink_caps = gst_caps_new_empty ();
2182 gst_caps_append_structure (cdata->sink_caps, gst_structure_copy (s));
2183 gst_caps_append_structure (cdata->sink_caps, gst_structure_copy (s));
2184 gst_caps_set_features(cdata->sink_caps, 0, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
2185 cdata->src_caps = gst_caps_copy(src_caps);
2186 gst_caps_set_features_simple(cdata->src_caps, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
2187 gst_caps_append(cdata->src_caps, gst_caps_copy (src_caps));
2188 type_name = gst_aml_v4l2_video_dec_set_metadata (s, cdata, basename);
2189
2190 /* Skip over if we hit an unmapped type */
2191 if (!type_name)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002192 {
bo.xiao857b8682024-09-12 16:40:32 +08002193 g_free (cdata);
2194 continue;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002195 }
bo.xiao857b8682024-09-12 16:40:32 +08002196
2197 type = gst_aml_v4l2_video_dec_get_type ();
2198 g_type_query (type, &type_query);
2199 memset (&type_info, 0, sizeof (type_info));
2200 type_info.class_size = type_query.class_size;
2201 type_info.instance_size = type_query.instance_size;
2202 type_info.class_init = gst_aml_v4l2_video_dec_subclass_init;
2203 type_info.class_data = cdata;
2204 type_info.instance_init = gst_aml_v4l2_video_dec_subinstance_init;
2205
2206 subtype = g_type_register_static (type, type_name, &type_info, 0);
2207 if (!gst_element_register (plugin, type_name, GST_RANK_PRIMARY + 1,
2208 subtype))
2209 GST_WARNING ("Failed to register plugin '%s'", type_name);
2210
2211 g_free (type_name);
2212 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002213}
xuesong.jiang61ea8012022-05-12 15:38:17 +08002214
2215#if GST_IMPORT_LGE_PROP
2216static void gst_aml_v4l2_video_dec_install_lge_properties_helper(GObjectClass *gobject_class)
2217{
2218 g_object_class_install_property(gobject_class, LGE_RESOURCE_INFO,
2219 g_param_spec_object("resource-info", "resource-info",
2220 "After acquisition of H/W resources is completed, allocated resource information must be delivered to the decoder and the sink",
2221 GST_TYPE_STRUCTURE,
2222 G_PARAM_READABLE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
2223
2224 g_object_class_install_property(gobject_class, LGE_DECODE_SIZE,
2225 g_param_spec_uint64("decoded-size", "decoded-size",
2226 "The total amount of decoder element's decoded video es after constructing pipeline or flushing pipeline update unit is byte.",
2227 0, G_MAXUINT64,
2228 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2229
2230 g_object_class_install_property(gobject_class, LGE_UNDECODE_SIZE,
2231 g_param_spec_uint64("undecoded-size", "undecoded-size",
2232 "video decoder element's total undecoded data update unit is byte.",
2233 0, G_MAXUINT64,
2234 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2235
2236 g_object_class_install_property(gobject_class, LGE_APP_TYPE,
2237 g_param_spec_string("app-type", "app-type",
2238 "set application type.",
2239 "default_app",
2240 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2241
2242 g_object_class_install_property(gobject_class, LGE_CLIP_MODE,
2243 g_param_spec_boolean("clip-mode", "clip-mode",
2244 "When seeking, Content is moving faster for a while to skip frames.",
2245 FALSE,
2246 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2247}
2248#endif