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
This commit is contained in:
Aurélien Zanelli 2014-09-18 11:49:13 +02:00 committed by Sebastian Dröge
parent 61c40523df
commit c9a196d54d

View file

@ -35,6 +35,7 @@
#include "gstvc1parser.h" #include "gstvc1parser.h"
#include "parserutils.h" #include "parserutils.h"
#include <gst/base/gstbytereader.h> #include <gst/base/gstbytereader.h>
#include <gst/base/gstbytewriter.h>
#include <gst/base/gstbitreader.h> #include <gst/base/gstbitreader.h>
#include <string.h> #include <string.h>
@ -1728,32 +1729,78 @@ gst_vc1_parse_sequence_layer (const guint8 * data, gsize size,
GstVC1SeqLayer * seqlayer) GstVC1SeqLayer * seqlayer)
{ {
guint32 tmp; 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); g_return_val_if_fail (seqlayer != NULL, GST_VC1_PARSER_ERROR);
READ_UINT32 (&br, tmp, 8); /* Thanks to the specification, structA and structB fields are defined
if (tmp != 0xC5) * 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; 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) if (tmp != 0x04)
goto failed; 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) == if (parse_sequence_header_struct_c (&br, &seqlayer->struct_c) ==
GST_VC1_PARSER_ERROR) GST_VC1_PARSER_ERROR)
goto failed; 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) == if (parse_sequence_header_struct_a (&br, &seqlayer->struct_a) ==
GST_VC1_PARSER_ERROR) GST_VC1_PARSER_ERROR)
goto failed; goto failed;
READ_UINT32 (&br, tmp, 32); /* 0x0000000C */
if (!gst_byte_reader_get_uint32_le (&byter, &tmp))
goto failed;
if (tmp != 0x0C) if (tmp != 0x0C)
goto failed; 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) == if (parse_sequence_header_struct_b (&br, &seqlayer->struct_b) ==
GST_VC1_PARSER_ERROR) GST_VC1_PARSER_ERROR)
goto failed; goto failed;