From c9a196d54dd41b68473e5a15d17cc37713735147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Zanelli?= Date: Thu, 18 Sep 2014 11:49:13 +0200 Subject: [PATCH] vc1parser: take care of endianness when parsing sequence-layer sequence-layer is serialized in little-endian byte order except for STRUCT_C which is serialized in big-endian byte order. But since STRUCT_A and STRUCT_B fields are defined as unsigned int msb first, we have to pass them as big-endian to their parsing function. So we basically use temporary buffers to convert them in big-endian. See SMPTE 421M Annex J and L. https://bugzilla.gnome.org/show_bug.cgi?id=736871 --- gst-libs/gst/codecparsers/gstvc1parser.c | 59 +++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 84817bbf8d..081e813264 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -35,6 +35,7 @@ #include "gstvc1parser.h" #include "parserutils.h" #include +#include #include #include @@ -1728,32 +1729,78 @@ gst_vc1_parse_sequence_layer (const guint8 * data, gsize size, GstVC1SeqLayer * seqlayer) { guint32 tmp; - GstBitReader br = GST_BIT_READER_INIT (data, size); + guint8 tmp8; + guint8 structA[8] = { 0, }; + guint8 structB[12] = { 0, }; + GstBitReader br; + GstByteReader byter = GST_BYTE_READER_INIT (data, size); + GstByteWriter bytew; g_return_val_if_fail (seqlayer != NULL, GST_VC1_PARSER_ERROR); - READ_UINT32 (&br, tmp, 8); - if (tmp != 0xC5) + /* Thanks to the specification, structA and structB fields are defined + * as unisgned integer msb first. + * But in sequence-layer there are serialized in little-endian byte order, + * so we must take care of their endianness before using bit reader */ + + if (!gst_byte_reader_get_uint24_le (&byter, &seqlayer->numframes)) goto failed; - READ_UINT32 (&br, seqlayer->numframes, 24); + if (!gst_byte_reader_get_uint8 (&byter, &tmp8)) + goto failed; + + if (tmp8 != 0xC5) + goto failed; + + /* 0x00000004 */ + if (!gst_byte_reader_get_uint32_le (&byter, &tmp)) + goto failed; - READ_UINT32 (&br, tmp, 32); if (tmp != 0x04) goto failed; + /* As an exception, structC is serialized in big-endian byte order so + * no endianness issue here but we should at least have 4 bytes */ + if (gst_byte_reader_get_remaining (&byter) < 4) + goto failed; + + gst_bit_reader_init (&br, data + gst_byte_reader_get_pos (&byter), 4); if (parse_sequence_header_struct_c (&br, &seqlayer->struct_c) == GST_VC1_PARSER_ERROR) goto failed; + gst_byte_reader_skip (&byter, 4); + + /* structA */ + gst_byte_writer_init_with_data (&bytew, structA, 8, TRUE); + gst_byte_reader_get_uint32_le (&byter, &tmp); + gst_byte_writer_put_uint32_be (&bytew, tmp); + gst_byte_reader_get_uint32_le (&byter, &tmp); + gst_byte_writer_put_uint32_be (&bytew, tmp); + + gst_bit_reader_init (&br, structA, 8); if (parse_sequence_header_struct_a (&br, &seqlayer->struct_a) == GST_VC1_PARSER_ERROR) goto failed; - READ_UINT32 (&br, tmp, 32); + /* 0x0000000C */ + if (!gst_byte_reader_get_uint32_le (&byter, &tmp)) + goto failed; + if (tmp != 0x0C) goto failed; + /* structB */ + gst_byte_writer_reset (&bytew); + gst_byte_writer_init_with_data (&bytew, structB, 12, TRUE); + gst_byte_reader_get_uint32_le (&byter, &tmp); + gst_byte_writer_put_uint32_be (&bytew, tmp); + gst_byte_reader_get_uint32_le (&byter, &tmp); + gst_byte_writer_put_uint32_be (&bytew, tmp); + gst_byte_reader_get_uint32_le (&byter, &tmp); + gst_byte_writer_put_uint32_be (&bytew, tmp); + + gst_bit_reader_init (&br, structB, 12); if (parse_sequence_header_struct_b (&br, &seqlayer->struct_b) == GST_VC1_PARSER_ERROR) goto failed;