Revert "h264dec: Actually do not accept level 5.1 in High profiles"
[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 <math.h>
38 #include "gstducatih264dec.h"
39
40
41 #define GST_BUFFER_FLAG_B_FRAME (GST_BUFFER_FLAG_LAST << 0)
42 #define PADX  32
43 #define PADY  24
44
45
46 GST_BOILERPLATE (GstDucatiH264Dec, gst_ducati_h264dec, GstDucatiVidDec,
47     GST_TYPE_DUCATIVIDDEC);
48
49 /* *INDENT-OFF* */
50 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
51     GST_PAD_SINK,
52     GST_PAD_ALWAYS,
53     GST_STATIC_CAPS ("video/x-h264, "
54         "stream-format = byte-stream, "   /* only byte-stream */
55         "alignment = au, "          /* only entire frames */
56         "width = (int)[ 16, 2048 ], "
57         "height = (int)[ 16, 2048 ], "
58         "framerate = (fraction)[ 0, max ],"
59         "profile = (string){constrained-baseline, baseline, main, extended};"
60         "video/x-h264, "
61         "stream-format = byte-stream, "   /* only byte-stream */
62         "alignment = au, "          /* only entire frames */
63         "width = (int)[ 16, 2048 ], "
64         "height = (int)[ 16, 2048 ], "
65         "framerate = (fraction)[ 0, max ],"
66         "profile = (string) {high, high-10-intra, high-10, high-4:2:2-intra, "
67         "high-4:2:2, high-4:4:4-intra, high-4:4:4, cavlc-4:4:4-intra}, "
68         "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, 5.1};")
69     );
70
71 static const struct
72 {
73   const char *level;
74   gint kb;
75 } max_dpb_by_level[] = {
76   { "1", 149 },
77   { "1b", 149 }, /* That one's not in the spec ?? */
78   { "1.1", 338 },
79   { "1.2", 891 },
80   { "1.3", 891 },
81   { "2", 891 },
82   { "2.1", 1782 },
83   { "2.2", 3038 },
84   { "3", 3038 },
85   { "3.1", 6750 },
86   { "3.2", 7680 },
87   { "4", 12288 },
88   { "4.1", 12288 },
89   { "4.2", 12288 },
90   { "5", 41400 },
91   { "5.1", 69120 },
92 };
93 /* *INDENT-ON* */
94
95 /* GstDucatiVidDec vmethod implementations */
96
97 static void
98 gst_ducati_h264dec_update_buffer_size (GstDucatiVidDec * self)
99 {
100   gint w = self->width;
101   gint h = self->height;
102
103   /* calculate output buffer parameters: */
104   self->padded_width = ALIGN2 (w + (2 * PADX), 7);
105   self->padded_height = h + 4 * PADY;
106   self->min_buffers = MIN (16, 32768 / ((w / 16) * (h / 16))) + 3;
107 }
108
109 static gboolean
110 gst_ducati_h264dec_allocate_params (GstDucatiVidDec * self, gint params_sz,
111     gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
112 {
113   gboolean ret = parent_class->allocate_params (self,
114       sizeof (IH264VDEC_Params), sizeof (IH264VDEC_DynamicParams),
115       sizeof (IH264VDEC_Status), sizeof (IH264VDEC_InArgs),
116       sizeof (IH264VDEC_OutArgs));
117
118   if (ret) {
119     IH264VDEC_Params *params = (IH264VDEC_Params *) self->params;
120
121     self->params->displayDelay = IVIDDEC3_DECODE_ORDER;
122     params->maxNumRefFrames = IH264VDEC_NUM_REFFRAMES_AUTO;
123     params->pConstantMemory = 0;
124     params->presetLevelIdc = IH264VDEC_LEVEL41;
125     params->errConcealmentMode = IH264VDEC_APPLY_CONCEALMENT;
126     params->temporalDirModePred = TRUE;
127   }
128
129   return ret;
130 }
131
132 static gint
133 gst_ducati_h264dec_handle_error (GstDucatiVidDec * self, gint ret,
134     gint extended_error, gint status_extended_error)
135 {
136   if (extended_error & 0x00000001) {
137     /* No valid slice. This seems to be bad enough that it's better to flush and
138      * skip to the next keyframe.
139      */
140
141     if (extended_error == 0x00000201) {
142       /* the codec doesn't unlock the input buffer in this case... */
143       gst_buffer_unref ((GstBuffer *) self->inArgs->inputID);
144       self->inArgs->inputID = 0;
145     }
146
147     self->needs_flushing = TRUE;
148   }
149
150   ret = parent_class->handle_error (self, ret, extended_error,
151       status_extended_error);
152
153   return ret;
154 }
155
156 static gboolean
157 gst_ducati_h264dec_query (GstDucatiVidDec * vdec, GstPad * pad,
158     GstQuery * query, gboolean * forward)
159 {
160   GstDucatiH264Dec *self = GST_DUCATIH264DEC (vdec);
161   gboolean res = TRUE;
162
163   switch (GST_QUERY_TYPE (query)) {
164     case GST_QUERY_LATENCY:
165     {
166       gboolean live;
167       GstClockTime min, max, latency;
168
169       if (vdec->fps_d == 0) {
170         GST_INFO_OBJECT (self, "not ready to report latency");
171         res = FALSE;
172         break;
173       }
174
175       gst_query_parse_latency (query, &live, &min, &max);
176       if (vdec->fps_n != 0)
177         latency = gst_util_uint64_scale (GST_SECOND, vdec->fps_d, vdec->fps_n);
178       else
179         latency = 0;
180
181       /* Take into account the backlog frames for reordering */
182       latency *= (vdec->backlog_maxframes + 1);
183
184       if (min == GST_CLOCK_TIME_NONE)
185         min = latency;
186       else
187         min += latency;
188
189       if (max != GST_CLOCK_TIME_NONE)
190         max += latency;
191
192       GST_INFO_OBJECT (self,
193           "latency %" GST_TIME_FORMAT " ours %" GST_TIME_FORMAT,
194           GST_TIME_ARGS (min), GST_TIME_ARGS (latency));
195       gst_query_set_latency (query, live, min, max);
196       break;
197     }
198     default:
199       break;
200   }
201
202   if (res)
203     res = parent_class->query (vdec, pad, query, forward);
204
205   return res;
206 }
207
208 static gboolean
209 gst_ducati_h264dec_can_drop_frame (GstDucatiVidDec * self, GstBuffer * buf,
210     gint64 diff)
211 {
212   gboolean is_bframe = GST_BUFFER_FLAG_IS_SET (buf,
213       GST_BUFFER_FLAG_B_FRAME);
214
215   if (diff >= 0 && is_bframe)
216     return TRUE;
217
218   return FALSE;
219 }
220
221 static gint
222 gst_ducati_h264dec_find_max_dpb_from_level (GstDucatiVidDec * self,
223     const char *level)
224 {
225   guint n;
226
227   for (n = 0; n < G_N_ELEMENTS (max_dpb_by_level); ++n)
228     if (!strcmp (level, max_dpb_by_level[n].level))
229       return max_dpb_by_level[n].kb;
230
231   GST_WARNING_OBJECT (self, "Max DBP not found for level %s", level);
232   return -1;
233 }
234
235 static gint
236 gst_ducati_h264dec_get_max_dpb_size (GstDucatiVidDec * self, GstCaps * caps)
237 {
238   gint wmb = (self->width + 15) / 16;
239   gint hmb = (self->height + 15) / 16;
240   gint max_dpb, max_dpb_size;
241   GstStructure *structure;
242   const char *level;
243   float chroma_factor = 1.5;    /* We only support NV12, which is 4:2:0 */
244
245   /* Min( 1024 * MaxDPB / ( PicWidthInMbs * FrameHeightInMbs * 256 * ChromaFormatFactor ), 16 ) */
246
247   structure = gst_caps_get_structure (caps, 0);
248   if (!structure)
249     return -1;
250
251   level = gst_structure_get_string (structure, "level");
252   if (!level)
253     return -1;
254
255   max_dpb = gst_ducati_h264dec_find_max_dpb_from_level (self, level);
256   if (max_dpb < 0)
257     return -1;
258
259   max_dpb_size =
260       lrint (ceil (1024 * max_dpb / (wmb * hmb * 256 * chroma_factor)));
261   if (max_dpb_size > MAX_BACKLOG_FRAMES)
262     max_dpb_size = MAX_BACKLOG_FRAMES;
263
264   return max_dpb_size;
265 }
266
267 static gboolean
268 gst_ducati_h264dec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
269 {
270   GstStructure *structure;
271
272   GST_DEBUG_OBJECT (self, "set_sink_caps: %" GST_PTR_FORMAT, caps);
273
274   if (!GST_CALL_PARENT_WITH_DEFAULT (GST_DUCATIVIDDEC_CLASS, set_sink_caps,
275           (self, caps), TRUE))
276     return FALSE;
277
278   /* HW decoder fails in GETSTATUS */
279 #if 0
280   /* When we have the first decoded buffer, we ask the decoder for the
281      max number of frames needed to reorder */
282   int err = VIDDEC3_control (self->codec, XDM_GETSTATUS,
283       self->dynParams, self->status);
284   if (!err) {
285     IH264VDEC_Status *s = (IH264VDEC_Status *) self->status;
286     if (s->spsMaxRefFrames > MAX_BACKLOG_FRAMES) {
287       h264dec->backlog_maxframes = MAX_BACKLOG_FRAMES;
288       GST_WARNING_OBJECT (self,
289           "Stream needs %d frames for reordering, we can only accomodate %d",
290           s->spsMaxRefFrames, MAX_BACKLOG_FRAMES);
291     } else {
292       h264dec->backlog_maxframes = s->spsMaxRefFrames;
293       GST_INFO_OBJECT (self, "Num frames for reordering: %d",
294           h264dec->backlog_maxframes);
295     }
296   } else {
297     h264dec->backlog_maxframes = MAX_BACKLOG_FRAMES;
298     GST_WARNING_OBJECT (self,
299         "Failed to request num frames for reordering, defaulting to %d",
300         h264dec->backlog_maxframes);
301   }
302 #endif
303
304   self->backlog_maxframes = -1;
305
306   structure = gst_caps_get_structure (caps, 0);
307   if (structure) {
308     gint num_ref_frames = -1, num_reorder_frames = -1;
309     const char *profile;
310
311     /* baseline profile does not use B frames (and I'll say constrained-baseline
312        is unlikely either from the name, it's not present in my H264 spec... */
313     profile = gst_structure_get_string (structure, "profile");
314     if (profile && (!strcmp (profile, "baseline")
315             || !strcmp (profile, "constrained-baseline"))) {
316       GST_DEBUG_OBJECT (self, "No need for reordering for %s profile", profile);
317       self->backlog_maxframes = 0;
318       goto no_b_frames;
319     }
320
321
322     if (gst_structure_get_int (structure, "num-ref-frames", &num_ref_frames)
323         && num_ref_frames >= 0) {
324       ((IH264VDEC_Params *) self->params)->maxNumRefFrames = num_ref_frames;
325     }
326     if (gst_structure_get_int (structure, "num-reorder-frames",
327             &num_reorder_frames)
328         && num_reorder_frames >= 0) {
329       if (num_reorder_frames > MAX_BACKLOG_FRAMES) {
330         self->backlog_maxframes = MAX_BACKLOG_FRAMES;
331         GST_WARNING_OBJECT (self,
332             "Stream needs %d frames for reordering, we can only accomodate %d",
333             num_reorder_frames, MAX_BACKLOG_FRAMES);
334       } else {
335         self->backlog_maxframes = num_reorder_frames;
336         GST_INFO_OBJECT (self, "Num frames for reordering: %d",
337             self->backlog_maxframes);
338       }
339     }
340   }
341
342   /* If not present, use the spec forumula for a bound */
343   if (self->backlog_maxframes < 0) {
344     self->backlog_maxframes = gst_ducati_h264dec_get_max_dpb_size (self, caps);
345     if (self->backlog_maxframes >= 0) {
346       GST_WARNING_OBJECT (self,
347           "num-reorder-frames not found on caps, calculation from stream parameters gives %d",
348           self->backlog_maxframes);
349     } else {
350       self->backlog_maxframes = MAX_H264_BACKLOG_FRAMES;
351     }
352   }
353   if (self->backlog_maxframes > self->backlog_max_maxframes)
354     self->backlog_maxframes = self->backlog_max_maxframes;
355   GST_WARNING_OBJECT (self,
356       "Using %d frames for reordering", self->backlog_maxframes);
357
358 no_b_frames:
359
360   return TRUE;
361 }
362
363 /* GObject vmethod implementations */
364
365 static void
366 gst_ducati_h264dec_base_init (gpointer gclass)
367 {
368   GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
369
370   gst_element_class_set_details_simple (element_class,
371       "DucatiH264Dec",
372       "Codec/Decoder/Video",
373       "Decodes video in H.264/bytestream format with ducati",
374       "Rob Clark <rob@ti.com>");
375
376   gst_element_class_add_pad_template (element_class,
377       gst_static_pad_template_get (&sink_factory));
378 }
379
380 static void
381 gst_ducati_h264dec_class_init (GstDucatiH264DecClass * klass)
382 {
383   GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
384   bclass->codec_name = "ivahd_h264dec";
385   bclass->update_buffer_size =
386       GST_DEBUG_FUNCPTR (gst_ducati_h264dec_update_buffer_size);
387   bclass->allocate_params =
388       GST_DEBUG_FUNCPTR (gst_ducati_h264dec_allocate_params);
389   bclass->handle_error = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_handle_error);
390   bclass->can_drop_frame =
391       GST_DEBUG_FUNCPTR (gst_ducati_h264dec_can_drop_frame);
392   bclass->query = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_query);
393   bclass->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_set_sink_caps);
394 }
395
396 static void
397 gst_ducati_h264dec_init (GstDucatiH264Dec * self,
398     GstDucatiH264DecClass * gclass)
399 {
400 }