212a4b88211796d6493eef41b04e99c88fb67ada
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-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 */
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
37 #include "gstducatimpeg4dec.h"
39 #include <math.h>
42 #define PADX 32
43 #define PADY 32
46 GST_BOILERPLATE (GstDucatiMpeg4Dec, gst_ducati_mpeg4dec, GstDucatiVidDec,
47 GST_TYPE_DUCATIVIDDEC);
49 #define MPEG4DEC_SINKCAPS_COMMON \
50 "width = (int)[ 16, 2048 ], " \
51 "height = (int)[ 16, 2048 ], " \
52 "framerate = (fraction)[ 0, max ]"
54 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
55 GST_PAD_SINK,
56 GST_PAD_ALWAYS,
57 GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int)4, " "systemstream = (boolean)false, " MPEG4DEC_SINKCAPS_COMMON ";" "video/x-divx, " "divxversion = (int)[4, 5], " /* TODO check this */
58 MPEG4DEC_SINKCAPS_COMMON ";"
59 "video/x-xvid, "
60 MPEG4DEC_SINKCAPS_COMMON ";"
61 "video/x-3ivx, " MPEG4DEC_SINKCAPS_COMMON ";")
62 );
64 /* GstDucatiVidDec vmethod implementations */
66 static void
67 gst_ducati_mpeg4dec_update_buffer_size (GstDucatiVidDec * self)
68 {
69 gint w = self->width;
70 gint h = self->height;
72 /* calculate output buffer parameters: */
73 self->padded_width = ALIGN2 (w + PADX, 7);
74 self->padded_height = h + PADY;
75 self->min_buffers = 8;
76 }
78 static gboolean
79 gst_ducati_mpeg4dec_allocate_params (GstDucatiVidDec * self, gint params_sz,
80 gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
81 {
82 gboolean ret = parent_class->allocate_params (self,
83 sizeof (IMPEG4VDEC_Params), sizeof (IMPEG4VDEC_DynamicParams),
84 sizeof (IMPEG4VDEC_Status), sizeof (IMPEG4VDEC_InArgs),
85 sizeof (IMPEG4VDEC_OutArgs));
87 if (ret) {
88 /* NB: custom params are needed as base params seem to break xvid */
89 IMPEG4VDEC_Params *params = (IMPEG4VDEC_Params *) self->params;
90 self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_AUTO;
91 self->dynParams->lateAcquireArg = -1;
92 params->outloopDeBlocking = FALSE;
93 params->sorensonSparkStream = FALSE;
94 params->errorConcealmentEnable = FALSE;
95 }
97 return ret;
98 }
100 #define VOS_START_CODE 0xb0 /* + visual object sequence */
101 #define VOS_END_CODE 0xb1
102 #define UD_START_CODE 0xb2 /* user data */
103 #define GVOP_START_CODE 0xb3 /* + group of VOP */
104 #define VS_ERROR_CODE 0xb4
105 #define VO_START_CODE 0xb5 /* visual object */
106 #define VOP_START_CODE 0xb6 /* + */
108 static const guint8 sc[] = { 0x00, 0x00, 0x01 }; /* start code */
110 #define SC_SZ G_N_ELEMENTS (sc) /* start code size */
112 static GstBitReader *
113 get_bit_reader (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
114 {
115 if (self->br) {
116 gst_bit_reader_init (self->br, data, size);
117 } else {
118 self->br = gst_bit_reader_new (data, size);
119 }
120 return self->br;
121 }
123 static void
124 decode_vol_header (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
125 {
126 GstBitReader *br = get_bit_reader (self, data, size);
127 guint32 is_oli = 0, vc_param = 0, vbv_param = 0;
128 guint32 ar_info = 0, vop_tir = 0;
130 gst_bit_reader_skip (br, 1); /* random_accessible_vol */
131 gst_bit_reader_skip (br, 8); /* video_object_type_indication */
133 gst_bit_reader_get_bits_uint32 (br, /* is_object_layer_identifier */
134 &is_oli, 1);
135 if (is_oli) {
136 gst_bit_reader_skip (br, 4); /* video_object_layer_verid */
137 gst_bit_reader_skip (br, 3); /* video_object_layer_priority */
138 }
140 gst_bit_reader_get_bits_uint32 (br, /* aspect_ratio_info */
141 &ar_info, 4);
142 if (ar_info == 0xf) {
143 gst_bit_reader_skip (br, 8); /* par_width */
144 gst_bit_reader_skip (br, 8); /* par_height */
145 }
147 gst_bit_reader_get_bits_uint32 (br, /* vol_control_parameters */
148 &vc_param, 1);
149 if (vc_param) {
150 gst_bit_reader_skip (br, 2); /* chroma_format */
151 gst_bit_reader_skip (br, 1); /* low_delay */
152 gst_bit_reader_get_bits_uint32 ( /* vbv_parameters */
153 br, &vbv_param, 1);
154 if (vbv_param) {
155 gst_bit_reader_skip (br, 79); /* don't care */
156 }
157 }
159 gst_bit_reader_skip (br, 2); /* video_object_layer_shape */
160 gst_bit_reader_skip (br, 1); /* marker_bit */
161 gst_bit_reader_get_bits_uint32 (br, /* vop_time_increment_resolution */
162 &vop_tir, 16);
163 gst_bit_reader_skip (br, 1); /* marker_bit */
165 self->time_increment_bits = (guint32) log2 ((double) (vop_tir - 1)) + 1;
167 GST_DEBUG_OBJECT (self, "vop_tir=%d, time_increment_bits=%d",
168 vop_tir, self->time_increment_bits);
170 if (self->time_increment_bits < 1)
171 self->time_increment_bits = 1;
173 /* we don't care about anything beyond here */
174 }
176 static void
177 decode_user_data (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
178 {
179 GstDucatiVidDec *vdec = GST_DUCATIVIDDEC (self);
180 const char *buf = (const char *) data;
181 int n, ver, build;
182 char c;
184 /* divx detection: */
185 n = sscanf (buf, "DivX%dBuild%d%c", &ver, &build, &c);
186 if (n < 2)
187 n = sscanf (buf, "DivX%db%d%c", &ver, &build, &c);
188 if (n >= 2) {
189 GST_INFO_OBJECT (self, "DivX: version %d, build %d", ver, build);
190 if ((n == 3) && (c == 'p')) {
191 GST_INFO_OBJECT (self, "detected packed B frames");
192 /* enable workarounds: */
193 vdec->ts_is_pts = TRUE;
194 }
195 }
197 /* xvid detection: */
198 n = sscanf (buf, "XviD%d", &build);
199 if (n == 1) {
200 GST_INFO_OBJECT (self, "XviD: build %d", build);
201 /* I believe we only get this in avi container, which means
202 * we also need to enable the workarounds:
203 */
204 vdec->ts_is_pts = TRUE;
205 }
206 }
208 static gboolean
209 is_vop_coded (GstDucatiMpeg4Dec * self, const guint8 * data, guint size)
210 {
211 GstBitReader *br = get_bit_reader (self, data, size);
212 guint32 b = 0;
214 gst_bit_reader_skip (br, 2); /* vop_coding_type */
216 do { /* modulo_time_base */
217 gst_bit_reader_get_bits_uint32 (br, &b, 1);
218 } while (b != 0);
220 gst_bit_reader_skip (br, 1); /* marker_bit */
221 gst_bit_reader_skip (br, /* vop_time_increment */
222 self->time_increment_bits);
223 gst_bit_reader_skip (br, 1); /* marker_bit */
224 gst_bit_reader_get_bits_uint32 (br, /* vop_coded */
225 &b, 1);
227 return b;
228 }
230 static GstBuffer *
231 gst_ducati_mpeg4dec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf)
232 {
233 GstDucatiMpeg4Dec *self = GST_DUCATIMPEG4DEC (vdec);
234 GstBuffer *remaining = NULL;
235 gint insize = GST_BUFFER_SIZE (buf);
236 const guint8 *in = GST_BUFFER_DATA (buf);
237 gint size = 0;
238 guint8 last_start_code = 0xff;
240 if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) {
241 push_input (vdec, GST_BUFFER_DATA (vdec->codec_data),
242 GST_BUFFER_SIZE (vdec->codec_data));
243 }
245 while (insize > (SC_SZ + 1)) {
246 gint nal_size;
247 guint8 start_code = in[SC_SZ];
248 gboolean skip = FALSE;
250 GST_DEBUG_OBJECT (self, "start_code: %02x", start_code);
252 if (size > 0) {
253 /* check if we've found a potential start of frame: */
254 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 */
255 /* if last was a VOP, or if this is first VOP, then what follows
256 * must be the next frame:
257 */
258 if (((last_start_code == 0xff) && (start_code == VOP_START_CODE)) ||
259 (last_start_code == VOP_START_CODE)) {
260 GST_DEBUG_OBJECT (self, "found end");
261 break;
262 }
263 } else if ((0x20 <= start_code) && (start_code <= 0x2f)) {
264 decode_vol_header (self, in + SC_SZ + 1, insize - SC_SZ - 1);
265 }
266 }
268 last_start_code = start_code;
270 nal_size = SC_SZ + find_start_code (sc, SC_SZ, in + SC_SZ, insize - SC_SZ);
272 if ((start_code == VOP_START_CODE) && (nal_size < 20)) {
273 /* suspiciously small nal.. check for !vop_coded and filter
274 * that out to avoid upsetting the decoder:
275 *
276 * XXX 20 is arbitrary value, but I want to avoid having
277 * to parse every VOP.. the non-coded VOP's I'm seeing
278 * are all 7 bytes but need to come up with some sane
279 * threshold
280 */
281 skip = !is_vop_coded (self, in + SC_SZ + 1, insize - SC_SZ - 1);
282 if (skip)
283 GST_DEBUG_OBJECT (self, "skipping non-coded VOP");
284 } else if (start_code == UD_START_CODE) {
285 decode_user_data (self, in + SC_SZ + 1, nal_size - SC_SZ - 1);
286 }
288 if (!skip)
289 push_input (vdec, in, nal_size);
291 in += nal_size;
292 insize -= nal_size;
293 size += nal_size;
294 }
296 /* if there are remaining bytes, wrap those back as a buffer
297 * for the next go around:
298 */
299 if (insize > 0) {
300 remaining = gst_buffer_create_sub (buf, size, insize);
302 GST_BUFFER_DURATION (remaining) = GST_BUFFER_DURATION (buf);
303 if (vdec->ts_is_pts) {
304 GST_BUFFER_TIMESTAMP (remaining) = GST_CLOCK_TIME_NONE;
305 } else {
306 GST_BUFFER_TIMESTAMP (remaining) = GST_BUFFER_TIMESTAMP (buf) +
307 GST_BUFFER_DURATION (buf);
308 }
309 }
311 gst_buffer_unref (buf);
313 return remaining;
314 }
316 /* GObject vmethod implementations */
318 static void
319 gst_ducati_mpeg4dec_finalize (GObject * obj)
320 {
321 GstDucatiMpeg4Dec *self = GST_DUCATIMPEG4DEC (obj);
322 if (self->br)
323 gst_bit_reader_free (self->br);
324 G_OBJECT_CLASS (parent_class)->finalize (obj);
325 }
327 static void
328 gst_ducati_mpeg4dec_base_init (gpointer gclass)
329 {
330 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
332 gst_element_class_set_details_simple (element_class,
333 "DucatiMpeg4Dec",
334 "Codec/Decoder/Video",
335 "Decodes video in MPEG-4 format with ducati", "Rob Clark <rob@ti.com>");
337 gst_element_class_add_pad_template (element_class,
338 gst_static_pad_template_get (&sink_factory));
339 }
341 static void
342 gst_ducati_mpeg4dec_class_init (GstDucatiMpeg4DecClass * klass)
343 {
344 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
345 GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
347 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_finalize);
349 bclass->codec_name = "ivahd_mpeg4dec";
350 bclass->update_buffer_size =
351 GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_update_buffer_size);
352 bclass->allocate_params =
353 GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_allocate_params);
354 bclass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_push_input);
355 }
357 static void
358 gst_ducati_mpeg4dec_init (GstDucatiMpeg4Dec * self,
359 GstDucatiMpeg4DecClass * gclass)
360 {
361 #ifndef GST_DISABLE_GST_DEBUG
362 GstDucatiVidDec *dec = GST_DUCATIVIDDEC (self);
364 dec->error_strings[0] = "no video object sequence found";
365 dec->error_strings[1] = "incorrect video object type";
366 dec->error_strings[2] = "error in video object layer";
367 dec->error_strings[3] = "error parsing group of video";
368 dec->error_strings[4] = "error parsing video object plane";
369 dec->error_strings[5] = "error in short header parsing";
370 dec->error_strings[6] = "error in GOB parsing";
371 dec->error_strings[7] = "error in video packet parsing";
372 dec->error_strings[16] = "error in MB data parsing";
373 dec->error_strings[17] = "invalid parameter";
374 dec->error_strings[18] = "unsupported feature";
375 dec->error_strings[19] = "stream end";
376 dec->error_strings[20] = "valid header not found";
377 dec->error_strings[21] = "unsupported resolution";
378 dec->error_strings[22] = "stream buffer underflow";
379 dec->error_strings[23] = "invalid mbox message";
380 dec->error_strings[24] = "no frame to flush";
381 dec->error_strings[25] = "given vop is not codec";
382 dec->error_strings[26] = "start code not present";
383 dec->error_strings[27] = "unsupported time increment resolution";
384 dec->error_strings[28] = "resolution change";
385 dec->error_strings[29] = "unsupported H263 annex";
386 dec->error_strings[30] = "bad HDVICP2 state";
387 dec->error_strings[31] = "frame dropped";
388 #endif
389 }