Add ssse3 version of aom_smooth_predictor_wxh()
[aom.git] / tools / obu_parser.cc
blob9345b231f0bbf24a1d5a5e986af8358837592748
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.
12 #include <cstdio>
13 #include <string>
15 // TODO(tomfinegan): Remove the aom_config.h include as soon as possible. At
16 // present it's required because aom_config.h determines if the library writes
17 // OBUs.
18 #include "./aom_config.h"
20 #include "aom/aom_integer.h"
21 #include "aom_ports/mem_ops.h"
22 #include "tools/obu_parser.h"
24 namespace {
25 const aom_tools::ObuExtensionHeader kEmptyObuExt = { 0, 0, 0, false };
26 const aom_tools::ObuHeader kEmptyObu = { 0, 0, false, kEmptyObuExt };
27 } // namespace
29 namespace aom_tools {
31 // Basic OBU syntax
32 // 4 bytes: length
33 // 8 bits: Header
34 // 7
35 // forbidden bit
36 // 6,5,4,3
37 // type bits
38 // 2,1
39 // reserved bits
40 // 0
41 // extension bit
42 const uint32_t kObuForbiddenBitMask = 0x1;
43 const uint32_t kObuForbiddenBitShift = 7;
44 const uint32_t kObuTypeBitsMask = 0xF;
45 const uint32_t kObuTypeBitsShift = 3;
46 const uint32_t kObuReservedBitsMask = 0x3;
47 const uint32_t kObuReservedBitsShift = 1;
48 const uint32_t kObuExtensionFlagBitMask = 0x1;
50 // When extension bit is set:
51 // 8 bits: extension header
52 // 7,6,5
53 // temporal ID
54 // 4,3
55 // spatial ID
56 // 2,1
57 // quality ID
58 // 0
59 // reserved bit
60 const uint32_t kObuExtTemporalIdBitsMask = 0x7;
61 const uint32_t kObuExtTemporalIdBitsShift = 5;
62 const uint32_t kObuExtSpatialIdBitsMask = 0x3;
63 const uint32_t kObuExtSpatialIdBitsShift = 3;
64 const uint32_t kObuExtQualityIdBitsMask = 0x3;
65 const uint32_t kObuExtQualityIdBitsShift = 1;
66 const uint32_t kObuExtReservedFlagBit = 0x1;
68 bool ValidObuType(int obu_type) {
69 switch (obu_type) {
70 case OBU_SEQUENCE_HEADER:
71 case OBU_TEMPORAL_DELIMITER:
72 case OBU_FRAME_HEADER:
73 case OBU_TILE_GROUP:
74 case OBU_METADATA:
75 case OBU_PADDING: return true;
77 return false;
80 bool ParseObuHeader(uint8_t obu_header_byte, ObuHeader *obu_header) {
81 const int forbidden_bit =
82 (obu_header_byte >> kObuForbiddenBitShift) & kObuForbiddenBitMask;
83 if (forbidden_bit) {
84 fprintf(stderr, "Invalid OBU, forbidden bit set.\n");
85 return false;
88 obu_header->type = (obu_header_byte >> kObuTypeBitsShift) & kObuTypeBitsMask;
89 if (!ValidObuType(obu_header->type)) {
90 fprintf(stderr, "Invalid OBU type: %d.\n", obu_header->type);
91 return false;
94 obu_header->reserved =
95 (obu_header_byte >> kObuReservedBitsShift) & kObuReservedBitsMask;
96 if (obu_header->reserved != 0) {
97 fprintf(stderr, "Invalid OBU: reserved bit(s) set.\n");
98 return false;
101 obu_header->has_extension = obu_header_byte & kObuExtensionFlagBitMask;
102 return true;
105 bool ParseObuExtensionHeader(uint8_t ext_header_byte,
106 ObuExtensionHeader *ext_header) {
107 ext_header->temporal_id = (ext_header_byte >> kObuExtTemporalIdBitsShift) &
108 kObuExtTemporalIdBitsMask;
109 ext_header->spatial_id =
110 (ext_header_byte >> kObuExtSpatialIdBitsShift) & kObuExtSpatialIdBitsMask;
111 ext_header->quality_id =
112 (ext_header_byte >> kObuExtQualityIdBitsShift) & kObuExtQualityIdBitsMask;
113 ext_header->reserved_flag = ext_header_byte & kObuExtReservedFlagBit;
115 if (ext_header->reserved_flag) {
116 fprintf(stderr, "Invalid OBU Extension: reserved flag set.\n");
117 return false;
120 return true;
123 std::string ObuTypeToString(int obu_type) {
124 switch (obu_type) {
125 case OBU_SEQUENCE_HEADER: return "OBU_SEQUENCE_HEADER";
126 case OBU_TEMPORAL_DELIMITER: return "OBU_TEMPORAL_DELIMITER";
127 case OBU_FRAME_HEADER: return "OBU_FRAME_HEADER";
128 case OBU_TILE_GROUP: return "OBU_TILE_GROUP";
129 case OBU_METADATA: return "OBU_METADATA";
130 case OBU_PADDING: return "OBU_PADDING";
132 return "";
135 void PrintObuHeader(const ObuHeader *header) {
136 printf(
137 " OBU type: %s\n"
138 " extension: %s\n",
139 ObuTypeToString(header->type).c_str(),
140 header->has_extension ? "yes" : "no");
141 if (header->has_extension) {
142 printf(
143 " temporal_id: %d\n"
144 " spatial_id: %d\n"
145 " quality_id: %d\n",
146 header->ext_header.temporal_id, header->ext_header.spatial_id,
147 header->ext_header.quality_id);
151 bool DumpObu(const uint8_t *data, int length, int *obu_overhead_bytes) {
152 const int kObuHeaderLengthSizeBytes = 1;
153 const int kMinimumBytesRequired = 1 + kObuHeaderLengthSizeBytes;
154 int consumed = 0;
155 int obu_overhead = 0;
156 ObuHeader obu_header;
157 while (consumed < length) {
158 const int remaining = length - consumed;
159 if (remaining < kMinimumBytesRequired) {
160 if (remaining > 0) {
161 fprintf(stderr,
162 "OBU parse error. Did not consume all data, %d bytes "
163 "remain.\n",
164 remaining);
166 return false;
169 #if CONFIG_OBU_SIZING
170 uint64_t obu_size = 0;
171 size_t length_field_size;
172 aom_uleb_decode(data + consumed, remaining, &obu_size, &length_field_size);
173 const int current_obu_length = static_cast<int>(obu_size);
174 #else
175 const int current_obu_length = mem_get_le32(data + consumed);
176 const int kObuLengthFieldSizeBytes = 4;
177 const size_t length_field_size = kObuLengthFieldSizeBytes;
178 #endif // CONFIG_OBU_SIZING
180 obu_overhead += (int)length_field_size;
182 if (current_obu_length > remaining) {
183 fprintf(stderr,
184 "OBU parsing failed at offset %d with bad length of %d "
185 "and %d bytes left.\n",
186 consumed, current_obu_length, remaining);
187 return false;
189 consumed += (int)length_field_size;
191 obu_header = kEmptyObu;
192 const uint8_t obu_header_byte = *(data + consumed);
193 if (!ParseObuHeader(obu_header_byte, &obu_header)) {
194 fprintf(stderr, "OBU parsing failed at offset %d.\n", consumed);
195 return false;
198 ++obu_overhead;
200 if (obu_header.has_extension) {
201 const uint8_t obu_ext_header_byte =
202 *(data + consumed + kObuHeaderLengthSizeBytes);
203 if (!ParseObuExtensionHeader(obu_ext_header_byte,
204 &obu_header.ext_header)) {
205 fprintf(stderr, "OBU extension parsing failed at offset %d.\n",
206 consumed);
207 return false;
210 ++obu_overhead;
213 PrintObuHeader(&obu_header);
215 // TODO(tomfinegan): Parse OBU payload. For now just consume it.
216 consumed += current_obu_length;
219 if (obu_overhead_bytes != nullptr) *obu_overhead_bytes = obu_overhead;
221 return true;
224 } // namespace aom_tools