2 * Copyright (C) <2011> Intel Corporation
3 * Copyright (C) <2011> Collabora Ltd.
4 * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
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>
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.
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.
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.
27 * SECTION:gstmpegvideoparser
28 * @short_description: Convenience library for mpeg1 and 2 video
33 * Provides useful functions for mpeg videos bitstream parsing.
42 #include "gstmpegvideoparser.h"
45 #include <gst/base/gstbitreader.h>
46 #include <gst/base/gstbytereader.h>
48 #define MARKER_BIT 0x1
50 #define GET_BITS(b, num, bits) G_STMT_START { \
51 if (!gst_bit_reader_get_bits_uint32(b, bits, num)) \
53 GST_TRACE ("parsed %d bits: %d", num, *(bits)); \
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); \
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); \
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); \
77 /* default intra quant matrix, in zig-zag order */
78 const guint8 default_intra_quantizer_matrix[64] = {
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,
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
107 GST_DEBUG_CATEGORY (mpegvideo_parser_debug);
108 #define GST_CAT_DEFAULT mpegvideo_parser_debug
110 static gboolean initialized = FALSE;
112 static inline gboolean
113 find_start_code (GstBitReader * b)
117 /* 0 bits until byte aligned */
118 while (b->bit != 0) {
119 GET_BITS (b, 1, &bits);
122 /* 0 bytes until startcode */
123 while (gst_bit_reader_peek_bits_uint32 (b, &bits, 32)) {
124 if (bits >> 8 == 0x1) {
127 gst_bit_reader_skip (b, 8);
137 /* Set the Pixel Aspect Ratio in our hdr from a DAR code in the data */
139 set_par_from_dar (GstMpegVideoSequenceHdr * seqhdr, guint8 asr_code)
141 /* Pixel_width = DAR_width * display_vertical_size */
142 /* Pixel_height = DAR_height * display_horizontal_size */
144 case 0x02: /* 3:4 DAR = 4:3 pixels */
145 seqhdr->par_w = 4 * seqhdr->height;
146 seqhdr->par_h = 3 * seqhdr->width;
148 case 0x03: /* 9:16 DAR */
149 seqhdr->par_w = 16 * seqhdr->height;
150 seqhdr->par_h = 9 * seqhdr->width;
152 case 0x04: /* 1:2.21 DAR */
153 seqhdr->par_w = 221 * seqhdr->height;
154 seqhdr->par_h = 100 * seqhdr->width;
156 case 0x01: /* Square pixels */
157 seqhdr->par_w = seqhdr->par_h = 1;
160 GST_DEBUG ("unknown/invalid aspect_ratio_information %d", asr_code);
166 set_fps_from_code (GstMpegVideoSequenceHdr * seqhdr, guint8 fps_code)
168 const gint framerates[][2] = {
169 {30, 1}, {24000, 1001}, {24, 1}, {25, 1},
170 {30000, 1001}, {30, 1}, {50, 1}, {60000, 1001},
174 if (fps_code && fps_code < 10) {
175 seqhdr->fps_n = framerates[fps_code][0];
176 seqhdr->fps_d = framerates[fps_code][1];
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;
187 gst_mpeg_video_parse_sequence (GstMpegVideoSequenceHdr * seqhdr,
191 guint8 load_intra_flag, load_non_intra_flag;
193 /* Setting the height/width codes */
194 READ_UINT16 (br, seqhdr->width, 12);
195 READ_UINT16 (br, seqhdr->height, 12);
197 READ_UINT8 (br, seqhdr->aspect_ratio_info, 4);
198 set_par_from_dar (seqhdr, seqhdr->aspect_ratio_info);
200 READ_UINT8 (br, seqhdr->frame_rate_code, 4);
201 set_fps_from_code (seqhdr, seqhdr->frame_rate_code);
203 READ_UINT32 (br, seqhdr->bitrate_value, 18);
204 if (seqhdr->bitrate_value == 0x3ffff) {
208 /* Value in header is in units of 400 bps */
209 seqhdr->bitrate *= 400;
212 READ_UINT8 (br, bits, 1);
213 if (bits != MARKER_BIT)
216 /* VBV buffer size */
217 READ_UINT16 (br, seqhdr->vbv_buffer_size_value, 10);
219 /* constrained_parameters_flag */
220 READ_UINT8 (br, seqhdr->constrained_parameters_flag, 1);
222 /* load_intra_quantiser_matrix */
223 READ_UINT8 (br, load_intra_flag, 1);
224 if (load_intra_flag) {
226 for (i = 0; i < 64; i++)
227 READ_UINT8 (br, seqhdr->intra_quantizer_matrix[mpeg_zigzag_8x8[i]], 8);
229 memcpy (seqhdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64);
231 /* non intra quantizer matrix */
232 READ_UINT8 (br, load_non_intra_flag, 1);
233 if (load_non_intra_flag) {
235 for (i = 0; i < 64; i++)
236 READ_UINT8 (br, seqhdr->non_intra_quantizer_matrix[mpeg_zigzag_8x8[i]],
239 memset (seqhdr->non_intra_quantizer_matrix, 16, 64);
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);
252 GST_WARNING ("Failed to parse sequence header");
253 /* clear out stuff */
254 memset (seqhdr, 0, sizeof (*seqhdr));
260 scan_for_start_codes (const GstByteReader * reader, guint offset, guint size)
266 g_return_val_if_fail (size > 0, -1);
267 g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
270 /* we can't find the pattern with less than 4 bytes */
271 if (G_UNLIKELY (size < 4))
274 data = reader->data + reader->byte + offset;
276 /* set the state to something that does not match */
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;
290 /* TODO: reimplement making 010001 not detected as a sc
291 * Accelerate search for start code
293 * while (i < (size - 4) && data[i] > 1) {
294 * if (data[i + 3] > 1)
299 * state = 0x00000100;
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
316 * Parses @data, and detects the different packets types, offset,
317 * and size, starting from @offset
319 * Returns: a #GList of #GstMpegVideoTypeOffsetSize
322 gst_mpeg_video_parse (guint8 * data, gsize size, guint offset)
327 size = size - offset;
330 GST_DEBUG_CATEGORY_INIT (mpegvideo_parser_debug, "codecparsers_mpegvideo",
331 0, "Mpegvideo parser library");
336 GST_DEBUG ("Can't parse from offset %d, buffer is to small", offset);
340 gst_byte_reader_init (&br, &data[offset], size);
342 off = scan_for_start_codes (&br, 0, size);
345 GST_DEBUG ("No start code prefix in this buffer");
349 while (off >= 0 && off + 3 < size) {
350 GstMpegVideoTypeOffsetSize *codoffsize;
352 gst_byte_reader_skip (&br, off + 3);
354 codoffsize = g_malloc (sizeof (GstMpegVideoTypeOffsetSize));
355 gst_byte_reader_get_uint8 (&br, &codoffsize->type);
357 codoffsize->offset = gst_byte_reader_get_pos (&br) + offset;
359 rsize = gst_byte_reader_get_remaining (&br);
363 off = scan_for_start_codes (&br, 0, rsize);
365 codoffsize->size = off;
367 ret = g_list_prepend (ret, codoffsize);
368 codoffsize = ret->data;
371 return g_list_reverse (ret);
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
381 * Sets the @seqhdr Mpeg Video Sequence Header structure members from @data
383 * Returns: %TRUE if the seqhdr could be parsed correctly, %FALSE otherwize.
386 gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * seqhdr,
387 guint8 * data, gsize size, guint offset)
391 size = size - offset;
393 if (size - offset < 4)
396 gst_bit_reader_init (&br, &data[offset], size);
398 return gst_mpeg_video_parse_sequence (seqhdr, &br);
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
408 * Sets the @seqext Mpeg Video Sequence Extension structure members from @data
410 * Returns: %TRUE if the seqext could be parsed correctly, %FALSE otherwize.
413 gst_mpeg_video_parse_sequence_extension (GstMpegVideoSequenceExt * seqext,
414 guint8 * data, gsize size, guint offset)
418 size = size - offset;
421 GST_DEBUG ("not enough bytes to parse the extension");
425 gst_bit_reader_init (&br, &data[offset], size);
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");
433 /* skip profile and level escape bit */
434 gst_bit_reader_skip_unchecked (&br, 1);
436 seqext->profile = gst_bit_reader_get_bits_uint8_unchecked (&br, 3);
437 seqext->level = gst_bit_reader_get_bits_uint8_unchecked (&br, 4);
440 seqext->progressive = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
443 seqext->chroma_format = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
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);
449 seqext->bitrate_ext = gst_bit_reader_get_bits_uint16_unchecked (&br, 12);
451 /* skip marker bits */
452 gst_bit_reader_skip_unchecked (&br, 1);
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);
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);
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
472 * Sets the @quant Mpeg Video Quant Matrix Extension structure members from
475 * Returns: %TRUE if the quant matrix extension could be parsed correctly,
479 gst_mpeg_video_parse_quant_matrix_extension (GstMpegVideoQuantMatrixExt * quant,
480 guint8 * data, gsize size, guint offset)
485 size = size - offset;
488 GST_DEBUG ("not enough bytes to parse the extension");
492 gst_bit_reader_init (&br, &data[offset], size);
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");
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);
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]],
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]],
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++) {
527 quant->chroma_non_intra_quantiser_matrix[mpeg_zigzag_8x8[i]], 8);
534 GST_WARNING ("error parsing \"Quant Matrix Extension\"");
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
545 * Sets the @ext Mpeg Video Picture Extension structure members from @data
547 * Returns: %TRUE if the picture extension could be parsed correctly,
551 gst_mpeg_video_parse_picture_extension (GstMpegVideoPictureExt * ext,
552 guint8 * data, gsize size, guint offset)
556 size = size - offset;
561 gst_bit_reader_init (&br, &data[offset], size);
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);
569 /* intra DC precision */
570 READ_UINT8 (&br, ext->intra_dc_precision, 2);
572 /* picture structure */
573 READ_UINT8 (&br, ext->picture_structure, 2);
575 /* top field first */
576 READ_UINT8 (&br, ext->top_field_first, 1);
578 /* frame pred frame dct */
579 READ_UINT8 (&br, ext->frame_pred_frame_dct, 1);
581 /* concealment motion vectors */
582 READ_UINT8 (&br, ext->concealment_motion_vectors, 1);
585 READ_UINT8 (&br, ext->q_scale_type, 1);
587 /* intra vlc format */
588 READ_UINT8 (&br, ext->intra_vlc_format, 1);
591 READ_UINT8 (&br, ext->alternate_scan, 1);
593 /* repeat first field */
594 READ_UINT8 (&br, ext->repeat_first_field, 1);
596 /* chroma_420_type */
597 READ_UINT8 (&br, ext->chroma_420_type, 1);
599 /* progressive_frame */
600 READ_UINT8 (&br, ext->progressive_frame, 1);
602 /* composite display */
603 READ_UINT8 (&br, ext->composite_display, 1);
605 if (ext->composite_display) {
608 READ_UINT8 (&br, ext->v_axis, 1);
611 READ_UINT8 (&br, ext->field_sequence, 3);
614 READ_UINT8 (&br, ext->sub_carrier, 1);
616 /* burst amplitude */
617 READ_UINT8 (&br, ext->burst_amplitude, 7);
619 /* sub_carrier phase */
620 READ_UINT8 (&br, ext->sub_carrier_phase, 8);
626 GST_WARNING ("error parsing \"Picture Coding Extension\"");
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
638 * Sets the @hdr Mpeg Video Picture Header structure members from @data
640 * Returns: %TRUE if the picture sequence could be parsed correctly, %FALSE otherwize.
643 gst_mpeg_video_parse_picture_header (GstMpegVideoPictureHdr * hdr,
644 guint8 * data, gsize size, guint offset)
648 size = size - offset;
653 gst_bit_reader_init (&br, &data[offset], size);
655 /* temperal sequence number */
656 if (!gst_bit_reader_get_bits_uint16 (&br, &hdr->tsn, 10))
660 if (!gst_bit_reader_get_bits_uint8 (&br, (guint8 *) & hdr->pic_type, 3))
663 if (hdr->pic_type == 0 || hdr->pic_type > 4)
664 return FALSE; /* Corrupted picture packet */
666 /* skype VBV delay */
667 if (!gst_bit_reader_skip (&br, 8))
670 if (hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_P
671 || hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_B) {
673 READ_UINT8 (&br, hdr->full_pel_forward_vector, 1);
675 READ_UINT8 (&br, hdr->f_code[0][0], 3);
676 hdr->f_code[0][1] = hdr->f_code[0][0];
678 hdr->full_pel_forward_vector = 0;
679 hdr->f_code[0][0] = hdr->f_code[0][1] = 0;
682 if (hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_B) {
683 READ_UINT8 (&br, hdr->full_pel_backward_vector, 1);
685 READ_UINT8 (&br, hdr->f_code[1][0], 3);
686 hdr->f_code[1][1] = hdr->f_code[1][0];
688 hdr->full_pel_backward_vector = 0;
689 hdr->f_code[1][0] = hdr->f_code[1][1] = 0;
696 GST_WARNING ("Failed to parse sequence extension");
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
709 * Sets the @gop Mpeg Video Group of Picture structure members from @data
711 * Returns: %TRUE if the gop could be parsed correctly, %FALSE otherwize.
714 gst_mpeg_video_parse_gop (GstMpegVideoGop * gop, guint8 * data,
715 gsize size, guint offset)
719 size = size - offset;
724 gst_bit_reader_init (&br, &data[offset], size);
726 READ_UINT8 (&br, gop->drop_frame_flag, 1);
728 READ_UINT8 (&br, gop->hour, 5);
730 READ_UINT8 (&br, gop->minute, 6);
732 /* skip unused bit */
733 if (!gst_bit_reader_skip (&br, 1))
736 READ_UINT8 (&br, gop->second, 6);
738 READ_UINT8 (&br, gop->frame, 6);
740 READ_UINT8 (&br, gop->closed_gop, 1);
742 READ_UINT8 (&br, gop->broken_gop, 1);
747 GST_WARNING ("error parsing \"GOP\"");