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.
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"
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
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
) {
60 case OBU_SEQUENCE_HEADER
:
61 case OBU_TEMPORAL_DELIMITER
:
62 case OBU_FRAME_HEADER
:
66 case OBU_REDUNDANT_FRAME_HEADER
:
68 case OBU_PADDING
: return true;
73 bool ParseObuHeader(uint8_t obu_header_byte
, ObuHeader
*obu_header
) {
74 const int forbidden_bit
=
75 (obu_header_byte
>> kObuForbiddenBitShift
) & kObuForbiddenBitMask
;
77 fprintf(stderr
, "Invalid OBU, forbidden bit set.\n");
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
);
88 obu_header
->has_extension
=
89 (obu_header_byte
>> kObuExtensionFlagBitShift
) & kObuExtensionFlagBitMask
;
90 obu_header
->has_size_field
=
91 (obu_header_byte
>> kObuHasSizeFieldBitShift
) & kObuHasSizeFieldBitMask
;
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
;
105 void PrintObuHeader(const ObuHeader
*header
) {
109 aom_obu_type_to_string(static_cast<OBU_TYPE
>(header
->type
)),
110 header
->has_extension
? "yes" : "no");
111 if (header
->has_extension
) {
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
;
123 int obu_overhead
= 0;
124 ObuHeader obu_header
;
125 while (consumed
< length
) {
126 const int remaining
= length
- consumed
;
127 if (remaining
< kMinimumBytesRequired
) {
129 "OBU parse error. Did not consume all data, %d bytes remain.\n",
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
);
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
);
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
);
170 int current_obu_length
= static_cast<int>(obu_size
);
171 if (obu_header_size
+ static_cast<int>(length_field_size
) +
174 fprintf(stderr
, "OBU parsing failed: not enough OBU data.\n");
177 consumed
+= obu_header_size
+ static_cast<int>(length_field_size
) +
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
);
190 } // namespace aom_tools