• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params, 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, &params);
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 }