ducatih264dec: don't free inArgs->inputID twice on some error conditions
[gstreamer-omap:gst-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  */
19
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  */
32
33 #ifdef HAVE_CONFIG_H
34 #  include <config.h>
35 #endif
36
37 #include "gstducatih264dec.h"
38
39
40 #define GST_BUFFER_FLAG_B_FRAME (GST_BUFFER_FLAG_LAST << 0)
41 #define PADX  32
42 #define PADY  24
43
44
45 GST_BOILERPLATE (GstDucatiH264Dec, gst_ducati_h264dec, GstDucatiVidDec,
46     GST_TYPE_DUCATIVIDDEC);
47
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     );
69
70 /* GstDucatiVidDec vmethod implementations */
71
72 static void
73 gst_ducati_h264dec_update_buffer_size (GstDucatiVidDec * self)
74 {
75   gint w = self->width;
76   gint h = self->height;
77
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 }
83
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));
92
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   }
102
103   return ret;
104 }
105
106 static gint
107 gst_ducati_h264dec_handle_error (GstDucatiVidDec * self, gint ret,
108     gint extended_error, gint status_extended_error)
109 {
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      */
114     gst_ducati_viddec_codec_flush (self, FALSE);
115   }
116
117   ret = parent_class->handle_error (self, ret, extended_error,
118       status_extended_error);
119
120   return ret;
121 }
122
123 static gboolean
124 gst_ducati_h264dec_query (GstDucatiVidDec * vdec, GstPad * pad,
125     GstQuery * query, gboolean * forward)
126 {
127   GstDucatiH264Dec * self = GST_DUCATIH264DEC (vdec);
128   gboolean res = TRUE;
129
130   switch (GST_QUERY_TYPE (query)) {
131     case GST_QUERY_LATENCY:
132     {
133       gboolean live;
134       GstClockTime min, max, latency;
135
136       if (vdec->fps_d == 0) {
137         GST_INFO_OBJECT (self, "not ready to report latency");
138         res = FALSE;
139         break;
140       }
141
142       gst_query_parse_latency (query, &live, &min, &max);
143       if (vdec->fps_n != 0)
144         latency = gst_util_uint64_scale (GST_SECOND,
145             vdec->fps_d, vdec->fps_n);
146       else
147         latency = 0;
148
149       if (min == GST_CLOCK_TIME_NONE)
150         min = latency;
151       else
152         min += latency;
153
154       if (max != GST_CLOCK_TIME_NONE)
155         max += latency;
156
157       GST_INFO_OBJECT (self, "latency %"GST_TIME_FORMAT " ours %"GST_TIME_FORMAT,
158           GST_TIME_ARGS (min), GST_TIME_ARGS (latency));
159       gst_query_set_latency (query, live, min, max);
160       break;
161     }
162     default:
163       break;
164   }
165
166   if (res)
167     res = parent_class->query (vdec, pad, query, forward);
168
169   return res;
170 }
171
172 static gboolean
173 gst_ducati_h264dec_drop_frame (GstDucatiVidDec * self, GstBuffer * buf,
174     gint64 diff)
175 {
176   gboolean is_bframe = GST_BUFFER_FLAG_IS_SET (buf,
177       GST_BUFFER_FLAG_B_FRAME);
178
179   if (diff >= 0 && is_bframe)
180     return TRUE;
181
182   return FALSE;
183 }
184
185 /* GObject vmethod implementations */
186
187 static void
188 gst_ducati_h264dec_base_init (gpointer gclass)
189 {
190   GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
191
192   gst_element_class_set_details_simple (element_class,
193       "DucatiH264Dec",
194       "Codec/Decoder/Video",
195       "Decodes video in H.264/bytestream format with ducati",
196       "Rob Clark <rob@ti.com>");
197
198   gst_element_class_add_pad_template (element_class,
199       gst_static_pad_template_get (&sink_factory));
200 }
201
202 static void
203 gst_ducati_h264dec_class_init (GstDucatiH264DecClass * klass)
204 {
205   GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
206   bclass->codec_name = "ivahd_h264dec";
207   bclass->update_buffer_size =
208       GST_DEBUG_FUNCPTR (gst_ducati_h264dec_update_buffer_size);
209   bclass->allocate_params =
210       GST_DEBUG_FUNCPTR (gst_ducati_h264dec_allocate_params);
211   bclass->handle_error = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_handle_error);
212   bclass->drop_frame = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_drop_frame);
213   bclass->query = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_query);
214 }
215
216 static void
217 gst_ducati_h264dec_init (GstDucatiH264Dec * self,
218     GstDucatiH264DecClass * gclass)
219 {
220 }