1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2018 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun * Author: Randy Li <randy.li@rock-chips.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2021 Rockchip Electronics Co., Ltd
6*4882a593Smuzhiyun * Author: Jeffy Chen <jeffy.chen@rock-chips.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This library is free software; you can redistribute it and/or
9*4882a593Smuzhiyun * modify it under the terms of the GNU Library General Public
10*4882a593Smuzhiyun * License as published by the Free Software Foundation; either
11*4882a593Smuzhiyun * version 2 of the License, or (at your option) any later version.
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * This library is distributed in the hope that it will be useful,
14*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16*4882a593Smuzhiyun * Library General Public License for more details.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * You should have received a copy of the GNU Library General Public
19*4882a593Smuzhiyun * License along with this library; if not, write to the
20*4882a593Smuzhiyun * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21*4882a593Smuzhiyun * Boston, MA 02110-1301, USA.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #ifdef HAVE_CONFIG_H
26*4882a593Smuzhiyun #include "config.h"
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include "gstmppallocator.h"
30*4882a593Smuzhiyun #include "gstmppdec.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define GST_CAT_DEFAULT mpp_dec_debug
33*4882a593Smuzhiyun GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define parent_class gst_mpp_dec_parent_class
36*4882a593Smuzhiyun G_DEFINE_ABSTRACT_TYPE (GstMppDec, gst_mpp_dec, GST_TYPE_VIDEO_DECODER);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define GST_MPP_DEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
39*4882a593Smuzhiyun GST_TYPE_MPP_DEC, GstMppDecClass))
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define MPP_OUTPUT_TIMEOUT_MS 200 /* Block timeout for MPP output queue */
42*4882a593Smuzhiyun #define MPP_INPUT_TIMEOUT_MS 2000 /* Block timeout for MPP input queue */
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #define MPP_TO_GST_PTS(pts) ((pts) * GST_MSECOND)
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define GST_MPP_DEC_TASK_STARTED(decoder) \
47*4882a593Smuzhiyun (gst_pad_get_task_state ((decoder)->srcpad) == GST_TASK_STARTED)
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun #define GST_MPP_DEC_MUTEX(decoder) (&GST_MPP_DEC (decoder)->mutex)
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define GST_MPP_DEC_LOCK(decoder) \
52*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder); \
53*4882a593Smuzhiyun g_mutex_lock (GST_MPP_DEC_MUTEX (decoder)); \
54*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define GST_MPP_DEC_UNLOCK(decoder) \
57*4882a593Smuzhiyun g_mutex_unlock (GST_MPP_DEC_MUTEX (decoder));
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define DEFAULT_PROP_ROTATION 0
60*4882a593Smuzhiyun #define DEFAULT_PROP_WIDTH 0 /* Original */
61*4882a593Smuzhiyun #define DEFAULT_PROP_HEIGHT 0 /* Original */
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static gboolean DEFAULT_PROP_IGNORE_ERROR = TRUE;
64*4882a593Smuzhiyun static gboolean DEFAULT_PROP_FAST_MODE = TRUE;
65*4882a593Smuzhiyun static gboolean DEFAULT_PROP_DMA_FEATURE = FALSE;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun enum
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun PROP_0,
70*4882a593Smuzhiyun PROP_ROTATION,
71*4882a593Smuzhiyun PROP_WIDTH,
72*4882a593Smuzhiyun PROP_HEIGHT,
73*4882a593Smuzhiyun PROP_CROP_RECTANGLE,
74*4882a593Smuzhiyun PROP_IGNORE_ERROR,
75*4882a593Smuzhiyun PROP_FAST_MODE,
76*4882a593Smuzhiyun PROP_DMA_FEATURE,
77*4882a593Smuzhiyun PROP_LAST,
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun static void
gst_mpp_dec_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)81*4882a593Smuzhiyun gst_mpp_dec_set_property (GObject * object,
82*4882a593Smuzhiyun guint prop_id, const GValue * value, GParamSpec * pspec)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun GstVideoDecoder *decoder = GST_VIDEO_DECODER (object);
85*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun switch (prop_id) {
88*4882a593Smuzhiyun case PROP_ROTATION:{
89*4882a593Smuzhiyun if (self->input_state)
90*4882a593Smuzhiyun GST_WARNING_OBJECT (decoder, "unable to change rotation");
91*4882a593Smuzhiyun else
92*4882a593Smuzhiyun self->rotation = g_value_get_enum (value);
93*4882a593Smuzhiyun break;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun case PROP_WIDTH:{
97*4882a593Smuzhiyun if (self->input_state)
98*4882a593Smuzhiyun GST_WARNING_OBJECT (decoder, "unable to change width");
99*4882a593Smuzhiyun else
100*4882a593Smuzhiyun self->width = g_value_get_uint (value);
101*4882a593Smuzhiyun break;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun case PROP_HEIGHT:{
104*4882a593Smuzhiyun if (self->input_state)
105*4882a593Smuzhiyun GST_WARNING_OBJECT (decoder, "unable to change height");
106*4882a593Smuzhiyun else
107*4882a593Smuzhiyun self->height = g_value_get_uint (value);
108*4882a593Smuzhiyun break;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun case PROP_CROP_RECTANGLE:{
111*4882a593Smuzhiyun const GValue *v;
112*4882a593Smuzhiyun gint rect[4], i;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun if (gst_value_array_get_size (value) != 4) {
115*4882a593Smuzhiyun GST_WARNING_OBJECT (decoder, "too less values for crop-rectangle");
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
120*4882a593Smuzhiyun v = gst_value_array_get_value (value, i);
121*4882a593Smuzhiyun if (!G_VALUE_HOLDS_INT (v)) {
122*4882a593Smuzhiyun GST_WARNING_OBJECT (decoder, "crop-rectangle needs int values");
123*4882a593Smuzhiyun break;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun rect[i] = g_value_get_int (v);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun self->crop_x = rect[0];
130*4882a593Smuzhiyun self->crop_y = rect[1];
131*4882a593Smuzhiyun self->crop_w = rect[2];
132*4882a593Smuzhiyun self->crop_h = rect[3];
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun break;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun case PROP_IGNORE_ERROR:{
137*4882a593Smuzhiyun if (self->input_state)
138*4882a593Smuzhiyun GST_WARNING_OBJECT (decoder, "unable to change error mode");
139*4882a593Smuzhiyun else
140*4882a593Smuzhiyun self->ignore_error = g_value_get_boolean (value);
141*4882a593Smuzhiyun break;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun case PROP_FAST_MODE:{
144*4882a593Smuzhiyun if (self->input_state)
145*4882a593Smuzhiyun GST_WARNING_OBJECT (decoder, "unable to change fast mode");
146*4882a593Smuzhiyun else
147*4882a593Smuzhiyun self->fast_mode = g_value_get_boolean (value);
148*4882a593Smuzhiyun break;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun case PROP_DMA_FEATURE:{
151*4882a593Smuzhiyun self->dma_feature = g_value_get_boolean (value);
152*4882a593Smuzhiyun break;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun default:
155*4882a593Smuzhiyun G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
156*4882a593Smuzhiyun break;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun static void
gst_mpp_dec_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)161*4882a593Smuzhiyun gst_mpp_dec_get_property (GObject * object,
162*4882a593Smuzhiyun guint prop_id, GValue * value, GParamSpec * pspec)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun GstVideoDecoder *decoder = GST_VIDEO_DECODER (object);
165*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun switch (prop_id) {
168*4882a593Smuzhiyun case PROP_ROTATION:
169*4882a593Smuzhiyun g_value_set_enum (value, self->rotation);
170*4882a593Smuzhiyun break;
171*4882a593Smuzhiyun case PROP_WIDTH:
172*4882a593Smuzhiyun g_value_set_uint (value, self->width);
173*4882a593Smuzhiyun break;
174*4882a593Smuzhiyun case PROP_HEIGHT:
175*4882a593Smuzhiyun g_value_set_uint (value, self->height);
176*4882a593Smuzhiyun break;
177*4882a593Smuzhiyun case PROP_IGNORE_ERROR:
178*4882a593Smuzhiyun g_value_set_boolean (value, self->ignore_error);
179*4882a593Smuzhiyun break;
180*4882a593Smuzhiyun case PROP_FAST_MODE:
181*4882a593Smuzhiyun g_value_set_boolean (value, self->fast_mode);
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun case PROP_DMA_FEATURE:
184*4882a593Smuzhiyun g_value_set_boolean (value, self->dma_feature);
185*4882a593Smuzhiyun break;
186*4882a593Smuzhiyun default:
187*4882a593Smuzhiyun G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
188*4882a593Smuzhiyun return;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun static void
gst_mpp_dec_stop_task(GstVideoDecoder * decoder,gboolean drain)193*4882a593Smuzhiyun gst_mpp_dec_stop_task (GstVideoDecoder * decoder, gboolean drain)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun GstMppDecClass *klass = GST_MPP_DEC_GET_CLASS (decoder);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (!GST_MPP_DEC_TASK_STARTED (decoder))
198*4882a593Smuzhiyun return;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun GST_DEBUG_OBJECT (decoder, "stopping decoding thread");
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
203*4882a593Smuzhiyun if (klass->shutdown && klass->shutdown (decoder, drain)) {
204*4882a593Smuzhiyun /* Wait for task thread to pause */
205*4882a593Smuzhiyun GstTask *task = decoder->srcpad->task;
206*4882a593Smuzhiyun if (task) {
207*4882a593Smuzhiyun GST_OBJECT_LOCK (task);
208*4882a593Smuzhiyun while (GST_TASK_STATE (task) == GST_TASK_STARTED)
209*4882a593Smuzhiyun GST_TASK_WAIT (task);
210*4882a593Smuzhiyun GST_OBJECT_UNLOCK (task);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun gst_pad_stop_task (decoder->srcpad);
215*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun static void
gst_mpp_dec_reset(GstVideoDecoder * decoder,gboolean drain,gboolean final)219*4882a593Smuzhiyun gst_mpp_dec_reset (GstVideoDecoder * decoder, gboolean drain, gboolean final)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun GST_MPP_DEC_LOCK (decoder);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "resetting");
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun self->flushing = TRUE;
228*4882a593Smuzhiyun self->draining = drain;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun gst_mpp_dec_stop_task (decoder, drain);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun self->flushing = final;
233*4882a593Smuzhiyun self->draining = FALSE;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun self->mpi->reset (self->mpp_ctx);
236*4882a593Smuzhiyun self->task_ret = GST_FLOW_OK;
237*4882a593Smuzhiyun self->decoded_frames = 0;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun GST_MPP_DEC_UNLOCK (decoder);
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun static gboolean
gst_mpp_dec_start(GstVideoDecoder * decoder)243*4882a593Smuzhiyun gst_mpp_dec_start (GstVideoDecoder * decoder)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "starting");
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun gst_video_info_init (&self->info);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun if (mpp_create (&self->mpp_ctx, &self->mpi))
252*4882a593Smuzhiyun return FALSE;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun self->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
255*4882a593Smuzhiyun self->mpp_type = MPP_VIDEO_CodingUnused;
256*4882a593Smuzhiyun self->seen_valid_pts = FALSE;
257*4882a593Smuzhiyun self->convert = FALSE;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun self->input_state = NULL;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun self->task_ret = GST_FLOW_OK;
262*4882a593Smuzhiyun self->decoded_frames = 0;
263*4882a593Smuzhiyun self->flushing = FALSE;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* Prefer using MPP PTS */
266*4882a593Smuzhiyun self->use_mpp_pts = TRUE;
267*4882a593Smuzhiyun self->mpp_delta_pts = 0;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun g_mutex_init (&self->mutex);
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "started");
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun return TRUE;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun static void
gst_mpp_dec_clear_allocator(GstVideoDecoder * decoder)277*4882a593Smuzhiyun gst_mpp_dec_clear_allocator (GstVideoDecoder * decoder)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
280*4882a593Smuzhiyun if (self->allocator) {
281*4882a593Smuzhiyun gst_mpp_allocator_set_cacheable (self->allocator, FALSE);
282*4882a593Smuzhiyun gst_object_unref (self->allocator);
283*4882a593Smuzhiyun self->allocator = NULL;
284*4882a593Smuzhiyun self->mpi->control (self->mpp_ctx, MPP_DEC_SET_EXT_BUF_GROUP, NULL);
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static gboolean
gst_mpp_dec_stop(GstVideoDecoder * decoder)289*4882a593Smuzhiyun gst_mpp_dec_stop (GstVideoDecoder * decoder)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "stopping");
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
296*4882a593Smuzhiyun gst_mpp_dec_reset (decoder, FALSE, TRUE);
297*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun g_mutex_clear (&self->mutex);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun mpp_destroy (self->mpp_ctx);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun if (self->input_state) {
304*4882a593Smuzhiyun gst_video_codec_state_unref (self->input_state);
305*4882a593Smuzhiyun self->input_state = NULL;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun gst_mpp_dec_clear_allocator (decoder);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "stopped");
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun return TRUE;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun static gboolean
gst_mpp_dec_flush(GstVideoDecoder * decoder)316*4882a593Smuzhiyun gst_mpp_dec_flush (GstVideoDecoder * decoder)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun GST_DEBUG_OBJECT (decoder, "flushing");
319*4882a593Smuzhiyun gst_mpp_dec_reset (decoder, FALSE, FALSE);
320*4882a593Smuzhiyun return TRUE;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun static GstFlowReturn
gst_mpp_dec_drain(GstVideoDecoder * decoder)324*4882a593Smuzhiyun gst_mpp_dec_drain (GstVideoDecoder * decoder)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun GST_DEBUG_OBJECT (decoder, "draining");
327*4882a593Smuzhiyun gst_mpp_dec_reset (decoder, TRUE, FALSE);
328*4882a593Smuzhiyun return GST_FLOW_OK;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun static GstFlowReturn
gst_mpp_dec_finish(GstVideoDecoder * decoder)332*4882a593Smuzhiyun gst_mpp_dec_finish (GstVideoDecoder * decoder)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun GST_DEBUG_OBJECT (decoder, "finishing");
335*4882a593Smuzhiyun gst_mpp_dec_reset (decoder, TRUE, FALSE);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun /* No need to caching buffers after finished */
338*4882a593Smuzhiyun gst_mpp_dec_clear_allocator (decoder);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun return GST_FLOW_OK;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun static gboolean
gst_mpp_dec_set_format(GstVideoDecoder * decoder,GstVideoCodecState * state)344*4882a593Smuzhiyun gst_mpp_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "setting format: %" GST_PTR_FORMAT, state->caps);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /* The MPP m2vd's PTS is buggy */
351*4882a593Smuzhiyun if (self->mpp_type == MPP_VIDEO_CodingMPEG2)
352*4882a593Smuzhiyun self->use_mpp_pts = FALSE;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun if (self->input_state) {
355*4882a593Smuzhiyun if (gst_caps_is_strictly_equal (self->input_state->caps, state->caps))
356*4882a593Smuzhiyun return TRUE;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun gst_mpp_dec_reset (decoder, TRUE, FALSE);
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun /* Clear cached buffers when format info changed */
361*4882a593Smuzhiyun gst_mpp_dec_clear_allocator (decoder);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun gst_video_codec_state_unref (self->input_state);
364*4882a593Smuzhiyun self->input_state = NULL;
365*4882a593Smuzhiyun } else {
366*4882a593Smuzhiyun /* NOTE: MPP fast mode must be applied before mpp_init() */
367*4882a593Smuzhiyun self->mpi->control (self->mpp_ctx, MPP_DEC_SET_PARSER_FAST_MODE,
368*4882a593Smuzhiyun &self->fast_mode);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun if (mpp_init (self->mpp_ctx, MPP_CTX_DEC, self->mpp_type)) {
371*4882a593Smuzhiyun GST_ERROR_OBJECT (self, "failed to init mpp ctx");
372*4882a593Smuzhiyun return FALSE;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun if (self->ignore_error)
377*4882a593Smuzhiyun self->mpi->control (self->mpp_ctx, MPP_DEC_SET_DISABLE_ERROR, NULL);
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun self->input_state = gst_video_codec_state_ref (state);
380*4882a593Smuzhiyun return TRUE;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun static gboolean
gst_mpp_dec_update_video_info(GstVideoDecoder * decoder,GstVideoFormat format,guint width,guint height,gint hstride,gint vstride,guint align,gboolean afbc)384*4882a593Smuzhiyun gst_mpp_dec_update_video_info (GstVideoDecoder * decoder, GstVideoFormat format,
385*4882a593Smuzhiyun guint width, guint height, gint hstride, gint vstride, guint align,
386*4882a593Smuzhiyun gboolean afbc)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
389*4882a593Smuzhiyun GstVideoInfo *info = &self->info;
390*4882a593Smuzhiyun GstVideoCodecState *output_state;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /* Sinks like kmssink require width and height align to 2 */
395*4882a593Smuzhiyun output_state = gst_video_decoder_set_output_state (decoder, format,
396*4882a593Smuzhiyun GST_ROUND_UP_2 (width), GST_ROUND_UP_2 (height), self->input_state);
397*4882a593Smuzhiyun output_state->caps = gst_video_info_to_caps (&output_state->info);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun if (afbc) {
400*4882a593Smuzhiyun if (!self->arm_afbc) {
401*4882a593Smuzhiyun GST_ERROR_OBJECT (self, "AFBC not supported");
402*4882a593Smuzhiyun return FALSE;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun gst_caps_set_simple (output_state->caps,
406*4882a593Smuzhiyun MPP_DEC_FEATURE_ARM_AFBC, G_TYPE_INT, afbc, NULL);
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun GST_VIDEO_INFO_SET_AFBC (&output_state->info);
409*4882a593Smuzhiyun } else {
410*4882a593Smuzhiyun GST_VIDEO_INFO_UNSET_AFBC (&output_state->info);
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun if (self->dma_feature) {
414*4882a593Smuzhiyun GstCaps *tmp_caps = gst_caps_copy (output_state->caps);
415*4882a593Smuzhiyun gst_caps_set_features (tmp_caps, 0,
416*4882a593Smuzhiyun gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_DMABUF, NULL));
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun /* HACK: Expose dmabuf feature when the subset check is hacked */
419*4882a593Smuzhiyun if (gst_caps_is_subset (tmp_caps, output_state->caps))
420*4882a593Smuzhiyun gst_caps_replace (&output_state->caps, tmp_caps);
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun gst_caps_unref (tmp_caps);
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun *info = output_state->info;
426*4882a593Smuzhiyun gst_video_codec_state_unref (output_state);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun if (!gst_video_decoder_negotiate (decoder))
429*4882a593Smuzhiyun return FALSE;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun align = align ? : 2;
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun hstride = hstride ? : GST_MPP_VIDEO_INFO_HSTRIDE (info);
434*4882a593Smuzhiyun hstride = GST_ROUND_UP_N (hstride, align);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun vstride = vstride ? : GST_MPP_VIDEO_INFO_VSTRIDE (info);
437*4882a593Smuzhiyun vstride = GST_ROUND_UP_N (vstride, align);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun return gst_mpp_video_info_align (info, hstride, vstride);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun gboolean
gst_mpp_dec_update_simple_video_info(GstVideoDecoder * decoder,GstVideoFormat format,guint width,guint height,guint align)443*4882a593Smuzhiyun gst_mpp_dec_update_simple_video_info (GstVideoDecoder * decoder,
444*4882a593Smuzhiyun GstVideoFormat format, guint width, guint height, guint align)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun return gst_mpp_dec_update_video_info (decoder, format, width, height, 0, 0,
447*4882a593Smuzhiyun align, FALSE);
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun void
gst_mpp_dec_fixup_video_info(GstVideoDecoder * decoder,GstVideoFormat format,gint width,gint height)451*4882a593Smuzhiyun gst_mpp_dec_fixup_video_info (GstVideoDecoder * decoder, GstVideoFormat format,
452*4882a593Smuzhiyun gint width, gint height)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
455*4882a593Smuzhiyun GstVideoInfo *info = &self->info;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if (self->rotation % 180)
458*4882a593Smuzhiyun SWAP (width, height);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /* Figure out output format */
461*4882a593Smuzhiyun if (self->format != GST_VIDEO_FORMAT_UNKNOWN)
462*4882a593Smuzhiyun /* Use specified format */
463*4882a593Smuzhiyun format = self->format;
464*4882a593Smuzhiyun if (format == GST_VIDEO_FORMAT_UNKNOWN)
465*4882a593Smuzhiyun /* Fallback to NV12 */
466*4882a593Smuzhiyun format = GST_VIDEO_FORMAT_NV12;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun #ifdef HAVE_NV12_10LE40
469*4882a593Smuzhiyun if (format == GST_VIDEO_FORMAT_NV12_10LE40 &&
470*4882a593Smuzhiyun g_getenv ("GST_MPP_DEC_DISABLE_NV12_10"))
471*4882a593Smuzhiyun format = GST_VIDEO_FORMAT_NV12;
472*4882a593Smuzhiyun #endif
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun #ifdef HAVE_NV16_10LE40
475*4882a593Smuzhiyun if (format == GST_VIDEO_FORMAT_NV16_10LE40 &&
476*4882a593Smuzhiyun g_getenv ("GST_MPP_DEC_DISABLE_NV16_10"))
477*4882a593Smuzhiyun format = GST_VIDEO_FORMAT_NV12;
478*4882a593Smuzhiyun #endif
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun gst_mpp_video_info_update_format (info, format,
481*4882a593Smuzhiyun self->width ? : width, self->height ? : height);
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun static GstFlowReturn
gst_mpp_dec_apply_info_change(GstVideoDecoder * decoder,MppFrame mframe)485*4882a593Smuzhiyun gst_mpp_dec_apply_info_change (GstVideoDecoder * decoder, MppFrame mframe)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
488*4882a593Smuzhiyun GstVideoFormat dst_format, src_format;
489*4882a593Smuzhiyun GstVideoInfo *info = &self->info;
490*4882a593Smuzhiyun MppFrameFormat mpp_format;
491*4882a593Smuzhiyun gint width = mpp_frame_get_width (mframe);
492*4882a593Smuzhiyun gint height = mpp_frame_get_height (mframe);
493*4882a593Smuzhiyun gint hstride = mpp_frame_get_hor_stride (mframe);
494*4882a593Smuzhiyun gint vstride = mpp_frame_get_ver_stride (mframe);
495*4882a593Smuzhiyun gint offset_x = mpp_frame_get_offset_x (mframe);
496*4882a593Smuzhiyun gint offset_y = mpp_frame_get_offset_y (mframe);
497*4882a593Smuzhiyun gint dst_width, dst_height;
498*4882a593Smuzhiyun gboolean afbc;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun if (hstride % 2 || vstride % 2)
501*4882a593Smuzhiyun return GST_FLOW_NOT_NEGOTIATED;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun mpp_format = mpp_frame_get_fmt (mframe);
504*4882a593Smuzhiyun afbc = !!MPP_FRAME_FMT_IS_FBC (mpp_format);
505*4882a593Smuzhiyun src_format = gst_mpp_mpp_format_to_gst_format (mpp_format);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun GST_INFO_OBJECT (self, "applying %s%s %dx%d (%dx%d)",
508*4882a593Smuzhiyun gst_mpp_video_format_to_string (src_format), afbc ? "(AFBC)" : "",
509*4882a593Smuzhiyun width, height, hstride, vstride);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /* Figure out final output info */
512*4882a593Smuzhiyun gst_mpp_dec_fixup_video_info (decoder, src_format, width, height);
513*4882a593Smuzhiyun dst_format = GST_VIDEO_INFO_FORMAT (info);
514*4882a593Smuzhiyun dst_width = GST_VIDEO_INFO_WIDTH (info);
515*4882a593Smuzhiyun dst_height = GST_VIDEO_INFO_HEIGHT (info);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if (self->rotation || dst_format != src_format ||
518*4882a593Smuzhiyun dst_width != width || dst_height != height) {
519*4882a593Smuzhiyun if (afbc || offset_x || offset_y) {
520*4882a593Smuzhiyun GST_ERROR_OBJECT (self, "unable to convert with AFBC or offsets (%d, %d)",
521*4882a593Smuzhiyun offset_x, offset_y);
522*4882a593Smuzhiyun return GST_FLOW_NOT_NEGOTIATED;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun /* Conversion required */
526*4882a593Smuzhiyun GST_INFO_OBJECT (self, "convert from %s (%dx%d) to %s (%dx%d)",
527*4882a593Smuzhiyun gst_mpp_video_format_to_string (src_format), width, height,
528*4882a593Smuzhiyun gst_mpp_video_format_to_string (dst_format), dst_width, dst_height);
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun self->convert = TRUE;
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun hstride = 0;
533*4882a593Smuzhiyun vstride = 0;
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (afbc) {
537*4882a593Smuzhiyun /* HACK: MPP would align width to 64 for AFBC */
538*4882a593Smuzhiyun dst_width = GST_ROUND_UP_64 (dst_width);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun /* HACK: MPP might have extra offsets for AFBC */
541*4882a593Smuzhiyun dst_height += offset_y;
542*4882a593Smuzhiyun vstride = dst_height;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun /* HACK: Fake hstride for Rockchip VOP driver */
545*4882a593Smuzhiyun hstride = 0;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if (!gst_mpp_dec_update_video_info (decoder, dst_format,
549*4882a593Smuzhiyun dst_width, dst_height, hstride, vstride, 0, afbc))
550*4882a593Smuzhiyun return GST_FLOW_NOT_NEGOTIATED;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun return GST_FLOW_OK;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun static GstVideoCodecFrame *
gst_mpp_dec_get_frame(GstVideoDecoder * decoder,GstClockTime pts)556*4882a593Smuzhiyun gst_mpp_dec_get_frame (GstVideoDecoder * decoder, GstClockTime pts)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
559*4882a593Smuzhiyun GstVideoCodecFrame *frame;
560*4882a593Smuzhiyun GList *frames, *l;
561*4882a593Smuzhiyun gboolean is_first_frame = !self->decoded_frames;
562*4882a593Smuzhiyun gint i;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun self->decoded_frames++;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun frames = gst_video_decoder_get_frames (decoder);
567*4882a593Smuzhiyun if (!frames) {
568*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "missing frame");
569*4882a593Smuzhiyun return NULL;
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun /* Choose PTS source when getting the first frame */
573*4882a593Smuzhiyun if (is_first_frame) {
574*4882a593Smuzhiyun frame = frames->data;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun if (self->use_mpp_pts) {
577*4882a593Smuzhiyun if (!GST_CLOCK_TIME_IS_VALID (pts)) {
578*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "MPP is not able to generate pts");
579*4882a593Smuzhiyun self->use_mpp_pts = FALSE;
580*4882a593Smuzhiyun } else {
581*4882a593Smuzhiyun if (GST_CLOCK_TIME_IS_VALID (frame->pts))
582*4882a593Smuzhiyun self->mpp_delta_pts = frame->pts - MPP_TO_GST_PTS (pts);
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun pts = GST_CLOCK_TIME_NONE;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "MPP delta pts=%" GST_TIME_FORMAT,
587*4882a593Smuzhiyun GST_TIME_ARGS (self->mpp_delta_pts));
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun if (self->use_mpp_pts)
592*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "using MPP pts");
593*4882a593Smuzhiyun else
594*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "using original pts");
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "using first frame (#%d)",
597*4882a593Smuzhiyun frame->system_frame_number);
598*4882a593Smuzhiyun goto out;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun if (!pts)
602*4882a593Smuzhiyun pts = GST_CLOCK_TIME_NONE;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun /* Fixup MPP PTS */
605*4882a593Smuzhiyun if (self->use_mpp_pts && GST_CLOCK_TIME_IS_VALID (pts)) {
606*4882a593Smuzhiyun pts = MPP_TO_GST_PTS (pts);
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun /* Apply delta PTS for frame matching */
609*4882a593Smuzhiyun pts += self->mpp_delta_pts;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "receiving pts=%" GST_TIME_FORMAT,
613*4882a593Smuzhiyun GST_TIME_ARGS (pts));
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun if (!self->seen_valid_pts) {
616*4882a593Smuzhiyun /* No frame with valid PTS, choose the oldest one */
617*4882a593Smuzhiyun frame = frames->data;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "using oldest frame (#%d)",
620*4882a593Smuzhiyun frame->system_frame_number);
621*4882a593Smuzhiyun goto out;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun /* MPP outputs frames in display order, so let's find the earliest one */
625*4882a593Smuzhiyun for (frame = NULL, l = frames, i = 0; l != NULL; l = l->next, i++) {
626*4882a593Smuzhiyun GstVideoCodecFrame *f = l->data;
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun if (GST_CLOCK_TIME_IS_VALID (f->pts)) {
629*4882a593Smuzhiyun /* Prefer frame with close PTS */
630*4882a593Smuzhiyun if (abs ((gint) f->pts - (gint) pts) < 3 * GST_MSECOND) {
631*4882a593Smuzhiyun frame = f;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "using matched frame (#%d)",
634*4882a593Smuzhiyun frame->system_frame_number);
635*4882a593Smuzhiyun goto out;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun /* Filter out future frames */
639*4882a593Smuzhiyun if (GST_CLOCK_TIME_IS_VALID (pts) && f->pts > pts)
640*4882a593Smuzhiyun continue;
641*4882a593Smuzhiyun } else if (self->interlace_mode == GST_VIDEO_INTERLACE_MODE_MIXED) {
642*4882a593Smuzhiyun /* Consider frames with invalid PTS are decode-only when deinterlaced */
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun /* Delay discarding frames for some broken videos */
645*4882a593Smuzhiyun if (i >= 16) {
646*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "discarding decode-only frame (#%d)",
647*4882a593Smuzhiyun f->system_frame_number);
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun gst_video_codec_frame_ref (f);
650*4882a593Smuzhiyun gst_video_decoder_release_frame (decoder, f);
651*4882a593Smuzhiyun continue;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun /* Find the frame with earliest PTS (including invalid PTS) */
656*4882a593Smuzhiyun if (!frame || frame->pts > f->pts)
657*4882a593Smuzhiyun frame = f;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun if (frame)
661*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "using guested frame (#%d)",
662*4882a593Smuzhiyun frame->system_frame_number);
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun out:
665*4882a593Smuzhiyun if (frame) {
666*4882a593Smuzhiyun gst_video_codec_frame_ref (frame);
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /* Prefer using MPP PTS */
669*4882a593Smuzhiyun if (self->use_mpp_pts)
670*4882a593Smuzhiyun frame->pts = pts;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun g_list_free_full (frames, (GDestroyNotify) gst_video_codec_frame_unref);
674*4882a593Smuzhiyun return frame;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun #ifdef HAVE_RGA
678*4882a593Smuzhiyun static gboolean
gst_mpp_dec_rga_convert(GstVideoDecoder * decoder,MppFrame mframe,GstBuffer * buffer)679*4882a593Smuzhiyun gst_mpp_dec_rga_convert (GstVideoDecoder * decoder, MppFrame mframe,
680*4882a593Smuzhiyun GstBuffer * buffer)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
683*4882a593Smuzhiyun GstVideoInfo *info = &self->info;
684*4882a593Smuzhiyun GstMemory *mem;
685*4882a593Smuzhiyun gboolean ret;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun mem = gst_allocator_alloc (self->allocator, GST_VIDEO_INFO_SIZE (info), NULL);
690*4882a593Smuzhiyun g_return_val_if_fail (mem, FALSE);
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun if (!gst_mpp_rga_convert_from_mpp_frame (mframe, mem, info, self->rotation)) {
693*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "failed to convert");
694*4882a593Smuzhiyun gst_memory_unref (mem);
695*4882a593Smuzhiyun ret = FALSE;
696*4882a593Smuzhiyun } else {
697*4882a593Smuzhiyun gst_buffer_replace_all_memory (buffer, mem);
698*4882a593Smuzhiyun ret = TRUE;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
702*4882a593Smuzhiyun return ret;
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun #endif
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun static GstBuffer *
gst_mpp_dec_get_gst_buffer(GstVideoDecoder * decoder,MppFrame mframe)707*4882a593Smuzhiyun gst_mpp_dec_get_gst_buffer (GstVideoDecoder * decoder, MppFrame mframe)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
710*4882a593Smuzhiyun GstVideoInfo *info = &self->info;
711*4882a593Smuzhiyun GstBuffer *buffer;
712*4882a593Smuzhiyun GstMemory *mem;
713*4882a593Smuzhiyun MppBuffer mbuf;
714*4882a593Smuzhiyun gint offset_x = mpp_frame_get_offset_x (mframe);
715*4882a593Smuzhiyun gint offset_y = mpp_frame_get_offset_y (mframe);
716*4882a593Smuzhiyun gint crop_x = self->crop_x;
717*4882a593Smuzhiyun gint crop_y = self->crop_y;
718*4882a593Smuzhiyun guint crop_w = self->crop_w;
719*4882a593Smuzhiyun guint crop_h = self->crop_h;
720*4882a593Smuzhiyun gboolean afbc = !!MPP_FRAME_FMT_IS_FBC (mpp_frame_get_fmt (mframe));
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun if (!self->allocator)
723*4882a593Smuzhiyun return NULL;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun mbuf = mpp_frame_get_buffer (mframe);
726*4882a593Smuzhiyun if (!mbuf)
727*4882a593Smuzhiyun return NULL;
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun /* Allocated from this MPP group in MPP */
730*4882a593Smuzhiyun mpp_buffer_set_index (mbuf, gst_mpp_allocator_get_index (self->allocator));
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun mem = gst_mpp_allocator_import_mppbuf (self->allocator, mbuf);
733*4882a593Smuzhiyun if (!mem)
734*4882a593Smuzhiyun return NULL;
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun buffer = gst_buffer_new ();
737*4882a593Smuzhiyun if (!buffer) {
738*4882a593Smuzhiyun gst_memory_unref (mem);
739*4882a593Smuzhiyun return NULL;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun if (afbc || offset_x || offset_y || crop_x || crop_y || crop_w || crop_h) {
743*4882a593Smuzhiyun GstVideoCropMeta *cmeta = gst_buffer_add_video_crop_meta (buffer);
744*4882a593Smuzhiyun gint width = mpp_frame_get_width (mframe);
745*4882a593Smuzhiyun gint height = mpp_frame_get_height (mframe);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun cmeta->x = CLAMP (crop_x, 0, width - 1);
748*4882a593Smuzhiyun cmeta->y = CLAMP (crop_y, 0, height - 1);
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun cmeta->width = width - cmeta->x;
751*4882a593Smuzhiyun cmeta->height = height - cmeta->y;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (crop_w && crop_w < cmeta->width)
754*4882a593Smuzhiyun cmeta->width = crop_w;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (crop_h && crop_h < cmeta->height)
757*4882a593Smuzhiyun cmeta->height = crop_h;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun /* Apply MPP offsets */
760*4882a593Smuzhiyun cmeta->x += offset_x;
761*4882a593Smuzhiyun cmeta->y += offset_y;
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "cropping <%d,%d,%d,%d> within <%d,%d,%d,%d>",
764*4882a593Smuzhiyun cmeta->x, cmeta->y, cmeta->width, cmeta->height, offset_x, offset_y,
765*4882a593Smuzhiyun GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun gst_buffer_append_memory (buffer, mem);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun gst_buffer_add_video_meta_full (buffer, GST_VIDEO_FRAME_FLAG_NONE,
771*4882a593Smuzhiyun GST_VIDEO_INFO_FORMAT (info),
772*4882a593Smuzhiyun GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info),
773*4882a593Smuzhiyun GST_VIDEO_INFO_N_PLANES (info), info->offset, info->stride);
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun if (!self->convert)
776*4882a593Smuzhiyun return buffer;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun #ifdef HAVE_RGA
779*4882a593Smuzhiyun if (gst_mpp_use_rga ()) {
780*4882a593Smuzhiyun if (!GST_VIDEO_INFO_IS_AFBC (info) && !offset_x && !offset_y &&
781*4882a593Smuzhiyun gst_mpp_dec_rga_convert (decoder, mframe, buffer))
782*4882a593Smuzhiyun return buffer;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun #endif
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "unable to convert frame");
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun gst_buffer_unref (buffer);
789*4882a593Smuzhiyun return NULL;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun static void
gst_mpp_dec_update_interlace_mode(GstVideoDecoder * decoder,GstBuffer * buffer,guint mode)793*4882a593Smuzhiyun gst_mpp_dec_update_interlace_mode (GstVideoDecoder * decoder,
794*4882a593Smuzhiyun GstBuffer * buffer, guint mode)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
797*4882a593Smuzhiyun GstVideoInterlaceMode interlace_mode;
798*4882a593Smuzhiyun GstVideoCodecState *output_state;
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun switch (mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) {
803*4882a593Smuzhiyun case MPP_FRAME_FLAG_BOT_FIRST:
804*4882a593Smuzhiyun GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
805*4882a593Smuzhiyun GST_BUFFER_FLAG_UNSET (buffer, GST_VIDEO_BUFFER_FLAG_TFF);
806*4882a593Smuzhiyun interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
807*4882a593Smuzhiyun break;
808*4882a593Smuzhiyun case MPP_FRAME_FLAG_TOP_FIRST:
809*4882a593Smuzhiyun GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
810*4882a593Smuzhiyun GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_FLAG_TFF);
811*4882a593Smuzhiyun interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
812*4882a593Smuzhiyun break;
813*4882a593Smuzhiyun case MPP_FRAME_FLAG_DEINTERLACED:
814*4882a593Smuzhiyun interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
815*4882a593Smuzhiyun /* fall-through */
816*4882a593Smuzhiyun default:
817*4882a593Smuzhiyun GST_BUFFER_FLAG_UNSET (buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
818*4882a593Smuzhiyun GST_BUFFER_FLAG_UNSET (buffer, GST_VIDEO_BUFFER_FLAG_TFF);
819*4882a593Smuzhiyun break;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun if (self->interlace_mode != interlace_mode) {
823*4882a593Smuzhiyun output_state = gst_video_decoder_get_output_state (decoder);
824*4882a593Smuzhiyun if (output_state) {
825*4882a593Smuzhiyun GstCaps *caps = gst_caps_copy (output_state->caps);
826*4882a593Smuzhiyun gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
827*4882a593Smuzhiyun gst_video_interlace_mode_to_string (interlace_mode), NULL);
828*4882a593Smuzhiyun gst_caps_replace (&output_state->caps, caps);
829*4882a593Smuzhiyun gst_caps_unref (caps);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun GST_VIDEO_INFO_INTERLACE_MODE (&output_state->info) = interlace_mode;
832*4882a593Smuzhiyun self->interlace_mode = interlace_mode;
833*4882a593Smuzhiyun gst_video_codec_state_unref (output_state);
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun static void
gst_mpp_dec_loop(GstVideoDecoder * decoder)839*4882a593Smuzhiyun gst_mpp_dec_loop (GstVideoDecoder * decoder)
840*4882a593Smuzhiyun {
841*4882a593Smuzhiyun GstMppDecClass *klass = GST_MPP_DEC_GET_CLASS (decoder);
842*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
843*4882a593Smuzhiyun GstVideoCodecFrame *frame;
844*4882a593Smuzhiyun GstBuffer *buffer;
845*4882a593Smuzhiyun MppFrame mframe;
846*4882a593Smuzhiyun int timeout, mode;
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun timeout = self->flushing ? MPP_TIMEOUT_NON_BLOCK : MPP_OUTPUT_TIMEOUT_MS;
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun mframe = klass->poll_mpp_frame (decoder, timeout);
851*4882a593Smuzhiyun /* Likely due to timeout */
852*4882a593Smuzhiyun if (!mframe)
853*4882a593Smuzhiyun return;
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun if (mpp_frame_get_info_change (mframe)) {
858*4882a593Smuzhiyun self->mpi->control (self->mpp_ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
859*4882a593Smuzhiyun self->task_ret = gst_mpp_dec_apply_info_change (decoder, mframe);
860*4882a593Smuzhiyun goto info_change;
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun if (!mpp_frame_get_buffer (mframe))
864*4882a593Smuzhiyun goto out;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun /* Apply info change when video info not unavaliable (no info-change event) */
867*4882a593Smuzhiyun if (!self->info.size)
868*4882a593Smuzhiyun self->task_ret = gst_mpp_dec_apply_info_change (decoder, mframe);
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun mode = mpp_frame_get_mode (mframe);
871*4882a593Smuzhiyun #ifdef MPP_FRAME_FLAG_IEP_DEI_MASK
872*4882a593Smuzhiyun /* IEP deinterlaced */
873*4882a593Smuzhiyun if (mode & MPP_FRAME_FLAG_IEP_DEI_MASK) {
874*4882a593Smuzhiyun #ifdef MPP_FRAME_FLAG_IEP_DEI_I4O2
875*4882a593Smuzhiyun if (mode & MPP_FRAME_FLAG_IEP_DEI_I4O2) {
876*4882a593Smuzhiyun /* 1 input frame generates 2 deinterlaced MPP frames */
877*4882a593Smuzhiyun static int mpp_i4o2_frames = 0;
878*4882a593Smuzhiyun if (mpp_i4o2_frames++ % 2) {
879*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "ignore extra MPP frame");
880*4882a593Smuzhiyun goto out;
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun #endif
884*4882a593Smuzhiyun mode = MPP_FRAME_FLAG_DEINTERLACED;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun #endif
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun frame = gst_mpp_dec_get_frame (decoder, mpp_frame_get_pts (mframe));
889*4882a593Smuzhiyun if (!frame)
890*4882a593Smuzhiyun goto no_frame;
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun if (mpp_frame_get_discard (mframe) || mpp_frame_get_errinfo (mframe))
893*4882a593Smuzhiyun goto error;
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun buffer = gst_mpp_dec_get_gst_buffer (decoder, mframe);
896*4882a593Smuzhiyun if (!buffer)
897*4882a593Smuzhiyun goto error;
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun gst_buffer_resize (buffer, 0, GST_VIDEO_INFO_SIZE (&self->info));
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun gst_mpp_dec_update_interlace_mode (decoder, buffer, mode);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun /* HACK: Mark lockable to avoid copying in make_writable() while shared */
904*4882a593Smuzhiyun GST_MINI_OBJECT_FLAG_SET (buffer, GST_MINI_OBJECT_FLAG_LOCKABLE);
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun frame->output_buffer = buffer;
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun if (self->flushing && !self->draining)
909*4882a593Smuzhiyun goto drop;
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "finish frame ts=%" GST_TIME_FORMAT,
912*4882a593Smuzhiyun GST_TIME_ARGS (frame->pts));
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun gst_video_decoder_finish_frame (decoder, frame);
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun out:
917*4882a593Smuzhiyun if (mpp_frame_get_eos (mframe)) {
918*4882a593Smuzhiyun GST_INFO_OBJECT (self, "got eos");
919*4882a593Smuzhiyun self->task_ret = GST_FLOW_EOS;
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun mpp_frame_deinit (&mframe);
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun if (self->task_ret != GST_FLOW_OK) {
925*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "leaving output thread: %s",
926*4882a593Smuzhiyun gst_flow_get_name (self->task_ret));
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun gst_pad_pause_task (decoder->srcpad);
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
932*4882a593Smuzhiyun return;
933*4882a593Smuzhiyun info_change:
934*4882a593Smuzhiyun GST_INFO_OBJECT (self, "video info changed");
935*4882a593Smuzhiyun goto out;
936*4882a593Smuzhiyun no_frame:
937*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "no matched frame");
938*4882a593Smuzhiyun goto out;
939*4882a593Smuzhiyun error:
940*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "can't process this frame");
941*4882a593Smuzhiyun goto drop;
942*4882a593Smuzhiyun drop:
943*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "drop frame");
944*4882a593Smuzhiyun gst_video_decoder_release_frame (decoder, frame);
945*4882a593Smuzhiyun goto out;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun static GstFlowReturn
gst_mpp_dec_handle_frame(GstVideoDecoder * decoder,GstVideoCodecFrame * frame)949*4882a593Smuzhiyun gst_mpp_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
950*4882a593Smuzhiyun {
951*4882a593Smuzhiyun GstMppDecClass *klass = GST_MPP_DEC_GET_CLASS (decoder);
952*4882a593Smuzhiyun GstMppDec *self = GST_MPP_DEC (decoder);
953*4882a593Smuzhiyun GstMapInfo mapinfo = { 0, };
954*4882a593Smuzhiyun GstBuffer *tmp;
955*4882a593Smuzhiyun GstFlowReturn ret;
956*4882a593Smuzhiyun gint timeout_ms = MPP_INPUT_TIMEOUT_MS;
957*4882a593Smuzhiyun gint interval_ms = 5;
958*4882a593Smuzhiyun MppPacket mpkt = NULL;
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun GST_MPP_DEC_LOCK (decoder);
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "handling frame %d", frame->system_frame_number);
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun if (G_UNLIKELY (self->flushing))
965*4882a593Smuzhiyun goto flushing;
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun if (!self->allocator) {
968*4882a593Smuzhiyun MppBufferGroup group;
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun self->allocator = gst_mpp_allocator_new ();
971*4882a593Smuzhiyun if (!self->allocator)
972*4882a593Smuzhiyun goto no_allocator;
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun group = gst_mpp_allocator_get_mpp_group (self->allocator);
975*4882a593Smuzhiyun self->mpi->control (self->mpp_ctx, MPP_DEC_SET_EXT_BUF_GROUP, group);
976*4882a593Smuzhiyun }
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun if (G_UNLIKELY (!GST_MPP_DEC_TASK_STARTED (decoder))) {
979*4882a593Smuzhiyun if (klass->startup && !klass->startup (decoder))
980*4882a593Smuzhiyun goto not_negotiated;
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun GST_DEBUG_OBJECT (self, "starting decoding thread");
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun gst_pad_start_task (decoder->srcpad,
985*4882a593Smuzhiyun (GstTaskFunction) gst_mpp_dec_loop, decoder, NULL);
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
989*4882a593Smuzhiyun gst_buffer_map (frame->input_buffer, &mapinfo, GST_MAP_READ);
990*4882a593Smuzhiyun mpkt = klass->get_mpp_packet (decoder, &mapinfo);
991*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
992*4882a593Smuzhiyun if (!mpkt)
993*4882a593Smuzhiyun goto no_packet;
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun mpp_packet_set_pts (mpkt, self->use_mpp_pts ? -1 : (gint64) frame->pts);
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun if (GST_CLOCK_TIME_IS_VALID (frame->pts))
998*4882a593Smuzhiyun self->seen_valid_pts = TRUE;
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun while (1) {
1001*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
1002*4882a593Smuzhiyun if (klass->send_mpp_packet (decoder, mpkt, interval_ms)) {
1003*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
1004*4882a593Smuzhiyun break;
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun timeout_ms -= interval_ms;
1009*4882a593Smuzhiyun if (timeout_ms <= 0)
1010*4882a593Smuzhiyun goto send_error;
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun /* NOTE: Sub-class takes over the MPP packet when success */
1014*4882a593Smuzhiyun mpkt = NULL;
1015*4882a593Smuzhiyun gst_buffer_unmap (frame->input_buffer, &mapinfo);
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun /* No need to keep input arround */
1018*4882a593Smuzhiyun tmp = frame->input_buffer;
1019*4882a593Smuzhiyun frame->input_buffer = gst_buffer_new ();
1020*4882a593Smuzhiyun gst_buffer_copy_into (frame->input_buffer, tmp,
1021*4882a593Smuzhiyun GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
1022*4882a593Smuzhiyun GST_BUFFER_COPY_META, 0, 0);
1023*4882a593Smuzhiyun gst_buffer_unref (tmp);
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun gst_video_codec_frame_unref (frame);
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun GST_MPP_DEC_UNLOCK (decoder);
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun return self->task_ret;
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun flushing:
1032*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "flushing");
1033*4882a593Smuzhiyun ret = GST_FLOW_FLUSHING;
1034*4882a593Smuzhiyun goto drop;
1035*4882a593Smuzhiyun no_allocator:
1036*4882a593Smuzhiyun GST_ERROR_OBJECT (self, "failed to create mpp allocator");
1037*4882a593Smuzhiyun ret = GST_FLOW_ERROR;
1038*4882a593Smuzhiyun goto drop;
1039*4882a593Smuzhiyun not_negotiated:
1040*4882a593Smuzhiyun GST_ERROR_OBJECT (self, "not negotiated");
1041*4882a593Smuzhiyun ret = GST_FLOW_NOT_NEGOTIATED;
1042*4882a593Smuzhiyun goto drop;
1043*4882a593Smuzhiyun no_packet:
1044*4882a593Smuzhiyun GST_ERROR_OBJECT (self, "failed to get packet");
1045*4882a593Smuzhiyun ret = GST_FLOW_ERROR;
1046*4882a593Smuzhiyun goto drop;
1047*4882a593Smuzhiyun send_error:
1048*4882a593Smuzhiyun GST_ERROR_OBJECT (self, "failed to send packet");
1049*4882a593Smuzhiyun ret = GST_FLOW_ERROR;
1050*4882a593Smuzhiyun goto drop;
1051*4882a593Smuzhiyun drop:
1052*4882a593Smuzhiyun GST_WARNING_OBJECT (self, "can't handle this frame");
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun if (mpkt)
1055*4882a593Smuzhiyun mpp_packet_deinit (&mpkt);
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun gst_buffer_unmap (frame->input_buffer, &mapinfo);
1058*4882a593Smuzhiyun gst_video_decoder_release_frame (decoder, frame);
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun GST_MPP_DEC_UNLOCK (decoder);
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun return ret;
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun static GstStateChangeReturn
gst_mpp_dec_change_state(GstElement * element,GstStateChange transition)1066*4882a593Smuzhiyun gst_mpp_dec_change_state (GstElement * element, GstStateChange transition)
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun GstVideoDecoder *decoder = GST_VIDEO_DECODER (element);
1069*4882a593Smuzhiyun
1070*4882a593Smuzhiyun if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) {
1071*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_LOCK (decoder);
1072*4882a593Smuzhiyun gst_mpp_dec_reset (decoder, FALSE, TRUE);
1073*4882a593Smuzhiyun GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun static void
gst_mpp_dec_init(GstMppDec * self)1080*4882a593Smuzhiyun gst_mpp_dec_init (GstMppDec * self)
1081*4882a593Smuzhiyun {
1082*4882a593Smuzhiyun GstVideoDecoder *decoder = GST_VIDEO_DECODER (self);
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun self->ignore_error = DEFAULT_PROP_IGNORE_ERROR;
1085*4882a593Smuzhiyun self->fast_mode = DEFAULT_PROP_FAST_MODE;
1086*4882a593Smuzhiyun self->dma_feature = DEFAULT_PROP_DMA_FEATURE;
1087*4882a593Smuzhiyun
1088*4882a593Smuzhiyun gst_video_decoder_set_packetized (decoder, TRUE);
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun #ifdef HAVE_RGA
1092*4882a593Smuzhiyun #define GST_TYPE_MPP_DEC_ROTATION (gst_mpp_dec_rotation_get_type ())
1093*4882a593Smuzhiyun static GType
gst_mpp_dec_rotation_get_type(void)1094*4882a593Smuzhiyun gst_mpp_dec_rotation_get_type (void)
1095*4882a593Smuzhiyun {
1096*4882a593Smuzhiyun static GType rotation = 0;
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun if (!rotation) {
1099*4882a593Smuzhiyun static const GEnumValue rotations[] = {
1100*4882a593Smuzhiyun {0, "Rotate 0", "0"},
1101*4882a593Smuzhiyun {90, "Rotate 90", "90"},
1102*4882a593Smuzhiyun {180, "Rotate 180", "180"},
1103*4882a593Smuzhiyun {270, "Rotate 270", "270"},
1104*4882a593Smuzhiyun {0, NULL, NULL}
1105*4882a593Smuzhiyun };
1106*4882a593Smuzhiyun rotation = g_enum_register_static ("GstMppDecRotation", rotations);
1107*4882a593Smuzhiyun }
1108*4882a593Smuzhiyun return rotation;
1109*4882a593Smuzhiyun }
1110*4882a593Smuzhiyun #endif
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun static void
gst_mpp_dec_class_init(GstMppDecClass * klass)1113*4882a593Smuzhiyun gst_mpp_dec_class_init (GstMppDecClass * klass)
1114*4882a593Smuzhiyun {
1115*4882a593Smuzhiyun GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
1116*4882a593Smuzhiyun GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1117*4882a593Smuzhiyun GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
1118*4882a593Smuzhiyun const gchar *env;
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "mppdec", 0, "MPP decoder");
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun decoder_class->start = GST_DEBUG_FUNCPTR (gst_mpp_dec_start);
1123*4882a593Smuzhiyun decoder_class->stop = GST_DEBUG_FUNCPTR (gst_mpp_dec_stop);
1124*4882a593Smuzhiyun decoder_class->flush = GST_DEBUG_FUNCPTR (gst_mpp_dec_flush);
1125*4882a593Smuzhiyun decoder_class->drain = GST_DEBUG_FUNCPTR (gst_mpp_dec_drain);
1126*4882a593Smuzhiyun decoder_class->finish = GST_DEBUG_FUNCPTR (gst_mpp_dec_finish);
1127*4882a593Smuzhiyun decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_mpp_dec_set_format);
1128*4882a593Smuzhiyun decoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_mpp_dec_handle_frame);
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_mpp_dec_set_property);
1131*4882a593Smuzhiyun gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_mpp_dec_get_property);
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun #ifdef HAVE_RGA
1134*4882a593Smuzhiyun if (!gst_mpp_use_rga ())
1135*4882a593Smuzhiyun goto no_rga;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun g_object_class_install_property (gobject_class, PROP_ROTATION,
1138*4882a593Smuzhiyun g_param_spec_enum ("rotation", "Rotation",
1139*4882a593Smuzhiyun "Rotation",
1140*4882a593Smuzhiyun GST_TYPE_MPP_DEC_ROTATION, DEFAULT_PROP_ROTATION,
1141*4882a593Smuzhiyun G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun g_object_class_install_property (gobject_class, PROP_WIDTH,
1144*4882a593Smuzhiyun g_param_spec_uint ("width", "Width",
1145*4882a593Smuzhiyun "Width (0 = original)",
1146*4882a593Smuzhiyun 0, G_MAXINT, DEFAULT_PROP_WIDTH,
1147*4882a593Smuzhiyun G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun g_object_class_install_property (gobject_class, PROP_HEIGHT,
1150*4882a593Smuzhiyun g_param_spec_uint ("height", "Height",
1151*4882a593Smuzhiyun "Height (0 = original)",
1152*4882a593Smuzhiyun 0, G_MAXINT, DEFAULT_PROP_HEIGHT,
1153*4882a593Smuzhiyun G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun no_rga:
1156*4882a593Smuzhiyun #endif
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun g_object_class_install_property (gobject_class, PROP_CROP_RECTANGLE,
1159*4882a593Smuzhiyun gst_param_spec_array ("crop-rectangle", "Crop Rectangle",
1160*4882a593Smuzhiyun "The crop rectangle ('<x, y, width, height>')",
1161*4882a593Smuzhiyun g_param_spec_int ("rect-value", "Rectangle Value",
1162*4882a593Smuzhiyun "One of x, y, width or height value.", 0, G_MAXINT, 0,
1163*4882a593Smuzhiyun G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS),
1164*4882a593Smuzhiyun G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun env = g_getenv ("GST_MPP_DEC_DEFAULT_IGNORE_ERROR");
1167*4882a593Smuzhiyun if (env && !strcmp (env, "0"))
1168*4882a593Smuzhiyun DEFAULT_PROP_IGNORE_ERROR = FALSE;
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun g_object_class_install_property (gobject_class, PROP_IGNORE_ERROR,
1171*4882a593Smuzhiyun g_param_spec_boolean ("ignore-error", "Ignore error",
1172*4882a593Smuzhiyun "Ignore MPP decode errors", DEFAULT_PROP_IGNORE_ERROR,
1173*4882a593Smuzhiyun G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun env = g_getenv ("GST_MPP_DEC_DEFAULT_FAST_MODE");
1176*4882a593Smuzhiyun if (env && !strcmp (env, "0"))
1177*4882a593Smuzhiyun DEFAULT_PROP_FAST_MODE = FALSE;
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun g_object_class_install_property (gobject_class, PROP_FAST_MODE,
1180*4882a593Smuzhiyun g_param_spec_boolean ("fast-mode", "Fast mode",
1181*4882a593Smuzhiyun "Enable MPP fast decode mode", DEFAULT_PROP_FAST_MODE,
1182*4882a593Smuzhiyun G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun env = g_getenv ("GST_MPP_DEC_DMA_FEATURE");
1185*4882a593Smuzhiyun if (env && !strcmp (env, "1"))
1186*4882a593Smuzhiyun DEFAULT_PROP_DMA_FEATURE = TRUE;
1187*4882a593Smuzhiyun
1188*4882a593Smuzhiyun g_object_class_install_property (gobject_class, PROP_DMA_FEATURE,
1189*4882a593Smuzhiyun g_param_spec_boolean ("dma-feature", "DMA feature",
1190*4882a593Smuzhiyun "Enable GST DMA feature", DEFAULT_PROP_DMA_FEATURE,
1191*4882a593Smuzhiyun G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun element_class->change_state = GST_DEBUG_FUNCPTR (gst_mpp_dec_change_state);
1194*4882a593Smuzhiyun }
1195