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.
18 #include "aom_ports/mem_ops.h"
19 #include "av1/common/common.h"
20 #include "av1/decoder/obu.h"
22 #define OBU_BUFFER_SIZE (500 * 1024)
24 #define OBU_HEADER_SIZE 1
25 #define OBU_EXTENSION_SIZE 1
26 #define OBU_MAX_LENGTH_FIELD_SIZE 8
27 #define OBU_DETECTION_SIZE \
28 (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + OBU_MAX_LENGTH_FIELD_SIZE)
30 // Reads unsigned LEB128 integer and returns 0 upon successful read and decode.
31 // Stores raw bytes in 'value_buffer', length of the number in 'value_length',
32 // and decoded value in 'value'.
33 static int obudec_read_leb128(FILE *f
, uint8_t *value_buffer
,
34 size_t *value_length
, uint64_t *value
) {
35 if (!f
|| !value_buffer
|| !value_length
|| !value
) return -1;
36 for (int len
= 0; len
< OBU_MAX_LENGTH_FIELD_SIZE
; ++len
) {
37 const size_t num_read
= fread(&value_buffer
[len
], 1, 1, f
);
39 // Ran out of data before completing read of value.
42 if ((value_buffer
[len
] >> 7) == 0) {
43 *value_length
= (size_t)(len
+ 1);
48 return aom_uleb_decode(value_buffer
, OBU_MAX_LENGTH_FIELD_SIZE
, value
, NULL
);
51 // Reads OBU size from infile and returns 0 upon success. Returns obu_size via
52 // output pointer obu_size. Returns -1 when reading or parsing fails. Always
53 // returns FILE pointer to position at time of call. Returns 0 and sets obu_size
54 // to 0 when end of file is reached.
55 static int obudec_read_obu_size(FILE *infile
, uint64_t *obu_size
,
56 size_t *length_field_size
) {
57 if (!infile
|| !obu_size
) return 1;
59 uint8_t read_buffer
[OBU_MAX_LENGTH_FIELD_SIZE
] = { 0 };
60 size_t bytes_read
= fread(read_buffer
, 1, OBU_MAX_LENGTH_FIELD_SIZE
, infile
);
63 if (bytes_read
== 0) {
67 const int seek_pos
= (int)bytes_read
;
68 if (seek_pos
!= 0 && fseek(infile
, -seek_pos
, SEEK_CUR
) != 0) return 1;
70 if (aom_uleb_decode(read_buffer
, bytes_read
, obu_size
, length_field_size
) !=
78 // Reads OBU header from 'f'. The 'buffer_capacity' passed in must be large
79 // enough to store an OBU header with extension (2 bytes). Raw OBU data is
80 // written to 'obu_data', parsed OBU header values are written to 'obu_header',
81 // and total bytes read from file are written to 'bytes_read'. Returns 0 for
82 // success, and non-zero on failure. When end of file is reached, the return
83 // value is 0 and the 'bytes_read' value is set to 0.
84 static int obudec_read_obu_header(FILE *f
, size_t buffer_capacity
,
85 uint8_t *obu_data
, ObuHeader
*obu_header
,
87 if (!f
|| buffer_capacity
< (OBU_HEADER_SIZE
+ OBU_EXTENSION_SIZE
) ||
88 !obu_data
|| !obu_header
|| !bytes_read
) {
91 *bytes_read
= fread(obu_data
, 1, 1, f
);
93 if (feof(f
) && *bytes_read
== 0) {
95 } else if (*bytes_read
!= 1) {
96 fprintf(stderr
, "obudec: Failure reading OBU header.\n");
100 const int has_extension
= (obu_data
[0] >> 2) & 0x1;
102 if (fread(&obu_data
[1], 1, 1, f
) != 1) {
103 fprintf(stderr
, "obudec: Failure reading OBU extension.");
109 size_t obu_bytes_parsed
= 0;
110 const aom_codec_err_t parse_result
=
111 aom_read_obu_header(obu_data
, *bytes_read
, &obu_bytes_parsed
, obu_header
);
112 if (parse_result
!= AOM_CODEC_OK
|| *bytes_read
!= obu_bytes_parsed
) {
113 fprintf(stderr
, "obudec: Error parsing OBU header.\n");
120 // Reads OBU payload from 'f' and returns 0 for success when all payload bytes
121 // are read from the file. Payload data is written to 'obu_data', and actual
122 // bytes read written to 'bytes_read'.
123 static int obudec_read_obu_payload(FILE *f
, uint64_t payload_length
,
124 uint8_t *obu_data
, size_t *bytes_read
) {
125 if (!f
|| payload_length
== 0 || !obu_data
|| !bytes_read
) return -1;
127 if (fread(obu_data
, 1, (size_t)payload_length
, f
) != payload_length
) {
128 fprintf(stderr
, "obudec: Failure reading OBU payload.\n");
132 *bytes_read
+= payload_length
;
136 static int obudec_read_one_obu(FILE *f
, size_t buffer_capacity
,
137 uint8_t *obu_data
, uint64_t *obu_length
,
138 ObuHeader
*obu_header
) {
139 const size_t kMinimumBufferSize
= OBU_DETECTION_SIZE
;
140 if (!f
|| !obu_data
|| !obu_length
|| !obu_header
||
141 buffer_capacity
< kMinimumBufferSize
) {
145 size_t bytes_read
= 0;
146 if (obudec_read_obu_header(f
, buffer_capacity
, obu_data
, obu_header
,
149 } else if (bytes_read
== 0) {
154 uint64_t obu_payload_length
= 0;
155 size_t leb128_length
= 0;
156 if (obudec_read_leb128(f
, &obu_data
[bytes_read
], &leb128_length
,
157 &obu_payload_length
) != 0) {
158 fprintf(stderr
, "obudec: Failure reading OBU payload length.\n");
161 bytes_read
+= leb128_length
;
163 if (UINT64_MAX
- bytes_read
< obu_payload_length
) return -1;
164 if (bytes_read
+ obu_payload_length
> buffer_capacity
) {
165 *obu_length
= bytes_read
+ obu_payload_length
;
169 if (obu_payload_length
> 0 &&
170 obudec_read_obu_payload(f
, obu_payload_length
, &obu_data
[bytes_read
],
175 *obu_length
= bytes_read
;
179 int file_is_obu(struct ObuDecInputContext
*obu_ctx
) {
180 if (!obu_ctx
|| !obu_ctx
->avx_ctx
) return 0;
182 struct AvxInputContext
*avx_ctx
= obu_ctx
->avx_ctx
;
183 uint8_t detect_buf
[OBU_DETECTION_SIZE
] = { 0 };
185 FILE *f
= avx_ctx
->file
;
186 uint64_t obu_length
= 0;
187 ObuHeader obu_header
;
188 memset(&obu_header
, 0, sizeof(obu_header
));
190 if (obudec_read_one_obu(f
, OBU_DETECTION_SIZE
, &detect_buf
[0], &obu_length
,
192 fprintf(stderr
, "obudec: Failure reading first OBU.\n");
197 if (obu_header
.type
!= OBU_TEMPORAL_DELIMITER
) return 0;
199 if (obu_header
.has_length_field
) {
200 uint64_t obu_payload_length
= 0;
201 size_t leb128_length
= 0;
202 const size_t obu_length_offset
= obu_header
.has_length_field
? 1 : 2;
203 if (aom_uleb_decode(&detect_buf
[obu_length_offset
], sizeof(leb128_length
),
204 &obu_payload_length
, &leb128_length
) != 0) {
205 fprintf(stderr
, "obudec: Failure decoding OBU payload length.\n");
209 if (obu_payload_length
!= 0) {
212 "obudec: Invalid OBU_TEMPORAL_DELIMITER payload length (non-zero).");
217 fprintf(stderr
, "obudec: OBU size fields required, cannot decode input.\n");
222 // Appears that input is valid Section 5 AV1 stream.
223 obu_ctx
->buffer
= (uint8_t *)calloc(OBU_BUFFER_SIZE
, 1);
224 if (!obu_ctx
->buffer
) {
225 fprintf(stderr
, "Out of memory.\n");
229 obu_ctx
->buffer_capacity
= OBU_BUFFER_SIZE
;
230 memcpy(obu_ctx
->buffer
, &detect_buf
[0], (size_t)obu_length
);
231 obu_ctx
->bytes_buffered
= (size_t)obu_length
;
236 int obudec_read_temporal_unit(struct ObuDecInputContext
*obu_ctx
,
237 uint8_t **buffer
, size_t *bytes_read
,
238 #if CONFIG_SCALABILITY
239 size_t *buffer_size
, int last_layer_id
244 FILE *f
= obu_ctx
->avx_ctx
->file
;
255 ObuHeader obu_header
;
256 memset(&obu_header
, 0, sizeof(obu_header
));
258 uint64_t obu_size
= 0;
259 uint8_t *data
= obu_ctx
->buffer
+ obu_ctx
->bytes_buffered
;
260 const size_t capacity
= obu_ctx
->buffer_capacity
- obu_ctx
->bytes_buffered
;
262 if (obudec_read_one_obu(f
, capacity
, data
, &obu_size
, &obu_header
) != 0) {
263 fprintf(stderr
, "obudec: read_one_obu failed in TU loop\n");
267 if (obu_header
.type
== OBU_TEMPORAL_DELIMITER
|| obu_size
== 0
268 #if CONFIG_SCALABILITY
269 || (obu_header
.has_extension
&&
270 obu_header
.enhancement_layer_id
> last_layer_id
)
273 const size_t tu_size
= obu_ctx
->bytes_buffered
;
275 #if defined AOM_MAX_ALLOCABLE_MEMORY
276 if (tu_size
> AOM_MAX_ALLOCABLE_MEMORY
) {
277 fprintf(stderr
, "obudec: Temporal Unit size exceeds max alloc size.\n");
281 uint8_t *new_buffer
= (uint8_t *)realloc(*buffer
, tu_size
);
284 fprintf(stderr
, "obudec: Out of memory.\n");
287 *buffer
= new_buffer
;
288 *bytes_read
= tu_size
;
289 *buffer_size
= tu_size
;
290 memcpy(*buffer
, obu_ctx
->buffer
, tu_size
);
292 memmove(obu_ctx
->buffer
, data
, (size_t)obu_size
);
293 obu_ctx
->bytes_buffered
= (size_t)obu_size
;
296 obu_ctx
->bytes_buffered
+= (size_t)obu_size
;
303 void obudec_free(struct ObuDecInputContext
*obu_ctx
) { free(obu_ctx
->buffer
); }