fa8a8c1da13ecba1c861da3adf01103a4ca4a88b
[glsdk/gst-plugin-ducati.git] / src / gstducatih264dec.c
1 /*
2  * GStreamer
3  * Copyright (c) 2010, Texas Instruments Incorporated
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation
8  * version 2.1 of the License.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
20 /**
21  * SECTION:element-ducatih264dec
22  *
23  * FIXME:Describe ducatih264dec here.
24  *
25  * <refsect2>
26  * <title>Example launch line</title>
27  * |[
28  * gst-launch -v -m fakesrc ! ducatih264dec ! fakesink silent=TRUE
29  * ]|
30  * </refsect2>
31  */
33 #ifdef HAVE_CONFIG_H
34 #  include <config.h>
35 #endif
37 #include "gstducatih264dec.h"
40 #define GST_BUFFER_FLAG_B_FRAME (GST_BUFFER_FLAG_LAST << 0)
41 #define PADX  32
42 #define PADY  24
45 GST_BOILERPLATE (GstDucatiH264Dec, gst_ducati_h264dec, GstDucatiVidDec,
46     GST_TYPE_DUCATIVIDDEC);
48 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
49     GST_PAD_SINK,
50     GST_PAD_ALWAYS,
51     GST_STATIC_CAPS ("video/x-h264, "
52         "stream-format = byte-stream, "   /* only byte-stream */
53         "align = au, "          /* only entire frames */
54         "width = (int)[ 16, 2048 ], "
55         "height = (int)[ 16, 2048 ], "
56         "framerate = (fraction)[ 0, max ],"
57         "profile = (string){constrained-baseline, baseline, main, extended};"
58         "video/x-h264, "
59         "stream-format = byte-stream, "   /* only byte-stream */
60         "align = au, "          /* only entire frames */
61         "width = (int)[ 16, 2048 ], "
62         "height = (int)[ 16, 2048 ], "
63         "framerate = (fraction)[ 0, max ],"
64         "profile = (string) {high, high-10-intra, high-10, high-4:2:2-intra, "
65         "high-4:2:2, high-4:4:4-intra, high-4:4:4, cavlc-4:4:4-intra}, "
66         "level = (string) {1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2};"
67         )
68     );
70 /* GstDucatiVidDec vmethod implementations */
72 static void
73 gst_ducati_h264dec_update_buffer_size (GstDucatiVidDec * self)
74 {
75   gint w = self->width;
76   gint h = self->height;
78   /* calculate output buffer parameters: */
79   self->padded_width = ALIGN2 (w + (2 * PADX), 7);
80   self->padded_height = h + 4 * PADY;
81   self->min_buffers = MIN (16, 32768 / ((w / 16) * (h / 16))) + 3;
82 }
84 static gboolean
85 gst_ducati_h264dec_allocate_params (GstDucatiVidDec * self, gint params_sz,
86     gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
87 {
88   gboolean ret = parent_class->allocate_params (self,
89       sizeof (IH264VDEC_Params), sizeof (IH264VDEC_DynamicParams),
90       sizeof (IH264VDEC_Status), sizeof (IH264VDEC_InArgs),
91       sizeof (IH264VDEC_OutArgs));
93   if (ret) {
94     IH264VDEC_Params *params = (IH264VDEC_Params *) self->params;
95     self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
96     params->maxNumRefFrames = IH264VDEC_NUM_REFFRAMES_AUTO;
97     params->pConstantMemory = 0;
98     params->presetLevelIdc = IH264VDEC_LEVEL41;
99     params->errConcealmentMode = IH264VDEC_APPLY_CONCEALMENT;
100     params->temporalDirModePred = TRUE;
101   }
103   return ret;
106 static gint
107 gst_ducati_h264dec_handle_error (GstDucatiVidDec * self, gint ret,
108     gint extended_error, gint status_extended_error)
110   if (extended_error & 0x00000001) {
111     /* No valid slice. This seems to be bad enough that it's better to flush and
112      * skip to the next keyframe.
113      */
115     if (extended_error == 0x00000201) {
116       /* the codec doesn't unlock the input buffer in this case... */
117       gst_buffer_unref ((GstBuffer *) self->inArgs->inputID);
118       self->inArgs->inputID = 0;
119     }
121     gst_ducati_viddec_codec_flush (self, FALSE);
122   }
124   ret = parent_class->handle_error (self, ret, extended_error,
125       status_extended_error);
127   return ret;
130 static gboolean
131 gst_ducati_h264dec_query (GstDucatiVidDec * vdec, GstPad * pad,
132     GstQuery * query, gboolean * forward)
134   GstDucatiH264Dec * self = GST_DUCATIH264DEC (vdec);
135   gboolean res = TRUE;
137   switch (GST_QUERY_TYPE (query)) {
138     case GST_QUERY_LATENCY:
139     {
140       gboolean live;
141       GstClockTime min, max, latency;
143       if (vdec->fps_d == 0) {
144         GST_INFO_OBJECT (self, "not ready to report latency");
145         res = FALSE;
146         break;
147       }
149       gst_query_parse_latency (query, &live, &min, &max);
150       if (vdec->fps_n != 0)
151         latency = gst_util_uint64_scale (GST_SECOND,
152             vdec->fps_d, vdec->fps_n);
153       else
154         latency = 0;
156       if (min == GST_CLOCK_TIME_NONE)
157         min = latency;
158       else
159         min += latency;
161       if (max != GST_CLOCK_TIME_NONE)
162         max += latency;
164       GST_INFO_OBJECT (self, "latency %"GST_TIME_FORMAT " ours %"GST_TIME_FORMAT,
165           GST_TIME_ARGS (min), GST_TIME_ARGS (latency));
166       gst_query_set_latency (query, live, min, max);
167       break;
168     }
169     default:
170       break;
171   }
173   if (res)
174     res = parent_class->query (vdec, pad, query, forward);
176   return res;
179 static gboolean
180 gst_ducati_h264dec_drop_frame (GstDucatiVidDec * self, GstBuffer * buf,
181     gint64 diff)
183   gboolean is_bframe = GST_BUFFER_FLAG_IS_SET (buf,
184       GST_BUFFER_FLAG_B_FRAME);
186   if (diff >= 0 && is_bframe)
187     return TRUE;
189   return FALSE;
192 /* GObject vmethod implementations */
194 static void
195 gst_ducati_h264dec_base_init (gpointer gclass)
197   GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
199   gst_element_class_set_details_simple (element_class,
200       "DucatiH264Dec",
201       "Codec/Decoder/Video",
202       "Decodes video in H.264/bytestream format with ducati",
203       "Rob Clark <rob@ti.com>");
205   gst_element_class_add_pad_template (element_class,
206       gst_static_pad_template_get (&sink_factory));
209 static void
210 gst_ducati_h264dec_class_init (GstDucatiH264DecClass * klass)
212   GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
213   bclass->codec_name = "ivahd_h264dec";
214   bclass->update_buffer_size =
215       GST_DEBUG_FUNCPTR (gst_ducati_h264dec_update_buffer_size);
216   bclass->allocate_params =
217       GST_DEBUG_FUNCPTR (gst_ducati_h264dec_allocate_params);
218   bclass->handle_error = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_handle_error);
219   bclass->drop_frame = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_drop_frame);
220   bclass->query = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_query);
223 static void
224 gst_ducati_h264dec_init (GstDucatiH264Dec * self,
225     GstDucatiH264DecClass * gclass)