codecparsers: mpeg: Add an mpeg video bitstream parsing library
[platform/upstream/gstreamer.git] / gst-libs / gst / codecparsers / gstmpegvideoparser.c
1 /* Gstreamer
2  * Copyright (C) <2011> Intel Corporation
3  * Copyright (C) <2011> Collabora Ltd.
4  * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
5  *
6  * From bad/sys/vdpau/mpeg/mpegutil.c:
7  *   Copyright (C) <2007> Jan Schmidt <thaytan@mad.scientist.com>
8  *   Copyright (C) <2009> Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 /**
27  * SECTION:gstmpegvideoparser
28  * @short_description: Convenience library for mpeg1 and 2 video
29  * bitstream parsing.
30  *
31  * <refsect2>
32  * <para>
33  * Provides useful functions for mpeg videos bitstream parsing.
34  * </para>
35  * </refsect2>
36  */
37
38 #ifdef HAVE_CONFIG_H
39 #  include "config.h"
40 #endif
41
42 #include "gstmpegvideoparser.h"
43
44 #include <string.h>
45 #include <gst/base/gstbitreader.h>
46 #include <gst/base/gstbytereader.h>
47
48 #define MARKER_BIT 0x1
49
50 #define GET_BITS(b, num, bits) G_STMT_START {        \
51   if (!gst_bit_reader_get_bits_uint32(b, bits, num)) \
52     goto failed;                                     \
53   GST_TRACE ("parsed %d bits: %d", num, *(bits));    \
54 } G_STMT_END
55
56 #define READ_UINT8(br, val, nbits) G_STMT_START {  \
57   if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
58     GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
59     goto failed; \
60   } \
61 } G_STMT_END
62
63 #define READ_UINT16(br, val, nbits) G_STMT_START { \
64   if (!gst_bit_reader_get_bits_uint16 (br, &val, nbits)) { \
65     GST_WARNING ("failed to read uint16, nbits: %d", nbits); \
66     goto failed; \
67   } \
68 } G_STMT_END
69
70 #define READ_UINT32(br, val, nbits) G_STMT_START { \
71   if (!gst_bit_reader_get_bits_uint32 (br, &val, nbits)) { \
72     GST_WARNING ("failed to read uint32, nbits: %d", nbits); \
73     goto failed; \
74   } \
75 } G_STMT_END
76
77 /* default intra quant matrix, in zig-zag order */
78 const guint8 default_intra_quantizer_matrix[64] = {
79   8,
80   16, 16,
81   19, 16, 19,
82   22, 22, 22, 22,
83   22, 22, 26, 24, 26,
84   27, 27, 27, 26, 26, 26,
85   26, 27, 27, 27, 29, 29, 29,
86   34, 34, 34, 29, 29, 29, 27, 27,
87   29, 29, 32, 32, 34, 34, 37,
88   38, 37, 35, 35, 34, 35,
89   38, 38, 40, 40, 40,
90   48, 48, 46, 46,
91   56, 56, 58,
92   69, 69,
93   83
94 };
95
96 const guint8 mpeg_zigzag_8x8[64] = {
97   0, 1, 8, 16, 9, 2, 3, 10,
98   17, 24, 32, 25, 18, 11, 4, 5,
99   12, 19, 26, 33, 40, 48, 41, 34,
100   27, 20, 13, 6, 7, 14, 21, 28,
101   35, 42, 49, 56, 57, 50, 43, 36,
102   29, 22, 15, 23, 30, 37, 44, 51,
103   58, 59, 52, 45, 38, 31, 39, 46,
104   53, 60, 61, 54, 47, 55, 62, 63
105 };
106
107 GST_DEBUG_CATEGORY (mpegvideo_parser_debug);
108 #define GST_CAT_DEFAULT mpegvideo_parser_debug
109
110 static gboolean initialized = FALSE;
111
112 static inline gboolean
113 find_start_code (GstBitReader * b)
114 {
115   guint32 bits;
116
117   /* 0 bits until byte aligned */
118   while (b->bit != 0) {
119     GET_BITS (b, 1, &bits);
120   }
121
122   /* 0 bytes until startcode */
123   while (gst_bit_reader_peek_bits_uint32 (b, &bits, 32)) {
124     if (bits >> 8 == 0x1) {
125       return TRUE;
126     } else {
127       gst_bit_reader_skip (b, 8);
128     }
129   }
130
131   return FALSE;
132
133 failed:
134   return FALSE;
135 }
136
137 /* Set the Pixel Aspect Ratio in our hdr from a DAR code in the data */
138 static void
139 set_par_from_dar (GstMpegVideoSequenceHdr * seqhdr, guint8 asr_code)
140 {
141   /* Pixel_width = DAR_width * display_vertical_size */
142   /* Pixel_height = DAR_height * display_horizontal_size */
143   switch (asr_code) {
144     case 0x02:                 /* 3:4 DAR = 4:3 pixels */
145       seqhdr->par_w = 4 * seqhdr->height;
146       seqhdr->par_h = 3 * seqhdr->width;
147       break;
148     case 0x03:                 /* 9:16 DAR */
149       seqhdr->par_w = 16 * seqhdr->height;
150       seqhdr->par_h = 9 * seqhdr->width;
151       break;
152     case 0x04:                 /* 1:2.21 DAR */
153       seqhdr->par_w = 221 * seqhdr->height;
154       seqhdr->par_h = 100 * seqhdr->width;
155       break;
156     case 0x01:                 /* Square pixels */
157       seqhdr->par_w = seqhdr->par_h = 1;
158       break;
159     default:
160       GST_DEBUG ("unknown/invalid aspect_ratio_information %d", asr_code);
161       break;
162   }
163 }
164
165 static void
166 set_fps_from_code (GstMpegVideoSequenceHdr * seqhdr, guint8 fps_code)
167 {
168   const gint framerates[][2] = {
169     {30, 1}, {24000, 1001}, {24, 1}, {25, 1},
170     {30000, 1001}, {30, 1}, {50, 1}, {60000, 1001},
171     {60, 1}, {30, 1}
172   };
173
174   if (fps_code && fps_code < 10) {
175     seqhdr->fps_n = framerates[fps_code][0];
176     seqhdr->fps_d = framerates[fps_code][1];
177   } else {
178     GST_DEBUG ("unknown/invalid frame_rate_code %d", fps_code);
179     /* Force a valid framerate */
180     /* FIXME or should this be kept unknown ?? */
181     seqhdr->fps_n = 30000;
182     seqhdr->fps_d = 1001;
183   }
184 }
185
186 static gboolean
187 gst_mpeg_video_parse_sequence (GstMpegVideoSequenceHdr * seqhdr,
188     GstBitReader * br)
189 {
190   guint8 bits;
191   guint8 load_intra_flag, load_non_intra_flag;
192
193   /* Setting the height/width codes */
194   READ_UINT16 (br, seqhdr->width, 12);
195   READ_UINT16 (br, seqhdr->height, 12);
196
197   READ_UINT8 (br, seqhdr->aspect_ratio_info, 4);
198   set_par_from_dar (seqhdr, seqhdr->aspect_ratio_info);
199
200   READ_UINT8 (br, seqhdr->frame_rate_code, 4);
201   set_fps_from_code (seqhdr, seqhdr->frame_rate_code);
202
203   READ_UINT32 (br, seqhdr->bitrate_value, 18);
204   if (seqhdr->bitrate_value == 0x3ffff) {
205     /* VBR stream */
206     seqhdr->bitrate = 0;
207   } else {
208     /* Value in header is in units of 400 bps */
209     seqhdr->bitrate *= 400;
210   }
211
212   READ_UINT8 (br, bits, 1);
213   if (bits != MARKER_BIT)
214     goto failed;
215
216   /* VBV buffer size */
217   READ_UINT16 (br, seqhdr->vbv_buffer_size_value, 10);
218
219   /* constrained_parameters_flag */
220   READ_UINT8 (br, seqhdr->constrained_parameters_flag, 1);
221
222   /* load_intra_quantiser_matrix */
223   READ_UINT8 (br, load_intra_flag, 1);
224   if (load_intra_flag) {
225     gint i;
226     for (i = 0; i < 64; i++)
227       READ_UINT8 (br, seqhdr->intra_quantizer_matrix[mpeg_zigzag_8x8[i]], 8);
228   } else
229     memcpy (seqhdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64);
230
231   /* non intra quantizer matrix */
232   READ_UINT8 (br, load_non_intra_flag, 1);
233   if (load_non_intra_flag) {
234     gint i;
235     for (i = 0; i < 64; i++)
236       READ_UINT8 (br, seqhdr->non_intra_quantizer_matrix[mpeg_zigzag_8x8[i]],
237           8);
238   } else
239     memset (seqhdr->non_intra_quantizer_matrix, 16, 64);
240
241   /* dump some info */
242   GST_LOG ("width x height: %d x %d", seqhdr->width, seqhdr->height);
243   GST_LOG ("fps: %d/%d", seqhdr->fps_n, seqhdr->fps_d);
244   GST_LOG ("par: %d/%d", seqhdr->par_w, seqhdr->par_h);
245   GST_LOG ("bitrate: %d", seqhdr->bitrate);
246
247   return TRUE;
248
249   /* ERRORS */
250 failed:
251   {
252     GST_WARNING ("Failed to parse sequence header");
253     /* clear out stuff */
254     memset (seqhdr, 0, sizeof (*seqhdr));
255     return FALSE;
256   }
257 }
258
259 static inline guint
260 scan_for_start_codes (const GstByteReader * reader, guint offset, guint size)
261 {
262   const guint8 *data;
263   guint32 state;
264   guint i;
265
266   g_return_val_if_fail (size > 0, -1);
267   g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
268       -1);
269
270   /* we can't find the pattern with less than 4 bytes */
271   if (G_UNLIKELY (size < 4))
272     return -1;
273
274   data = reader->data + reader->byte + offset;
275
276   /* set the state to something that does not match */
277   state = 0xffffffff;
278
279   /* now find data */
280   for (i = 0; i < size; i++) {
281     /* throw away one byte and move in the next byte */
282     state = ((state << 8) | data[i]);
283     if (G_UNLIKELY ((state & 0xffffff00) == 0x00000100)) {
284       /* we have a match but we need to have skipped at
285        * least 4 bytes to fill the state. */
286       if (G_LIKELY (i >= 3))
287         return offset + i - 3;
288     }
289
290     /* TODO: reimplement making 010001 not detected as a sc
291      * Accelerate search for start code
292      * if (data[i] > 1) {
293      * while (i < (size - 4) && data[i] > 1) {
294      *   if (data[i + 3] > 1)
295      *     i += 4;
296      *   else
297      *     i += 1;
298      * }
299      * state = 0x00000100;
300      *}
301      */
302   }
303
304   /* nothing found */
305   return -1;
306 }
307
308 /****** API *******/
309
310 /**
311  * gst_mpeg_video_parse:
312  * @data: The datas from which to parse
313  * @size: The size of @data
314  * @offset: The offset from which to start the parsing
315  *
316  * Parses @data, and detects the different packets types, offset,
317  * and size, starting from @offset
318  *
319  * Returns: a #GList of #GstMpegVideoTypeOffsetSize
320  */
321 GList *
322 gst_mpeg_video_parse (guint8 * data, gsize size, guint offset)
323 {
324   gint off, rsize;
325   GstByteReader br;
326   GList *ret = NULL;
327   size = size - offset;
328
329   if (!initialized) {
330     GST_DEBUG_CATEGORY_INIT (mpegvideo_parser_debug, "codecparsers_mpegvideo",
331         0, "Mpegvideo parser library");
332     initialized = TRUE;
333   }
334
335   if (size <= 0) {
336     GST_DEBUG ("Can't parse from offset %d, buffer is to small", offset);
337     return NULL;
338   }
339
340   gst_byte_reader_init (&br, &data[offset], size);
341
342   off = scan_for_start_codes (&br, 0, size);
343
344   if (off < 0) {
345     GST_DEBUG ("No start code prefix in this buffer");
346     return NULL;
347   }
348
349   while (off >= 0 && off + 3 < size) {
350     GstMpegVideoTypeOffsetSize *codoffsize;
351
352     gst_byte_reader_skip (&br, off + 3);
353
354     codoffsize = g_malloc (sizeof (GstMpegVideoTypeOffsetSize));
355     gst_byte_reader_get_uint8 (&br, &codoffsize->type);
356
357     codoffsize->offset = gst_byte_reader_get_pos (&br) + offset;
358
359     rsize = gst_byte_reader_get_remaining (&br);
360     if (rsize <= 0)
361       break;
362
363     off = scan_for_start_codes (&br, 0, rsize);
364
365     codoffsize->size = off;
366
367     ret = g_list_prepend (ret, codoffsize);
368     codoffsize = ret->data;
369   }
370
371   return g_list_reverse (ret);
372 }
373
374 /**
375  * gst_mpeg_video_parse_sequence_header:
376  * @seqhdr: The #GstMpegVideoSequenceHdr to set
377  * @data: The datas from which to parse the seqhdr
378  * @size: The size of @data
379  * @offset: The offset in byte from which to start parsing @data
380  *
381  * Sets the @seqhdr Mpeg Video Sequence Header structure members from @data
382  *
383  * Returns: %TRUE if the seqhdr could be parsed correctly, %FALSE otherwize.
384  */
385 gboolean
386 gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * seqhdr,
387     guint8 * data, gsize size, guint offset)
388 {
389   GstBitReader br;
390
391   size = size - offset;
392
393   if (size - offset < 4)
394     return FALSE;
395
396   gst_bit_reader_init (&br, &data[offset], size);
397
398   return gst_mpeg_video_parse_sequence (seqhdr, &br);
399 }
400
401 /**
402  * gst_mpeg_video_parse_sequence_extension:
403  * @seqhdr: The #GstMpegVideoSequenceExt to set
404  * @data: The datas from which to parse the seqext
405  * @size: The size of @data
406  * @offset: The offset in byte from which to start parsing @data
407  *
408  * Sets the @seqext Mpeg Video Sequence Extension structure members from @data
409  *
410  * Returns: %TRUE if the seqext could be parsed correctly, %FALSE otherwize.
411  */
412 gboolean
413 gst_mpeg_video_parse_sequence_extension (GstMpegVideoSequenceExt * seqext,
414     guint8 * data, gsize size, guint offset)
415 {
416   GstBitReader br;
417
418   size = size - offset;
419
420   if (size < 6) {
421     GST_DEBUG ("not enough bytes to parse the extension");
422     return FALSE;
423   }
424
425   gst_bit_reader_init (&br, &data[offset], size);
426
427   if (gst_bit_reader_get_bits_uint8_unchecked (&br, 4) !=
428       GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE) {
429     GST_DEBUG ("Not parsing a sequence extension");
430     return FALSE;
431   }
432
433   /* skip profile and level escape bit */
434   gst_bit_reader_skip_unchecked (&br, 1);
435
436   seqext->profile = gst_bit_reader_get_bits_uint8_unchecked (&br, 3);
437   seqext->level = gst_bit_reader_get_bits_uint8_unchecked (&br, 4);
438
439   /* progressive */
440   seqext->progressive = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
441
442   /* chroma format */
443   seqext->chroma_format = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
444
445   /* resolution extension */
446   seqext->horiz_size_ext = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
447   seqext->vert_size_ext = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
448
449   seqext->bitrate_ext = gst_bit_reader_get_bits_uint16_unchecked (&br, 12);
450
451   /* skip marker bits */
452   gst_bit_reader_skip_unchecked (&br, 1);
453
454   seqext->vbv_buffer_size_extension =
455       gst_bit_reader_get_bits_uint8_unchecked (&br, 8);
456   seqext->low_delay = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
457
458   /* framerate extension */
459   seqext->fps_n_ext = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
460   seqext->fps_d_ext = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
461
462   return TRUE;
463 }
464
465 /**
466  * gst_mpeg_video_parse_quant_matrix_extension:
467  * @ext: The #GstMpegVideoQuantMatrixExt to set
468  * @data: The datas from which to parse @quant
469  * @size: The size of @data
470  * @offset: The offset in byte from which to start the parsing
471  *
472  * Sets the @quant Mpeg Video Quant Matrix Extension structure members from
473  * @data
474  *
475  * Returns: %TRUE if the quant matrix extension could be parsed correctly,
476  * %FALSE otherwize.
477  */
478 gboolean
479 gst_mpeg_video_parse_quant_matrix_extension (GstMpegVideoQuantMatrixExt * quant,
480     guint8 * data, gsize size, guint offset)
481 {
482   guint8 i;
483   GstBitReader br;
484
485   size = size - offset;
486
487   if (size < 1) {
488     GST_DEBUG ("not enough bytes to parse the extension");
489     return FALSE;
490   }
491
492   gst_bit_reader_init (&br, &data[offset], size);
493
494   if (gst_bit_reader_get_bits_uint8_unchecked (&br, 4) !=
495       GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX) {
496     GST_DEBUG ("Not parsing a quant matrix extension");
497     return FALSE;
498   }
499
500   READ_UINT8 (&br, quant->load_intra_quantiser_matrix, 1);
501   if (quant->load_intra_quantiser_matrix) {
502     for (i = 0; i < 64; i++) {
503       READ_UINT8 (&br, quant->intra_quantiser_matrix[mpeg_zigzag_8x8[i]], 8);
504     }
505   }
506
507   READ_UINT8 (&br, quant->load_non_intra_quantiser_matrix, 1);
508   if (quant->load_non_intra_quantiser_matrix) {
509     for (i = 0; i < 64; i++) {
510       READ_UINT8 (&br, quant->non_intra_quantiser_matrix[mpeg_zigzag_8x8[i]],
511           8);
512     }
513   }
514
515   READ_UINT8 (&br, quant->load_chroma_intra_quantiser_matrix, 1);
516   if (quant->load_non_intra_quantiser_matrix) {
517     for (i = 0; i < 64; i++) {
518       READ_UINT8 (&br, quant->chroma_intra_quantiser_matrix[mpeg_zigzag_8x8[i]],
519           8);
520     }
521   }
522
523   READ_UINT8 (&br, quant->load_chroma_non_intra_quantiser_matrix, 1);
524   if (quant->load_chroma_non_intra_quantiser_matrix) {
525     for (i = 0; i < 64; i++) {
526       READ_UINT8 (&br,
527           quant->chroma_non_intra_quantiser_matrix[mpeg_zigzag_8x8[i]], 8);
528     }
529   }
530
531   return TRUE;
532
533 failed:
534   GST_WARNING ("error parsing \"Quant Matrix Extension\"");
535   return FALSE;
536 }
537
538 /**
539  * gst_mpeg_video_parse_picture_extension:
540  * @ext: The #GstMpegVideoPictureExt to set
541  * @data: The datas from which to parse the ext
542  * @size: The size of @data
543  * @offset: The offset in byte from which to start the parsing
544  *
545  * Sets the @ext Mpeg Video Picture Extension structure members from @data
546  *
547  * Returns: %TRUE if the picture extension could be parsed correctly,
548  * %FALSE otherwize.
549  */
550 gboolean
551 gst_mpeg_video_parse_picture_extension (GstMpegVideoPictureExt * ext,
552     guint8 * data, gsize size, guint offset)
553 {
554   GstBitReader br;
555
556   size = size - offset;
557
558   if (size < 4)
559     return FALSE;
560
561   gst_bit_reader_init (&br, &data[offset], size);
562
563   /* f_code */
564   READ_UINT8 (&br, ext->f_code[0][0], 4);
565   READ_UINT8 (&br, ext->f_code[0][1], 4);
566   READ_UINT8 (&br, ext->f_code[1][0], 4);
567   READ_UINT8 (&br, ext->f_code[1][1], 4);
568
569   /* intra DC precision */
570   READ_UINT8 (&br, ext->intra_dc_precision, 2);
571
572   /* picture structure */
573   READ_UINT8 (&br, ext->picture_structure, 2);
574
575   /* top field first */
576   READ_UINT8 (&br, ext->top_field_first, 1);
577
578   /* frame pred frame dct */
579   READ_UINT8 (&br, ext->frame_pred_frame_dct, 1);
580
581   /* concealment motion vectors */
582   READ_UINT8 (&br, ext->concealment_motion_vectors, 1);
583
584   /* q scale type */
585   READ_UINT8 (&br, ext->q_scale_type, 1);
586
587   /* intra vlc format */
588   READ_UINT8 (&br, ext->intra_vlc_format, 1);
589
590   /* alternate scan */
591   READ_UINT8 (&br, ext->alternate_scan, 1);
592
593   /* repeat first field */
594   READ_UINT8 (&br, ext->repeat_first_field, 1);
595
596   /* chroma_420_type */
597   READ_UINT8 (&br, ext->chroma_420_type, 1);
598
599   /* progressive_frame */
600   READ_UINT8 (&br, ext->progressive_frame, 1);
601
602   /* composite display */
603   READ_UINT8 (&br, ext->composite_display, 1);
604
605   if (ext->composite_display) {
606
607     /* v axis */
608     READ_UINT8 (&br, ext->v_axis, 1);
609
610     /* field sequence */
611     READ_UINT8 (&br, ext->field_sequence, 3);
612
613     /* sub carrier */
614     READ_UINT8 (&br, ext->sub_carrier, 1);
615
616     /* burst amplitude */
617     READ_UINT8 (&br, ext->burst_amplitude, 7);
618
619     /* sub_carrier phase */
620     READ_UINT8 (&br, ext->sub_carrier_phase, 8);
621   }
622
623   return TRUE;
624
625 failed:
626   GST_WARNING ("error parsing \"Picture Coding Extension\"");
627   return FALSE;
628
629 }
630
631 /**
632  * gst_mpeg_video_parse_picture_header:
633  * @hdr: The #GstMpegVideoPictureHdr to set
634  * @data: The datas from which to parse the hdr
635  * @size: The size of @data
636  * @offset: The offset in byte from which to start the parsing
637  *
638  * Sets the @hdr Mpeg Video Picture Header structure members from @data
639  *
640  * Returns: %TRUE if the picture sequence could be parsed correctly, %FALSE otherwize.
641  */
642 gboolean
643 gst_mpeg_video_parse_picture_header (GstMpegVideoPictureHdr * hdr,
644     guint8 * data, gsize size, guint offset)
645 {
646   GstBitReader br;
647
648   size = size - offset;
649
650   if (size < 4)
651     return FALSE;
652
653   gst_bit_reader_init (&br, &data[offset], size);
654
655   /* temperal sequence number */
656   if (!gst_bit_reader_get_bits_uint16 (&br, &hdr->tsn, 10))
657     return FALSE;
658
659   /* frame type */
660   if (!gst_bit_reader_get_bits_uint8 (&br, (guint8 *) & hdr->pic_type, 3))
661     return FALSE;
662
663   if (hdr->pic_type == 0 || hdr->pic_type > 4)
664     return FALSE;               /* Corrupted picture packet */
665
666   /* skype VBV delay */
667   if (!gst_bit_reader_skip (&br, 8))
668     return FALSE;
669
670   if (hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_P
671       || hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_B) {
672
673     READ_UINT8 (&br, hdr->full_pel_forward_vector, 1);
674
675     READ_UINT8 (&br, hdr->f_code[0][0], 3);
676     hdr->f_code[0][1] = hdr->f_code[0][0];
677   } else {
678     hdr->full_pel_forward_vector = 0;
679     hdr->f_code[0][0] = hdr->f_code[0][1] = 0;
680   }
681
682   if (hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_B) {
683     READ_UINT8 (&br, hdr->full_pel_backward_vector, 1);
684
685     READ_UINT8 (&br, hdr->f_code[1][0], 3);
686     hdr->f_code[1][1] = hdr->f_code[1][0];
687   } else {
688     hdr->full_pel_backward_vector = 0;
689     hdr->f_code[1][0] = hdr->f_code[1][1] = 0;
690   }
691
692   return TRUE;
693
694 failed:
695   {
696     GST_WARNING ("Failed to parse sequence extension");
697     return FALSE;
698   }
699 }
700
701 /**
702  * gst_mpeg_video_parse_gop:
703  * @gop: The #GstMpegVideoGop to set
704  * @data: The datas from which to parse the gop
705  * @size: The size of @data
706  * @offset: The offset in byte from which to start the parsing
707  *
708  *
709  * Sets the @gop Mpeg Video Group of Picture structure members from @data
710  *
711  * Returns: %TRUE if the gop could be parsed correctly, %FALSE otherwize.
712  */
713 gboolean
714 gst_mpeg_video_parse_gop (GstMpegVideoGop * gop, guint8 * data,
715     gsize size, guint offset)
716 {
717   GstBitReader br;
718
719   size = size - offset;
720
721   if (size < 4)
722     return FALSE;
723
724   gst_bit_reader_init (&br, &data[offset], size);
725
726   READ_UINT8 (&br, gop->drop_frame_flag, 1);
727
728   READ_UINT8 (&br, gop->hour, 5);
729
730   READ_UINT8 (&br, gop->minute, 6);
731
732   /* skip unused bit */
733   if (!gst_bit_reader_skip (&br, 1))
734     return FALSE;
735
736   READ_UINT8 (&br, gop->second, 6);
737
738   READ_UINT8 (&br, gop->frame, 6);
739
740   READ_UINT8 (&br, gop->closed_gop, 1);
741
742   READ_UINT8 (&br, gop->broken_gop, 1);
743
744   return TRUE;
745
746 failed:
747   GST_WARNING ("error parsing \"GOP\"");
748   return FALSE;
749 }