Port DucatiVidDec to the Gstreamer 1.0 API
[gstreamer-omap:gst-ducati.git] / src / gstducatimpeg4dec.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-ducatimpeg4dec
22  *
23  * FIXME:Describe ducatimpeg4dec here.
24  *
25  * <refsect2>
26  * <title>Example launch line</title>
27  * |[
28  * gst-launch -v -m fakesrc ! ducatimpeg4dec ! fakesink silent=TRUE
29  * ]|
30  * </refsect2>
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #  include <config.h>
35 #endif
36
37 #include "gstducatimpeg4dec.h"
38
39 #include <math.h>
40
41
42 #define PADX  32
43 #define PADY  32
44
45
46 #define gst_ducati_mpeg4dec_parent_class parent_class
47 G_DEFINE_TYPE (GstDucatiMpeg4Dec, gst_ducati_mpeg4dec, GST_TYPE_DUCATIVIDDEC);
48
49 /* *INDENT-OFF* */
50 #define MPEG4DEC_SINKCAPS_COMMON \
51     "width = (int)[ 16, 2048 ], " \
52     "height = (int)[ 16, 2048 ], " \
53     "framerate = (fraction)[ 0, max ]"
54
55
56 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
57     GST_PAD_SINK,
58     GST_PAD_ALWAYS,
59     GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int)4, " "systemstream = (boolean)false, " MPEG4DEC_SINKCAPS_COMMON ";" "video/x-divx, " "divxversion = (int)[4, 5], "      /* TODO check this */
60         MPEG4DEC_SINKCAPS_COMMON ";"
61         "video/x-xvid, "
62         MPEG4DEC_SINKCAPS_COMMON ";"
63         "video/x-3ivx, " MPEG4DEC_SINKCAPS_COMMON ";")
64     );
65 /* *INDENT-ON* */
66
67 /* GstDucatiVidDec vmethod implementations */
68
69 static void
70 gst_ducati_mpeg4dec_update_buffer_size (GstDucatiVidDec * self)
71 {
72   gint w = self->width;
73   gint h = self->height;
74
75   /* calculate output buffer parameters: */
76   self->padded_width = ALIGN2 (w + PADX, 7);
77   self->padded_height = h + PADY;
78   self->min_buffers = 8;
79 }
80
81 static gboolean
82 gst_ducati_mpeg4dec_allocate_params (GstDucatiVidDec * self, gint params_sz,
83     gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
84 {
85   gboolean ret = GST_DUCATIVIDDEC_CLASS (parent_class)->allocate_params (self,
86       sizeof (IMPEG4VDEC_Params), sizeof (IMPEG4VDEC_DynamicParams),
87       sizeof (IMPEG4VDEC_Status), sizeof (IMPEG4VDEC_InArgs),
88       sizeof (IMPEG4VDEC_OutArgs));
89
90   if (ret) {
91     /* NB: custom params are needed as base params seem to break xvid */
92     IMPEG4VDEC_Params *params = (IMPEG4VDEC_Params *) self->params;
93     self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
94     self->dynParams->lateAcquireArg = -1;
95     params->outloopDeBlocking = FALSE;
96     params->sorensonSparkStream = FALSE;
97     params->errorConcealmentEnable = FALSE;
98   }
99
100   return ret;
101 }
102
103 #define VOS_START_CODE    0xb0  /* + visual object sequence */
104 #define VOS_END_CODE      0xb1
105 #define UD_START_CODE     0xb2  /* user data */
106 #define GVOP_START_CODE   0xb3  /* + group of VOP */
107 #define VS_ERROR_CODE     0xb4
108 #define VO_START_CODE     0xb5  /* visual object */
109 #define VOP_START_CODE    0xb6  /* + */
110
111 static const guint8 sc[] = { 0x00, 0x00, 0x01 };        /* start code */
112
113 #define SC_SZ                G_N_ELEMENTS (sc)  /* start code size */
114
115 static GstBitReader *
116 get_bit_reader (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
117 {
118   if (self->br) {
119     gst_bit_reader_init (self->br, data, size);
120   } else {
121     self->br = gst_bit_reader_new (data, size);
122   }
123   return self->br;
124 }
125
126 static void
127 decode_vol_header (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
128 {
129   GstBitReader *br = get_bit_reader (self, data, size);
130   guint32 is_oli = 0, vc_param = 0, vbv_param = 0;
131   guint32 ar_info = 0, vop_tir = 0;
132
133   gst_bit_reader_skip (br, 1);  /* random_accessible_vol */
134   gst_bit_reader_skip (br, 8);  /* video_object_type_indication */
135
136   gst_bit_reader_get_bits_uint32 (br,   /* is_object_layer_identifier */
137       &is_oli, 1);
138   if (is_oli) {
139     gst_bit_reader_skip (br, 4);        /* video_object_layer_verid */
140     gst_bit_reader_skip (br, 3);        /* video_object_layer_priority */
141   }
142
143   gst_bit_reader_get_bits_uint32 (br,   /* aspect_ratio_info */
144       &ar_info, 4);
145   if (ar_info == 0xf) {
146     gst_bit_reader_skip (br, 8);        /* par_width */
147     gst_bit_reader_skip (br, 8);        /* par_height */
148   }
149
150   gst_bit_reader_get_bits_uint32 (br,   /* vol_control_parameters */
151       &vc_param, 1);
152   if (vc_param) {
153     gst_bit_reader_skip (br, 2);        /* chroma_format */
154     gst_bit_reader_skip (br, 1);        /* low_delay */
155     gst_bit_reader_get_bits_uint32 (    /* vbv_parameters */
156         br, &vbv_param, 1);
157     if (vbv_param) {
158       gst_bit_reader_skip (br, 79);     /* don't care */
159     }
160   }
161
162   gst_bit_reader_skip (br, 2);  /* video_object_layer_shape */
163   gst_bit_reader_skip (br, 1);  /* marker_bit */
164   gst_bit_reader_get_bits_uint32 (br,   /* vop_time_increment_resolution */
165       &vop_tir, 16);
166   gst_bit_reader_skip (br, 1);  /* marker_bit */
167
168   self->time_increment_bits = (guint32) log2 ((double) (vop_tir - 1)) + 1;
169
170   GST_DEBUG_OBJECT (self, "vop_tir=%d, time_increment_bits=%d",
171       vop_tir, self->time_increment_bits);
172
173   if (self->time_increment_bits < 1)
174     self->time_increment_bits = 1;
175
176   /* we don't care about anything beyond here */
177 }
178
179 static void
180 decode_user_data (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
181 {
182   GstDucatiVidDec *vdec = GST_DUCATIVIDDEC (self);
183   const char *buf = (const char *) data;
184   int n, ver, build;
185   char c;
186
187   /* divx detection: */
188   n = sscanf (buf, "DivX%dBuild%d%c", &ver, &build, &c);
189   if (n < 2)
190     n = sscanf (buf, "DivX%db%d%c", &ver, &build, &c);
191   if (n >= 2) {
192     GST_INFO_OBJECT (self, "DivX: version %d, build %d", ver, build);
193     if ((n == 3) && (c == 'p')) {
194       GST_INFO_OBJECT (self, "detected packed B frames");
195       /* enable workarounds: */
196       vdec->ts_is_pts = TRUE;
197     }
198   }
199
200   /* xvid detection: */
201   n = sscanf (buf, "XviD%d", &build);
202   if (n == 1) {
203     GST_INFO_OBJECT (self, "XviD: build %d", build);
204     /* I believe we only get this in avi container, which means
205      * we also need to enable the workarounds:
206      */
207     vdec->ts_is_pts = TRUE;
208   }
209 }
210
211 static gboolean
212 is_vop_coded (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
213 {
214   GstBitReader *br = get_bit_reader (self, data, size);
215   guint32 b = 0;
216
217   gst_bit_reader_skip (br, 2);  /* vop_coding_type */
218
219   do {                          /* modulo_time_base */
220     gst_bit_reader_get_bits_uint32 (br, &b, 1);
221   } while (b != 0);
222
223   gst_bit_reader_skip (br, 1);  /* marker_bit */
224   gst_bit_reader_skip (br,      /* vop_time_increment */
225       self->time_increment_bits);
226   gst_bit_reader_skip (br, 1);  /* marker_bit */
227   gst_bit_reader_get_bits_uint32 (br,   /* vop_coded */
228       &b, 1);
229
230   return b;
231 }
232
233 static GstFlowReturn
234 video_decoder_parse (GstVideoDecoder * decoder,
235     GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos)
236 {
237   gint size = 0;
238   guint8 last_start_code = 0xff;
239   gint insize = gst_adapter_available (adapter);
240   GstDucatiMpeg4Dec *self = GST_DUCATIMPEG4DEC (decoder);
241   const guint8 *in = gst_adapter_map (adapter, insize);
242
243   /* TODO: Use the mpeg4video parser functions from codecparser
244    * instead of our own grown ones
245    *
246    * IMPORTANT TODO: Detect KeyFrames */
247   while (insize > (SC_SZ + 1)) {
248     gint nal_size;
249     guint8 start_code = in[SC_SZ];
250     gboolean skip = FALSE;
251
252     GST_DEBUG_OBJECT (self, "start_code: %02x", start_code);
253
254     if (size > 0) {
255       /* check if we've found a potential start of frame: */
256       if ((start_code == VOS_START_CODE) || (start_code == GVOP_START_CODE) || (start_code == VOP_START_CODE) || (start_code <= 0x1f)) {        /* 00->0f is video_object_start_code */
257         /* if last was a VOP, or if this is first VOP, then what follows
258          * must be the next frame:
259          */
260         if (((last_start_code == 0xff) && (start_code == VOP_START_CODE)) ||
261             (last_start_code == VOP_START_CODE)) {
262           GST_DEBUG_OBJECT (self, "found end");
263
264           gst_video_decoder_add_to_frame (decoder, size);
265
266           /* Got a full frame */
267           return gst_video_decoder_have_frame (decoder);
268         }
269       } else if ((0x20 <= start_code) && (start_code <= 0x2f)) {
270         decode_vol_header (self, in + SC_SZ + 1, insize - SC_SZ - 1);
271       }
272     }
273
274     last_start_code = start_code;
275
276     nal_size = SC_SZ + find_start_code (sc, SC_SZ, in + SC_SZ, insize - SC_SZ);
277
278     if ((start_code == VOP_START_CODE) && (nal_size < 20)) {
279       /* suspiciously small nal..  check for !vop_coded and filter
280        * that out to avoid upsetting the decoder:
281        *
282        * XXX 20 is arbitrary value, but I want to avoid having
283        * to parse every VOP.. the non-coded VOP's I'm seeing
284        * are all 7 bytes but need to come up with some sane
285        * threshold
286        */
287       skip = !is_vop_coded (self, in + SC_SZ + 1, insize - SC_SZ - 1);
288       if (skip)
289         GST_DEBUG_OBJECT (self, "skipping non-coded VOP");
290     } else if (start_code == UD_START_CODE) {
291       decode_user_data (self, in + SC_SZ + 1, nal_size - SC_SZ - 1);
292     }
293
294     if (!skip)
295       gst_video_decoder_add_to_frame (decoder, size);
296
297     in += nal_size;
298     insize -= nal_size;
299     size += nal_size;
300   }
301   gst_adapter_unmap (adapter);
302
303   return GST_VIDEO_DECODER_FLOW_NEED_DATA;
304 }
305
306 static gboolean
307 videodecoder_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state)
308 {
309   gboolean parsed;
310   GstStructure *structure;
311
312   if (!GST_CALL_PARENT_WITH_DEFAULT (GST_VIDEO_DECODER_CLASS, set_format,
313           (decoder, state), TRUE))
314     return FALSE;
315
316   /* Check if packetized or not */
317   structure = gst_caps_get_structure (state->caps, 0);
318   parsed = gst_structure_get_boolean (structure, "parsed", &parsed);
319   GST_DEBUG_OBJECT (decoder, "Caps %" GST_PTR_FORMAT, structure);
320   if (!parsed) {
321     GST_DEBUG_OBJECT (decoder, "Not in packetized mode");
322     gst_video_decoder_set_packetized (decoder, FALSE);
323   }
324
325   return TRUE;
326 }
327
328 /* GObject vmethod implementations */
329
330 static void
331 gst_ducati_mpeg4dec_finalize (GObject * obj)
332 {
333   GstDucatiMpeg4Dec *self = GST_DUCATIMPEG4DEC (obj);
334   if (self->br)
335     gst_bit_reader_free (self->br);
336   G_OBJECT_CLASS (parent_class)->finalize (obj);
337 }
338
339 static void
340 gst_ducati_mpeg4dec_class_init (GstDucatiMpeg4DecClass * klass)
341 {
342   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
343   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
344   GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
345   GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
346
347   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_finalize);
348
349   gst_element_class_set_static_metadata (element_class,
350       "DucatiMpeg4Dec",
351       "Codec/Decoder/Video",
352       "Decodes video in MPEG-4 format with ducati", "Rob Clark <rob@ti.com>");
353
354   gst_element_class_add_pad_template (element_class,
355       gst_static_pad_template_get (&sink_factory));
356
357   bclass->codec_name = "ivahd_mpeg4dec";
358   bclass->update_buffer_size =
359       GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_update_buffer_size);
360   bclass->allocate_params =
361       GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_allocate_params);
362
363   decoder_class->parse = GST_DEBUG_FUNCPTR (video_decoder_parse);
364   decoder_class->set_format = GST_DEBUG_FUNCPTR (videodecoder_set_format);
365 }
366
367 static void
368 gst_ducati_mpeg4dec_init (GstDucatiMpeg4Dec * self)
369 {
370 #ifndef GST_DISABLE_GST_DEBUG
371   GstDucatiVidDec *dec = GST_DUCATIVIDDEC (self);
372
373   dec->error_strings[0] = "no video object sequence found";
374   dec->error_strings[1] = "incorrect video object type";
375   dec->error_strings[2] = "error in video object layer";
376   dec->error_strings[3] = "error parsing group of video";
377   dec->error_strings[4] = "error parsing video object plane";
378   dec->error_strings[5] = "error in short header parsing";
379   dec->error_strings[6] = "error in GOB parsing";
380   dec->error_strings[7] = "error in video packet parsing";
381   dec->error_strings[16] = "error in MB data parsing";
382   dec->error_strings[17] = "invalid parameter";
383   dec->error_strings[18] = "unsupported feature";
384   dec->error_strings[19] = "stream end";
385   dec->error_strings[20] = "valid header not found";
386   dec->error_strings[21] = "unsupported resolution";
387   dec->error_strings[22] = "stream buffer underflow";
388   dec->error_strings[23] = "invalid mbox message";
389   dec->error_strings[24] = "no frame to flush";
390   dec->error_strings[25] = "given vop is not codec";
391   dec->error_strings[26] = "start code not present";
392   dec->error_strings[27] = "unsupported time increment resolution";
393   dec->error_strings[28] = "resolution change";
394   dec->error_strings[29] = "unsupported H263 annex";
395   dec->error_strings[30] = "bad HDVICP2 state";
396   dec->error_strings[31] = "frame dropped";
397 #endif
398 }