Line data Source code
1 : /*
2 : * Copyright (c) 2016, 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 <assert.h>
13 : #include <limits.h>
14 : #include <stdio.h>
15 :
16 : #include "./av1_rtcd.h"
17 : #include "./aom_dsp_rtcd.h"
18 : #include "./aom_scale_rtcd.h"
19 :
20 : #include "aom_mem/aom_mem.h"
21 : #include "aom_ports/system_state.h"
22 : #include "aom_ports/aom_once.h"
23 : #include "aom_ports/aom_timer.h"
24 : #include "aom_scale/aom_scale.h"
25 : #include "aom_util/aom_thread.h"
26 :
27 : #include "av1/common/alloccommon.h"
28 : #include "av1/common/av1_loopfilter.h"
29 : #include "av1/common/onyxc_int.h"
30 : #include "av1/common/quant_common.h"
31 : #include "av1/common/reconinter.h"
32 : #include "av1/common/reconintra.h"
33 :
34 : #include "av1/decoder/decodeframe.h"
35 : #include "av1/decoder/decoder.h"
36 :
37 : #if !CONFIG_PVQ
38 : #include "av1/decoder/detokenize.h"
39 : #endif
40 :
41 0 : static void initialize_dec(void) {
42 : static volatile int init_done = 0;
43 :
44 0 : if (!init_done) {
45 0 : av1_rtcd();
46 0 : aom_dsp_rtcd();
47 0 : aom_scale_rtcd();
48 0 : av1_init_intra_predictors();
49 : #if CONFIG_EXT_INTER
50 0 : av1_init_wedge_masks();
51 : #endif // CONFIG_EXT_INTER
52 0 : init_done = 1;
53 0 : av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv,
54 : av1_intra_mode_tree);
55 0 : av1_indices_from_tree(av1_switchable_interp_ind, av1_switchable_interp_inv,
56 : av1_switchable_interp_tree);
57 : #if CONFIG_EXT_TX
58 : int s;
59 0 : for (s = 1; s < EXT_TX_SETS_INTRA; ++s)
60 0 : av1_indices_from_tree(av1_ext_tx_intra_ind[s], av1_ext_tx_intra_inv[s],
61 0 : av1_ext_tx_intra_tree[s]);
62 0 : for (s = 1; s < EXT_TX_SETS_INTER; ++s)
63 0 : av1_indices_from_tree(av1_ext_tx_inter_ind[s], av1_ext_tx_inter_inv[s],
64 0 : av1_ext_tx_inter_tree[s]);
65 : #else
66 : av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, av1_ext_tx_tree);
67 : #endif
68 0 : av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv,
69 : av1_inter_mode_tree);
70 : }
71 0 : }
72 :
73 0 : static void av1_dec_setup_mi(AV1_COMMON *cm) {
74 0 : cm->mi = cm->mip + cm->mi_stride + 1;
75 0 : cm->mi_grid_visible = cm->mi_grid_base + cm->mi_stride + 1;
76 0 : memset(cm->mi_grid_base, 0,
77 0 : cm->mi_stride * (cm->mi_rows + 1) * sizeof(*cm->mi_grid_base));
78 0 : }
79 :
80 0 : static int av1_dec_alloc_mi(AV1_COMMON *cm, int mi_size) {
81 0 : cm->mip = aom_calloc(mi_size, sizeof(*cm->mip));
82 0 : if (!cm->mip) return 1;
83 0 : cm->mi_alloc_size = mi_size;
84 0 : cm->mi_grid_base = (MODE_INFO **)aom_calloc(mi_size, sizeof(MODE_INFO *));
85 0 : if (!cm->mi_grid_base) return 1;
86 0 : return 0;
87 : }
88 :
89 0 : static void av1_dec_free_mi(AV1_COMMON *cm) {
90 0 : aom_free(cm->mip);
91 0 : cm->mip = NULL;
92 0 : aom_free(cm->mi_grid_base);
93 0 : cm->mi_grid_base = NULL;
94 0 : }
95 :
96 0 : AV1Decoder *av1_decoder_create(BufferPool *const pool) {
97 0 : AV1Decoder *volatile const pbi = aom_memalign(32, sizeof(*pbi));
98 0 : AV1_COMMON *volatile const cm = pbi ? &pbi->common : NULL;
99 :
100 0 : if (!cm) return NULL;
101 :
102 0 : av1_zero(*pbi);
103 :
104 0 : if (setjmp(cm->error.jmp)) {
105 0 : cm->error.setjmp = 0;
106 0 : av1_decoder_remove(pbi);
107 0 : return NULL;
108 : }
109 :
110 0 : cm->error.setjmp = 1;
111 :
112 0 : CHECK_MEM_ERROR(cm, cm->fc,
113 : (FRAME_CONTEXT *)aom_memalign(32, sizeof(*cm->fc)));
114 0 : CHECK_MEM_ERROR(cm, cm->frame_contexts,
115 : (FRAME_CONTEXT *)aom_memalign(
116 : 32, FRAME_CONTEXTS * sizeof(*cm->frame_contexts)));
117 0 : memset(cm->fc, 0, sizeof(*cm->fc));
118 0 : memset(cm->frame_contexts, 0, FRAME_CONTEXTS * sizeof(*cm->frame_contexts));
119 :
120 0 : pbi->need_resync = 1;
121 0 : once(initialize_dec);
122 :
123 : // Initialize the references to not point to any frame buffers.
124 0 : memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map));
125 0 : memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map));
126 :
127 0 : cm->current_video_frame = 0;
128 0 : pbi->ready_for_new_data = 1;
129 0 : pbi->common.buffer_pool = pool;
130 :
131 0 : cm->bit_depth = AOM_BITS_8;
132 0 : cm->dequant_bit_depth = AOM_BITS_8;
133 :
134 0 : cm->alloc_mi = av1_dec_alloc_mi;
135 0 : cm->free_mi = av1_dec_free_mi;
136 0 : cm->setup_mi = av1_dec_setup_mi;
137 :
138 0 : av1_loop_filter_init(cm);
139 :
140 : #if CONFIG_AOM_QM
141 : aom_qm_init(cm);
142 : #endif
143 : #if CONFIG_LOOP_RESTORATION
144 : av1_loop_restoration_precal();
145 : #endif // CONFIG_LOOP_RESTORATION
146 : #if CONFIG_ACCOUNTING
147 : pbi->acct_enabled = 1;
148 : aom_accounting_init(&pbi->accounting);
149 : #endif
150 :
151 0 : cm->error.setjmp = 0;
152 :
153 0 : aom_get_worker_interface()->init(&pbi->lf_worker);
154 :
155 0 : return pbi;
156 : }
157 :
158 0 : void av1_decoder_remove(AV1Decoder *pbi) {
159 : int i;
160 :
161 0 : if (!pbi) return;
162 :
163 0 : aom_get_worker_interface()->end(&pbi->lf_worker);
164 0 : aom_free(pbi->lf_worker.data1);
165 0 : aom_free(pbi->tile_data);
166 0 : for (i = 0; i < pbi->num_tile_workers; ++i) {
167 0 : AVxWorker *const worker = &pbi->tile_workers[i];
168 0 : aom_get_worker_interface()->end(worker);
169 : }
170 0 : aom_free(pbi->tile_worker_data);
171 0 : aom_free(pbi->tile_worker_info);
172 0 : aom_free(pbi->tile_workers);
173 :
174 0 : if (pbi->num_tile_workers > 0) {
175 0 : av1_loop_filter_dealloc(&pbi->lf_row_sync);
176 : }
177 :
178 : #if CONFIG_ACCOUNTING
179 : aom_accounting_clear(&pbi->accounting);
180 : #endif
181 :
182 0 : aom_free(pbi);
183 : }
184 :
185 0 : static int equal_dimensions(const YV12_BUFFER_CONFIG *a,
186 : const YV12_BUFFER_CONFIG *b) {
187 0 : return a->y_height == b->y_height && a->y_width == b->y_width &&
188 0 : a->uv_height == b->uv_height && a->uv_width == b->uv_width;
189 : }
190 :
191 0 : aom_codec_err_t av1_copy_reference_dec(AV1Decoder *pbi,
192 : AOM_REFFRAME ref_frame_flag,
193 : YV12_BUFFER_CONFIG *sd) {
194 0 : AV1_COMMON *cm = &pbi->common;
195 :
196 : /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
197 : * encoder is using the frame buffers for. This is just a stub to keep the
198 : * aomenc --test-decode functionality working, and will be replaced in a
199 : * later commit that adds AV1-specific controls for this functionality.
200 : */
201 0 : if (ref_frame_flag == AOM_LAST_FLAG) {
202 0 : const YV12_BUFFER_CONFIG *const cfg = get_ref_frame(cm, 0);
203 0 : if (cfg == NULL) {
204 0 : aom_internal_error(&cm->error, AOM_CODEC_ERROR,
205 : "No 'last' reference frame");
206 0 : return AOM_CODEC_ERROR;
207 : }
208 0 : if (!equal_dimensions(cfg, sd))
209 0 : aom_internal_error(&cm->error, AOM_CODEC_ERROR,
210 : "Incorrect buffer dimensions");
211 : else
212 0 : aom_yv12_copy_frame(cfg, sd);
213 : } else {
214 0 : aom_internal_error(&cm->error, AOM_CODEC_ERROR, "Invalid reference frame");
215 : }
216 :
217 0 : return cm->error.error_code;
218 : }
219 :
220 0 : aom_codec_err_t av1_set_reference_dec(AV1_COMMON *cm,
221 : AOM_REFFRAME ref_frame_flag,
222 : YV12_BUFFER_CONFIG *sd) {
223 : int idx;
224 0 : YV12_BUFFER_CONFIG *ref_buf = NULL;
225 :
226 : // TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
227 : // encoder is using the frame buffers for. This is just a stub to keep the
228 : // aomenc --test-decode functionality working, and will be replaced in a
229 : // later commit that adds AV1-specific controls for this functionality.
230 :
231 : // (Yunqing) The set_reference control depends on the following setting in
232 : // encoder.
233 : // cpi->lst_fb_idx = 0;
234 : // #if CONFIG_EXT_REFS
235 : // cpi->lst2_fb_idx = 1;
236 : // cpi->lst3_fb_idx = 2;
237 : // cpi->gld_fb_idx = 3;
238 : // cpi->bwd_fb_idx = 4;
239 : // cpi->alt_fb_idx = 5;
240 : // #else // CONFIG_EXT_REFS
241 : // cpi->gld_fb_idx = 1;
242 : // cpi->alt_fb_idx = 2;
243 : // #endif // CONFIG_EXT_REFS
244 :
245 : // TODO(zoeliu): To revisit following code and reconsider what assumption we
246 : // may take on the reference frame buffer virtual indexes
247 0 : if (ref_frame_flag == AOM_LAST_FLAG) {
248 0 : idx = cm->ref_frame_map[0];
249 : #if CONFIG_EXT_REFS
250 0 : } else if (ref_frame_flag == AOM_LAST2_FLAG) {
251 0 : idx = cm->ref_frame_map[1];
252 0 : } else if (ref_frame_flag == AOM_LAST3_FLAG) {
253 0 : idx = cm->ref_frame_map[2];
254 0 : } else if (ref_frame_flag == AOM_GOLD_FLAG) {
255 0 : idx = cm->ref_frame_map[3];
256 0 : } else if (ref_frame_flag == AOM_BWD_FLAG) {
257 0 : idx = cm->ref_frame_map[4];
258 0 : } else if (ref_frame_flag == AOM_ALT_FLAG) {
259 0 : idx = cm->ref_frame_map[5];
260 : #else
261 : } else if (ref_frame_flag == AOM_GOLD_FLAG) {
262 : idx = cm->ref_frame_map[1];
263 : } else if (ref_frame_flag == AOM_ALT_FLAG) {
264 : idx = cm->ref_frame_map[2];
265 : #endif // CONFIG_EXT_REFS
266 : } else {
267 0 : aom_internal_error(&cm->error, AOM_CODEC_ERROR, "Invalid reference frame");
268 0 : return cm->error.error_code;
269 : }
270 :
271 0 : if (idx < 0 || idx >= FRAME_BUFFERS) {
272 0 : aom_internal_error(&cm->error, AOM_CODEC_ERROR,
273 : "Invalid reference frame map");
274 0 : return cm->error.error_code;
275 : }
276 :
277 : // Get the destination reference buffer.
278 0 : ref_buf = &cm->buffer_pool->frame_bufs[idx].buf;
279 :
280 0 : if (!equal_dimensions(ref_buf, sd)) {
281 0 : aom_internal_error(&cm->error, AOM_CODEC_ERROR,
282 : "Incorrect buffer dimensions");
283 : } else {
284 : // Overwrite the reference frame buffer.
285 0 : aom_yv12_copy_frame(sd, ref_buf);
286 : }
287 :
288 0 : return cm->error.error_code;
289 : }
290 :
291 : /* If any buffer updating is signaled it should be done here. */
292 0 : static void swap_frame_buffers(AV1Decoder *pbi) {
293 0 : int ref_index = 0, mask;
294 0 : AV1_COMMON *const cm = &pbi->common;
295 0 : BufferPool *const pool = cm->buffer_pool;
296 0 : RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
297 :
298 0 : lock_buffer_pool(pool);
299 0 : for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
300 0 : const int old_idx = cm->ref_frame_map[ref_index];
301 : // Current thread releases the holding of reference frame.
302 0 : decrease_ref_count(old_idx, frame_bufs, pool);
303 :
304 : // Release the reference frame holding in the reference map for the decoding
305 : // of the next frame.
306 0 : if (mask & 1) decrease_ref_count(old_idx, frame_bufs, pool);
307 0 : cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
308 0 : ++ref_index;
309 : }
310 :
311 : // Current thread releases the holding of reference frame.
312 0 : for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
313 0 : const int old_idx = cm->ref_frame_map[ref_index];
314 0 : decrease_ref_count(old_idx, frame_bufs, pool);
315 0 : cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
316 : }
317 :
318 0 : unlock_buffer_pool(pool);
319 0 : pbi->hold_ref_buf = 0;
320 0 : cm->frame_to_show = get_frame_new_buffer(cm);
321 :
322 : // TODO(zoeliu): To fix the ref frame buffer update for the scenario of
323 : // cm->frame_parellel_decode == 1
324 0 : if (!cm->frame_parallel_decode || !cm->show_frame) {
325 0 : lock_buffer_pool(pool);
326 0 : --frame_bufs[cm->new_fb_idx].ref_count;
327 0 : unlock_buffer_pool(pool);
328 : }
329 :
330 : // Invalidate these references until the next frame starts.
331 0 : for (ref_index = 0; ref_index < INTER_REFS_PER_FRAME; ref_index++) {
332 0 : cm->frame_refs[ref_index].idx = INVALID_IDX;
333 0 : cm->frame_refs[ref_index].buf = NULL;
334 : }
335 0 : }
336 :
337 0 : int av1_receive_compressed_data(AV1Decoder *pbi, size_t size,
338 : const uint8_t **psource) {
339 0 : AV1_COMMON *volatile const cm = &pbi->common;
340 0 : BufferPool *volatile const pool = cm->buffer_pool;
341 0 : RefCntBuffer *volatile const frame_bufs = cm->buffer_pool->frame_bufs;
342 0 : const uint8_t *source = *psource;
343 0 : int retcode = 0;
344 0 : cm->error.error_code = AOM_CODEC_OK;
345 :
346 0 : if (size == 0) {
347 : // This is used to signal that we are missing frames.
348 : // We do not know if the missing frame(s) was supposed to update
349 : // any of the reference buffers, but we act conservative and
350 : // mark only the last buffer as corrupted.
351 : //
352 : // TODO(jkoleszar): Error concealment is undefined and non-normative
353 : // at this point, but if it becomes so, [0] may not always be the correct
354 : // thing to do here.
355 0 : if (cm->frame_refs[0].idx > 0) {
356 0 : assert(cm->frame_refs[0].buf != NULL);
357 0 : cm->frame_refs[0].buf->corrupted = 1;
358 : }
359 : }
360 :
361 0 : pbi->ready_for_new_data = 0;
362 :
363 : // Find a free buffer for the new frame, releasing the reference previously
364 : // held.
365 :
366 : // Check if the previous frame was a frame without any references to it.
367 : // Release frame buffer if not decoding in frame parallel mode.
368 0 : if (!cm->frame_parallel_decode && cm->new_fb_idx >= 0 &&
369 0 : frame_bufs[cm->new_fb_idx].ref_count == 0)
370 0 : pool->release_fb_cb(pool->cb_priv,
371 0 : &frame_bufs[cm->new_fb_idx].raw_frame_buffer);
372 :
373 : // Find a free frame buffer. Return error if can not find any.
374 0 : cm->new_fb_idx = get_free_fb(cm);
375 0 : if (cm->new_fb_idx == INVALID_IDX) return AOM_CODEC_MEM_ERROR;
376 :
377 : // Assign a MV array to the frame buffer.
378 0 : cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
379 :
380 0 : pbi->hold_ref_buf = 0;
381 0 : if (cm->frame_parallel_decode) {
382 0 : AVxWorker *const worker = pbi->frame_worker_owner;
383 0 : av1_frameworker_lock_stats(worker);
384 0 : frame_bufs[cm->new_fb_idx].frame_worker_owner = worker;
385 : // Reset decoding progress.
386 0 : pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
387 0 : pbi->cur_buf->row = -1;
388 0 : pbi->cur_buf->col = -1;
389 0 : av1_frameworker_unlock_stats(worker);
390 : } else {
391 0 : pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
392 : }
393 :
394 0 : if (setjmp(cm->error.jmp)) {
395 0 : const AVxWorkerInterface *const winterface = aom_get_worker_interface();
396 : int i;
397 :
398 0 : cm->error.setjmp = 0;
399 0 : pbi->ready_for_new_data = 1;
400 :
401 : // Synchronize all threads immediately as a subsequent decode call may
402 : // cause a resize invalidating some allocations.
403 0 : winterface->sync(&pbi->lf_worker);
404 0 : for (i = 0; i < pbi->num_tile_workers; ++i) {
405 0 : winterface->sync(&pbi->tile_workers[i]);
406 : }
407 :
408 0 : lock_buffer_pool(pool);
409 : // Release all the reference buffers if worker thread is holding them.
410 0 : if (pbi->hold_ref_buf == 1) {
411 0 : int ref_index = 0, mask;
412 0 : for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
413 0 : const int old_idx = cm->ref_frame_map[ref_index];
414 : // Current thread releases the holding of reference frame.
415 0 : decrease_ref_count(old_idx, frame_bufs, pool);
416 :
417 : // Release the reference frame holding in the reference map for the
418 : // decoding of the next frame.
419 0 : if (mask & 1) decrease_ref_count(old_idx, frame_bufs, pool);
420 0 : ++ref_index;
421 : }
422 :
423 : // Current thread releases the holding of reference frame.
424 0 : for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
425 0 : const int old_idx = cm->ref_frame_map[ref_index];
426 0 : decrease_ref_count(old_idx, frame_bufs, pool);
427 : }
428 0 : pbi->hold_ref_buf = 0;
429 : }
430 : // Release current frame.
431 0 : decrease_ref_count(cm->new_fb_idx, frame_bufs, pool);
432 0 : unlock_buffer_pool(pool);
433 :
434 0 : aom_clear_system_state();
435 0 : return -1;
436 : }
437 :
438 0 : cm->error.setjmp = 1;
439 0 : av1_decode_frame(pbi, source, source + size, psource);
440 :
441 0 : swap_frame_buffers(pbi);
442 :
443 : #if CONFIG_EXT_TILE
444 : // For now, we only extend the frame borders when the whole frame is decoded.
445 : // Later, if needed, extend the border for the decoded tile on the frame
446 : // border.
447 : if (pbi->dec_tile_row == -1 && pbi->dec_tile_col == -1)
448 : #endif // CONFIG_EXT_TILE
449 0 : aom_extend_frame_inner_borders(cm->frame_to_show);
450 :
451 0 : aom_clear_system_state();
452 :
453 0 : if (!cm->show_existing_frame) {
454 0 : cm->last_show_frame = cm->show_frame;
455 :
456 : #if CONFIG_EXT_REFS
457 : // NOTE: It is not supposed to ref to any frame not used as reference
458 0 : if (cm->is_reference_frame)
459 : #endif // CONFIG_EXT_REFS
460 0 : cm->prev_frame = cm->cur_frame;
461 :
462 0 : if (cm->seg.enabled && !cm->frame_parallel_decode)
463 0 : av1_swap_current_and_last_seg_map(cm);
464 : }
465 :
466 : // Update progress in frame parallel decode.
467 0 : if (cm->frame_parallel_decode) {
468 : // Need to lock the mutex here as another thread may
469 : // be accessing this buffer.
470 0 : AVxWorker *const worker = pbi->frame_worker_owner;
471 0 : FrameWorkerData *const frame_worker_data = worker->data1;
472 0 : av1_frameworker_lock_stats(worker);
473 :
474 0 : if (cm->show_frame) {
475 0 : cm->current_video_frame++;
476 : }
477 0 : frame_worker_data->frame_decoded = 1;
478 0 : frame_worker_data->frame_context_ready = 1;
479 0 : av1_frameworker_signal_stats(worker);
480 0 : av1_frameworker_unlock_stats(worker);
481 : } else {
482 0 : cm->last_width = cm->width;
483 0 : cm->last_height = cm->height;
484 0 : if (cm->show_frame) {
485 0 : cm->current_video_frame++;
486 : }
487 : }
488 :
489 0 : cm->error.setjmp = 0;
490 0 : return retcode;
491 : }
492 :
493 0 : int av1_get_raw_frame(AV1Decoder *pbi, YV12_BUFFER_CONFIG *sd) {
494 0 : AV1_COMMON *const cm = &pbi->common;
495 0 : int ret = -1;
496 0 : if (pbi->ready_for_new_data == 1) return ret;
497 :
498 0 : pbi->ready_for_new_data = 1;
499 :
500 : /* no raw frame to show!!! */
501 0 : if (!cm->show_frame) return ret;
502 :
503 0 : pbi->ready_for_new_data = 1;
504 0 : *sd = *cm->frame_to_show;
505 0 : ret = 0;
506 0 : aom_clear_system_state();
507 0 : return ret;
508 : }
509 :
510 0 : int av1_get_frame_to_show(AV1Decoder *pbi, YV12_BUFFER_CONFIG *frame) {
511 0 : AV1_COMMON *const cm = &pbi->common;
512 :
513 0 : if (!cm->show_frame || !cm->frame_to_show) return -1;
514 :
515 0 : *frame = *cm->frame_to_show;
516 0 : return 0;
517 : }
518 :
519 0 : aom_codec_err_t av1_parse_superframe_index(const uint8_t *data, size_t data_sz,
520 : uint32_t sizes[8], int *count,
521 : aom_decrypt_cb decrypt_cb,
522 : void *decrypt_state) {
523 : // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
524 : // it is a super frame index. If the last byte of real video compression
525 : // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
526 : // not the associated matching marker byte at the front of the index we have
527 : // an invalid bitstream and need to return an error.
528 :
529 : uint8_t marker;
530 0 : size_t frame_sz_sum = 0;
531 :
532 0 : assert(data_sz);
533 0 : marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1);
534 0 : *count = 0;
535 :
536 0 : if ((marker & 0xe0) == 0xc0) {
537 0 : const uint32_t frames = (marker & 0x7) + 1;
538 0 : const uint32_t mag = ((marker >> 3) & 0x3) + 1;
539 0 : const size_t index_sz = 2 + mag * (frames - 1);
540 :
541 : // This chunk is marked as having a superframe index but doesn't have
542 : // enough data for it, thus it's an invalid superframe index.
543 0 : if (data_sz < index_sz) return AOM_CODEC_CORRUPT_FRAME;
544 :
545 : {
546 0 : const uint8_t marker2 =
547 0 : read_marker(decrypt_cb, decrypt_state, data + data_sz - index_sz);
548 :
549 : // This chunk is marked as having a superframe index but doesn't have
550 : // the matching marker byte at the front of the index therefore it's an
551 : // invalid chunk.
552 0 : if (marker != marker2) return AOM_CODEC_CORRUPT_FRAME;
553 : }
554 :
555 : {
556 : // Found a valid superframe index.
557 : uint32_t i, j;
558 0 : const uint8_t *x = &data[data_sz - index_sz + 1];
559 :
560 : // Frames has a maximum of 8 and mag has a maximum of 4.
561 : uint8_t clear_buffer[28];
562 0 : assert(sizeof(clear_buffer) >= (frames - 1) * mag);
563 0 : if (decrypt_cb) {
564 0 : decrypt_cb(decrypt_state, x, clear_buffer, (frames - 1) * mag);
565 0 : x = clear_buffer;
566 : }
567 :
568 0 : for (i = 0; i < frames - 1; ++i) {
569 0 : uint32_t this_sz = 0;
570 :
571 0 : for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
572 0 : this_sz += 1;
573 0 : sizes[i] = this_sz;
574 0 : frame_sz_sum += this_sz;
575 : }
576 0 : sizes[i] = (uint32_t)(data_sz - index_sz - frame_sz_sum);
577 0 : *count = frames;
578 : }
579 : }
580 0 : return AOM_CODEC_OK;
581 : }
|