Simplify read_obu_header.
Remove unnecessary preproc macros and instead support
parsing of OBU header with extensions unconditionally.
Add OBU type validation and return parsed values to
caller via OBUHeader struct.
Change-Id: I57a36c3cfc59b0c7e894ceb14ed947676f545348
diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c
index ae75220..072ea47 100644
--- a/av1/decoder/obu.c
+++ b/av1/decoder/obu.c
@@ -41,47 +41,69 @@
} SCALABILITY_STRUCTURES;
#endif
+typedef struct {
+ size_t size;
+ OBU_TYPE type;
+ int has_extension;
+ int temporal_layer_id;
+ int enhancement_layer_id;
+} ObuHeader;
+
int get_obu_type(uint8_t obu_header, OBU_TYPE *obu_type) {
if (!obu_type) return -1;
*obu_type = (OBU_TYPE)((obu_header >> 3) & 0xF);
switch (*obu_type) {
- case OBU_SEQUENCE_HEADER: break;
- case OBU_TEMPORAL_DELIMITER: break;
- case OBU_FRAME_HEADER: break;
- case OBU_TILE_GROUP: break;
- case OBU_METADATA: break;
+ case OBU_SEQUENCE_HEADER:
+ case OBU_TEMPORAL_DELIMITER:
+ case OBU_FRAME_HEADER:
+ case OBU_TILE_GROUP:
+ case OBU_METADATA:
case OBU_PADDING: break;
default: return -1;
}
return 0;
}
-static OBU_TYPE read_obu_header(struct aom_read_bit_buffer *rb,
- size_t *header_size,
- uint8_t *obu_extension_header) {
- *header_size = 1;
+// Returns 1 when OBU type is valid, and 0 otherwise.
+static int valid_obu_type(int obu_type) {
+ int valid_type = 0;
+ switch (obu_type) {
+ case OBU_SEQUENCE_HEADER:
+ case OBU_TEMPORAL_DELIMITER:
+ case OBU_FRAME_HEADER:
+ case OBU_TILE_GROUP:
+ case OBU_METADATA:
+ case OBU_PADDING: valid_type = 1; break;
+ default: break;
+ }
+ return valid_type;
+}
+
+// Parses OBU header and stores values in 'header'. Returns 0 for success, and
+// -1 when an error occurs.
+static int read_obu_header(struct aom_read_bit_buffer *rb, ObuHeader *header) {
+ if (!rb || !header) return AOM_CODEC_INVALID_PARAM;
+
+ header->size = 1;
// first bit is obu_forbidden_bit (0) according to R19
aom_rb_read_bit(rb);
- const OBU_TYPE obu_type = (OBU_TYPE)aom_rb_read_literal(rb, 4);
+ header->type = (OBU_TYPE)aom_rb_read_literal(rb, 4);
+
+ if (!valid_obu_type(header->type)) return AOM_CODEC_CORRUPT_FRAME;
+
aom_rb_read_literal(rb, 2); // reserved
- const int obu_extension_flag = aom_rb_read_bit(rb);
- if (obu_extension_header) *obu_extension_header = 0;
- if (obu_extension_flag) {
- *header_size += 1;
-#if !CONFIG_SCALABILITY
- aom_rb_read_literal(rb, 3); // temporal_id
- aom_rb_read_literal(rb, 2);
- aom_rb_read_literal(rb, 2);
- aom_rb_read_literal(rb, 1); // reserved
-#else
- if (obu_extension_header)
- *obu_extension_header = (uint8_t)aom_rb_read_literal(rb, 8);
-#endif
+
+ header->has_extension = aom_rb_read_bit(rb);
+ if (header->has_extension) {
+ header->size += 1;
+ header->temporal_layer_id = aom_rb_read_literal(rb, 3);
+ header->enhancement_layer_id = aom_rb_read_literal(rb, 2);
+ aom_rb_read_literal(rb, 3); // reserved
}
- return obu_type;
+ return AOM_CODEC_OK;
}
static uint32_t read_temporal_delimiter_obu() { return 0; }
@@ -258,13 +280,6 @@
return sz;
}
-#if CONFIG_SCALABILITY
-static const uint32_t kObuExtTemporalIdBitsMask = 0x7;
-static const uint32_t kObuExtTemporalIdBitsShift = 5;
-static const uint32_t kObuExtEnhancementIdBitsMask = 0x3;
-static const uint32_t kObuExtEnhancementIdBitsShift = 3;
-#endif
-
#if CONFIG_OBU_SIZING
static aom_codec_err_t read_obu_size(const uint8_t *data,
size_t bytes_available,
@@ -291,9 +306,8 @@
int frame_header_size = 0;
int seq_header_received = 0;
size_t seq_header_size = 0;
-#if CONFIG_SCALABILITY
- uint8_t obu_extension_header = 0;
-#endif
+ ObuHeader obu_header;
+ memset(&obu_header, 0, sizeof(obu_header));
if (data_end < data) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
@@ -303,7 +317,6 @@
// decode frame as a series of OBUs
while (!frame_decoding_finished && !cm->error.error_code) {
struct aom_read_bit_buffer rb;
- size_t obu_header_size = 0;
size_t obu_payload_size = 0;
const size_t bytes_available = data_end - data;
@@ -323,6 +336,7 @@
return;
}
#endif // !CONFIG_OBU_SIZING
+
#if CONFIG_OBU_SIZE_AFTER_HEADER
size_t length_field_size = 0;
#else
@@ -334,41 +348,37 @@
return;
}
#endif // CONFIG_OBU_SIZE_AFTER_HEADER
+
av1_init_read_bit_buffer(pbi, &rb, data + length_field_size, data_end);
-#if !CONFIG_SCALABILITY
- const OBU_TYPE obu_type = read_obu_header(&rb, &obu_header_size, NULL);
-#else
- const OBU_TYPE obu_type =
- read_obu_header(&rb, &obu_header_size, &obu_extension_header);
-#endif
+ if (read_obu_header(&rb, &obu_header) != AOM_CODEC_OK) {
+ cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
+ return;
+ }
+
#if CONFIG_OBU_SIZE_AFTER_HEADER
size_t obu_size;
- if (read_obu_size(data + obu_header_size, bytes_available - obu_header_size,
+ if (read_obu_size(data + obu_header.size, bytes_available - obu_header.size,
&obu_size, &length_field_size) != AOM_CODEC_OK) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return;
}
av1_init_read_bit_buffer(
- pbi, &rb, data + length_field_size + obu_header_size, data_end);
+ pbi, &rb, data + length_field_size + obu_header.size, data_end);
#endif // CONFIG_OBU_SIZE_AFTER_HEADER
- data += length_field_size + obu_header_size;
+ data += length_field_size + obu_header.size;
if (data_end < data) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return;
}
#if CONFIG_SCALABILITY
- cm->temporal_layer_id =
- (obu_extension_header >> kObuExtTemporalIdBitsShift) &
- kObuExtTemporalIdBitsMask;
- cm->enhancement_layer_id =
- (obu_extension_header >> kObuExtEnhancementIdBitsShift) &
- kObuExtEnhancementIdBitsMask;
+ cm->temporal_layer_id = obu_header.temporal_layer_id;
+ cm->enhancement_layer_id = obu_header.enhancement_layer_id;
#endif
- switch (obu_type) {
+ switch (obu_header.type) {
case OBU_TEMPORAL_DELIMITER:
obu_payload_size = read_temporal_delimiter_obu();
break;
@@ -380,7 +390,7 @@
} else {
// Seeing another sequence header, skip as all sequence headers
// are requred to be identical.
- if (obu_size - obu_header_size != seq_header_size) {
+ if (obu_size - obu_header.size != seq_header_size) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return;
}
@@ -406,7 +416,7 @@
// In this case, obu_size is already excluding the header size.
const size_t payload_offset = obu_size;
#else
- const size_t payload_offset = obu_size - obu_header_size;
+ const size_t payload_offset = obu_size - obu_header.size;
#endif // CONFIG_OBU_SIZE_AFTER_HEADER
obu_payload_size = read_one_tile_group_obu(
pbi, &rb, is_first_tg_obu_received, data, data + payload_offset,