1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2017, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker *
4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker */
11*77c1e3ccSAndroid Build Coastguard Worker
12*77c1e3ccSAndroid Build Coastguard Worker #include <stdio.h>
13*77c1e3ccSAndroid Build Coastguard Worker #include <stdlib.h>
14*77c1e3ccSAndroid Build Coastguard Worker #include <string.h>
15*77c1e3ccSAndroid Build Coastguard Worker #include <assert.h>
16*77c1e3ccSAndroid Build Coastguard Worker
17*77c1e3ccSAndroid Build Coastguard Worker #include "common/obudec.h"
18*77c1e3ccSAndroid Build Coastguard Worker
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem_ops.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/common.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/obu_util.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "tools_common.h"
24*77c1e3ccSAndroid Build Coastguard Worker
25*77c1e3ccSAndroid Build Coastguard Worker #define OBU_BUFFER_SIZE (500 * 1024)
26*77c1e3ccSAndroid Build Coastguard Worker
27*77c1e3ccSAndroid Build Coastguard Worker #define OBU_HEADER_SIZE 1
28*77c1e3ccSAndroid Build Coastguard Worker #define OBU_EXTENSION_SIZE 1
29*77c1e3ccSAndroid Build Coastguard Worker #define OBU_MAX_LENGTH_FIELD_SIZE 8
30*77c1e3ccSAndroid Build Coastguard Worker
31*77c1e3ccSAndroid Build Coastguard Worker #define OBU_MAX_HEADER_SIZE \
32*77c1e3ccSAndroid Build Coastguard Worker (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + 2 * OBU_MAX_LENGTH_FIELD_SIZE)
33*77c1e3ccSAndroid Build Coastguard Worker
34*77c1e3ccSAndroid Build Coastguard Worker #define OBU_DETECTION_SIZE \
35*77c1e3ccSAndroid Build Coastguard Worker (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + 4 * OBU_MAX_LENGTH_FIELD_SIZE)
36*77c1e3ccSAndroid Build Coastguard Worker
37*77c1e3ccSAndroid Build Coastguard Worker // Reads unsigned LEB128 integer and returns 0 upon successful read and decode.
38*77c1e3ccSAndroid Build Coastguard Worker // Stores raw bytes in 'value_buffer', length of the number in 'value_length',
39*77c1e3ccSAndroid Build Coastguard Worker // and decoded value in 'value'. If 'buffered' is true, it is buffered in the
40*77c1e3ccSAndroid Build Coastguard Worker // detect buffer first.
obudec_read_leb128(struct AvxInputContext * input_ctx,uint8_t * value_buffer,size_t * value_length,uint64_t * value,bool buffered)41*77c1e3ccSAndroid Build Coastguard Worker static int obudec_read_leb128(struct AvxInputContext *input_ctx,
42*77c1e3ccSAndroid Build Coastguard Worker uint8_t *value_buffer, size_t *value_length,
43*77c1e3ccSAndroid Build Coastguard Worker uint64_t *value, bool buffered) {
44*77c1e3ccSAndroid Build Coastguard Worker if (!input_ctx || !value_buffer || !value_length || !value) return -1;
45*77c1e3ccSAndroid Build Coastguard Worker size_t len;
46*77c1e3ccSAndroid Build Coastguard Worker for (len = 0; len < OBU_MAX_LENGTH_FIELD_SIZE; ++len) {
47*77c1e3ccSAndroid Build Coastguard Worker const size_t num_read =
48*77c1e3ccSAndroid Build Coastguard Worker buffer_input(input_ctx, 1, &value_buffer[len], buffered);
49*77c1e3ccSAndroid Build Coastguard Worker if (num_read == 0) {
50*77c1e3ccSAndroid Build Coastguard Worker if (len == 0 && input_eof(input_ctx)) {
51*77c1e3ccSAndroid Build Coastguard Worker *value_length = 0;
52*77c1e3ccSAndroid Build Coastguard Worker return 0;
53*77c1e3ccSAndroid Build Coastguard Worker }
54*77c1e3ccSAndroid Build Coastguard Worker // Ran out of data before completing read of value.
55*77c1e3ccSAndroid Build Coastguard Worker return -1;
56*77c1e3ccSAndroid Build Coastguard Worker }
57*77c1e3ccSAndroid Build Coastguard Worker if ((value_buffer[len] >> 7) == 0) {
58*77c1e3ccSAndroid Build Coastguard Worker ++len;
59*77c1e3ccSAndroid Build Coastguard Worker *value_length = len;
60*77c1e3ccSAndroid Build Coastguard Worker break;
61*77c1e3ccSAndroid Build Coastguard Worker }
62*77c1e3ccSAndroid Build Coastguard Worker }
63*77c1e3ccSAndroid Build Coastguard Worker
64*77c1e3ccSAndroid Build Coastguard Worker return aom_uleb_decode(value_buffer, len, value, NULL);
65*77c1e3ccSAndroid Build Coastguard Worker }
66*77c1e3ccSAndroid Build Coastguard Worker
67*77c1e3ccSAndroid Build Coastguard Worker // Reads OBU header from 'input_ctx'. The 'buffer_capacity' passed in must be
68*77c1e3ccSAndroid Build Coastguard Worker // large enough to store an OBU header with extension (2 bytes). Raw OBU data is
69*77c1e3ccSAndroid Build Coastguard Worker // written to 'obu_data', parsed OBU header values are written to 'obu_header',
70*77c1e3ccSAndroid Build Coastguard Worker // and total bytes read from file are written to 'bytes_read'. Returns 0 for
71*77c1e3ccSAndroid Build Coastguard Worker // success, and non-zero on failure. When end of file is reached, the return
72*77c1e3ccSAndroid Build Coastguard Worker // value is 0 and the 'bytes_read' value is set to 0. If 'buffered' is true, it
73*77c1e3ccSAndroid Build Coastguard Worker // is buffered in the detect buffer first.
obudec_read_obu_header(struct AvxInputContext * input_ctx,size_t buffer_capacity,int is_annexb,uint8_t * obu_data,ObuHeader * obu_header,size_t * bytes_read,bool buffered)74*77c1e3ccSAndroid Build Coastguard Worker static int obudec_read_obu_header(struct AvxInputContext *input_ctx,
75*77c1e3ccSAndroid Build Coastguard Worker size_t buffer_capacity, int is_annexb,
76*77c1e3ccSAndroid Build Coastguard Worker uint8_t *obu_data, ObuHeader *obu_header,
77*77c1e3ccSAndroid Build Coastguard Worker size_t *bytes_read, bool buffered) {
78*77c1e3ccSAndroid Build Coastguard Worker if (!input_ctx || buffer_capacity < (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE) ||
79*77c1e3ccSAndroid Build Coastguard Worker !obu_data || !obu_header || !bytes_read) {
80*77c1e3ccSAndroid Build Coastguard Worker return -1;
81*77c1e3ccSAndroid Build Coastguard Worker }
82*77c1e3ccSAndroid Build Coastguard Worker *bytes_read = buffer_input(input_ctx, 1, obu_data, buffered);
83*77c1e3ccSAndroid Build Coastguard Worker
84*77c1e3ccSAndroid Build Coastguard Worker if (input_eof(input_ctx) && *bytes_read == 0) {
85*77c1e3ccSAndroid Build Coastguard Worker return 0;
86*77c1e3ccSAndroid Build Coastguard Worker } else if (*bytes_read != 1) {
87*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading OBU header.\n");
88*77c1e3ccSAndroid Build Coastguard Worker return -1;
89*77c1e3ccSAndroid Build Coastguard Worker }
90*77c1e3ccSAndroid Build Coastguard Worker
91*77c1e3ccSAndroid Build Coastguard Worker const int has_extension = (obu_data[0] >> 2) & 0x1;
92*77c1e3ccSAndroid Build Coastguard Worker if (has_extension) {
93*77c1e3ccSAndroid Build Coastguard Worker if (buffer_input(input_ctx, 1, &obu_data[1], buffered) != 1) {
94*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading OBU extension.");
95*77c1e3ccSAndroid Build Coastguard Worker return -1;
96*77c1e3ccSAndroid Build Coastguard Worker }
97*77c1e3ccSAndroid Build Coastguard Worker ++*bytes_read;
98*77c1e3ccSAndroid Build Coastguard Worker }
99*77c1e3ccSAndroid Build Coastguard Worker
100*77c1e3ccSAndroid Build Coastguard Worker size_t obu_bytes_parsed = 0;
101*77c1e3ccSAndroid Build Coastguard Worker const aom_codec_err_t parse_result = aom_read_obu_header(
102*77c1e3ccSAndroid Build Coastguard Worker obu_data, *bytes_read, &obu_bytes_parsed, obu_header, is_annexb);
103*77c1e3ccSAndroid Build Coastguard Worker if (parse_result != AOM_CODEC_OK || *bytes_read != obu_bytes_parsed) {
104*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Error parsing OBU header.\n");
105*77c1e3ccSAndroid Build Coastguard Worker return -1;
106*77c1e3ccSAndroid Build Coastguard Worker }
107*77c1e3ccSAndroid Build Coastguard Worker
108*77c1e3ccSAndroid Build Coastguard Worker return 0;
109*77c1e3ccSAndroid Build Coastguard Worker }
110*77c1e3ccSAndroid Build Coastguard Worker
111*77c1e3ccSAndroid Build Coastguard Worker // Reads OBU payload from 'input_ctx' and returns 0 for success when all payload
112*77c1e3ccSAndroid Build Coastguard Worker // bytes are read from the file. Payload data is written to 'obu_data', and
113*77c1e3ccSAndroid Build Coastguard Worker // actual bytes read added to 'bytes_read'. If 'buffered' is true, it is
114*77c1e3ccSAndroid Build Coastguard Worker // buffered in the detect buffer first.
obudec_read_obu_payload(struct AvxInputContext * input_ctx,size_t payload_length,uint8_t * obu_data,size_t * bytes_read,bool buffered)115*77c1e3ccSAndroid Build Coastguard Worker static int obudec_read_obu_payload(struct AvxInputContext *input_ctx,
116*77c1e3ccSAndroid Build Coastguard Worker size_t payload_length, uint8_t *obu_data,
117*77c1e3ccSAndroid Build Coastguard Worker size_t *bytes_read, bool buffered) {
118*77c1e3ccSAndroid Build Coastguard Worker if (!input_ctx || payload_length == 0 || !obu_data || !bytes_read) return -1;
119*77c1e3ccSAndroid Build Coastguard Worker
120*77c1e3ccSAndroid Build Coastguard Worker if (buffer_input(input_ctx, payload_length, obu_data, buffered) !=
121*77c1e3ccSAndroid Build Coastguard Worker payload_length) {
122*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading OBU payload.\n");
123*77c1e3ccSAndroid Build Coastguard Worker return -1;
124*77c1e3ccSAndroid Build Coastguard Worker }
125*77c1e3ccSAndroid Build Coastguard Worker
126*77c1e3ccSAndroid Build Coastguard Worker *bytes_read += payload_length;
127*77c1e3ccSAndroid Build Coastguard Worker return 0;
128*77c1e3ccSAndroid Build Coastguard Worker }
129*77c1e3ccSAndroid Build Coastguard Worker
obudec_read_obu_header_and_size(struct AvxInputContext * input_ctx,size_t buffer_capacity,int is_annexb,uint8_t * buffer,size_t * bytes_read,size_t * payload_length,ObuHeader * obu_header,bool buffered)130*77c1e3ccSAndroid Build Coastguard Worker static int obudec_read_obu_header_and_size(
131*77c1e3ccSAndroid Build Coastguard Worker struct AvxInputContext *input_ctx, size_t buffer_capacity, int is_annexb,
132*77c1e3ccSAndroid Build Coastguard Worker uint8_t *buffer, size_t *bytes_read, size_t *payload_length,
133*77c1e3ccSAndroid Build Coastguard Worker ObuHeader *obu_header, bool buffered) {
134*77c1e3ccSAndroid Build Coastguard Worker const size_t kMinimumBufferSize = OBU_MAX_HEADER_SIZE;
135*77c1e3ccSAndroid Build Coastguard Worker if (!input_ctx || !buffer || !bytes_read || !payload_length || !obu_header ||
136*77c1e3ccSAndroid Build Coastguard Worker buffer_capacity < kMinimumBufferSize) {
137*77c1e3ccSAndroid Build Coastguard Worker return -1;
138*77c1e3ccSAndroid Build Coastguard Worker }
139*77c1e3ccSAndroid Build Coastguard Worker
140*77c1e3ccSAndroid Build Coastguard Worker size_t leb128_length_obu = 0;
141*77c1e3ccSAndroid Build Coastguard Worker size_t leb128_length_payload = 0;
142*77c1e3ccSAndroid Build Coastguard Worker uint64_t obu_size = 0;
143*77c1e3ccSAndroid Build Coastguard Worker if (is_annexb) {
144*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_leb128(input_ctx, &buffer[0], &leb128_length_obu, &obu_size,
145*77c1e3ccSAndroid Build Coastguard Worker buffered) != 0) {
146*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading OBU size length.\n");
147*77c1e3ccSAndroid Build Coastguard Worker return -1;
148*77c1e3ccSAndroid Build Coastguard Worker } else if (leb128_length_obu == 0) {
149*77c1e3ccSAndroid Build Coastguard Worker *payload_length = 0;
150*77c1e3ccSAndroid Build Coastguard Worker return 0;
151*77c1e3ccSAndroid Build Coastguard Worker }
152*77c1e3ccSAndroid Build Coastguard Worker if (obu_size > UINT32_MAX) {
153*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: OBU payload length too large.\n");
154*77c1e3ccSAndroid Build Coastguard Worker return -1;
155*77c1e3ccSAndroid Build Coastguard Worker }
156*77c1e3ccSAndroid Build Coastguard Worker }
157*77c1e3ccSAndroid Build Coastguard Worker
158*77c1e3ccSAndroid Build Coastguard Worker size_t header_size = 0;
159*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_obu_header(input_ctx, buffer_capacity - leb128_length_obu,
160*77c1e3ccSAndroid Build Coastguard Worker is_annexb, buffer + leb128_length_obu, obu_header,
161*77c1e3ccSAndroid Build Coastguard Worker &header_size, buffered) != 0) {
162*77c1e3ccSAndroid Build Coastguard Worker return -1;
163*77c1e3ccSAndroid Build Coastguard Worker } else if (header_size == 0) {
164*77c1e3ccSAndroid Build Coastguard Worker *payload_length = 0;
165*77c1e3ccSAndroid Build Coastguard Worker return 0;
166*77c1e3ccSAndroid Build Coastguard Worker }
167*77c1e3ccSAndroid Build Coastguard Worker
168*77c1e3ccSAndroid Build Coastguard Worker if (!obu_header->has_size_field) {
169*77c1e3ccSAndroid Build Coastguard Worker assert(is_annexb);
170*77c1e3ccSAndroid Build Coastguard Worker if (obu_size < header_size) {
171*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: OBU size is too small.\n");
172*77c1e3ccSAndroid Build Coastguard Worker return -1;
173*77c1e3ccSAndroid Build Coastguard Worker }
174*77c1e3ccSAndroid Build Coastguard Worker *payload_length = (size_t)obu_size - header_size;
175*77c1e3ccSAndroid Build Coastguard Worker } else {
176*77c1e3ccSAndroid Build Coastguard Worker uint64_t u64_payload_length = 0;
177*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_leb128(input_ctx, &buffer[leb128_length_obu + header_size],
178*77c1e3ccSAndroid Build Coastguard Worker &leb128_length_payload, &u64_payload_length,
179*77c1e3ccSAndroid Build Coastguard Worker buffered) != 0) {
180*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading OBU payload length.\n");
181*77c1e3ccSAndroid Build Coastguard Worker return -1;
182*77c1e3ccSAndroid Build Coastguard Worker }
183*77c1e3ccSAndroid Build Coastguard Worker if (u64_payload_length > UINT32_MAX) {
184*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: OBU payload length too large.\n");
185*77c1e3ccSAndroid Build Coastguard Worker return -1;
186*77c1e3ccSAndroid Build Coastguard Worker }
187*77c1e3ccSAndroid Build Coastguard Worker
188*77c1e3ccSAndroid Build Coastguard Worker *payload_length = (size_t)u64_payload_length;
189*77c1e3ccSAndroid Build Coastguard Worker }
190*77c1e3ccSAndroid Build Coastguard Worker
191*77c1e3ccSAndroid Build Coastguard Worker *bytes_read = leb128_length_obu + header_size + leb128_length_payload;
192*77c1e3ccSAndroid Build Coastguard Worker return 0;
193*77c1e3ccSAndroid Build Coastguard Worker }
194*77c1e3ccSAndroid Build Coastguard Worker
obudec_grow_buffer(size_t growth_amount,uint8_t ** obu_buffer,size_t * obu_buffer_capacity)195*77c1e3ccSAndroid Build Coastguard Worker static int obudec_grow_buffer(size_t growth_amount, uint8_t **obu_buffer,
196*77c1e3ccSAndroid Build Coastguard Worker size_t *obu_buffer_capacity) {
197*77c1e3ccSAndroid Build Coastguard Worker if (!*obu_buffer || !obu_buffer_capacity || growth_amount == 0) {
198*77c1e3ccSAndroid Build Coastguard Worker return -1;
199*77c1e3ccSAndroid Build Coastguard Worker }
200*77c1e3ccSAndroid Build Coastguard Worker
201*77c1e3ccSAndroid Build Coastguard Worker const size_t capacity = *obu_buffer_capacity;
202*77c1e3ccSAndroid Build Coastguard Worker if (SIZE_MAX - growth_amount < capacity) {
203*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: cannot grow buffer, capacity will roll over.\n");
204*77c1e3ccSAndroid Build Coastguard Worker return -1;
205*77c1e3ccSAndroid Build Coastguard Worker }
206*77c1e3ccSAndroid Build Coastguard Worker
207*77c1e3ccSAndroid Build Coastguard Worker const size_t new_capacity = capacity + growth_amount;
208*77c1e3ccSAndroid Build Coastguard Worker
209*77c1e3ccSAndroid Build Coastguard Worker #if defined AOM_MAX_ALLOCABLE_MEMORY
210*77c1e3ccSAndroid Build Coastguard Worker if (new_capacity > AOM_MAX_ALLOCABLE_MEMORY) {
211*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: OBU size exceeds max alloc size.\n");
212*77c1e3ccSAndroid Build Coastguard Worker return -1;
213*77c1e3ccSAndroid Build Coastguard Worker }
214*77c1e3ccSAndroid Build Coastguard Worker #endif
215*77c1e3ccSAndroid Build Coastguard Worker
216*77c1e3ccSAndroid Build Coastguard Worker uint8_t *new_buffer = (uint8_t *)realloc(*obu_buffer, new_capacity);
217*77c1e3ccSAndroid Build Coastguard Worker if (!new_buffer) {
218*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failed to allocate compressed data buffer.\n");
219*77c1e3ccSAndroid Build Coastguard Worker return -1;
220*77c1e3ccSAndroid Build Coastguard Worker }
221*77c1e3ccSAndroid Build Coastguard Worker
222*77c1e3ccSAndroid Build Coastguard Worker *obu_buffer = new_buffer;
223*77c1e3ccSAndroid Build Coastguard Worker *obu_buffer_capacity = new_capacity;
224*77c1e3ccSAndroid Build Coastguard Worker return 0;
225*77c1e3ccSAndroid Build Coastguard Worker }
226*77c1e3ccSAndroid Build Coastguard Worker
obudec_read_one_obu(struct AvxInputContext * input_ctx,uint8_t ** obu_buffer,size_t obu_bytes_buffered,size_t * obu_buffer_capacity,size_t * obu_length,ObuHeader * obu_header,int is_annexb,bool buffered)227*77c1e3ccSAndroid Build Coastguard Worker static int obudec_read_one_obu(struct AvxInputContext *input_ctx,
228*77c1e3ccSAndroid Build Coastguard Worker uint8_t **obu_buffer, size_t obu_bytes_buffered,
229*77c1e3ccSAndroid Build Coastguard Worker size_t *obu_buffer_capacity, size_t *obu_length,
230*77c1e3ccSAndroid Build Coastguard Worker ObuHeader *obu_header, int is_annexb,
231*77c1e3ccSAndroid Build Coastguard Worker bool buffered) {
232*77c1e3ccSAndroid Build Coastguard Worker if (!input_ctx || !(*obu_buffer) || !obu_buffer_capacity || !obu_length ||
233*77c1e3ccSAndroid Build Coastguard Worker !obu_header) {
234*77c1e3ccSAndroid Build Coastguard Worker return -1;
235*77c1e3ccSAndroid Build Coastguard Worker }
236*77c1e3ccSAndroid Build Coastguard Worker
237*77c1e3ccSAndroid Build Coastguard Worker size_t bytes_read = 0;
238*77c1e3ccSAndroid Build Coastguard Worker size_t obu_payload_length = 0;
239*77c1e3ccSAndroid Build Coastguard Worker size_t available_buffer_capacity = *obu_buffer_capacity - obu_bytes_buffered;
240*77c1e3ccSAndroid Build Coastguard Worker
241*77c1e3ccSAndroid Build Coastguard Worker if (available_buffer_capacity < OBU_MAX_HEADER_SIZE) {
242*77c1e3ccSAndroid Build Coastguard Worker if (obudec_grow_buffer(AOMMAX(*obu_buffer_capacity, OBU_MAX_HEADER_SIZE),
243*77c1e3ccSAndroid Build Coastguard Worker obu_buffer, obu_buffer_capacity) != 0) {
244*77c1e3ccSAndroid Build Coastguard Worker *obu_length = bytes_read;
245*77c1e3ccSAndroid Build Coastguard Worker return -1;
246*77c1e3ccSAndroid Build Coastguard Worker }
247*77c1e3ccSAndroid Build Coastguard Worker available_buffer_capacity +=
248*77c1e3ccSAndroid Build Coastguard Worker AOMMAX(*obu_buffer_capacity, OBU_MAX_HEADER_SIZE);
249*77c1e3ccSAndroid Build Coastguard Worker }
250*77c1e3ccSAndroid Build Coastguard Worker
251*77c1e3ccSAndroid Build Coastguard Worker const int status = obudec_read_obu_header_and_size(
252*77c1e3ccSAndroid Build Coastguard Worker input_ctx, available_buffer_capacity, is_annexb,
253*77c1e3ccSAndroid Build Coastguard Worker *obu_buffer + obu_bytes_buffered, &bytes_read, &obu_payload_length,
254*77c1e3ccSAndroid Build Coastguard Worker obu_header, buffered);
255*77c1e3ccSAndroid Build Coastguard Worker if (status < 0) return status;
256*77c1e3ccSAndroid Build Coastguard Worker
257*77c1e3ccSAndroid Build Coastguard Worker if (obu_payload_length > SIZE_MAX - bytes_read) return -1;
258*77c1e3ccSAndroid Build Coastguard Worker
259*77c1e3ccSAndroid Build Coastguard Worker if (obu_payload_length > 256 * 1024 * 1024) {
260*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Read invalid OBU size (%u)\n",
261*77c1e3ccSAndroid Build Coastguard Worker (unsigned int)obu_payload_length);
262*77c1e3ccSAndroid Build Coastguard Worker *obu_length = bytes_read + obu_payload_length;
263*77c1e3ccSAndroid Build Coastguard Worker return -1;
264*77c1e3ccSAndroid Build Coastguard Worker }
265*77c1e3ccSAndroid Build Coastguard Worker
266*77c1e3ccSAndroid Build Coastguard Worker if (bytes_read + obu_payload_length > available_buffer_capacity &&
267*77c1e3ccSAndroid Build Coastguard Worker obudec_grow_buffer(AOMMAX(*obu_buffer_capacity, obu_payload_length),
268*77c1e3ccSAndroid Build Coastguard Worker obu_buffer, obu_buffer_capacity) != 0) {
269*77c1e3ccSAndroid Build Coastguard Worker *obu_length = bytes_read + obu_payload_length;
270*77c1e3ccSAndroid Build Coastguard Worker return -1;
271*77c1e3ccSAndroid Build Coastguard Worker }
272*77c1e3ccSAndroid Build Coastguard Worker
273*77c1e3ccSAndroid Build Coastguard Worker if (obu_payload_length > 0 &&
274*77c1e3ccSAndroid Build Coastguard Worker obudec_read_obu_payload(input_ctx, obu_payload_length,
275*77c1e3ccSAndroid Build Coastguard Worker *obu_buffer + obu_bytes_buffered + bytes_read,
276*77c1e3ccSAndroid Build Coastguard Worker &bytes_read, buffered) != 0) {
277*77c1e3ccSAndroid Build Coastguard Worker return -1;
278*77c1e3ccSAndroid Build Coastguard Worker }
279*77c1e3ccSAndroid Build Coastguard Worker
280*77c1e3ccSAndroid Build Coastguard Worker *obu_length = bytes_read;
281*77c1e3ccSAndroid Build Coastguard Worker return 0;
282*77c1e3ccSAndroid Build Coastguard Worker }
283*77c1e3ccSAndroid Build Coastguard Worker
file_is_obu(struct ObuDecInputContext * obu_ctx)284*77c1e3ccSAndroid Build Coastguard Worker int file_is_obu(struct ObuDecInputContext *obu_ctx) {
285*77c1e3ccSAndroid Build Coastguard Worker if (!obu_ctx || !obu_ctx->avx_ctx) return 0;
286*77c1e3ccSAndroid Build Coastguard Worker
287*77c1e3ccSAndroid Build Coastguard Worker struct AvxInputContext *avx_ctx = obu_ctx->avx_ctx;
288*77c1e3ccSAndroid Build Coastguard Worker uint8_t detect_buf[OBU_DETECTION_SIZE] = { 0 };
289*77c1e3ccSAndroid Build Coastguard Worker const int is_annexb = obu_ctx->is_annexb;
290*77c1e3ccSAndroid Build Coastguard Worker size_t payload_length = 0;
291*77c1e3ccSAndroid Build Coastguard Worker ObuHeader obu_header;
292*77c1e3ccSAndroid Build Coastguard Worker memset(&obu_header, 0, sizeof(obu_header));
293*77c1e3ccSAndroid Build Coastguard Worker size_t length_of_unit_size = 0;
294*77c1e3ccSAndroid Build Coastguard Worker size_t annexb_header_length = 0;
295*77c1e3ccSAndroid Build Coastguard Worker uint64_t unit_size = 0;
296*77c1e3ccSAndroid Build Coastguard Worker
297*77c1e3ccSAndroid Build Coastguard Worker if (is_annexb) {
298*77c1e3ccSAndroid Build Coastguard Worker // read the size of first temporal unit
299*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_leb128(avx_ctx, &detect_buf[0], &length_of_unit_size,
300*77c1e3ccSAndroid Build Coastguard Worker &unit_size, /*buffered=*/true) != 0) {
301*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading temporal unit header\n");
302*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
303*77c1e3ccSAndroid Build Coastguard Worker return 0;
304*77c1e3ccSAndroid Build Coastguard Worker }
305*77c1e3ccSAndroid Build Coastguard Worker
306*77c1e3ccSAndroid Build Coastguard Worker // read the size of first frame unit
307*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_leb128(avx_ctx, &detect_buf[length_of_unit_size],
308*77c1e3ccSAndroid Build Coastguard Worker &annexb_header_length, &unit_size,
309*77c1e3ccSAndroid Build Coastguard Worker /*buffered=*/true) != 0) {
310*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading frame unit header\n");
311*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
312*77c1e3ccSAndroid Build Coastguard Worker return 0;
313*77c1e3ccSAndroid Build Coastguard Worker }
314*77c1e3ccSAndroid Build Coastguard Worker annexb_header_length += length_of_unit_size;
315*77c1e3ccSAndroid Build Coastguard Worker }
316*77c1e3ccSAndroid Build Coastguard Worker
317*77c1e3ccSAndroid Build Coastguard Worker size_t bytes_read = 0;
318*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_obu_header_and_size(
319*77c1e3ccSAndroid Build Coastguard Worker avx_ctx, OBU_DETECTION_SIZE - annexb_header_length, is_annexb,
320*77c1e3ccSAndroid Build Coastguard Worker &detect_buf[annexb_header_length], &bytes_read, &payload_length,
321*77c1e3ccSAndroid Build Coastguard Worker &obu_header, /*buffered=*/true) != 0) {
322*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading first OBU.\n");
323*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
324*77c1e3ccSAndroid Build Coastguard Worker return 0;
325*77c1e3ccSAndroid Build Coastguard Worker }
326*77c1e3ccSAndroid Build Coastguard Worker
327*77c1e3ccSAndroid Build Coastguard Worker if (is_annexb) {
328*77c1e3ccSAndroid Build Coastguard Worker bytes_read += annexb_header_length;
329*77c1e3ccSAndroid Build Coastguard Worker }
330*77c1e3ccSAndroid Build Coastguard Worker
331*77c1e3ccSAndroid Build Coastguard Worker if (obu_header.type != OBU_TEMPORAL_DELIMITER &&
332*77c1e3ccSAndroid Build Coastguard Worker obu_header.type != OBU_SEQUENCE_HEADER) {
333*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
334*77c1e3ccSAndroid Build Coastguard Worker return 0;
335*77c1e3ccSAndroid Build Coastguard Worker }
336*77c1e3ccSAndroid Build Coastguard Worker
337*77c1e3ccSAndroid Build Coastguard Worker if (obu_header.has_size_field) {
338*77c1e3ccSAndroid Build Coastguard Worker if (obu_header.type == OBU_TEMPORAL_DELIMITER && payload_length != 0) {
339*77c1e3ccSAndroid Build Coastguard Worker fprintf(
340*77c1e3ccSAndroid Build Coastguard Worker stderr,
341*77c1e3ccSAndroid Build Coastguard Worker "obudec: Invalid OBU_TEMPORAL_DELIMITER payload length (non-zero).");
342*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
343*77c1e3ccSAndroid Build Coastguard Worker return 0;
344*77c1e3ccSAndroid Build Coastguard Worker }
345*77c1e3ccSAndroid Build Coastguard Worker } else if (!is_annexb) {
346*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: OBU size fields required, cannot decode input.\n");
347*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
348*77c1e3ccSAndroid Build Coastguard Worker return 0;
349*77c1e3ccSAndroid Build Coastguard Worker }
350*77c1e3ccSAndroid Build Coastguard Worker
351*77c1e3ccSAndroid Build Coastguard Worker // Appears that input is valid Section 5 AV1 stream.
352*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->buffer = (uint8_t *)malloc(OBU_BUFFER_SIZE);
353*77c1e3ccSAndroid Build Coastguard Worker if (!obu_ctx->buffer) {
354*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "Out of memory.\n");
355*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
356*77c1e3ccSAndroid Build Coastguard Worker return 0;
357*77c1e3ccSAndroid Build Coastguard Worker }
358*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->buffer_capacity = OBU_BUFFER_SIZE;
359*77c1e3ccSAndroid Build Coastguard Worker
360*77c1e3ccSAndroid Build Coastguard Worker memcpy(obu_ctx->buffer, &detect_buf[0], bytes_read);
361*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->bytes_buffered = bytes_read;
362*77c1e3ccSAndroid Build Coastguard Worker // If the first OBU is a SEQUENCE_HEADER, then it will have a payload.
363*77c1e3ccSAndroid Build Coastguard Worker // We need to read this in so that our buffer only contains complete OBUs.
364*77c1e3ccSAndroid Build Coastguard Worker if (payload_length > 0) {
365*77c1e3ccSAndroid Build Coastguard Worker if (payload_length > (obu_ctx->buffer_capacity - bytes_read)) {
366*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: First OBU's payload is too large\n");
367*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
368*77c1e3ccSAndroid Build Coastguard Worker obudec_free(obu_ctx);
369*77c1e3ccSAndroid Build Coastguard Worker return 0;
370*77c1e3ccSAndroid Build Coastguard Worker }
371*77c1e3ccSAndroid Build Coastguard Worker
372*77c1e3ccSAndroid Build Coastguard Worker size_t payload_bytes = 0;
373*77c1e3ccSAndroid Build Coastguard Worker const int status = obudec_read_obu_payload(
374*77c1e3ccSAndroid Build Coastguard Worker avx_ctx, payload_length, &obu_ctx->buffer[bytes_read], &payload_bytes,
375*77c1e3ccSAndroid Build Coastguard Worker /*buffered=*/false);
376*77c1e3ccSAndroid Build Coastguard Worker if (status < 0) {
377*77c1e3ccSAndroid Build Coastguard Worker rewind_detect(avx_ctx);
378*77c1e3ccSAndroid Build Coastguard Worker obudec_free(obu_ctx);
379*77c1e3ccSAndroid Build Coastguard Worker return 0;
380*77c1e3ccSAndroid Build Coastguard Worker }
381*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->bytes_buffered += payload_bytes;
382*77c1e3ccSAndroid Build Coastguard Worker }
383*77c1e3ccSAndroid Build Coastguard Worker return 1;
384*77c1e3ccSAndroid Build Coastguard Worker }
385*77c1e3ccSAndroid Build Coastguard Worker
obudec_read_temporal_unit(struct ObuDecInputContext * obu_ctx,uint8_t ** buffer,size_t * bytes_read,size_t * buffer_size)386*77c1e3ccSAndroid Build Coastguard Worker int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx,
387*77c1e3ccSAndroid Build Coastguard Worker uint8_t **buffer, size_t *bytes_read,
388*77c1e3ccSAndroid Build Coastguard Worker size_t *buffer_size) {
389*77c1e3ccSAndroid Build Coastguard Worker FILE *f = obu_ctx->avx_ctx->file;
390*77c1e3ccSAndroid Build Coastguard Worker if (!f) return -1;
391*77c1e3ccSAndroid Build Coastguard Worker
392*77c1e3ccSAndroid Build Coastguard Worker *buffer_size = 0;
393*77c1e3ccSAndroid Build Coastguard Worker *bytes_read = 0;
394*77c1e3ccSAndroid Build Coastguard Worker
395*77c1e3ccSAndroid Build Coastguard Worker if (input_eof(obu_ctx->avx_ctx)) {
396*77c1e3ccSAndroid Build Coastguard Worker return 1;
397*77c1e3ccSAndroid Build Coastguard Worker }
398*77c1e3ccSAndroid Build Coastguard Worker
399*77c1e3ccSAndroid Build Coastguard Worker size_t tu_size;
400*77c1e3ccSAndroid Build Coastguard Worker size_t obu_size = 0;
401*77c1e3ccSAndroid Build Coastguard Worker size_t length_of_temporal_unit_size = 0;
402*77c1e3ccSAndroid Build Coastguard Worker uint8_t tuheader[OBU_MAX_LENGTH_FIELD_SIZE] = { 0 };
403*77c1e3ccSAndroid Build Coastguard Worker
404*77c1e3ccSAndroid Build Coastguard Worker if (obu_ctx->is_annexb) {
405*77c1e3ccSAndroid Build Coastguard Worker uint64_t size = 0;
406*77c1e3ccSAndroid Build Coastguard Worker
407*77c1e3ccSAndroid Build Coastguard Worker if (obu_ctx->bytes_buffered == 0) {
408*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_leb128(obu_ctx->avx_ctx, &tuheader[0],
409*77c1e3ccSAndroid Build Coastguard Worker &length_of_temporal_unit_size, &size,
410*77c1e3ccSAndroid Build Coastguard Worker /*buffered=*/false) != 0) {
411*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading temporal unit header\n");
412*77c1e3ccSAndroid Build Coastguard Worker return -1;
413*77c1e3ccSAndroid Build Coastguard Worker }
414*77c1e3ccSAndroid Build Coastguard Worker if (size == 0 && input_eof(obu_ctx->avx_ctx)) {
415*77c1e3ccSAndroid Build Coastguard Worker return 1;
416*77c1e3ccSAndroid Build Coastguard Worker }
417*77c1e3ccSAndroid Build Coastguard Worker } else {
418*77c1e3ccSAndroid Build Coastguard Worker // temporal unit size was already stored in buffer
419*77c1e3ccSAndroid Build Coastguard Worker if (aom_uleb_decode(obu_ctx->buffer, obu_ctx->bytes_buffered, &size,
420*77c1e3ccSAndroid Build Coastguard Worker &length_of_temporal_unit_size) != 0) {
421*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failure reading temporal unit header\n");
422*77c1e3ccSAndroid Build Coastguard Worker return -1;
423*77c1e3ccSAndroid Build Coastguard Worker }
424*77c1e3ccSAndroid Build Coastguard Worker }
425*77c1e3ccSAndroid Build Coastguard Worker
426*77c1e3ccSAndroid Build Coastguard Worker if (size > UINT32_MAX || size + length_of_temporal_unit_size > UINT32_MAX) {
427*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: TU too large.\n");
428*77c1e3ccSAndroid Build Coastguard Worker return -1;
429*77c1e3ccSAndroid Build Coastguard Worker }
430*77c1e3ccSAndroid Build Coastguard Worker
431*77c1e3ccSAndroid Build Coastguard Worker size += length_of_temporal_unit_size;
432*77c1e3ccSAndroid Build Coastguard Worker tu_size = (size_t)size;
433*77c1e3ccSAndroid Build Coastguard Worker } else {
434*77c1e3ccSAndroid Build Coastguard Worker while (1) {
435*77c1e3ccSAndroid Build Coastguard Worker ObuHeader obu_header;
436*77c1e3ccSAndroid Build Coastguard Worker memset(&obu_header, 0, sizeof(obu_header));
437*77c1e3ccSAndroid Build Coastguard Worker
438*77c1e3ccSAndroid Build Coastguard Worker if (obudec_read_one_obu(obu_ctx->avx_ctx, &obu_ctx->buffer,
439*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->bytes_buffered,
440*77c1e3ccSAndroid Build Coastguard Worker &obu_ctx->buffer_capacity, &obu_size, &obu_header,
441*77c1e3ccSAndroid Build Coastguard Worker 0, /*buffered=*/false) != 0) {
442*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: read_one_obu failed in TU loop\n");
443*77c1e3ccSAndroid Build Coastguard Worker return -1;
444*77c1e3ccSAndroid Build Coastguard Worker }
445*77c1e3ccSAndroid Build Coastguard Worker
446*77c1e3ccSAndroid Build Coastguard Worker if (obu_header.type == OBU_TEMPORAL_DELIMITER || obu_size == 0) {
447*77c1e3ccSAndroid Build Coastguard Worker tu_size = obu_ctx->bytes_buffered;
448*77c1e3ccSAndroid Build Coastguard Worker break;
449*77c1e3ccSAndroid Build Coastguard Worker } else {
450*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->bytes_buffered += obu_size;
451*77c1e3ccSAndroid Build Coastguard Worker }
452*77c1e3ccSAndroid Build Coastguard Worker }
453*77c1e3ccSAndroid Build Coastguard Worker }
454*77c1e3ccSAndroid Build Coastguard Worker
455*77c1e3ccSAndroid Build Coastguard Worker #if defined AOM_MAX_ALLOCABLE_MEMORY
456*77c1e3ccSAndroid Build Coastguard Worker if (tu_size > AOM_MAX_ALLOCABLE_MEMORY) {
457*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Temporal Unit size exceeds max alloc size.\n");
458*77c1e3ccSAndroid Build Coastguard Worker return -1;
459*77c1e3ccSAndroid Build Coastguard Worker }
460*77c1e3ccSAndroid Build Coastguard Worker #endif
461*77c1e3ccSAndroid Build Coastguard Worker if (tu_size > 0) {
462*77c1e3ccSAndroid Build Coastguard Worker uint8_t *new_buffer = (uint8_t *)realloc(*buffer, tu_size);
463*77c1e3ccSAndroid Build Coastguard Worker if (!new_buffer) {
464*77c1e3ccSAndroid Build Coastguard Worker free(*buffer);
465*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Out of memory.\n");
466*77c1e3ccSAndroid Build Coastguard Worker return -1;
467*77c1e3ccSAndroid Build Coastguard Worker }
468*77c1e3ccSAndroid Build Coastguard Worker *buffer = new_buffer;
469*77c1e3ccSAndroid Build Coastguard Worker }
470*77c1e3ccSAndroid Build Coastguard Worker *bytes_read = tu_size;
471*77c1e3ccSAndroid Build Coastguard Worker *buffer_size = tu_size;
472*77c1e3ccSAndroid Build Coastguard Worker
473*77c1e3ccSAndroid Build Coastguard Worker if (!obu_ctx->is_annexb) {
474*77c1e3ccSAndroid Build Coastguard Worker memcpy(*buffer, obu_ctx->buffer, tu_size);
475*77c1e3ccSAndroid Build Coastguard Worker
476*77c1e3ccSAndroid Build Coastguard Worker // At this point, (obu_ctx->buffer + obu_ctx->bytes_buffered + obu_size)
477*77c1e3ccSAndroid Build Coastguard Worker // points to the end of the buffer.
478*77c1e3ccSAndroid Build Coastguard Worker memmove(obu_ctx->buffer, obu_ctx->buffer + obu_ctx->bytes_buffered,
479*77c1e3ccSAndroid Build Coastguard Worker obu_size);
480*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->bytes_buffered = obu_size;
481*77c1e3ccSAndroid Build Coastguard Worker } else {
482*77c1e3ccSAndroid Build Coastguard Worker if (!input_eof(obu_ctx->avx_ctx)) {
483*77c1e3ccSAndroid Build Coastguard Worker size_t data_size;
484*77c1e3ccSAndroid Build Coastguard Worker size_t offset;
485*77c1e3ccSAndroid Build Coastguard Worker if (!obu_ctx->bytes_buffered) {
486*77c1e3ccSAndroid Build Coastguard Worker data_size = tu_size - length_of_temporal_unit_size;
487*77c1e3ccSAndroid Build Coastguard Worker memcpy(*buffer, &tuheader[0], length_of_temporal_unit_size);
488*77c1e3ccSAndroid Build Coastguard Worker offset = length_of_temporal_unit_size;
489*77c1e3ccSAndroid Build Coastguard Worker } else {
490*77c1e3ccSAndroid Build Coastguard Worker const size_t copy_size = AOMMIN(obu_ctx->bytes_buffered, tu_size);
491*77c1e3ccSAndroid Build Coastguard Worker memcpy(*buffer, obu_ctx->buffer, copy_size);
492*77c1e3ccSAndroid Build Coastguard Worker offset = copy_size;
493*77c1e3ccSAndroid Build Coastguard Worker data_size = tu_size - copy_size;
494*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->bytes_buffered -= copy_size;
495*77c1e3ccSAndroid Build Coastguard Worker }
496*77c1e3ccSAndroid Build Coastguard Worker
497*77c1e3ccSAndroid Build Coastguard Worker if (read_from_input(obu_ctx->avx_ctx, data_size, *buffer + offset) !=
498*77c1e3ccSAndroid Build Coastguard Worker data_size) {
499*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "obudec: Failed to read full temporal unit\n");
500*77c1e3ccSAndroid Build Coastguard Worker return -1;
501*77c1e3ccSAndroid Build Coastguard Worker }
502*77c1e3ccSAndroid Build Coastguard Worker }
503*77c1e3ccSAndroid Build Coastguard Worker }
504*77c1e3ccSAndroid Build Coastguard Worker return 0;
505*77c1e3ccSAndroid Build Coastguard Worker }
506*77c1e3ccSAndroid Build Coastguard Worker
obudec_free(struct ObuDecInputContext * obu_ctx)507*77c1e3ccSAndroid Build Coastguard Worker void obudec_free(struct ObuDecInputContext *obu_ctx) {
508*77c1e3ccSAndroid Build Coastguard Worker free(obu_ctx->buffer);
509*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->buffer = NULL;
510*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->buffer_capacity = 0;
511*77c1e3ccSAndroid Build Coastguard Worker obu_ctx->bytes_buffered = 0;
512*77c1e3ccSAndroid Build Coastguard Worker }
513