From 37ff8abe1cbb575d738b2692383b59d451cd7ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Mar 2016 13:48:09 +0200 Subject: [PATCH] dash: Add helper for parsing box headers https://bugzilla.gnome.org/show_bug.cgi?id=741104 --- ext/dash/gstisoff.c | 75 ++++++++++++++++++++++++++++++++++++++------- ext/dash/gstisoff.h | 3 ++ 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/ext/dash/gstisoff.c b/ext/dash/gstisoff.c index 3c303931b7..b0b7fcde60 100644 --- a/ext/dash/gstisoff.c +++ b/ext/dash/gstisoff.c @@ -25,6 +25,8 @@ #include "gstisoff.h" #include +#include + void gst_isoff_sidx_parser_init (GstSidxParser * parser) { @@ -56,6 +58,60 @@ gst_isoff_parse_sidx_entry (GstSidxBoxEntry * entry, GstByteReader * reader) entry->sap_delta_time = aux & 0xFFFFFFF; } +/* gst_isoff_parse_box: + * @reader: + * @type: type that was found at the current position + * @extended_type: (allow-none): extended type if type=='uuid' + * @header_size: (allow-none): size of the box header (type, extended type and size) + * @size: size of the complete box including type, extended type and size + * + * Advances the byte reader to the start of the box content. To skip + * over the complete box, skip size - header_size bytes. + * + * Returns: TRUE if a box header could be parsed, FALSE if more data is needed + */ +gboolean +gst_isoff_parse_box_header (GstByteReader * reader, guint32 * type, + guint8 extended_type[16], guint * header_size, guint64 * size) +{ + guint header_start_offset; + guint32 size_field; + + header_start_offset = gst_byte_reader_get_pos (reader); + + if (gst_byte_reader_get_remaining (reader) < 8) + goto not_enough_data; + + size_field = gst_byte_reader_get_uint32_be_unchecked (reader); + *type = gst_byte_reader_get_uint32_le_unchecked (reader); + + if (size_field == 1) { + if (gst_byte_reader_get_remaining (reader) < 8) + goto not_enough_data; + *size = gst_byte_reader_get_uint64_be_unchecked (reader); + } else { + *size = size_field; + } + + if (*type == GST_MAKE_FOURCC ('u', 'u', 'i', 'd')) { + if (gst_byte_reader_get_remaining (reader) < 16) + goto not_enough_data; + + if (extended_type) + memcpy (extended_type, gst_byte_reader_get_data_unchecked (reader, 16), + 16); + } + + if (header_size) + *header_size = gst_byte_reader_get_pos (reader) - header_start_offset; + + return TRUE; + +not_enough_data: + gst_byte_reader_set_pos (reader, header_start_offset); + return FALSE; +} + GstIsoffParserResult gst_isoff_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer, guint * consumed) @@ -75,30 +131,27 @@ gst_isoff_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer, switch (parser->status) { case GST_ISOFF_SIDX_PARSER_INIT: - if (gst_byte_reader_get_remaining (&reader) < GST_ISOFF_FULL_BOX_SIZE) { + if (!gst_isoff_parse_box_header (&reader, &fourcc, NULL, NULL, + &parser->size)) break; - } - parser->size = gst_byte_reader_get_uint32_be_unchecked (&reader); - fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader); if (fourcc != GST_ISOFF_FOURCC_SIDX) { res = GST_ISOFF_PARSER_UNEXPECTED; gst_byte_reader_set_pos (&reader, 0); break; } - if (parser->size == 1) { - if (gst_byte_reader_get_remaining (&reader) < 12) { - gst_byte_reader_set_pos (&reader, 0); - break; - } - parser->size = gst_byte_reader_get_uint64_be_unchecked (&reader); - } if (parser->size == 0) { res = GST_ISOFF_PARSER_ERROR; gst_byte_reader_set_pos (&reader, 0); break; } + + /* Try again once we have enough data for the FullBox header */ + if (gst_byte_reader_get_remaining (&reader) < 4) { + gst_byte_reader_set_pos (&reader, 0); + break; + } parser->sidx.version = gst_byte_reader_get_uint8_unchecked (&reader); parser->sidx.flags = gst_byte_reader_get_uint24_le_unchecked (&reader); diff --git a/ext/dash/gstisoff.h b/ext/dash/gstisoff.h index e535c69c0d..7142727987 100644 --- a/ext/dash/gstisoff.h +++ b/ext/dash/gstisoff.h @@ -26,6 +26,7 @@ #define __GST_ISOFF_H__ #include +#include G_BEGIN_DECLS @@ -36,6 +37,8 @@ typedef enum { GST_ISOFF_PARSER_ERROR } GstIsoffParserResult; +gboolean gst_isoff_parse_box_header (GstByteReader * reader, guint32 * type, guint8 extended_type[16], guint * header_size, guint64 * size); + /* this is the minimum size, it can be larger if it * uses extended size or type */ #define GST_ISOFF_FULL_BOX_SIZE 12