xref: /OK3568_Linux_fs/external/gstreamer-rockchip/gst/rockchipmpp/gstmppdec.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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