blob: 21a7fc0d030edb08cdd4d6fe7e533133ebdf97f6 [file] [log] [blame]
Cyril Concolato6c788832017-10-30 16:30:35 -07001/*
2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
3 *
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.
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "./obudec.h"
17
18#include "aom_ports/mem_ops.h"
19#include "av1/common/common.h"
Tom Finegan13ee28c2018-02-26 19:37:41 -080020#include "av1/decoder/obu.h"
Cyril Concolato6c788832017-10-30 16:30:35 -070021
Tom Finegan66ae9162018-03-19 18:12:50 -070022#define OBU_BUFFER_SIZE (500 * 1024)
Tom Fineganccb8cc42018-02-22 14:08:13 -080023
Tom Finegan66ae9162018-03-19 18:12:50 -070024#define OBU_HEADER_SIZE 1
25#define OBU_EXTENSION_SIZE 1
Tom Fineganccb8cc42018-02-22 14:08:13 -080026#define OBU_MAX_LENGTH_FIELD_SIZE 8
Tom Finegan66ae9162018-03-19 18:12:50 -070027#define OBU_DETECTION_SIZE \
28 (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + OBU_MAX_LENGTH_FIELD_SIZE)
Cyril Concolato6c788832017-10-30 16:30:35 -070029
Tom Finegan66ae9162018-03-19 18:12:50 -070030// 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'.
33static 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) {
Tom Finegan85db49b2018-03-23 10:49:51 -070037 const size_t num_read = fread(&value_buffer[len], 1, 1, f);
38 if (num_read != 1) {
39 // Ran out of data before completing read of value.
40 return -1;
41 }
Tom Finegan66ae9162018-03-19 18:12:50 -070042 if ((value_buffer[len] >> 7) == 0) {
43 *value_length = (size_t)(len + 1);
44 break;
45 }
46 }
47
48 return aom_uleb_decode(value_buffer, OBU_MAX_LENGTH_FIELD_SIZE, value, NULL);
49}
50
Tom Fineganccb8cc42018-02-22 14:08:13 -080051// 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.
Tom Finegan66ae9162018-03-19 18:12:50 -070055static int obudec_read_obu_size(FILE *infile, uint64_t *obu_size,
56 size_t *length_field_size) {
Tom Fineganccb8cc42018-02-22 14:08:13 -080057 if (!infile || !obu_size) return 1;
58
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);
61 *obu_size = 0;
62
63 if (bytes_read == 0) {
64 return 0;
65 }
66
67 const int seek_pos = (int)bytes_read;
68 if (seek_pos != 0 && fseek(infile, -seek_pos, SEEK_CUR) != 0) return 1;
69
Tom Fineganccb8cc42018-02-22 14:08:13 -080070 if (aom_uleb_decode(read_buffer, bytes_read, obu_size, length_field_size) !=
71 0) {
72 return 1;
73 }
Tom Fineganccb8cc42018-02-22 14:08:13 -080074
75 return 0;
76}
77
Tom Finegan66ae9162018-03-19 18:12:50 -070078// 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.
84static int obudec_read_obu_header(FILE *f, size_t buffer_capacity,
85 uint8_t *obu_data, ObuHeader *obu_header,
86 size_t *bytes_read) {
87 if (!f || buffer_capacity < (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE) ||
Tom Finegan85db49b2018-03-23 10:49:51 -070088 !obu_data || !obu_header || !bytes_read) {
Tom Finegan66ae9162018-03-19 18:12:50 -070089 return -1;
90 }
91 *bytes_read = fread(obu_data, 1, 1, f);
Cyril Concolato6c788832017-10-30 16:30:35 -070092
Tom Finegan66ae9162018-03-19 18:12:50 -070093 if (feof(f) && *bytes_read == 0) {
94 return 0;
95 } else if (*bytes_read != 1) {
96 fprintf(stderr, "obudec: Failure reading OBU header.\n");
97 return -1;
Cyril Concolato6c788832017-10-30 16:30:35 -070098 }
99
Tom Finegan85db49b2018-03-23 10:49:51 -0700100 const int has_extension = (obu_data[0] >> 2) & 0x1;
Tom Finegan66ae9162018-03-19 18:12:50 -0700101 if (has_extension) {
102 if (fread(&obu_data[1], 1, 1, f) != 1) {
103 fprintf(stderr, "obudec: Failure reading OBU extension.");
104 return -1;
Cyril Concolato6c788832017-10-30 16:30:35 -0700105 }
Tom Finegan66ae9162018-03-19 18:12:50 -0700106 ++*bytes_read;
107 }
Cyril Concolato6c788832017-10-30 16:30:35 -0700108
Tom Finegan66ae9162018-03-19 18:12:50 -0700109 size_t obu_bytes_parsed = 0;
Tom Finegan85db49b2018-03-23 10:49:51 -0700110 const aom_codec_err_t parse_result =
Tom Finegan66ae9162018-03-19 18:12:50 -0700111 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");
114 return -1;
Cyril Concolato6c788832017-10-30 16:30:35 -0700115 }
Tom Fineganccb8cc42018-02-22 14:08:13 -0800116
Cyril Concolato6c788832017-10-30 16:30:35 -0700117 return 0;
118}
119
Tom Finegan66ae9162018-03-19 18:12:50 -0700120// 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'.
123static 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;
Tom Fineganccb8cc42018-02-22 14:08:13 -0800126
Tom Finegan66ae9162018-03-19 18:12:50 -0700127 if (fread(obu_data, 1, (size_t)payload_length, f) != payload_length) {
128 fprintf(stderr, "obudec: Failure reading OBU payload.\n");
129 return -1;
130 }
Cyril Concolato6c788832017-10-30 16:30:35 -0700131
Tom Finegan66ae9162018-03-19 18:12:50 -0700132 *bytes_read += payload_length;
133 return 0;
134}
135
136static 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) {
142 return -1;
143 }
144
145 size_t bytes_read = 0;
146 if (obudec_read_obu_header(f, buffer_capacity, obu_data, obu_header,
147 &bytes_read) != 0) {
148 return -1;
149 } else if (bytes_read == 0) {
150 *obu_length = 0;
Hui Sue19c3212018-02-21 14:32:18 -0800151 return 0;
152 }
Tom Finegan41150ad2018-01-23 11:42:55 -0800153
Tom Finegan66ae9162018-03-19 18:12:50 -0700154 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");
159 return -1;
160 }
161 bytes_read += leb128_length;
162
Tom Finegan85db49b2018-03-23 10:49:51 -0700163 if (UINT64_MAX - bytes_read < obu_payload_length) return -1;
Tom Finegan66ae9162018-03-19 18:12:50 -0700164 if (bytes_read + obu_payload_length > buffer_capacity) {
165 *obu_length = bytes_read + obu_payload_length;
166 return -1;
167 }
168
169 if (obu_payload_length > 0 &&
170 obudec_read_obu_payload(f, obu_payload_length, &obu_data[bytes_read],
171 &bytes_read) != 0) {
172 return -1;
173 }
174
175 *obu_length = bytes_read;
176 return 0;
177}
178
179int file_is_obu(struct ObuDecInputContext *obu_ctx) {
180 if (!obu_ctx || !obu_ctx->avx_ctx) return 0;
181
182 struct AvxInputContext *avx_ctx = obu_ctx->avx_ctx;
183 uint8_t detect_buf[OBU_DETECTION_SIZE] = { 0 };
184
185 FILE *f = avx_ctx->file;
186 uint64_t obu_length = 0;
187 ObuHeader obu_header;
188 memset(&obu_header, 0, sizeof(obu_header));
189
190 if (obudec_read_one_obu(f, OBU_DETECTION_SIZE, &detect_buf[0], &obu_length,
191 &obu_header) != 0) {
192 fprintf(stderr, "obudec: Failure reading first OBU.\n");
193 rewind(f);
Tom Fineganccb8cc42018-02-22 14:08:13 -0800194 return 0;
195 }
Tom Finegan9d9ec1f2018-03-14 17:55:18 -0700196
Tom Finegan66ae9162018-03-19 18:12:50 -0700197 if (obu_header.type != OBU_TEMPORAL_DELIMITER) return 0;
Tom Finegan41150ad2018-01-23 11:42:55 -0800198
Tom Finegan66ae9162018-03-19 18:12:50 -0700199 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");
206 rewind(f);
207 return 0;
208 }
209 if (obu_payload_length != 0) {
210 fprintf(
211 stderr,
212 "obudec: Invalid OBU_TEMPORAL_DELIMITER payload length (non-zero).");
213 rewind(f);
214 return 0;
215 }
216 } else {
217 fprintf(stderr, "obudec: OBU size fields required, cannot decode input.\n");
218 rewind(f);
Tom Fineganccb8cc42018-02-22 14:08:13 -0800219 return 0;
220 }
221
Tom Finegan66ae9162018-03-19 18:12:50 -0700222 // 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");
226 rewind(f);
227 return 0;
228 }
229 obu_ctx->buffer_capacity = OBU_BUFFER_SIZE;
230 memcpy(obu_ctx->buffer, &detect_buf[0], obu_length);
231 obu_ctx->bytes_buffered = obu_length;
232
Cyril Concolato6c788832017-10-30 16:30:35 -0700233 return 1;
234}
235
Tom Finegan66ae9162018-03-19 18:12:50 -0700236int 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
240#else
241 size_t *buffer_size
Cyril Concolato6c788832017-10-30 16:30:35 -0700242#endif
Tom Finegan66ae9162018-03-19 18:12:50 -0700243) {
244 FILE *f = obu_ctx->avx_ctx->file;
Tom Finegan85db49b2018-03-23 10:49:51 -0700245 if (!f) return -1;
Tom Finegan66ae9162018-03-19 18:12:50 -0700246
247 *buffer_size = 0;
248 *bytes_read = 0;
249
250 if (feof(f)) {
251 return 1;
252 }
253
254 while (1) {
255 ObuHeader obu_header;
256 memset(&obu_header, 0, sizeof(obu_header));
257
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;
261
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");
264 return -1;
265 }
266
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)
271#endif
272 ) {
273 const uint64_t tu_size = obu_ctx->bytes_buffered;
274
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");
278 return -1;
279 }
280#endif
281 uint8_t *new_buffer = (uint8_t *)realloc(*buffer, tu_size);
282 if (!new_buffer) {
283 free(*buffer);
284 fprintf(stderr, "obudec: Out of memory.\n");
285 return -1;
286 }
287 *buffer = new_buffer;
288 *bytes_read = tu_size;
289 *buffer_size = tu_size;
290 memcpy(*buffer, obu_ctx->buffer, tu_size);
291
292 memmove(obu_ctx->buffer, data, obu_size);
293 obu_ctx->bytes_buffered = obu_size;
294 break;
295 } else {
296 obu_ctx->bytes_buffered += obu_size;
297 }
298 }
299
300 return 0;
301}
302
303void obudec_free(struct ObuDecInputContext *obu_ctx) { free(obu_ctx->buffer); }