Bug 1558783 - Fixes the subgrid and parent grid highlighter states when both are...
[gecko.git] / third_party / aom / tools / obu_parser.cc
blob7d71386ce4209e0c160c3d4e97d09d9cef3409fc
1 /*
2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
11 #include <string.h>
13 #include <cstdio>
14 #include <string>
16 #include "aom/aom_codec.h"
17 #include "aom/aom_integer.h"
18 #include "aom_ports/mem_ops.h"
19 #include "av1/common/obu_util.h"
20 #include "tools/obu_parser.h"
22 namespace aom_tools {
24 // Basic OBU syntax
25 // 8 bits: Header
26 // 7
27 // forbidden bit
28 // 6,5,4,3
29 // type bits
30 // 2
31 // extension flag bit
32 // 1
33 // has size field bit
34 // 0
35 // reserved bit
36 const uint32_t kObuForbiddenBitMask = 0x1;
37 const uint32_t kObuForbiddenBitShift = 7;
38 const uint32_t kObuTypeBitsMask = 0xF;
39 const uint32_t kObuTypeBitsShift = 3;
40 const uint32_t kObuExtensionFlagBitMask = 0x1;
41 const uint32_t kObuExtensionFlagBitShift = 2;
42 const uint32_t kObuHasSizeFieldBitMask = 0x1;
43 const uint32_t kObuHasSizeFieldBitShift = 1;
45 // When extension flag bit is set:
46 // 8 bits: extension header
47 // 7,6,5
48 // temporal ID
49 // 4,3
50 // spatial ID
51 // 2,1,0
52 // reserved bits
53 const uint32_t kObuExtTemporalIdBitsMask = 0x7;
54 const uint32_t kObuExtTemporalIdBitsShift = 5;
55 const uint32_t kObuExtSpatialIdBitsMask = 0x3;
56 const uint32_t kObuExtSpatialIdBitsShift = 3;
58 bool ValidObuType(int obu_type) {
59 switch (obu_type) {
60 case OBU_SEQUENCE_HEADER:
61 case OBU_TEMPORAL_DELIMITER:
62 case OBU_FRAME_HEADER:
63 case OBU_TILE_GROUP:
64 case OBU_METADATA:
65 case OBU_FRAME:
66 case OBU_REDUNDANT_FRAME_HEADER:
67 case OBU_TILE_LIST:
68 case OBU_PADDING: return true;
70 return false;
73 bool ParseObuHeader(uint8_t obu_header_byte, ObuHeader *obu_header) {
74 const int forbidden_bit =
75 (obu_header_byte >> kObuForbiddenBitShift) & kObuForbiddenBitMask;
76 if (forbidden_bit) {
77 fprintf(stderr, "Invalid OBU, forbidden bit set.\n");
78 return false;
81 obu_header->type = static_cast<OBU_TYPE>(
82 (obu_header_byte >> kObuTypeBitsShift) & kObuTypeBitsMask);
83 if (!ValidObuType(obu_header->type)) {
84 fprintf(stderr, "Invalid OBU type: %d.\n", obu_header->type);
85 return false;
88 obu_header->has_extension =
89 (obu_header_byte >> kObuExtensionFlagBitShift) & kObuExtensionFlagBitMask;
90 obu_header->has_size_field =
91 (obu_header_byte >> kObuHasSizeFieldBitShift) & kObuHasSizeFieldBitMask;
92 return true;
95 bool ParseObuExtensionHeader(uint8_t ext_header_byte, ObuHeader *obu_header) {
96 obu_header->temporal_layer_id =
97 (ext_header_byte >> kObuExtTemporalIdBitsShift) &
98 kObuExtTemporalIdBitsMask;
99 obu_header->spatial_layer_id =
100 (ext_header_byte >> kObuExtSpatialIdBitsShift) & kObuExtSpatialIdBitsMask;
102 return true;
105 void PrintObuHeader(const ObuHeader *header) {
106 printf(
107 " OBU type: %s\n"
108 " extension: %s\n",
109 aom_obu_type_to_string(static_cast<OBU_TYPE>(header->type)),
110 header->has_extension ? "yes" : "no");
111 if (header->has_extension) {
112 printf(
113 " temporal_id: %d\n"
114 " spatial_id: %d\n",
115 header->temporal_layer_id, header->temporal_layer_id);
119 bool DumpObu(const uint8_t *data, int length, int *obu_overhead_bytes) {
120 const int kObuHeaderSizeBytes = 1;
121 const int kMinimumBytesRequired = 1 + kObuHeaderSizeBytes;
122 int consumed = 0;
123 int obu_overhead = 0;
124 ObuHeader obu_header;
125 while (consumed < length) {
126 const int remaining = length - consumed;
127 if (remaining < kMinimumBytesRequired) {
128 fprintf(stderr,
129 "OBU parse error. Did not consume all data, %d bytes remain.\n",
130 remaining);
131 return false;
134 int obu_header_size = 0;
136 memset(&obu_header, 0, sizeof(obu_header));
137 const uint8_t obu_header_byte = *(data + consumed);
138 if (!ParseObuHeader(obu_header_byte, &obu_header)) {
139 fprintf(stderr, "OBU parsing failed at offset %d.\n", consumed);
140 return false;
143 ++obu_overhead;
144 ++obu_header_size;
146 if (obu_header.has_extension) {
147 const uint8_t obu_ext_header_byte =
148 *(data + consumed + kObuHeaderSizeBytes);
149 if (!ParseObuExtensionHeader(obu_ext_header_byte, &obu_header)) {
150 fprintf(stderr, "OBU extension parsing failed at offset %d.\n",
151 consumed + kObuHeaderSizeBytes);
152 return false;
155 ++obu_overhead;
156 ++obu_header_size;
159 PrintObuHeader(&obu_header);
161 uint64_t obu_size = 0;
162 size_t length_field_size = 0;
163 if (aom_uleb_decode(data + consumed + obu_header_size,
164 remaining - obu_header_size, &obu_size,
165 &length_field_size) != 0) {
166 fprintf(stderr, "OBU size parsing failed at offset %d.\n",
167 consumed + obu_header_size);
168 return false;
170 int current_obu_length = static_cast<int>(obu_size);
171 if (obu_header_size + static_cast<int>(length_field_size) +
172 current_obu_length >
173 remaining) {
174 fprintf(stderr, "OBU parsing failed: not enough OBU data.\n");
175 return false;
177 consumed += obu_header_size + static_cast<int>(length_field_size) +
178 current_obu_length;
179 printf(" length: %d\n",
180 static_cast<int>(obu_header_size + length_field_size +
181 current_obu_length));
184 if (obu_overhead_bytes != nullptr) *obu_overhead_bytes = obu_overhead;
185 printf(" TU size: %d\n", consumed);
187 return true;
190 } // namespace aom_tools