1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "gst_vdec_base.h"
17 #include <vector>
18 #include <iostream>
19 #include <malloc.h>
20 #include "securec.h"
21 #include "buffer_type_meta.h"
22 #include "scope_guard.h"
23 #include "gst_codec_video_common.h"
24 #include "param_wrapper.h"
25 #include "media_dfx.h"
26 #include "media_log.h"
27
28 using namespace OHOS;
29 using namespace OHOS::Media;
30 GST_DEBUG_CATEGORY_STATIC(gst_vdec_base_debug_category);
31 #define GST_CAT_DEFAULT gst_vdec_base_debug_category
32 #define gst_vdec_base_parent_class parent_class
33 #define GST_VDEC_BASE_SUPPORTED_FORMATS "{ NV12, NV21 }"
34 #define DEFAULT_MAX_QUEUE_SIZE 30
35 #define DEFAULT_WIDTH 1920
36 #define DEFAULT_HEIGHT 1080
37 #define DEFAULT_SEEK_FRAME_RATE 1000
38 #define BLOCKING_ACQUIRE_BUFFER_THRESHOLD 5
39 #define DRAIN_TIME_OUT_MIN (G_TIME_SPAN_SECOND * 2)
40 #define DRAIN_TIME_OUT_MAX (G_TIME_SPAN_SECOND * 5)
41 #define DRAIN_TIME_OUT_BY_FRAMERATE(rate) (static_cast<gint64>(G_TIME_SPAN_SECOND * 30 / (rate)))
42
43 static void gst_vdec_base_class_install_property(GObjectClass *gobject_class);
44 static void gst_vdec_base_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
45 static gboolean gst_vdec_base_open(GstVideoDecoder *decoder);
46 static gboolean gst_vdec_base_close(GstVideoDecoder *decoder);
47 static gboolean gst_vdec_base_start(GstVideoDecoder *decoder);
48 static gboolean gst_vdec_base_stop(GstVideoDecoder *decoder);
49 static gboolean gst_vdec_base_set_format(GstVideoDecoder *decoder, GstVideoCodecState *state);
50 static gboolean gst_vdec_base_flush(GstVideoDecoder *decoder);
51 static GstFlowReturn gst_vdec_base_handle_frame(GstVideoDecoder *decoder, GstVideoCodecFrame *frame);
52 static GstFlowReturn gst_vdec_base_drain(GstVideoDecoder *decoder);
53 static void gst_vdec_base_finalize(GObject *object);
54 static GstFlowReturn gst_vdec_base_finish(GstVideoDecoder *decoder);
55 static void gst_vdec_base_loop(GstVdecBase *self);
56 static void gst_vdec_base_pause_loop(GstVdecBase *self);
57 static gboolean gst_vdec_base_event(GstVideoDecoder *decoder, GstEvent *event);
58 static gboolean gst_vdec_base_decide_allocation(GstVideoDecoder *decoder, GstQuery *query);
59 static gboolean gst_vdec_base_propose_allocation(GstVideoDecoder *decoder, GstQuery *query);
60 static gboolean gst_vdec_base_check_allocate_input(GstVdecBase *self);
61 static gboolean gst_codec_return_is_ok(const GstVdecBase *decoder, gint ret,
62 const char *error_name, gboolean need_report);
63 static GstStateChangeReturn gst_vdec_base_change_state(GstElement *element, GstStateChange transition);
64 static gboolean gst_vdec_base_update_out_port_def(GstVdecBase *self, guint *size);
65 static void gst_vdec_base_update_out_pool(GstVdecBase *self, GstBufferPool **pool, GstCaps *outcaps, gint size);
66 static void gst_vdec_base_set_flushing(GstVdecBase *self, const gboolean flushing);
67 static gboolean gst_vdec_base_allocate_in_buffers(GstVdecBase *self);
68 static gboolean gst_vdec_base_allocate_out_buffers(GstVdecBase *self);
69 static GstBufferPool *gst_vdec_base_new_in_shmem_pool(GstVdecBase *self, GstCaps *outcaps, gint size,
70 guint min_buffer_cnt, guint max_buffer_cnt);
71 static void gst_vdec_base_post_resolution_changed_message(GstVdecBase *self, gboolean need_post);
72
73 enum {
74 PROP_0,
75 PROP_VENDOR,
76 PROP_SURFACE_POOL,
77 PROP_SINK_CAPS,
78 PROP_PERFORMANCE_MODE,
79 PROP_PLAYER_SCENE,
80 PROP_SEEK,
81 PROP_PLAYER_MODE,
82 PROP_METADATA_MODE,
83 PROP_FREE_CODEC_BUFFERS,
84 PROP_RECOVER_CODEC_BUFFERS,
85 PROP_STOP_FORMAT_CHANGED,
86 };
87
88 enum {
89 SIGNAL_CAPS_FIX_ERROR,
90 SIGNAL_LAST
91 };
92
93 static guint signals[SIGNAL_LAST] = { 0, };
94
95 G_DEFINE_ABSTRACT_TYPE(GstVdecBase, gst_vdec_base, GST_TYPE_VIDEO_DECODER);
96
gst_vdec_base_class_init(GstVdecBaseClass * kclass)97 static void gst_vdec_base_class_init(GstVdecBaseClass *kclass)
98 {
99 GST_DEBUG_OBJECT(kclass, "Class init");
100 g_return_if_fail(kclass != nullptr);
101 GObjectClass *gobject_class = G_OBJECT_CLASS(kclass);
102 GstElementClass *element_class = GST_ELEMENT_CLASS(kclass);
103 GstVideoDecoderClass *video_decoder_class = GST_VIDEO_DECODER_CLASS(kclass);
104 GST_DEBUG_CATEGORY_INIT (gst_vdec_base_debug_category, "vdecbase", 0, "video decoder base class");
105 gobject_class->set_property = gst_vdec_base_set_property;
106 gobject_class->finalize = gst_vdec_base_finalize;
107 video_decoder_class->open = gst_vdec_base_open;
108 video_decoder_class->close = gst_vdec_base_close;
109 video_decoder_class->start = gst_vdec_base_start;
110 video_decoder_class->stop = gst_vdec_base_stop;
111 video_decoder_class->flush = gst_vdec_base_flush;
112 video_decoder_class->set_format = gst_vdec_base_set_format;
113 video_decoder_class->handle_frame = gst_vdec_base_handle_frame;
114 video_decoder_class->finish = gst_vdec_base_finish;
115 video_decoder_class->sink_event = gst_vdec_base_event;
116 video_decoder_class->drain = gst_vdec_base_drain;
117 video_decoder_class->decide_allocation = gst_vdec_base_decide_allocation;
118 video_decoder_class->propose_allocation = gst_vdec_base_propose_allocation;
119 element_class->change_state = gst_vdec_base_change_state;
120
121 gst_vdec_base_class_install_property(gobject_class);
122
123 signals[SIGNAL_CAPS_FIX_ERROR] =
124 g_signal_new ("caps-fix-error", G_TYPE_FROM_CLASS (kclass),
125 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
126
127 const gchar *src_caps_string = GST_VIDEO_CAPS_MAKE(GST_VDEC_BASE_SUPPORTED_FORMATS);
128 GST_DEBUG_OBJECT(kclass, "Pad template caps %s", src_caps_string);
129
130 GstCaps *src_caps = gst_caps_from_string(src_caps_string);
131 if (src_caps != nullptr) {
132 GstPadTemplate *src_templ = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps);
133 gst_element_class_add_pad_template(element_class, src_templ);
134 gst_caps_unref(src_caps);
135 }
136 }
137
gst_vdec_base_class_install_property(GObjectClass * gobject_class)138 static void gst_vdec_base_class_install_property(GObjectClass *gobject_class)
139 {
140 g_object_class_install_property(gobject_class, PROP_VENDOR,
141 g_param_spec_pointer("vendor", "Vendor property", "Vendor property",
142 (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
143
144 g_object_class_install_property(gobject_class, PROP_SURFACE_POOL,
145 g_param_spec_pointer("surface-pool", "Surface pool", "Surface pool",
146 (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
147
148 g_object_class_install_property(gobject_class, PROP_SINK_CAPS,
149 g_param_spec_boxed("sink-caps", "Sink Caps",
150 "The caps use with surface pool", GST_TYPE_CAPS,
151 (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
152
153 g_object_class_install_property(gobject_class, PROP_PERFORMANCE_MODE,
154 g_param_spec_boolean("performance-mode", "performance mode", "performance mode",
155 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
156
157 g_object_class_install_property(gobject_class, PROP_PLAYER_SCENE,
158 g_param_spec_boolean("player-scene", "player scene", "player scene",
159 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
160
161 g_object_class_install_property(gobject_class, PROP_PLAYER_MODE,
162 g_param_spec_boolean("player-mode", "player mode", "player mode",
163 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
164
165 g_object_class_install_property(gobject_class, PROP_SEEK,
166 g_param_spec_boolean("seeking", "Seeking", "Whether the decoder is in seek",
167 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
168
169 g_object_class_install_property(gobject_class, PROP_METADATA_MODE,
170 g_param_spec_boolean("metadata-mode", "Metadata-mode", "Metadata Mode",
171 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
172
173 g_object_class_install_property(gobject_class, PROP_FREE_CODEC_BUFFERS,
174 g_param_spec_boolean("free-codec-buffers", "Free-codec-buffers", "Free Codec Buffers",
175 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
176
177 g_object_class_install_property(gobject_class, PROP_RECOVER_CODEC_BUFFERS,
178 g_param_spec_boolean("recover-codec-buffers", "Recover-codec-buffers", "Recover Codec Buffers",
179 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
180
181 g_object_class_install_property(gobject_class, PROP_STOP_FORMAT_CHANGED,
182 g_param_spec_boolean("stop-format-change", "stop-format-change", "stop-format-change",
183 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
184 }
185
gst_vdec_base_free_codec_buffers(GstVdecBase * self)186 static gboolean gst_vdec_base_free_codec_buffers(GstVdecBase *self)
187 {
188 g_return_val_if_fail(self != nullptr && self->decoder != nullptr, FALSE);
189 gint ret;
190 GST_DEBUG_OBJECT(self, "enter free buffers, is_free_codec_buffers:%d is_eos_state:%d",
191 self->is_free_codec_buffers, self->is_eos_state);
192 if (!self->is_free_codec_buffers) {
193 if (!self->is_eos_state) {
194 GST_VIDEO_DECODER_STREAM_LOCK(self);
195 (void)self->decoder->Flush(GST_CODEC_ALL);
196 gst_vdec_base_set_flushing(self, TRUE);
197 GST_VIDEO_DECODER_STREAM_UNLOCK(self);
198 g_return_val_if_fail(gst_pad_push_event(GST_VIDEO_DECODER_SRC_PAD(self),
199 gst_event_new_flush_start()), FALSE);
200 g_return_val_if_fail(gst_pad_push_event(GST_VIDEO_DECODER_SRC_PAD(self),
201 gst_event_new_flush_stop(FALSE)), FALSE);
202 self->is_eos_state = FALSE;
203 }
204 if (self->decoder_start) {
205 ret = self->decoder->Stop();
206 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "DecoderStop", TRUE), FALSE);
207 self->decoder_start = FALSE;
208 }
209 GstPad *pad = GST_VIDEO_DECODER_SRC_PAD(self);
210 if (gst_pad_get_task_state(pad) != GST_TASK_STOPPED) {
211 g_return_val_if_fail(gst_pad_stop_task(pad), FALSE);
212 }
213 if (self->outpool) {
214 g_return_val_if_fail(gst_buffer_pool_set_active(self->outpool, FALSE), FALSE);
215 }
216 if (self->input.allocator) {
217 gst_object_unref(self->input.allocator);
218 self->input.allocator = nullptr;
219 }
220 if (self->inpool) {
221 g_return_val_if_fail(gst_buffer_pool_set_active(self->inpool, FALSE), FALSE);
222 gst_object_unref(self->inpool);
223 self->inpool = nullptr;
224 self->input.av_shmem_pool = nullptr;
225 }
226 ret = self->decoder->FreeInputBuffers();
227 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "FreeInput", TRUE), FALSE);
228 ret = self->decoder->FreeOutputBuffers();
229 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "FreeOutput", TRUE), FALSE);
230 self->is_free_codec_buffers = TRUE;
231 }
232 return TRUE;
233 }
234
gst_vdec_base_recover_codec_buffers(GstVdecBase * self)235 static gboolean gst_vdec_base_recover_codec_buffers(GstVdecBase *self)
236 {
237 g_return_val_if_fail(self != nullptr, FALSE);
238 if (self->is_free_codec_buffers) {
239 mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
240 mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
241 self->input.allocator = gst_shmem_allocator_new();
242 self->inpool = gst_vdec_base_new_in_shmem_pool(self, self->input_state->caps, self->input.buffer_size,
243 self->input.buffer_cnt, self->input.buffer_cnt);
244 g_return_val_if_fail(self->inpool != nullptr, FALSE);
245 g_return_val_if_fail(gst_buffer_pool_set_active(self->inpool, TRUE), FALSE);
246
247 if (self->outpool) {
248 self->decoder->SetOutputPool(self->outpool);
249 g_return_val_if_fail(gst_buffer_pool_set_active(self->outpool, TRUE), FALSE);
250 }
251 g_return_val_if_fail(gst_vdec_base_allocate_in_buffers(self), FALSE);
252 g_return_val_if_fail(gst_vdec_base_allocate_out_buffers(self), FALSE);
253 self->is_free_codec_buffers = FALSE;
254 }
255 return TRUE;
256 }
257
gst_vdec_reset_sink_caps(GstVdecBase * self)258 static inline void gst_vdec_reset_sink_caps(GstVdecBase *self)
259 {
260 if (self->sink_caps != nullptr) {
261 gst_caps_unref(self->sink_caps);
262 self->sink_caps = nullptr;
263 }
264 }
265
gst_vdec_reset_inpool(GstVdecBase * self)266 static inline void gst_vdec_reset_inpool(GstVdecBase *self)
267 {
268 if (self->inpool) {
269 gst_object_unref(self->inpool);
270 self->inpool = nullptr;
271 }
272 }
273
gst_vdec_reset_outpool(GstVdecBase * self)274 static inline void gst_vdec_reset_outpool(GstVdecBase *self)
275 {
276 if (self->outpool) {
277 gst_buffer_pool_set_active(self->outpool, FALSE);
278 gst_object_unref(self->outpool);
279 self->outpool = nullptr;
280 }
281 }
282
gst_vdec_base_prob_seek(GstVdecBase * self,const GValue * value)283 static void gst_vdec_base_prob_seek(GstVdecBase *self, const GValue *value)
284 {
285 GST_OBJECT_LOCK(self);
286 if (self->decoder != nullptr) {
287 self->seek_frame_rate = g_value_get_boolean(value) ? DEFAULT_SEEK_FRAME_RATE : self->frame_rate;
288 self->decoder->SetParameter(GST_DYNAMIC_FRAME_RATE, GST_ELEMENT(self));
289 }
290 GST_OBJECT_UNLOCK(self);
291 }
292
gst_vdec_base_prob_surface_pool(GstVdecBase * self,const GValue * value)293 static void gst_vdec_base_prob_surface_pool(GstVdecBase *self, const GValue *value)
294 {
295 gst_vdec_reset_outpool(self);
296 self->outpool = static_cast<GstBufferPool *>(g_value_get_pointer(value));
297 gst_object_ref(self->outpool);
298 }
299
gst_vdec_base_prob_sink_caps(GstVdecBase * self,const GValue * value)300 static void gst_vdec_base_prob_sink_caps(GstVdecBase *self, const GValue *value)
301 {
302 const GstCaps *caps = gst_value_get_caps(value);
303 gst_vdec_reset_sink_caps(self);
304 self->sink_caps = gst_caps_copy(caps);
305 }
306
gst_vdec_base_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)307 static void gst_vdec_base_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
308 {
309 (void)pspec;
310 g_return_if_fail(object != nullptr && value != nullptr);
311 GstVdecBase *self = GST_VDEC_BASE(object);
312 GST_INFO_OBJECT(object, "Prop id %u", prop_id);
313
314 switch (prop_id) {
315 case PROP_SURFACE_POOL:
316 gst_vdec_base_prob_surface_pool(self, value);
317 break;
318 case PROP_SINK_CAPS:
319 gst_vdec_base_prob_sink_caps(self, value);
320 break;
321 case PROP_PERFORMANCE_MODE:
322 self->performance_mode = g_value_get_boolean(value);
323 break;
324 case PROP_PLAYER_SCENE:
325 self->player_scene = g_value_get_boolean(value);
326 break;
327 case PROP_SEEK:
328 gst_vdec_base_prob_seek(self, value);
329 break;
330 case PROP_PLAYER_MODE:
331 self->player_mode = g_value_get_boolean(value);
332 break;
333 case PROP_METADATA_MODE:
334 self->metadata_mode = g_value_get_boolean(value);
335 break;
336 case PROP_FREE_CODEC_BUFFERS:
337 (void)gst_vdec_base_free_codec_buffers(self);
338 break;
339 case PROP_RECOVER_CODEC_BUFFERS:
340 (void)gst_vdec_base_recover_codec_buffers(self);
341 break;
342 case PROP_STOP_FORMAT_CHANGED:
343 g_mutex_lock(&self->format_changed_lock);
344 self->unsupport_format_changed = g_value_get_boolean(value);
345 g_mutex_unlock(&self->format_changed_lock);
346 break;
347 default:
348 break;
349 }
350 }
351
gst_vdec_base_check_input_need_copy(GstVdecBase * self)352 static void gst_vdec_base_check_input_need_copy(GstVdecBase *self)
353 {
354 GstVdecBaseClass *base_class = GST_VDEC_BASE_GET_CLASS(self);
355 g_return_if_fail(base_class != nullptr);
356 if (base_class->input_need_copy != nullptr) {
357 self->input_need_ashmem = base_class->input_need_copy();
358 }
359 }
360
gst_vdec_base_check_support_swap_width_height(GstVdecBase * self)361 static void gst_vdec_base_check_support_swap_width_height(GstVdecBase *self)
362 {
363 GstVdecBaseClass *base_class = GST_VDEC_BASE_GET_CLASS(self);
364 g_return_if_fail(base_class != nullptr);
365 GstElementClass *element_class = GST_ELEMENT_CLASS(base_class);
366 if (base_class->support_swap_width_height != nullptr) {
367 self->is_support_swap_width_height = base_class->support_swap_width_height(element_class);
368 }
369 }
370
gst_vdec_base_property_init(GstVdecBase * self)371 static void gst_vdec_base_property_init(GstVdecBase *self)
372 {
373 g_mutex_init(&self->lock);
374
375 g_mutex_init(&self->drain_lock);
376 g_cond_init(&self->drain_cond);
377 self->draining = FALSE;
378 self->flushing = FALSE;
379 self->prepared = FALSE;
380 self->idrframe = FALSE;
381 self->width = DEFAULT_WIDTH;
382 self->height = DEFAULT_HEIGHT;
383 self->frame_rate = 0;
384 self->seek_frame_rate = 0;
385 self->memtype = GST_MEMTYPE_INVALID;
386 (void)memset_s(&self->input, sizeof(GstVdecBasePort), 0, sizeof(GstVdecBasePort));
387 (void)memset_s(&self->output, sizeof(GstVdecBasePort), 0, sizeof(GstVdecBasePort));
388 self->coding_outbuf_cnt = 0;
389 self->input_state = nullptr;
390 self->output_state = nullptr;
391 self->last_pts = GST_CLOCK_TIME_NONE;
392 self->flushing_stoping = FALSE;
393 self->decoder_start = FALSE;
394 self->stride = 0;
395 self->stride_height = 0;
396 self->real_stride = 0;
397 self->real_stride_height = 0;
398 (void)memset_s(&self->rect, sizeof(DisplayRect), 0, sizeof(DisplayRect));
399 self->inpool = nullptr;
400 self->outpool = nullptr;
401 self->out_buffer_max_cnt = DEFAULT_MAX_QUEUE_SIZE;
402 self->pre_init_pool = FALSE;
403 self->performance_mode = FALSE;
404 self->player_scene = FALSE;
405 self->resolution_changed = FALSE;
406 self->input_need_ashmem = FALSE;
407 self->has_set_format = FALSE;
408 self->player_mode = FALSE;
409 self->metadata_mode = FALSE;
410 self->is_eos_state = FALSE;
411 self->is_support_swap_width_height = FALSE;
412 g_mutex_init(&self->format_changed_lock);
413 self->unsupport_format_changed = FALSE;
414 }
415
gst_vdec_base_init(GstVdecBase * self)416 static void gst_vdec_base_init(GstVdecBase *self)
417 {
418 GST_DEBUG_OBJECT(self, "Init, id = %d", static_cast<int32_t>(FAKE_POINTER(self)));
419 g_return_if_fail(self != nullptr && GST_VIDEO_DECODER_SINK_PAD(self) != nullptr);
420 // The upstreamer must after parser.
421 gst_video_decoder_set_packetized(GST_VIDEO_DECODER(self), TRUE);
422 // Use accept caps from default.
423 gst_video_decoder_set_use_default_pad_acceptcaps(GST_VIDEO_DECODER_CAST (self), TRUE);
424 GST_PAD_SET_ACCEPT_TEMPLATE(GST_VIDEO_DECODER_SINK_PAD(self));
425
426 gst_vdec_base_property_init(self);
427 self->input.allocator = gst_shmem_allocator_new();
428 self->output.allocator = gst_shmem_allocator_new();
429 gst_allocation_params_init(&self->input.allocParams);
430 gst_allocation_params_init(&self->output.allocParams);
431 self->input.frame_cnt = 0;
432 self->input.first_frame_time = 0;
433 self->input.last_frame_time = 0;
434 self->input.enable_dump = FALSE;
435 self->input.dump_file = nullptr;
436 self->output.frame_cnt = 0;
437 self->output.first_frame_time = 0;
438 self->output.last_frame_time = 0;
439 self->output.enable_dump = FALSE;
440 self->output.dump_file = nullptr;
441 self->input.first_frame = TRUE;
442 self->output.first_frame = TRUE;
443 self->codec_data_update = FALSE;
444 self->codec_data = nullptr;
445 }
446
gst_vdec_base_finalize(GObject * object)447 static void gst_vdec_base_finalize(GObject *object)
448 {
449 GST_DEBUG_OBJECT(object, "Finalize");
450 g_return_if_fail(object != nullptr);
451 GstVdecBase *self = GST_VDEC_BASE(object);
452 g_mutex_clear(&self->drain_lock);
453 g_cond_clear(&self->drain_cond);
454 g_mutex_clear(&self->lock);
455 if (self->input.allocator) {
456 gst_object_unref(self->input.allocator);
457 self->input.allocator = nullptr;
458 }
459 if (self->output.allocator) {
460 gst_object_unref(self->output.allocator);
461 self->output.allocator = nullptr;
462 }
463 gst_vdec_reset_inpool(self);
464 gst_vdec_reset_outpool(self);
465 gst_vdec_reset_sink_caps(self);
466
467 g_mutex_clear(&self->format_changed_lock);
468 std::list<GstClockTime> tempList;
469 tempList.swap(self->pts_list);
470 std::vector<GstVideoFormat> tempVec;
471 tempVec.swap(self->formats);
472
473 self->input.av_shmem_pool = nullptr;
474 self->output.av_shmem_pool = nullptr;
475 self->decoder = nullptr;
476 G_OBJECT_CLASS(parent_class)->finalize(object);
477 }
478
gst_vdec_base_open(GstVideoDecoder * decoder)479 static gboolean gst_vdec_base_open(GstVideoDecoder *decoder)
480 {
481 GST_DEBUG_OBJECT(decoder, "Open");
482 g_return_val_if_fail(decoder != nullptr, FALSE);
483 GstVdecBase *self = GST_VDEC_BASE(decoder);
484 GstVdecBaseClass *base_class = GST_VDEC_BASE_GET_CLASS(self);
485 g_return_val_if_fail(base_class != nullptr && base_class->create_codec != nullptr, FALSE);
486 self->decoder = base_class->create_codec(reinterpret_cast<GstElementClass*>(base_class));
487 g_return_val_if_fail(self->decoder != nullptr, FALSE);
488 gst_vdec_base_check_input_need_copy(self);
489 gst_vdec_base_check_support_swap_width_height(self);
490 return TRUE;
491 }
492
gst_vdec_base_is_flushing(GstVdecBase * self)493 static gboolean gst_vdec_base_is_flushing(GstVdecBase *self)
494 {
495 g_return_val_if_fail(self != nullptr, FALSE);
496 GST_OBJECT_LOCK(self);
497 gboolean flushing = self->flushing;
498 GST_OBJECT_UNLOCK(self);
499 GST_DEBUG_OBJECT(self, "Flushing %d", flushing);
500 return flushing;
501 }
502
gst_vdec_base_set_flushing(GstVdecBase * self,const gboolean flushing)503 static void gst_vdec_base_set_flushing(GstVdecBase *self, const gboolean flushing)
504 {
505 GST_DEBUG_OBJECT(self, "Set flushing %d", flushing);
506 g_return_if_fail(self != nullptr);
507 GST_OBJECT_LOCK(self);
508 self->flushing = flushing;
509 GST_OBJECT_UNLOCK(self);
510 }
511
gst_vdec_base_change_state(GstElement * element,GstStateChange transition)512 static GstStateChangeReturn gst_vdec_base_change_state(GstElement *element, GstStateChange transition)
513 {
514 g_return_val_if_fail(element != nullptr, GST_STATE_CHANGE_FAILURE);
515 GstVdecBase *self = GST_VDEC_BASE(element);
516
517 GST_DEBUG_OBJECT(element, "change state %d", transition);
518 switch (transition) {
519 case GST_STATE_CHANGE_PAUSED_TO_READY:
520 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: stop start");
521 gst_buffer_pool_set_active(self->outpool, FALSE);
522 GST_VIDEO_DECODER_STREAM_LOCK(self);
523 if (self->decoder != nullptr) {
524 (void)self->decoder->Flush(GST_CODEC_ALL);
525 }
526 gst_vdec_base_set_flushing(self, TRUE);
527
528 GST_VIDEO_DECODER_STREAM_UNLOCK(self);
529 break;
530 case GST_STATE_CHANGE_READY_TO_NULL:
531 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: close start");
532 break;
533 default:
534 break;
535 }
536
537 GstStateChangeReturn ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
538
539 switch (transition) {
540 case GST_STATE_CHANGE_PAUSED_TO_READY:
541 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: stop end");
542 break;
543 case GST_STATE_CHANGE_READY_TO_NULL:
544 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: close end");
545 break;
546 default:
547 break;
548 }
549 return ret;
550 }
551
gst_vdec_base_close(GstVideoDecoder * decoder)552 static gboolean gst_vdec_base_close(GstVideoDecoder *decoder)
553 {
554 GST_DEBUG_OBJECT(decoder, "Close");
555 g_return_val_if_fail(decoder != nullptr, FALSE);
556 GstVdecBase *self = GST_VDEC_BASE(decoder);
557 g_return_val_if_fail(self->decoder != nullptr, FALSE);
558 self->decoder->Deinit();
559 self->decoder = nullptr;
560 return TRUE;
561 }
562
gst_vdec_base_dump_from_sys_param(GstVdecBase * self)563 void gst_vdec_base_dump_from_sys_param(GstVdecBase *self)
564 {
565 std::string dump_vdec;
566 self->input.enable_dump = FALSE;
567 self->output.enable_dump = FALSE;
568 int32_t res = OHOS::system::GetStringParameter("sys.media.dump.codec.vdec", dump_vdec, "");
569 if (res != 0 || dump_vdec.empty()) {
570 GST_DEBUG_OBJECT(self, "sys.media.dump.codec.vdec");
571 return;
572 }
573 GST_DEBUG_OBJECT(self, "sys.media.dump.codec.vdec=%s", dump_vdec.c_str());
574
575 if (dump_vdec == "INPUT" || dump_vdec == "ALL") {
576 self->input.enable_dump = TRUE;
577 }
578 if (dump_vdec == "OUTPUT" || dump_vdec == "ALL") {
579 self->output.enable_dump = TRUE;
580 }
581 }
582
gst_vdec_base_start(GstVideoDecoder * decoder)583 static gboolean gst_vdec_base_start(GstVideoDecoder *decoder)
584 {
585 GST_DEBUG_OBJECT(decoder, "Start");
586 GstVdecBase *self = GST_VDEC_BASE(decoder);
587 g_return_val_if_fail(self != nullptr, FALSE);
588 self->input.frame_cnt = 0;
589 self->input.first_frame_time = 0;
590 self->input.last_frame_time = 0;
591 self->output.frame_cnt = 0;
592 self->output.first_frame_time = 0;
593 self->output.last_frame_time = 0;
594 std::list<GstClockTime> empty;
595 self->pts_list.swap(empty);
596 self->last_pts = GST_CLOCK_TIME_NONE;
597 gst_vdec_base_dump_from_sys_param(self);
598 return TRUE;
599 }
600
gst_vdec_base_stop_after(GstVdecBase * self)601 static void gst_vdec_base_stop_after(GstVdecBase *self)
602 {
603 g_return_if_fail(self != nullptr);
604 self->prepared = FALSE;
605 self->idrframe = FALSE;
606 self->input.first_frame = TRUE;
607 self->output.first_frame = TRUE;
608 self->decoder_start = FALSE;
609 self->pre_init_pool = FALSE;
610 self->performance_mode = FALSE;
611 self->resolution_changed = FALSE;
612 self->has_set_format = FALSE;
613 gst_vdec_base_set_flushing(self, FALSE);
614 if (self->input.dump_file != nullptr) {
615 fclose(self->input.dump_file);
616 self->input.dump_file = nullptr;
617 }
618 if (self->output.dump_file != nullptr) {
619 fclose(self->output.dump_file);
620 self->output.dump_file = nullptr;
621 }
622 gst_vdec_reset_sink_caps(self);
623 self->codec_data_update = FALSE;
624 if (self->codec_data) {
625 gst_buffer_unref(self->codec_data);
626 self->codec_data = nullptr;
627 }
628 }
629
gst_vdec_base_stop(GstVideoDecoder * decoder)630 static gboolean gst_vdec_base_stop(GstVideoDecoder *decoder)
631 {
632 GstVdecBase *self = GST_VDEC_BASE(decoder);
633 g_return_val_if_fail(self != nullptr, FALSE);
634 g_return_val_if_fail(self->decoder != nullptr, FALSE);
635 GST_DEBUG_OBJECT(self, "Stop decoder start");
636
637 g_mutex_lock(&self->drain_lock);
638 self->draining = FALSE;
639 g_cond_broadcast(&self->drain_cond);
640 g_mutex_unlock(&self->drain_lock);
641
642 gint ret = self->decoder->Stop();
643 (void)gst_codec_return_is_ok(self, ret, "Stop", TRUE);
644 if (self->input_state) {
645 gst_video_codec_state_unref(self->input_state);
646 }
647 if (self->output_state) {
648 gst_video_codec_state_unref(self->output_state);
649 }
650 self->input_state = nullptr;
651 self->output_state = nullptr;
652
653 gst_pad_stop_task(GST_VIDEO_DECODER_SRC_PAD(decoder));
654 ret = self->decoder->FreeInputBuffers();
655 (void)gst_codec_return_is_ok(self, ret, "FreeInput", TRUE);
656 ret = self->decoder->FreeOutputBuffers();
657 (void)gst_codec_return_is_ok(self, ret, "FreeOutput", TRUE);
658 gst_vdec_reset_inpool(self);
659 gst_vdec_reset_outpool(self);
660 gst_vdec_base_stop_after(self);
661 GST_DEBUG_OBJECT(self, "Stop decoder end");
662 return TRUE;
663 }
664
gst_codec_return_is_ok(const GstVdecBase * decoder,gint ret,const char * error_name,gboolean need_report)665 static gboolean gst_codec_return_is_ok(const GstVdecBase *decoder, gint ret,
666 const char *error_name, gboolean need_report)
667 {
668 if (ret == GST_CODEC_OK) {
669 return TRUE;
670 }
671 if (need_report) {
672 GST_ELEMENT_ERROR(decoder, STREAM, DECODE, ("hardware decoder error!"), ("%s", error_name));
673 } else {
674 GST_ERROR_OBJECT(decoder, "hardware decoder error %s", error_name);
675 }
676 return FALSE;
677 }
678
gst_vdec_base_flush(GstVideoDecoder * decoder)679 static gboolean gst_vdec_base_flush(GstVideoDecoder *decoder)
680 {
681 GstVdecBase *self = GST_VDEC_BASE(decoder);
682 g_return_val_if_fail(self != nullptr, FALSE);
683
684 g_mutex_lock(&self->format_changed_lock);
685 ON_SCOPE_EXIT(0) { g_mutex_unlock(&self->format_changed_lock); };
686
687 g_return_val_if_fail(self->decoder != nullptr, FALSE);
688 GST_DEBUG_OBJECT(self, "Flush start");
689
690 if (!self->flushing_stoping) {
691 gst_vdec_base_set_flushing(self, TRUE);
692 gint ret = self->decoder->Flush(GST_CODEC_ALL);
693 (void)gst_codec_return_is_ok(self, ret, "flush", FALSE);
694 gst_vdec_base_set_flushing(self, FALSE);
695 }
696
697 GST_DEBUG_OBJECT(self, "Flush end");
698 return TRUE;
699 }
700
update_caps_format(GstVdecBase * self,GstCaps * caps)701 static gboolean update_caps_format(GstVdecBase *self, GstCaps *caps)
702 {
703 g_return_val_if_fail(self != nullptr, FALSE);
704 g_return_val_if_fail(self->decoder != nullptr, FALSE);
705 gint ret = self->decoder->GetParameter(GST_VIDEO_FORMAT, GST_ELEMENT(self));
706 (void)gst_codec_return_is_ok(self, ret, "flush", FALSE);
707 GST_DEBUG_OBJECT(self, "update_caps_format");
708
709 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "flush", FALSE), FALSE);
710 GValue value_list = G_VALUE_INIT;
711 GValue value = G_VALUE_INIT;
712
713 if (!self->formats.empty()) {
714 g_value_init(&value_list, GST_TYPE_LIST);
715 g_value_init(&value, G_TYPE_STRING);
716 for (auto format : self->formats) {
717 if (format != GST_VIDEO_FORMAT_UNKNOWN) {
718 g_value_set_string(&value, gst_video_format_to_string(format));
719 gst_value_list_append_value(&value_list, &value);
720 }
721 }
722 gst_caps_set_value(caps, "format", &value_list);
723 g_value_unset(&value);
724 g_value_unset(&value_list);
725 }
726
727 return TRUE;
728 }
729
get_memtype(GstVdecBase * self,const GstStructure * structure)730 static gboolean get_memtype(GstVdecBase *self, const GstStructure *structure)
731 {
732 g_return_val_if_fail(self != nullptr, FALSE);
733 g_return_val_if_fail(self->decoder != nullptr, FALSE);
734 g_return_val_if_fail(structure != nullptr, FALSE);
735 const gchar *memtype = gst_structure_get_string(structure, "memtype");
736 g_return_val_if_fail(memtype != nullptr, FALSE);
737
738 if (strcmp("surface", memtype) == 0) {
739 self->memtype = GST_MEMTYPE_SURFACE;
740 } else if (strcmp("avshmem", memtype) == 0) {
741 self->memtype = GST_MEMTYPE_AVSHMEM;
742 }
743
744 if (self->memtype == GST_MEMTYPE_SURFACE) {
745 gint ret = self->decoder->SetParameter(GST_VIDEO_SURFACE_INIT, GST_ELEMENT(self));
746 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "GST_VIDEO_SURFACE_INIT", TRUE), FALSE);
747 }
748
749 return TRUE;
750 }
751
gst_vdec_base_negotiate_format(GstVdecBase * self)752 static gboolean gst_vdec_base_negotiate_format(GstVdecBase *self)
753 {
754 GST_DEBUG_OBJECT(self, "Negotiate format");
755 g_return_val_if_fail(self != nullptr, FALSE);
756 g_return_val_if_fail(self->decoder != nullptr, FALSE);
757 g_return_val_if_fail(GST_VIDEO_DECODER_SRC_PAD(self) != nullptr, FALSE);
758
759 GST_DEBUG_OBJECT(self, "Trying to negotiate a video format with downstream");
760 if (self->performance_mode && self->pre_init_pool) {
761 return TRUE;
762 }
763 GstCaps *templ_caps = gst_pad_get_pad_template_caps(GST_VIDEO_DECODER_SRC_PAD(self));
764 g_return_val_if_fail(templ_caps != nullptr, FALSE);
765
766 (void)update_caps_format(self, templ_caps);
767 GstCaps *intersection = gst_pad_peer_query_caps(GST_VIDEO_DECODER_SRC_PAD(self), templ_caps);
768 gst_caps_unref(templ_caps);
769 g_return_val_if_fail(intersection != nullptr, FALSE);
770 // We need unref at end.
771 ON_SCOPE_EXIT(0) { gst_caps_unref(intersection); };
772 g_return_val_if_fail(gst_caps_is_empty(intersection) == FALSE, FALSE);
773
774 intersection = gst_caps_truncate(intersection);
775 intersection = gst_caps_fixate(intersection);
776
777 GstStructure *structure = gst_caps_get_structure(intersection, 0);
778 const gchar *format_str = gst_structure_get_string(structure, "format");
779 g_return_val_if_fail(format_str != nullptr, FALSE);
780
781 GstVideoFormat format = gst_video_format_from_string(format_str);
782 g_return_val_if_fail(format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
783
784 self->format = format;
785 gint ret = self->decoder->SetParameter(GST_VIDEO_FORMAT, GST_ELEMENT(self));
786 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "setparameter", TRUE), FALSE);
787 return TRUE;
788 }
789
gst_vdec_base_set_outstate(GstVdecBase * self)790 static gboolean gst_vdec_base_set_outstate(GstVdecBase *self)
791 {
792 g_return_val_if_fail(self != nullptr, FALSE);
793 g_return_val_if_fail(GST_VIDEO_DECODER_SRC_PAD(self) != nullptr, FALSE);
794 GstVideoDecoder *decoder = GST_VIDEO_DECODER(self);
795
796 GST_DEBUG_OBJECT(self, "Setting output state: format %s, width %u, height %u",
797 gst_video_format_to_string(self->format), self->width, self->height);
798 GstVideoCodecState *out_state = gst_video_decoder_set_output_state(GST_VIDEO_DECODER(self),
799 self->format, self->width, self->height, self->input_state);
800 g_return_val_if_fail(out_state != nullptr, FALSE);
801 if (self->output_state != nullptr) {
802 gst_video_codec_state_unref(self->output_state);
803 }
804 self->output_state = out_state;
805 if (GST_VIDEO_INFO_MULTIVIEW_MODE(&out_state->info) == GST_VIDEO_MULTIVIEW_MODE_NONE) {
806 GST_VIDEO_INFO_MULTIVIEW_MODE(&out_state->info) = GST_VIDEO_MULTIVIEW_MODE_MONO;
807 GST_VIDEO_INFO_MULTIVIEW_FLAGS(&out_state->info) = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
808 }
809 if (out_state->caps == nullptr) {
810 out_state->caps = gst_video_info_to_caps(&out_state->info);
811 }
812 if (out_state->allocation_caps == nullptr) {
813 out_state->allocation_caps = gst_caps_ref(out_state->caps);
814 }
815 g_return_val_if_fail(gst_pad_set_caps(decoder->srcpad, out_state->caps), FALSE);
816 return TRUE;
817 }
818
gst_vdec_base_remove_reconfig_flag(GstVideoDecoder * decoder)819 static void gst_vdec_base_remove_reconfig_flag(GstVideoDecoder *decoder)
820 {
821 (void)gst_pad_check_reconfigure(decoder->srcpad);
822 }
823
gst_vdec_base_negotiate(GstVdecBase * self)824 static gboolean gst_vdec_base_negotiate(GstVdecBase *self)
825 {
826 MediaTrace trace("VdecBase::Negotiate");
827 GST_DEBUG_OBJECT(self, "Negotiate");
828 g_return_val_if_fail(self != nullptr, FALSE);
829 g_return_val_if_fail(GST_VIDEO_DECODER_SRC_PAD(self) != nullptr, FALSE);
830 g_return_val_if_fail(gst_vdec_base_negotiate_format(self), FALSE);
831 g_return_val_if_fail(gst_vdec_base_set_outstate(self), FALSE);
832 g_return_val_if_fail(gst_video_decoder_negotiate(GST_VIDEO_DECODER(self)), FALSE);
833 gst_vdec_base_remove_reconfig_flag(GST_VIDEO_DECODER(self));
834 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: negotiate end");
835 return TRUE;
836 }
837
gst_vdec_base_allocate_in_buffers(GstVdecBase * self)838 static gboolean gst_vdec_base_allocate_in_buffers(GstVdecBase *self)
839 {
840 GST_DEBUG_OBJECT(self, "Allocate input buffers");
841 g_return_val_if_fail(self != nullptr, FALSE);
842 g_return_val_if_fail(self->decoder != nullptr, FALSE);
843 g_return_val_if_fail(self->inpool != nullptr, FALSE);
844 std::vector<GstBuffer*> buffers;
845 GstBufferPool *pool = reinterpret_cast<GstBufferPool*>(gst_object_ref(self->inpool));
846 ON_SCOPE_EXIT(0) { gst_object_unref(pool); };
847 for (guint i = 0; i < self->input.buffer_cnt; ++i) {
848 GST_DEBUG_OBJECT(self, "Allocate Buffer %u", i);
849 GstBuffer *buffer = nullptr;
850 GstFlowReturn flow_ret = gst_buffer_pool_acquire_buffer(pool, &buffer, nullptr);
851 if (flow_ret != GST_FLOW_OK || buffer == nullptr) {
852 GST_WARNING_OBJECT(self, "Acquire buffer is nullptr");
853 gst_buffer_unref(buffer);
854 continue;
855 }
856 buffers.push_back(buffer);
857 }
858 GST_DEBUG_OBJECT(self, "Use input buffers start");
859 // no give ref to decoder
860 gint ret = self->decoder->UseInputBuffers(buffers);
861 // Return buffers to pool
862 for (auto buffer : buffers) {
863 gst_buffer_unref(buffer);
864 }
865 buffers.clear();
866 GST_DEBUG_OBJECT(self, "Use input buffers end");
867 return gst_codec_return_is_ok(self, ret, "usebuffer", TRUE);
868 }
869
gst_vdec_base_update_out_port_def(GstVdecBase * self,guint * size)870 static gboolean gst_vdec_base_update_out_port_def(GstVdecBase *self, guint *size)
871 {
872 g_return_val_if_fail(self != nullptr, FALSE);
873 g_return_val_if_fail(self->decoder != nullptr, FALSE);
874 g_return_val_if_fail(size != nullptr, FALSE);
875 gint ret = self->decoder->GetParameter(GST_VIDEO_OUTPUT_COMMON, GST_ELEMENT(self));
876 g_return_val_if_fail(ret == GST_CODEC_OK, FALSE);
877 g_return_val_if_fail(self->output.min_buffer_cnt <= self->out_buffer_max_cnt, FALSE);
878 self->output.buffer_cnt =
879 self->out_buffer_max_cnt > self->output.buffer_cnt ? self->output.buffer_cnt : self->out_buffer_max_cnt;
880 ret = self->decoder->SetParameter(GST_VIDEO_OUTPUT_COMMON, GST_ELEMENT(self));
881 g_return_val_if_fail(ret == GST_CODEC_OK, FALSE);
882 if (self->metadata_mode) {
883 GST_DEBUG_OBJECT(self, "Set metadata mode");
884 ret = self->decoder->SetParameter(GST_METADATA_MODE, GST_ELEMENT(self));
885 g_return_val_if_fail(ret == GST_CODEC_OK, FALSE);
886 }
887 ret = self->decoder->GetParameter(GST_VIDEO_OUTPUT_COMMON, GST_ELEMENT(self));
888 g_return_val_if_fail(ret == GST_CODEC_OK, FALSE);
889 GST_INFO_OBJECT(self, "output params is min buffer count %u, buffer count %u, buffer size is %u",
890 self->output.min_buffer_cnt, self->output.buffer_cnt, self->output.buffer_size);
891 *size = self->output.buffer_size > *size ? self->output.buffer_size : *size;
892 self->out_buffer_cnt = self->output.buffer_cnt;
893 return TRUE;
894 }
895
gst_vdec_base_allocate_out_buffers(GstVdecBase * self)896 static gboolean gst_vdec_base_allocate_out_buffers(GstVdecBase *self)
897 {
898 GST_DEBUG_OBJECT(self, "Allocate output buffers");
899 g_return_val_if_fail(self != nullptr, FALSE);
900 g_return_val_if_fail(self->decoder != nullptr, FALSE);
901 std::vector<GstBuffer*> buffers;
902 self->coding_outbuf_cnt = self->out_buffer_cnt;
903 if (self->memtype != GST_MEMTYPE_SURFACE) {
904 MediaTrace trace("VdecBase::AllocateOutPutBuffer");
905 for (guint i = 0; i < self->out_buffer_cnt; ++i) {
906 GST_DEBUG_OBJECT(self, "Allocate output buffer %u", i);
907 GstBuffer *buffer = gst_video_decoder_allocate_output_buffer(GST_VIDEO_DECODER(self));
908 if (buffer != nullptr) {
909 buffers.push_back(buffer);
910 }
911 g_warn_if_fail(buffer != nullptr);
912 }
913 }
914
915 gint ret;
916 {
917 MediaTrace trace("VdecBase::UseOutputBuffers");
918 // give buffer ref to decoder
919 ret = self->decoder->UseOutputBuffers(buffers);
920 }
921 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "usebuffer", TRUE), FALSE);
922 return TRUE;
923 }
924
gst_vdec_base_prepare(GstVdecBase * self)925 static gboolean gst_vdec_base_prepare(GstVdecBase *self)
926 {
927 GST_DEBUG_OBJECT(self, "Prepare");
928 g_return_val_if_fail(self != nullptr, FALSE);
929
930 // Negotiate with downstream and get format
931 g_return_val_if_fail(gst_vdec_base_negotiate(self), FALSE);
932
933 if (!gst_vdec_base_is_flushing(self)) {
934 // Check allocate input buffer already
935 gst_vdec_base_check_allocate_input(self);
936
937 // To allocate output memory, we need to give the size
938 g_return_val_if_fail(gst_vdec_base_allocate_out_buffers(self), FALSE);
939 }
940
941 return TRUE;
942 }
943
gst_vdec_base_clean_all_frames(GstVideoDecoder * decoder)944 static void gst_vdec_base_clean_all_frames(GstVideoDecoder *decoder)
945 {
946 GST_DEBUG_OBJECT(decoder, "Clean all frames");
947 g_return_if_fail(decoder != nullptr);
948 GList *frame_head = gst_video_decoder_get_frames(decoder);
949 g_return_if_fail(frame_head != nullptr);
950 for (GList *frame = frame_head; frame != nullptr; frame = frame->next) {
951 GstVideoCodecFrame *tmp = reinterpret_cast<GstVideoCodecFrame*>(frame->data);
952 if (tmp != nullptr) {
953 gst_video_decoder_release_frame(decoder, tmp);
954 }
955 }
956 g_list_free(frame_head);
957 }
958
gst_vdec_debug_input_time(GstVdecBase * self)959 static void gst_vdec_debug_input_time(GstVdecBase *self)
960 {
961 if (self->input.first_frame_time == 0) {
962 self->input.first_frame_time = g_get_monotonic_time();
963 } else {
964 self->input.last_frame_time = g_get_monotonic_time();
965 }
966 self->input.frame_cnt++;
967 gint64 time_interval = self->input.last_frame_time - self->input.first_frame_time;
968 gint64 frame_cnt = self->input.frame_cnt - 1;
969 if (frame_cnt > 0) {
970 gint64 time_every_frame = time_interval / frame_cnt;
971 GST_DEBUG_OBJECT(self, "Decoder Input Time interval %" G_GINT64_FORMAT " us, frame count %" G_GINT64_FORMAT
972 " ,every frame time %" G_GINT64_FORMAT " us, frame rate %.9f", time_interval, self->input.frame_cnt,
973 time_every_frame, static_cast<double>(G_TIME_SPAN_SECOND) / static_cast<double>(time_every_frame));
974 }
975 }
976
gst_vdec_debug_output_time(GstVdecBase * self)977 static void gst_vdec_debug_output_time(GstVdecBase *self)
978 {
979 if (self->output.first_frame_time == 0) {
980 self->output.first_frame_time = g_get_monotonic_time();
981 } else {
982 self->output.last_frame_time = g_get_monotonic_time();
983 }
984 self->output.frame_cnt++;
985 gint64 time_interval = self->output.last_frame_time - self->output.first_frame_time;
986 gint64 frame_cnt = self->output.frame_cnt - 1;
987 if (frame_cnt > 0) {
988 gint64 time_every_frame = time_interval / frame_cnt;
989 GST_DEBUG_OBJECT(self, "Decoder Output Time interval %" G_GINT64_FORMAT " us, frame count %" G_GINT64_FORMAT
990 " ,every frame time %" G_GINT64_FORMAT " us, frame rate %.9f", time_interval, self->output.frame_cnt,
991 time_every_frame, static_cast<double>(G_TIME_SPAN_SECOND) / static_cast<double>(time_every_frame));
992 }
993 }
994
gst_vdec_base_dump_input_buffer(GstVdecBase * self,GstBuffer * buffer)995 static void gst_vdec_base_dump_input_buffer(GstVdecBase *self, GstBuffer *buffer)
996 {
997 g_return_if_fail(self != nullptr);
998 g_return_if_fail(buffer != nullptr);
999 if (self->input.enable_dump == FALSE) {
1000 return;
1001 }
1002 GST_DEBUG_OBJECT(self, "Dump input buffer");
1003 std::string input_dump_file = "/data/media/vdecbase-in-" +
1004 std::to_string(static_cast<int32_t>(FAKE_POINTER(self))) + ".es";
1005 if (self->input.dump_file == nullptr) {
1006 self->input.dump_file = fopen(input_dump_file.c_str(), "wb+");
1007 }
1008 if (self->input.dump_file == nullptr) {
1009 GST_ERROR_OBJECT(self, "open file failed");
1010 return;
1011 }
1012 GstMapInfo info = GST_MAP_INFO_INIT;
1013 g_return_if_fail(gst_buffer_map(buffer, &info, GST_MAP_READ));
1014 (void)fwrite(info.data, info.size, 1, self->input.dump_file);
1015 (void)fflush(self->input.dump_file);
1016 gst_buffer_unmap(buffer, &info);
1017 }
1018
gst_vdec_base_dump_output_buffer(GstVdecBase * self,GstBuffer * buffer)1019 static void gst_vdec_base_dump_output_buffer(GstVdecBase *self, GstBuffer *buffer)
1020 {
1021 g_return_if_fail(self != nullptr);
1022 g_return_if_fail(buffer != nullptr);
1023 if (self->output.enable_dump == FALSE) {
1024 return;
1025 }
1026 GST_DEBUG_OBJECT(self, "Dump output buffer");
1027 std::string output_dump_file = "/data/media/vdecbase-out-" +
1028 std::to_string(static_cast<int32_t>(FAKE_POINTER(self))) + ".yuv";
1029 if (self->output.dump_file == nullptr) {
1030 self->output.dump_file = fopen(output_dump_file.c_str(), "wb+");
1031 }
1032 if (self->output.dump_file == nullptr) {
1033 GST_DEBUG_OBJECT(self, "open file failed");
1034 return;
1035 }
1036 GstMapInfo info = GST_MAP_INFO_INIT;
1037 g_return_if_fail(gst_buffer_map(buffer, &info, GST_MAP_READ));
1038 guint stride = (guint)(self->real_stride == 0 ? self->stride : self->real_stride);
1039 guint stride_height = (guint)(self->real_stride_height == 0 ? self->stride_height : self->real_stride_height);
1040 stride = stride == 0 ? self->width : stride;
1041 stride_height = stride_height == 0 ? self->height : stride_height;
1042 // yuv size
1043 guint size = stride * stride_height * 3 / 2;
1044 size = size > info.size ? info.size : size;
1045 (void)fwrite(info.data, size, 1, self->output.dump_file);
1046 (void)fflush(self->output.dump_file);
1047 gst_buffer_unmap(buffer, &info);
1048 }
1049
gst_vdec_base_input_frame_pts_to_list(GstVdecBase * self,GstVideoCodecFrame * frame)1050 static void gst_vdec_base_input_frame_pts_to_list(GstVdecBase *self, GstVideoCodecFrame *frame)
1051 {
1052 GST_DEBUG_OBJECT(self, "Input frame pts %" G_GUINT64_FORMAT, frame->pts);
1053 g_mutex_lock(&self->lock);
1054 if (frame->pts == GST_CLOCK_TIME_NONE) {
1055 g_mutex_unlock(&self->lock);
1056 return;
1057 }
1058 if (self->pts_list.empty() || frame->pts > self->pts_list.back()) {
1059 self->pts_list.push_back(frame->pts);
1060 self->last_pts = frame->pts;
1061 g_mutex_unlock(&self->lock);
1062 return;
1063 }
1064 for (auto iter = self->pts_list.begin(); iter != self->pts_list.end(); ++iter) {
1065 if ((*iter) == frame->pts) {
1066 break;
1067 }
1068 if ((*iter) > frame->pts) {
1069 self->pts_list.insert(iter, frame->pts);
1070 break;
1071 }
1072 }
1073 g_mutex_unlock(&self->lock);
1074 }
1075
gst_vdec_base_push_input_buffer_with_copy(GstVdecBase * self,GstBuffer * src_buffer,gboolean is_codec_data)1076 static int32_t gst_vdec_base_push_input_buffer_with_copy(GstVdecBase *self, GstBuffer *src_buffer,
1077 gboolean is_codec_data)
1078 {
1079 MediaTrace trace("VdecBase::InputCopy");
1080 GstBuffer* dts_buffer;
1081 GstBufferPool *pool = reinterpret_cast<GstBufferPool *>(gst_object_ref(self->inpool));
1082 ON_SCOPE_EXIT(0) { gst_object_unref(pool); };
1083 GstFlowReturn flow_ret = gst_buffer_pool_acquire_buffer(pool, &dts_buffer, nullptr);
1084 ON_SCOPE_EXIT(1) { gst_buffer_unref(dts_buffer); };
1085 g_return_val_if_fail(flow_ret == GST_FLOW_OK && dts_buffer != nullptr, GST_CODEC_FLUSH);
1086 GstMapInfo dts_map = GST_MAP_INFO_INIT;
1087 g_return_val_if_fail(gst_buffer_map(dts_buffer, &dts_map, GST_MAP_WRITE) == TRUE, GST_CODEC_ERROR);
1088 ON_SCOPE_EXIT(2) { gst_buffer_unmap(dts_buffer, &dts_map); };
1089 GstMapInfo src_map = GST_MAP_INFO_INIT;
1090 g_return_val_if_fail(gst_buffer_map(src_buffer, &src_map, GST_MAP_READ) == TRUE, GST_CODEC_ERROR);
1091 ON_SCOPE_EXIT(3) { gst_buffer_unmap(src_buffer, &src_map); };
1092
1093 GstBufferTypeMeta *meta = gst_buffer_get_buffer_type_meta(dts_buffer);
1094 g_return_val_if_fail(meta != nullptr, GST_CODEC_ERROR);
1095 GstVdecBaseClass *kclass = GST_VDEC_BASE_GET_CLASS(self);
1096 if (kclass->parser) {
1097 ParseMeta parse_meta = {src_map, dts_map, is_codec_data, meta->length};
1098 g_return_val_if_fail(kclass->parser(self, parse_meta) == TRUE, GST_CODEC_ERROR);
1099 } else {
1100 auto ret = memcpy_s(dts_map.data, dts_map.size, src_map.data, src_map.size);
1101 g_return_val_if_fail(ret == EOK, GST_CODEC_ERROR);
1102 meta->length = src_map.size;
1103 }
1104 CANCEL_SCOPE_EXIT_GUARD(2);
1105 CANCEL_SCOPE_EXIT_GUARD(3);
1106 gst_buffer_unmap(dts_buffer, &dts_map);
1107 gst_buffer_unmap(src_buffer, &src_map);
1108 gst_buffer_set_size(dts_buffer, meta->length);
1109 GST_BUFFER_PTS(dts_buffer) = GST_BUFFER_PTS(src_buffer);
1110 GST_BUFFER_DTS(dts_buffer) = GST_BUFFER_DTS(src_buffer);
1111 GST_BUFFER_DURATION(dts_buffer) = GST_BUFFER_DURATION(src_buffer);
1112 GST_DEBUG_OBJECT(self, "Input frame pts %" G_GUINT64_FORMAT, GST_BUFFER_PTS(dts_buffer));
1113 gst_vdec_base_dump_input_buffer(self, dts_buffer);
1114 gint codec_ret = self->decoder->PushInputBuffer(dts_buffer);
1115 return codec_ret;
1116 }
1117
gst_vdec_check_ashmem_buffer(GstBuffer * buffer)1118 static gboolean gst_vdec_check_ashmem_buffer(GstBuffer *buffer)
1119 {
1120 g_return_val_if_fail(buffer != nullptr, FALSE);
1121 GstMemory *memory = gst_buffer_peek_memory(buffer, 0);
1122 return gst_is_shmem_memory(memory);
1123 }
1124
gst_vdec_base_push_input_buffer(GstVideoDecoder * decoder,GstVideoCodecFrame * frame)1125 static GstFlowReturn gst_vdec_base_push_input_buffer(GstVideoDecoder *decoder, GstVideoCodecFrame *frame)
1126 {
1127 MediaTrace trace("VdecBase::PushInputBuffer");
1128 GstVdecBase *self = GST_VDEC_BASE(decoder);
1129 gst_vdec_debug_input_time(self);
1130 gst_vdec_base_input_frame_pts_to_list(self, frame);
1131 GstVdecBaseClass *kclass = GST_VDEC_BASE_GET_CLASS(self);
1132 GstBuffer *buf = nullptr;
1133 if (kclass->handle_slice_buffer != nullptr && self->player_scene == true) {
1134 bool ready_push_slice_buffer = false;
1135 GstBuffer *cat_buffer = kclass->handle_slice_buffer(self, frame->input_buffer, ready_push_slice_buffer, false);
1136 if (cat_buffer != nullptr && ready_push_slice_buffer == true) {
1137 buf = cat_buffer;
1138 GST_BUFFER_PTS(buf) = GST_BUFFER_PTS(frame->input_buffer);
1139 GST_BUFFER_DTS(buf) = GST_BUFFER_DTS(frame->input_buffer);
1140 GST_BUFFER_DURATION(buf) = GST_BUFFER_DURATION(frame->input_buffer);
1141 }
1142 } else {
1143 buf = frame->input_buffer;
1144 gst_buffer_ref(buf);
1145 }
1146
1147 if (buf == nullptr) {
1148 GST_DEBUG_OBJECT(self, "buffer is null");
1149 return GST_FLOW_OK;
1150 }
1151
1152 GST_VIDEO_DECODER_STREAM_UNLOCK(self);
1153
1154 gint codec_ret = GST_CODEC_OK;
1155 if (!gst_vdec_check_ashmem_buffer(buf) && self->input_need_ashmem) {
1156 // codec data just for mkv/mp4, and this scene is no ashmem
1157 if (self->codec_data_update) {
1158 self->codec_data_update = FALSE;
1159 (void)gst_vdec_base_push_input_buffer_with_copy(self, self->codec_data, TRUE);
1160 }
1161 codec_ret = gst_vdec_base_push_input_buffer_with_copy(self, buf, FALSE);
1162 } else {
1163 gst_vdec_base_dump_input_buffer(self, buf);
1164 codec_ret = self->decoder->PushInputBuffer(buf);
1165 }
1166 gst_buffer_unref(buf);
1167 GST_VIDEO_DECODER_STREAM_LOCK(self);
1168 GstFlowReturn ret = GST_FLOW_OK;
1169 switch (codec_ret) {
1170 case GST_CODEC_OK:
1171 break;
1172 case GST_CODEC_FLUSH:
1173 ret = GST_FLOW_FLUSHING;
1174 GST_DEBUG_OBJECT(self, "Flushing");
1175 break;
1176 default:
1177 ret = GST_FLOW_ERROR;
1178 GST_ELEMENT_WARNING(self, STREAM, ENCODE, ("Hardware encoder error!"), ("pull"));
1179 }
1180 return ret;
1181 }
1182
gst_vdec_base_handle_frame(GstVideoDecoder * decoder,GstVideoCodecFrame * frame)1183 static GstFlowReturn gst_vdec_base_handle_frame(GstVideoDecoder *decoder, GstVideoCodecFrame *frame)
1184 {
1185 MediaTrace trace("VdecBase::HandleFrame");
1186 GST_DEBUG_OBJECT(decoder, "Handle frame");
1187 GstVdecBase *self = GST_VDEC_BASE(decoder);
1188 ON_SCOPE_EXIT(0) { gst_video_codec_frame_unref(frame); };
1189 g_return_val_if_fail(GST_IS_VDEC_BASE(self), GST_FLOW_ERROR);
1190 g_return_val_if_fail(self != nullptr && frame != nullptr && self->decoder != nullptr, GST_FLOW_ERROR);
1191 if (self->input.first_frame) {
1192 GST_WARNING_OBJECT(decoder, "KPI-TRACE-VDEC: first in frame");
1193 self->input.first_frame = FALSE;
1194 }
1195
1196 if (gst_vdec_base_is_flushing(self)) {
1197 return GST_FLOW_FLUSHING;
1198 }
1199 gst_vdec_base_clean_all_frames(decoder);
1200
1201 GstVdecBaseClass *kclass = GST_VDEC_BASE_GET_CLASS(self);
1202 if (kclass->bypass_frame != nullptr && self->player_scene == true) {
1203 g_return_val_if_fail(!kclass->bypass_frame(self, frame), GST_FLOW_OK); // no fail
1204 }
1205
1206 if (!self->prepared) {
1207 g_return_val_if_fail(gst_vdec_base_prepare(self), GST_FLOW_ERROR);
1208
1209 /* When the resolution of HLS changes, the new one will block on the pad port and wait for connection.
1210 At this time, if the seek operation is issued, the pad port will be activated. At this time,
1211 the negotiation is unreliable and the frame data needs to be refreshed */
1212 g_return_val_if_fail(!gst_vdec_base_is_flushing(self), GST_FLOW_FLUSHING);
1213 self->prepared = TRUE;
1214 }
1215 GstPad *pad = GST_VIDEO_DECODER_SRC_PAD(self);
1216 if (!self->decoder_start) {
1217 gint ret = self->decoder->Start();
1218 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "start", TRUE), GST_FLOW_ERROR);
1219 self->decoder_start = TRUE;
1220 self->is_eos_state = FALSE;
1221 GST_WARNING_OBJECT(decoder, "KPI-TRACE-VDEC: start end");
1222 }
1223 g_return_val_if_fail(gst_pad_get_task_state(pad) == GST_TASK_STARTED ||
1224 gst_pad_start_task(pad, (GstTaskFunction)gst_vdec_base_loop, decoder, nullptr) == TRUE, GST_FLOW_ERROR);
1225
1226 GstFlowReturn ret = gst_vdec_base_push_input_buffer(decoder, frame);
1227 return ret;
1228 }
1229
update_video_meta(const GstVdecBase * self,GstBuffer * buffer)1230 static void update_video_meta(const GstVdecBase *self, GstBuffer *buffer)
1231 {
1232 GST_DEBUG_OBJECT(self, "Update buffer video meta");
1233 g_return_if_fail(self != nullptr);
1234 g_return_if_fail(buffer != nullptr);
1235 GstVideoMeta *video_meta = gst_buffer_get_video_meta(buffer);
1236 if (video_meta == nullptr) {
1237 gst_buffer_add_video_meta(buffer, GST_VIDEO_FRAME_FLAG_NONE, self->format, self->width, self->height);
1238 } else {
1239 GST_DEBUG_OBJECT(self, "stride is %d, stride_height is %d", self->real_stride, self->real_stride_height);
1240 video_meta->width = self->width;
1241 video_meta->height = self->height;
1242 video_meta->offset[0] = 0;
1243 video_meta->stride[0] = self->real_stride;
1244 video_meta->stride[1] = self->real_stride;
1245 video_meta->offset[1] = self->real_stride * self->real_stride_height;
1246 }
1247 }
1248
gst_vdec_base_new_frame(GstVdecBase * self,GstBuffer * buffer)1249 static GstVideoCodecFrame *gst_vdec_base_new_frame(GstVdecBase *self, GstBuffer *buffer)
1250 {
1251 GST_DEBUG_OBJECT(self, "New frame");
1252 GstVideoCodecFrame *frame = g_slice_new0(GstVideoCodecFrame);
1253 g_return_val_if_fail(frame != nullptr, nullptr);
1254 frame->ref_count = 1;
1255 frame->system_frame_number = 0;
1256 frame->decode_frame_number = 0;
1257 frame->dts = GST_CLOCK_TIME_NONE;
1258 g_mutex_lock(&self->lock);
1259 if (self->player_mode == FALSE) {
1260 frame->pts = GST_BUFFER_PTS(buffer);
1261 } else {
1262 frame->pts = self->last_pts;
1263 if (!self->pts_list.empty()) {
1264 frame->pts = self->pts_list.front();
1265 GST_DEBUG_OBJECT(self, "Pts %" G_GUINT64_FORMAT, frame->pts);
1266 self->pts_list.pop_front();
1267 }
1268 }
1269 g_mutex_unlock(&self->lock);
1270 frame->duration = GST_CLOCK_TIME_NONE;
1271 frame->events = nullptr;
1272
1273 return frame;
1274 }
1275
gst_vdec_base_post_resolution_changed_message(GstVdecBase * self,gboolean need_post)1276 static void gst_vdec_base_post_resolution_changed_message(GstVdecBase *self, gboolean need_post)
1277 {
1278 if (!need_post) {
1279 return;
1280 }
1281 GstMessage *msg_resolution_changed = nullptr;
1282 msg_resolution_changed = gst_message_new_resolution_changed(GST_OBJECT(self),
1283 self->width, self->height);
1284 if (msg_resolution_changed) {
1285 gst_element_post_message(GST_ELEMENT(self), msg_resolution_changed);
1286 }
1287 self->resolution_changed = TRUE;
1288 GST_DEBUG_OBJECT(self, "post resolution changed message");
1289 }
1290
push_output_buffer(GstVdecBase * self,GstBuffer * buffer)1291 static GstFlowReturn push_output_buffer(GstVdecBase *self, GstBuffer *buffer)
1292 {
1293 MediaTrace trace("VdecBase::PushBufferToSurfaceSink");
1294 GST_DEBUG_OBJECT(self, "Push output buffer");
1295 if (!gst_video_decoder_need_decode(GST_VIDEO_DECODER(self))) {
1296 GST_INFO_OBJECT(self, "only need one frame!");
1297 gst_buffer_unref(buffer);
1298 return GST_FLOW_OK;
1299 }
1300 g_return_val_if_fail(self != nullptr, GST_FLOW_ERROR);
1301 g_return_val_if_fail(buffer != nullptr, GST_FLOW_ERROR);
1302 update_video_meta(self, buffer);
1303 GstVideoCodecFrame *frame = gst_vdec_base_new_frame(self, buffer);
1304 g_return_val_if_fail(frame != nullptr, GST_FLOW_ERROR);
1305 gst_vdec_debug_output_time(self);
1306
1307 gst_vdec_base_post_resolution_changed_message(self, self->resolution_changed == FALSE);
1308
1309 frame->output_buffer = buffer;
1310 gst_vdec_base_dump_output_buffer(self, buffer);
1311 GstFlowReturn flow_ret = gst_video_decoder_finish_frame(GST_VIDEO_DECODER(self), frame);
1312 return flow_ret;
1313 }
1314
gst_vdec_check_out_format_change(GstVdecBase * self)1315 static gboolean gst_vdec_check_out_format_change(GstVdecBase *self)
1316 {
1317 gboolean is_format_change = (self->width != self->rect.width) || (self->height != self->rect.height);
1318
1319 GST_INFO_OBJECT(self, "Format change width %d to %d, height %d to %d",
1320 self->width, self->output.width, self->height, self->output.height);
1321 self->width = self->rect.width;
1322 self->height = self->rect.height;
1323 return is_format_change;
1324 }
1325
gst_vdec_check_out_buffer_cnt(GstVdecBase * self)1326 static gboolean gst_vdec_check_out_buffer_cnt(GstVdecBase *self)
1327 {
1328 g_return_val_if_fail(self->output.min_buffer_cnt <= self->out_buffer_max_cnt, FALSE);
1329 self->output.buffer_cnt =
1330 self->output.buffer_cnt > self->out_buffer_max_cnt ? self->out_buffer_max_cnt : self->output.buffer_cnt;
1331 gboolean is_buffer_cnt_change = self->out_buffer_cnt != self->output.buffer_cnt;
1332 GST_INFO_OBJECT(self, "Format change buffer %u to %u", self->out_buffer_cnt, self->output.buffer_cnt);
1333 self->out_buffer_cnt = self->output.buffer_cnt;
1334 return is_buffer_cnt_change;
1335 }
1336
gst_vdec_check_out_buffer_usage(GstVdecBase * self)1337 static gboolean gst_vdec_check_out_buffer_usage(GstVdecBase *self)
1338 {
1339 guint64 old_usage = self->usage;
1340 (void)self->decoder->GetParameter(GST_BUFFER_USAGE, GST_ELEMENT(self));
1341 GST_INFO_OBJECT(self, "buffer usage %" G_GUINT64_FORMAT " change to %" G_GUINT64_FORMAT,
1342 old_usage, self->usage);
1343 gboolean is_usage_change = old_usage != self->usage;
1344 return is_usage_change;
1345 }
1346
gst_vdec_base_get_real_stride(GstVdecBase * self)1347 static void gst_vdec_base_get_real_stride(GstVdecBase *self)
1348 {
1349 self->real_stride = self->stride;
1350 self->real_stride_height = self->stride_height;
1351 }
1352
gst_vdec_base_format_change(GstVdecBase * self)1353 static GstFlowReturn gst_vdec_base_format_change(GstVdecBase *self)
1354 {
1355 g_return_val_if_fail(self != nullptr, GST_FLOW_ERROR);
1356 g_return_val_if_fail(self->decoder != nullptr, GST_FLOW_ERROR);
1357
1358 g_mutex_lock(&self->format_changed_lock);
1359 ON_SCOPE_EXIT(0) { g_mutex_unlock(&self->format_changed_lock); };
1360 if (self->unsupport_format_changed || !self->decoder->IsFormatChanged()) {
1361 return GST_FLOW_OK;
1362 }
1363
1364 MediaTrace trace("VdecBase::FormatChange");
1365 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: format change start");
1366 gint ret = self->decoder->ActiveBufferMgr(GST_CODEC_OUTPUT, false);
1367 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "ActiveBufferMgr", TRUE), GST_FLOW_ERROR);
1368 ret = self->decoder->GetParameter(GST_VIDEO_OUTPUT_COMMON, GST_ELEMENT(self));
1369 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "GetParameter", TRUE), GST_FLOW_ERROR);
1370 gst_vdec_base_get_real_stride(self);
1371 gboolean format_change = gst_vdec_check_out_format_change(self);
1372 gboolean buffer_cnt_change = gst_vdec_check_out_buffer_cnt(self);
1373 gboolean buffer_usage_change = gst_vdec_check_out_buffer_usage(self);
1374 gst_vdec_base_post_resolution_changed_message(self, format_change == TRUE);
1375 if (format_change || buffer_usage_change || (buffer_cnt_change && self->memtype != GST_MEMTYPE_SURFACE)) {
1376 // wait all sufacebuffer already render
1377 GstQuery *query = gst_query_new_drain();
1378 if (!gst_pad_peer_query(GST_VIDEO_DECODER_SRC_PAD(self), query)) {
1379 GST_WARNING_OBJECT(self, "drain query failed");
1380 }
1381 gst_query_unref(query);
1382 g_return_val_if_fail(gst_buffer_pool_set_active(GST_BUFFER_POOL(self->outpool), FALSE), GST_FLOW_ERROR);
1383 ret = self->decoder->FreeOutputBuffers();
1384 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "freebuffer", TRUE), GST_FLOW_ERROR);
1385 g_return_val_if_fail(gst_vdec_base_set_outstate(self), GST_FLOW_ERROR);
1386 g_return_val_if_fail(gst_video_decoder_negotiate(GST_VIDEO_DECODER(self)), GST_FLOW_ERROR);
1387 } else if (buffer_cnt_change) {
1388 ret = self->decoder->FreeOutputBuffers();
1389 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "freebuffer", TRUE), GST_FLOW_ERROR);
1390 g_object_set(self->outpool, "dynamic-buffer-num", self->out_buffer_cnt, nullptr);
1391 } else {
1392 ret = self->decoder->FreeOutputBuffers();
1393 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "freebuffer", TRUE), GST_FLOW_ERROR);
1394 }
1395
1396 ret = self->decoder->ActiveBufferMgr(GST_CODEC_OUTPUT, true);
1397 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "ActiveBufferMgr", TRUE), GST_FLOW_ERROR);
1398 g_return_val_if_fail(gst_vdec_base_allocate_out_buffers(self), GST_FLOW_ERROR);
1399 ret = self->decoder->Start();
1400 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "Start", TRUE), GST_FLOW_ERROR);
1401 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: format change end");
1402 return GST_FLOW_OK;
1403 }
1404
gst_vdec_base_codec_eos(GstVdecBase * self)1405 static GstFlowReturn gst_vdec_base_codec_eos(GstVdecBase *self)
1406 {
1407 GST_DEBUG_OBJECT(self, "Eos");
1408 g_return_val_if_fail(self != nullptr, GST_FLOW_ERROR);
1409 g_return_val_if_fail(GST_VIDEO_DECODER_SRC_PAD(self) != nullptr, GST_FLOW_ERROR);
1410 g_mutex_lock(&self->drain_lock);
1411 if (self->draining) {
1412 GstQuery *query = gst_query_new_drain();
1413
1414 if (!gst_pad_peer_query(GST_VIDEO_DECODER_SRC_PAD(self), query)) {
1415 GST_WARNING_OBJECT(self, "drain query failed");
1416 }
1417 gst_query_unref(query);
1418
1419 GST_DEBUG_OBJECT(self, "Drained");
1420 self->draining = FALSE;
1421 g_cond_broadcast(&self->drain_cond);
1422 }
1423 g_mutex_unlock(&self->drain_lock);
1424 gst_vdec_base_pause_loop(self);
1425 return GST_FLOW_OK;
1426 }
1427
gst_vdec_base_pause_loop(GstVdecBase * self)1428 static void gst_vdec_base_pause_loop(GstVdecBase *self)
1429 {
1430 GST_DEBUG_OBJECT(self, "Pause loop start");
1431 g_return_if_fail(self != nullptr);
1432 g_mutex_lock(&self->drain_lock);
1433 if (self->draining) {
1434 self->draining = FALSE;
1435 g_cond_broadcast(&self->drain_cond);
1436 }
1437 g_mutex_unlock(&self->drain_lock);
1438 GST_DEBUG_OBJECT(self, "pause loop end");
1439 gst_pad_pause_task(GST_VIDEO_DECODER_SRC_PAD(self));
1440 }
1441
gst_vdec_base_push_out_buffers(GstVdecBase * self)1442 static gboolean gst_vdec_base_push_out_buffers(GstVdecBase *self)
1443 {
1444 MediaTrace trace("VdecBase::PushOutputBuffer");
1445 GST_DEBUG_OBJECT(self, "Push out buffers");
1446 g_return_val_if_fail(self != nullptr, FALSE);
1447 g_return_val_if_fail(self->decoder != nullptr, FALSE);
1448 GstBuffer *buffer = nullptr;
1449 GstBufferPool *pool = gst_video_decoder_get_buffer_pool(GST_VIDEO_DECODER(self));
1450 ON_SCOPE_EXIT(0) { gst_object_unref(pool); };
1451 GstFlowReturn flow = GST_FLOW_OK;
1452 GstBufferPoolAcquireParams params;
1453 g_return_val_if_fail(memset_s(¶ms, sizeof(params), 0, sizeof(params)) == EOK, FALSE);
1454 if (self->coding_outbuf_cnt > BLOCKING_ACQUIRE_BUFFER_THRESHOLD) {
1455 params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
1456 }
1457 while (flow == GST_FLOW_OK) {
1458 flow = gst_buffer_pool_acquire_buffer(pool, &buffer, ¶ms);
1459 if (flow == GST_FLOW_OK) {
1460 g_return_val_if_fail(buffer != nullptr, FALSE);
1461 ON_SCOPE_EXIT(1) {
1462 gst_buffer_unref(buffer);
1463 };
1464 gint codec_ret = self->decoder->PushOutputBuffer(buffer);
1465 g_return_val_if_fail(codec_ret != GST_CODEC_FLUSH, FALSE);
1466 g_return_val_if_fail(gst_codec_return_is_ok(self, codec_ret, "push buffer", TRUE), FALSE);
1467 self->coding_outbuf_cnt++;
1468 params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
1469 }
1470 }
1471 if (flow != GST_FLOW_EOS) {
1472 GST_ELEMENT_ERROR(self, STREAM, DECODE, ("hardware decoder error!"), ("%s", "acquire buffer"));
1473 return FALSE;
1474 }
1475 return TRUE;
1476 }
1477
gst_vdec_reduce_coding_buffer(GstVdecBase * self)1478 inline static void gst_vdec_reduce_coding_buffer(GstVdecBase *self)
1479 {
1480 if (self->memtype != GST_MEMTYPE_SURFACE) {
1481 self->coding_outbuf_cnt--;
1482 }
1483 }
1484
gst_vdec_base_loop(GstVdecBase * self)1485 static void gst_vdec_base_loop(GstVdecBase *self)
1486 {
1487 GST_DEBUG_OBJECT(self, "Loop in");
1488 g_return_if_fail(self != nullptr);
1489 g_return_if_fail(self->decoder != nullptr);
1490
1491 pthread_setname_np(pthread_self(), "VDecOutPut");
1492 GstBuffer *gst_buffer = nullptr;
1493 if (self->memtype != GST_MEMTYPE_SURFACE) {
1494 ON_SCOPE_EXIT(0) { gst_vdec_base_pause_loop(self); };
1495 g_return_if_fail(gst_vdec_base_push_out_buffers(self) == TRUE);
1496 CANCEL_SCOPE_EXIT_GUARD(0);
1497 GST_DEBUG_OBJECT(self, "coding buffers %u", self->coding_outbuf_cnt);
1498 }
1499 gint codec_ret = GST_CODEC_OK;
1500 {
1501 MediaTrace trace("VdecBase::PullOutputBuffer");
1502 codec_ret = self->decoder->PullOutputBuffer(&gst_buffer);
1503 }
1504 gint flow_ret = GST_FLOW_OK;
1505 GST_DEBUG_OBJECT(self, "Pull ret %d", codec_ret);
1506 switch (codec_ret) {
1507 case GST_CODEC_OK:
1508 gst_vdec_reduce_coding_buffer(self);
1509 flow_ret = push_output_buffer(self, gst_buffer);
1510 break;
1511 case GST_CODEC_FORMAT_CHANGE:
1512 (void)gst_vdec_base_format_change(self);
1513 return;
1514 case GST_CODEC_EOS:
1515 gst_vdec_reduce_coding_buffer(self);
1516 flow_ret = gst_vdec_base_codec_eos(self);
1517 break;
1518 case GST_CODEC_FLUSH:
1519 flow_ret = GST_FLOW_FLUSHING;
1520 break;
1521 case GST_CODEC_ERROR:
1522 GST_ELEMENT_WARNING(self, STREAM, DECODE, ("Hardware decoder error!"), ("pull"));
1523 flow_ret = GST_FLOW_ERROR;
1524 break;
1525 default:
1526 flow_ret = GST_FLOW_ERROR;
1527 GST_ERROR_OBJECT(self, "Unknown error");
1528 }
1529 switch (flow_ret) {
1530 case GST_FLOW_OK:
1531 return;
1532 case GST_FLOW_FLUSHING:
1533 GST_DEBUG_OBJECT(self, "Flushing");
1534 break;
1535 case GST_FLOW_EOS:
1536 GST_DEBUG_OBJECT(self, "Eos");
1537 gst_pad_push_event(GST_VIDEO_DECODER_SRC_PAD(self), gst_event_new_eos());
1538 break;
1539 default:
1540 gst_pad_push_event(GST_VIDEO_DECODER_SRC_PAD(self), gst_event_new_eos());
1541 }
1542 gst_vdec_base_pause_loop(self);
1543 }
1544
gst_vdec_swap_width_height(GstCaps * caps)1545 static GstCaps* gst_vdec_swap_width_height(GstCaps *caps)
1546 {
1547 caps = gst_caps_make_writable(caps);
1548 g_return_val_if_fail(caps != nullptr, nullptr);
1549 GstStructure *structure = gst_caps_get_structure(caps, 0);
1550 g_return_val_if_fail(structure != nullptr, caps);
1551
1552 const GValue *width = gst_structure_get_value(structure, "width");
1553 const GValue *height = gst_structure_get_value(structure, "height");
1554 GValue temp_width = G_VALUE_INIT;
1555 gst_value_init_and_copy (&temp_width, width);
1556 width = &temp_width;
1557 gst_structure_set_value(structure, "width", height);
1558 gst_structure_set_value(structure, "height", width);
1559 return caps;
1560 }
1561
gst_vdec_caps_fix_sink_caps(GstVdecBase * self)1562 static gboolean gst_vdec_caps_fix_sink_caps(GstVdecBase *self)
1563 {
1564 GstCaps *templ_caps = gst_pad_get_pad_template_caps(GST_VIDEO_DECODER_SRC_PAD(self));
1565 g_return_val_if_fail(templ_caps != nullptr, FALSE);
1566 ON_SCOPE_EXIT(0) { gst_caps_unref(templ_caps); };
1567 GstCaps *pool_caps = gst_caps_intersect(self->sink_caps, templ_caps);
1568 gboolean is_caps_valid = TRUE;
1569 if (gst_caps_is_empty(pool_caps)) {
1570 is_caps_valid = FALSE;
1571 if (self->is_support_swap_width_height) {
1572 templ_caps = gst_vdec_swap_width_height(templ_caps);
1573 gst_caps_unref(pool_caps);
1574 pool_caps = gst_caps_intersect(self->sink_caps, templ_caps);
1575 if (!gst_caps_is_empty(pool_caps)) {
1576 is_caps_valid = TRUE;
1577 }
1578 }
1579 }
1580 if (!is_caps_valid) {
1581 gst_caps_unref(pool_caps);
1582 return FALSE;
1583 }
1584 pool_caps = gst_caps_fixate(pool_caps);
1585 g_return_val_if_fail(pool_caps != nullptr, FALSE);
1586 gst_caps_unref(self->sink_caps);
1587 self->sink_caps = pool_caps;
1588
1589 GstStructure *structure = gst_caps_get_structure(pool_caps, 0);
1590 const gchar *format_str = gst_structure_get_string(structure, "format");
1591 g_return_val_if_fail(format_str != nullptr, FALSE);
1592
1593 GstVideoFormat format = gst_video_format_from_string(format_str);
1594 g_return_val_if_fail(format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
1595
1596 self->format = format;
1597 gint ret = self->decoder->SetParameter(GST_VIDEO_FORMAT, GST_ELEMENT(self));
1598 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "setparameter", TRUE), FALSE);
1599 return TRUE;
1600 }
1601
gst_vdec_base_pre_init_surface(GstVdecBase * self)1602 static gboolean gst_vdec_base_pre_init_surface(GstVdecBase *self)
1603 {
1604 GST_DEBUG_OBJECT(self, "surface pre init");
1605 g_return_val_if_fail(self != nullptr, FALSE);
1606 g_return_val_if_fail(self->decoder != nullptr, FALSE);
1607 g_return_val_if_fail(self->sink_caps != nullptr, FALSE);
1608 g_return_val_if_fail(self->outpool != nullptr, FALSE);
1609
1610 guint size = 0;
1611 GstStructure *structure = gst_caps_get_structure(self->sink_caps, 0);
1612 g_return_val_if_fail(structure != nullptr, FALSE);
1613 gst_structure_set(structure, "width", G_TYPE_INT, self->width, nullptr);
1614 gst_structure_set(structure, "height", G_TYPE_INT, self->height, nullptr);
1615
1616 self->memtype = GST_MEMTYPE_SURFACE;
1617 gint ret = self->decoder->SetParameter(GST_VIDEO_SURFACE_INIT, GST_ELEMENT(self));
1618 g_return_val_if_fail(gst_codec_return_is_ok(self, ret, "GST_VIDEO_SURFACE_INIT", TRUE), FALSE);
1619
1620 if (!gst_vdec_caps_fix_sink_caps(self)) {
1621 g_signal_emit(self, signals[SIGNAL_CAPS_FIX_ERROR], 0, nullptr);
1622 return FALSE;
1623 }
1624 gst_vdec_base_update_out_port_def(self, &size);
1625 gst_vdec_base_update_out_pool(self, &self->outpool, self->sink_caps, size);
1626 gst_buffer_pool_set_active(self->outpool, TRUE);
1627 self->pre_init_pool = TRUE;
1628 return TRUE;
1629 }
1630
gst_vdec_base_set_format(GstVideoDecoder * decoder,GstVideoCodecState * state)1631 static gboolean gst_vdec_base_set_format(GstVideoDecoder *decoder, GstVideoCodecState *state)
1632 {
1633 GstVdecBase *self = GST_VDEC_BASE(decoder);
1634 g_return_val_if_fail(self != nullptr, FALSE);
1635 if (self->prepared || self->has_set_format) {
1636 return TRUE;
1637 }
1638 g_return_val_if_fail(self->decoder != nullptr, FALSE);
1639 g_return_val_if_fail(state != nullptr, FALSE);
1640 GstVideoInfo *info = &state->info;
1641 g_return_val_if_fail(info != nullptr, FALSE);
1642 gboolean is_format_change = FALSE;
1643 gint ret = self->decoder->GetParameter(GST_VIDEO_INPUT_COMMON, GST_ELEMENT(self));
1644 g_return_val_if_fail(ret == GST_CODEC_OK, FALSE);
1645 GST_INFO_OBJECT(self, "Input params is min buffer count %u, buffer count %u, buffer size is %u",
1646 self->input.min_buffer_cnt, self->input.buffer_cnt, self->input.buffer_size);
1647
1648 GST_DEBUG_OBJECT(self, "Setting new caps");
1649
1650 constexpr gfloat epsilon = 1e-6;
1651 is_format_change = is_format_change || self->width != info->width;
1652 is_format_change = is_format_change || self->height != GST_VIDEO_INFO_FIELD_HEIGHT(info);
1653 is_format_change = is_format_change || (info->fps_n != 0 && self->frame_rate < epsilon &&
1654 self->frame_rate > -epsilon);
1655
1656 if (is_format_change && info->width != 0 && GST_VIDEO_INFO_FIELD_HEIGHT(info) != 0) {
1657 self->width = info->width;
1658 self->height = GST_VIDEO_INFO_FIELD_HEIGHT(info);
1659 self->real_stride = self->width;
1660 self->real_stride_height = self->height;
1661 self->frame_rate = static_cast<gfloat>(info->fps_n) / static_cast<gfloat>(info->fps_d);
1662 gst_vdec_base_post_resolution_changed_message(self, TRUE);
1663 GST_DEBUG_OBJECT(self, "width: %d, height: %d, frame_rate: %.3f", self->width, self->height, self->frame_rate);
1664 }
1665
1666 GST_DEBUG_OBJECT(self, "Setting input port definition");
1667 ret = self->decoder->SetParameter(GST_VIDEO_INPUT_COMMON, GST_ELEMENT(self));
1668 g_return_val_if_fail(ret == GST_CODEC_OK, FALSE);
1669 ret = self->decoder->GetParameter(GST_VIDEO_INPUT_COMMON, GST_ELEMENT(self));
1670 g_return_val_if_fail(ret == GST_CODEC_OK, FALSE);
1671 self->input_state = gst_video_codec_state_ref(state);
1672 if (self->performance_mode) {
1673 g_return_val_if_fail(gst_vdec_base_pre_init_surface(self) != FALSE, FALSE);
1674 }
1675 self->has_set_format = TRUE;
1676 if (state->codec_data != nullptr && state->codec_data != self->codec_data) {
1677 gst_buffer_unref(self->codec_data);
1678 self->codec_data = gst_buffer_ref(state->codec_data);
1679 self->codec_data_update = TRUE;
1680 }
1681
1682 return TRUE;
1683 }
1684
gst_vdec_base_finish(GstVideoDecoder * decoder)1685 static GstFlowReturn gst_vdec_base_finish(GstVideoDecoder *decoder)
1686 {
1687 GstVdecBase *self = GST_VDEC_BASE(decoder);
1688 g_return_val_if_fail(self != nullptr && self->decoder != nullptr, GST_FLOW_ERROR);
1689 GST_DEBUG_OBJECT(self, "Finish codec start");
1690 GstPad *pad = GST_VIDEO_DECODER_SRC_PAD(self);
1691 if (gst_pad_get_task_state(pad) != GST_TASK_STARTED) {
1692 GST_DEBUG_OBJECT(self, "vdec not start yet");
1693 return GST_FLOW_OK;
1694 }
1695 GstVdecBaseClass *kclass = GST_VDEC_BASE_GET_CLASS(self);
1696 if (kclass->handle_slice_buffer != nullptr && self->player_scene == true) {
1697 bool ready_push_slice_buffer = false;
1698 GstBuffer *cat_buffer = kclass->handle_slice_buffer(self, nullptr, ready_push_slice_buffer, true);
1699 if (cat_buffer != nullptr && ready_push_slice_buffer == true) {
1700 GST_VIDEO_DECODER_STREAM_UNLOCK(self);
1701 gint codec_ret = GST_CODEC_OK;
1702 if (!gst_vdec_check_ashmem_buffer(cat_buffer) && self->input_need_ashmem) {
1703 codec_ret = gst_vdec_base_push_input_buffer_with_copy(self, cat_buffer, FALSE);
1704 } else {
1705 gst_vdec_base_dump_input_buffer(self, cat_buffer);
1706 codec_ret = self->decoder->PushInputBuffer(cat_buffer);
1707 }
1708 gst_codec_return_is_ok(self, codec_ret, "Finish push buffer failed", FALSE);
1709 gst_buffer_unref(cat_buffer);
1710 }
1711 } else {
1712 GST_VIDEO_DECODER_STREAM_UNLOCK(self);
1713 }
1714
1715 g_mutex_lock(&self->drain_lock);
1716 ON_SCOPE_EXIT(0) {
1717 g_mutex_unlock(&self->drain_lock);
1718 GST_VIDEO_DECODER_STREAM_LOCK(self);
1719 };
1720 self->draining = TRUE;
1721 gint ret = self->decoder->PushInputBuffer(nullptr);
1722 g_return_val_if_fail(ret == GST_CODEC_OK, GST_FLOW_ERROR);
1723 gint64 wait_time = std::min(DRAIN_TIME_OUT_MAX,
1724 std::max(DRAIN_TIME_OUT_MIN, DRAIN_TIME_OUT_BY_FRAMERATE(self->frame_rate)));
1725 gint64 wait_until = g_get_monotonic_time() + wait_time;
1726 GST_DEBUG_OBJECT(self, "Waiting until codec is drained, wait %" G_GINT64_FORMAT " us", wait_time);
1727 if (!g_cond_wait_until(&self->drain_cond, &self->drain_lock, wait_until)) {
1728 GST_ERROR_OBJECT(self, "Drain timed out");
1729 } else {
1730 GST_DEBUG_OBJECT(self, "finish hdi end");
1731 }
1732
1733 return GST_FLOW_OK;
1734 }
1735
gst_vdec_base_drain(GstVideoDecoder * decoder)1736 static GstFlowReturn gst_vdec_base_drain(GstVideoDecoder *decoder)
1737 {
1738 GST_DEBUG_OBJECT(decoder, "Draining codec start");
1739 g_return_val_if_fail(decoder != nullptr, GST_FLOW_ERROR);
1740 GstFlowReturn ret = gst_vdec_base_finish(decoder);
1741 gst_vdec_base_flush(decoder);
1742 GST_DEBUG_OBJECT(decoder, "Draining codec end");
1743 return ret;
1744 }
1745
gst_vdec_base_event_flush_start(GstVideoDecoder * decoder)1746 static void gst_vdec_base_event_flush_start(GstVideoDecoder *decoder)
1747 {
1748 GstVdecBase *self = GST_VDEC_BASE(decoder);
1749 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: flush start");
1750 if (!self->prepared) {
1751 gst_vdec_base_set_flushing(self, TRUE);
1752 return;
1753 }
1754 g_mutex_lock(&self->format_changed_lock);
1755 GST_VIDEO_DECODER_STREAM_LOCK(self);
1756 GstVdecBaseClass *kclass = GST_VDEC_BASE_GET_CLASS(self);
1757 if (kclass->flush_cache_slice_buffer != nullptr) {
1758 (void)kclass->flush_cache_slice_buffer(self);
1759 }
1760 gst_vdec_base_set_flushing(self, TRUE);
1761 self->decoder_start = FALSE;
1762 self->idrframe = FALSE;
1763 if (self->decoder != nullptr) {
1764 (void)self->decoder->Flush(GST_CODEC_ALL);
1765 }
1766 GST_VIDEO_DECODER_STREAM_UNLOCK(self);
1767 g_mutex_unlock(&self->format_changed_lock);
1768 }
1769
gst_vdec_base_event_flush_stop(GstVideoDecoder * decoder,GstEvent * event)1770 static gboolean gst_vdec_base_event_flush_stop(GstVideoDecoder *decoder, GstEvent *event)
1771 {
1772 gboolean ret = TRUE;
1773 GstVdecBase *self = GST_VDEC_BASE(decoder);
1774 self->flushing_stoping = TRUE;
1775 ret = GST_VIDEO_DECODER_CLASS(parent_class)->sink_event(decoder, event);
1776 {
1777 g_mutex_lock(&self->lock);
1778 std::list<GstClockTime> empty;
1779 self->pts_list.swap(empty);
1780 self->last_pts = GST_CLOCK_TIME_NONE;
1781 g_mutex_unlock(&self->lock);
1782 }
1783 gst_vdec_base_set_flushing(self, FALSE);
1784 self->flushing_stoping = FALSE;
1785 GST_WARNING_OBJECT(self, "KPI-TRACE-VDEC: flush stop");
1786 return ret;
1787 }
1788
gst_vdec_base_event(GstVideoDecoder * decoder,GstEvent * event)1789 static gboolean gst_vdec_base_event(GstVideoDecoder *decoder, GstEvent *event)
1790 {
1791 g_return_val_if_fail(decoder != nullptr, FALSE);
1792 g_return_val_if_fail(event != nullptr, FALSE);
1793 g_return_val_if_fail(GST_VIDEO_DECODER_CLASS(parent_class) != nullptr, FALSE);
1794 GstVdecBase *self = GST_VDEC_BASE(decoder);
1795 GST_DEBUG_OBJECT(self, "Gst_vdec_base_sink_event, type=%s", GST_EVENT_TYPE_NAME(event));
1796
1797 switch (GST_EVENT_TYPE(event)) {
1798 case GST_EVENT_FLUSH_START:
1799 gst_vdec_base_event_flush_start(decoder);
1800 break;
1801 case GST_EVENT_FLUSH_STOP:
1802 return gst_vdec_base_event_flush_stop(decoder, event);
1803 case GST_EVENT_EOS:
1804 self->is_eos_state = TRUE;
1805 break;
1806 default:
1807 break;
1808 }
1809
1810 return GST_VIDEO_DECODER_CLASS(parent_class)->sink_event(decoder, event);
1811 }
1812
gst_vdec_base_new_out_shmem_pool(GstVdecBase * self,GstCaps * outcaps,gint size)1813 static GstBufferPool *gst_vdec_base_new_out_shmem_pool(GstVdecBase *self, GstCaps *outcaps, gint size)
1814 {
1815 g_return_val_if_fail(outcaps != nullptr, nullptr);
1816 GstShMemPool *pool = gst_shmem_pool_new();
1817 g_return_val_if_fail(pool != nullptr, nullptr);
1818 ON_SCOPE_EXIT(0) { gst_object_unref(pool); };
1819 g_return_val_if_fail(self->output.allocator != nullptr, nullptr);
1820
1821 self->output.av_shmem_pool = std::make_shared<OHOS::Media::AVSharedMemoryPool>("vdec_out");
1822 (void)gst_shmem_pool_set_avshmempool(pool, self->output.av_shmem_pool);
1823 (void)gst_shmem_allocator_set_pool(self->output.allocator, self->output.av_shmem_pool);
1824 GstStructure *config = gst_buffer_pool_get_config(GST_BUFFER_POOL_CAST(pool));
1825 g_return_val_if_fail(config != nullptr, nullptr);
1826 gst_buffer_pool_config_set_allocator(config, GST_ALLOCATOR_CAST(self->output.allocator),
1827 &self->output.allocParams);
1828 gst_buffer_pool_config_set_params(config, outcaps, size, self->out_buffer_cnt, self->out_buffer_cnt);
1829 g_return_val_if_fail(gst_buffer_pool_set_config(GST_BUFFER_POOL_CAST(pool), config), nullptr);
1830 CANCEL_SCOPE_EXIT_GUARD(0);
1831 return GST_BUFFER_POOL(pool);
1832 }
1833
gst_vdec_base_new_in_shmem_pool(GstVdecBase * self,GstCaps * outcaps,gint size,guint min_buffer_cnt,guint max_buffer_cnt)1834 static GstBufferPool *gst_vdec_base_new_in_shmem_pool(GstVdecBase *self, GstCaps *outcaps, gint size,
1835 guint min_buffer_cnt, guint max_buffer_cnt)
1836 {
1837 g_return_val_if_fail(outcaps != nullptr, nullptr);
1838 GstShMemPool *pool = gst_shmem_pool_new();
1839 g_return_val_if_fail(pool != nullptr, nullptr);
1840 ON_SCOPE_EXIT(0) { gst_object_unref(pool); };
1841 g_return_val_if_fail(self->input.allocator != nullptr, nullptr);
1842
1843 self->input.av_shmem_pool = std::make_shared<OHOS::Media::AVSharedMemoryPool>("vdec_in");
1844 (void)gst_shmem_pool_set_avshmempool(pool, self->input.av_shmem_pool);
1845 (void)gst_shmem_allocator_set_pool(self->input.allocator, self->input.av_shmem_pool);
1846 GstStructure *config = gst_buffer_pool_get_config(GST_BUFFER_POOL_CAST(pool));
1847 g_return_val_if_fail(config != nullptr, nullptr);
1848 gst_buffer_pool_config_set_allocator(config, GST_ALLOCATOR_CAST(self->input.allocator), &self->input.allocParams);
1849 gst_buffer_pool_config_set_params(config, outcaps, size, min_buffer_cnt, max_buffer_cnt);
1850 g_return_val_if_fail(gst_buffer_pool_set_config(GST_BUFFER_POOL_CAST(pool), config), nullptr);
1851 CANCEL_SCOPE_EXIT_GUARD(0);
1852 return GST_BUFFER_POOL(pool);
1853 }
1854
gst_vdec_base_update_out_pool(GstVdecBase * self,GstBufferPool ** pool,GstCaps * outcaps,gint size)1855 static void gst_vdec_base_update_out_pool(GstVdecBase *self, GstBufferPool **pool, GstCaps *outcaps,
1856 gint size)
1857 {
1858 g_return_if_fail(self != nullptr);
1859 g_return_if_fail(self->decoder != nullptr);
1860 g_return_if_fail(*pool != nullptr);
1861 GST_INFO_OBJECT(self, "vdec memType %d", self->memtype);
1862 ON_SCOPE_EXIT(0) { gst_object_unref(*pool); *pool = nullptr; };
1863 GstStructure *config = gst_buffer_pool_get_config(*pool);
1864 g_return_if_fail(config != nullptr);
1865 gst_buffer_pool_config_set_params(config, outcaps, size, self->out_buffer_cnt, self->out_buffer_cnt);
1866 if (self->memtype == GST_MEMTYPE_SURFACE) {
1867 gst_structure_set(config, "usage", G_TYPE_UINT64, self->usage, nullptr);
1868 self->decoder->SetOutputPool(*pool);
1869 }
1870 g_return_if_fail(gst_buffer_pool_set_config(*pool, config));
1871 CANCEL_SCOPE_EXIT_GUARD(0);
1872 }
1873
gst_vdec_base_check_mem_type(GstVdecBase * self,GstQuery * query)1874 static gboolean gst_vdec_base_check_mem_type(GstVdecBase *self, GstQuery *query)
1875 {
1876 guint index = 0;
1877 const GstStructure *buffer_type_struct = nullptr;
1878 if (gst_query_find_allocation_meta(query, GST_BUFFER_TYPE_META_API_TYPE, &index)) {
1879 (void)gst_query_parse_nth_allocation_meta(query, index, &buffer_type_struct);
1880 (void)get_memtype(self, buffer_type_struct);
1881 } else {
1882 GST_INFO_OBJECT(self, "No meta api");
1883 return FALSE;
1884 }
1885 return TRUE;
1886 }
1887
gst_vdec_base_decide_allocation_with_pre_init_pool(GstVdecBase * self,GstQuery * query)1888 static gboolean gst_vdec_base_decide_allocation_with_pre_init_pool(GstVdecBase *self, GstQuery *query)
1889 {
1890 g_return_val_if_fail(self != nullptr && query != nullptr, FALSE);
1891 GST_DEBUG_OBJECT(self, "Performance mode");
1892 guint pool_num = gst_query_get_n_allocation_pools(query);
1893 GstBufferPool *pool = self->outpool;
1894 guint size = self->output.buffer_size;
1895 if (pool_num > 0) {
1896 gst_query_set_nth_allocation_pool(query, 0, pool, size, self->output.buffer_cnt, self->output.buffer_cnt);
1897 } else {
1898 gst_query_add_allocation_pool(query, pool, size, self->output.buffer_cnt, self->output.buffer_cnt);
1899 }
1900 return TRUE;
1901 }
1902
gst_vdec_base_decide_allocation(GstVideoDecoder * decoder,GstQuery * query)1903 static gboolean gst_vdec_base_decide_allocation(GstVideoDecoder *decoder, GstQuery *query)
1904 {
1905 g_return_val_if_fail(decoder != nullptr && query != nullptr, FALSE);
1906 GstVdecBase *self = GST_VDEC_BASE(decoder);
1907 if (self->performance_mode && self->pre_init_pool) {
1908 self->pre_init_pool = FALSE;
1909 return gst_vdec_base_decide_allocation_with_pre_init_pool(self, query);
1910 }
1911 GstCaps *outcaps = nullptr;
1912 GstVideoInfo vinfo;
1913 GstBufferPool *pool = nullptr;
1914 guint size = 0;
1915 guint min_buf = 0;
1916 guint max_buf = 0;
1917 gst_query_parse_allocation(query, &outcaps, nullptr);
1918 gst_video_info_init(&vinfo);
1919 if (outcaps != nullptr) {
1920 gst_video_info_from_caps(&vinfo, outcaps);
1921 }
1922 gboolean update_pool = FALSE;
1923 guint pool_num = gst_query_get_n_allocation_pools(query);
1924 if (pool_num > 0) {
1925 gst_query_parse_nth_allocation_pool(query, 0, &pool, &size, &min_buf, &max_buf);
1926 if (gst_vdec_base_check_mem_type(self, query) != TRUE) {
1927 gst_object_unref(pool);
1928 pool = nullptr;
1929 }
1930 update_pool = TRUE;
1931 }
1932 size = vinfo.size;
1933 self->out_buffer_max_cnt = max_buf == 0 ? DEFAULT_MAX_QUEUE_SIZE : max_buf;
1934 g_return_val_if_fail(gst_vdec_base_update_out_port_def(self, &size), FALSE);
1935 if (pool == nullptr) {
1936 pool = gst_vdec_base_new_out_shmem_pool(self, outcaps, size);
1937 } else {
1938 gst_vdec_base_update_out_pool(self, &pool, outcaps, size);
1939 }
1940 g_return_val_if_fail(pool != nullptr, FALSE);
1941 if (update_pool) {
1942 gst_query_set_nth_allocation_pool(query, 0, pool, size, self->output.buffer_cnt, self->output.buffer_cnt);
1943 } else {
1944 gst_query_add_allocation_pool(query, pool, size, self->output.buffer_cnt, self->output.buffer_cnt);
1945 }
1946 GST_DEBUG_OBJECT(decoder, "Pool ref %u", (reinterpret_cast<GObject*>(pool)->ref_count));
1947 gst_object_unref(self->outpool);
1948 self->outpool = pool;
1949 return TRUE;
1950 }
1951
gst_vdec_base_check_allocate_input(GstVdecBase * self)1952 static gboolean gst_vdec_base_check_allocate_input(GstVdecBase *self)
1953 {
1954 MediaTrace trace("VdecBase::AllocateInputBuffer");
1955 g_return_val_if_fail(self != nullptr, FALSE);
1956 if (self->inpool == nullptr) {
1957 mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
1958 mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
1959 self->inpool = gst_vdec_base_new_in_shmem_pool(self, self->input_state->caps, self->input.buffer_size,
1960 self->input.buffer_cnt, self->input.buffer_cnt);
1961 gst_buffer_pool_set_active(self->inpool, TRUE);
1962 g_return_val_if_fail(self->inpool != nullptr, FALSE);
1963 g_return_val_if_fail(gst_vdec_base_allocate_in_buffers(self), FALSE);
1964 }
1965 return TRUE;
1966 }
1967
gst_vdec_base_propose_allocation(GstVideoDecoder * decoder,GstQuery * query)1968 static gboolean gst_vdec_base_propose_allocation(GstVideoDecoder *decoder, GstQuery *query)
1969 {
1970 g_return_val_if_fail(decoder != nullptr, FALSE);
1971 g_return_val_if_fail(query != nullptr, FALSE);
1972 GstVdecBase *self = GST_VDEC_BASE(decoder);
1973 GstCaps *incaps = nullptr;
1974 GstBufferPool *pool = nullptr;
1975 guint size = 0;
1976 gst_query_parse_allocation(query, &incaps, nullptr);
1977 guint pool_num = gst_query_get_n_allocation_pools(query);
1978 size = self->input.buffer_size;
1979 pool = gst_vdec_base_new_in_shmem_pool(self, incaps, size, self->input.buffer_cnt, self->input.buffer_cnt);
1980 g_return_val_if_fail(pool != nullptr, FALSE);
1981 if (pool_num > 0) {
1982 gst_query_set_nth_allocation_pool(query, 0, pool, size, self->input.buffer_cnt, self->input.buffer_cnt);
1983 } else {
1984 gst_query_add_allocation_pool(query, pool, size, self->input.buffer_cnt, self->input.buffer_cnt);
1985 }
1986 gst_vdec_reset_inpool(self);
1987 self->inpool = pool;
1988 GST_DEBUG_OBJECT(decoder, "pool ref_count %u", ((GObject *)pool)->ref_count);
1989 gst_buffer_pool_set_active(pool, TRUE);
1990 g_return_val_if_fail(gst_vdec_base_allocate_in_buffers(self), FALSE);
1991 gst_query_add_allocation_meta(query, GST_BUFFER_TYPE_META_API_TYPE, nullptr);
1992 return TRUE;
1993 }