1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <limits.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
14*fb1b10abSAndroid Build Coastguard Worker
15*fb1b10abSAndroid Build Coastguard Worker #include "./vp9_rtcd.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_scale_rtcd.h"
18*fb1b10abSAndroid Build Coastguard Worker
19*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/system_state.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/vpx_once.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/vpx_timer.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "vpx_scale/vpx_scale.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vpx_util/vpx_pthread.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vpx_util/vpx_thread.h"
26*fb1b10abSAndroid Build Coastguard Worker
27*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_alloccommon.h"
28*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_loopfilter.h"
29*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_onyxc_int.h"
30*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_POSTPROC
31*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_postproc.h"
32*fb1b10abSAndroid Build Coastguard Worker #endif
33*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_quant_common.h"
34*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconintra.h"
35*fb1b10abSAndroid Build Coastguard Worker
36*fb1b10abSAndroid Build Coastguard Worker #include "vp9/decoder/vp9_decodeframe.h"
37*fb1b10abSAndroid Build Coastguard Worker #include "vp9/decoder/vp9_decoder.h"
38*fb1b10abSAndroid Build Coastguard Worker #include "vp9/decoder/vp9_detokenize.h"
39*fb1b10abSAndroid Build Coastguard Worker
initialize_dec(void)40*fb1b10abSAndroid Build Coastguard Worker static void initialize_dec(void) {
41*fb1b10abSAndroid Build Coastguard Worker static volatile int init_done = 0;
42*fb1b10abSAndroid Build Coastguard Worker
43*fb1b10abSAndroid Build Coastguard Worker if (!init_done) {
44*fb1b10abSAndroid Build Coastguard Worker vp9_rtcd();
45*fb1b10abSAndroid Build Coastguard Worker vpx_dsp_rtcd();
46*fb1b10abSAndroid Build Coastguard Worker vpx_scale_rtcd();
47*fb1b10abSAndroid Build Coastguard Worker vp9_init_intra_predictors();
48*fb1b10abSAndroid Build Coastguard Worker init_done = 1;
49*fb1b10abSAndroid Build Coastguard Worker }
50*fb1b10abSAndroid Build Coastguard Worker }
51*fb1b10abSAndroid Build Coastguard Worker
vp9_dec_setup_mi(VP9_COMMON * cm)52*fb1b10abSAndroid Build Coastguard Worker static void vp9_dec_setup_mi(VP9_COMMON *cm) {
53*fb1b10abSAndroid Build Coastguard Worker cm->mi = cm->mip + cm->mi_stride + 1;
54*fb1b10abSAndroid Build Coastguard Worker cm->mi_grid_visible = cm->mi_grid_base + cm->mi_stride + 1;
55*fb1b10abSAndroid Build Coastguard Worker memset(cm->mi_grid_base, 0,
56*fb1b10abSAndroid Build Coastguard Worker cm->mi_stride * (cm->mi_rows + 1) * sizeof(*cm->mi_grid_base));
57*fb1b10abSAndroid Build Coastguard Worker }
58*fb1b10abSAndroid Build Coastguard Worker
vp9_dec_alloc_row_mt_mem(RowMTWorkerData * row_mt_worker_data,VP9_COMMON * cm,int num_sbs,int max_threads,int num_jobs)59*fb1b10abSAndroid Build Coastguard Worker void vp9_dec_alloc_row_mt_mem(RowMTWorkerData *row_mt_worker_data,
60*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *cm, int num_sbs, int max_threads,
61*fb1b10abSAndroid Build Coastguard Worker int num_jobs) {
62*fb1b10abSAndroid Build Coastguard Worker int plane;
63*fb1b10abSAndroid Build Coastguard Worker const size_t dqcoeff_size = (num_sbs << DQCOEFFS_PER_SB_LOG2) *
64*fb1b10abSAndroid Build Coastguard Worker sizeof(*row_mt_worker_data->dqcoeff[0]);
65*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->num_jobs = num_jobs;
66*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
67*fb1b10abSAndroid Build Coastguard Worker {
68*fb1b10abSAndroid Build Coastguard Worker int i;
69*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
70*fb1b10abSAndroid Build Coastguard Worker &cm->error, row_mt_worker_data->recon_sync_mutex,
71*fb1b10abSAndroid Build Coastguard Worker vpx_malloc(sizeof(*row_mt_worker_data->recon_sync_mutex) * num_jobs));
72*fb1b10abSAndroid Build Coastguard Worker if (row_mt_worker_data->recon_sync_mutex) {
73*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < num_jobs; ++i) {
74*fb1b10abSAndroid Build Coastguard Worker pthread_mutex_init(&row_mt_worker_data->recon_sync_mutex[i], NULL);
75*fb1b10abSAndroid Build Coastguard Worker }
76*fb1b10abSAndroid Build Coastguard Worker }
77*fb1b10abSAndroid Build Coastguard Worker
78*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
79*fb1b10abSAndroid Build Coastguard Worker &cm->error, row_mt_worker_data->recon_sync_cond,
80*fb1b10abSAndroid Build Coastguard Worker vpx_malloc(sizeof(*row_mt_worker_data->recon_sync_cond) * num_jobs));
81*fb1b10abSAndroid Build Coastguard Worker if (row_mt_worker_data->recon_sync_cond) {
82*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < num_jobs; ++i) {
83*fb1b10abSAndroid Build Coastguard Worker pthread_cond_init(&row_mt_worker_data->recon_sync_cond[i], NULL);
84*fb1b10abSAndroid Build Coastguard Worker }
85*fb1b10abSAndroid Build Coastguard Worker }
86*fb1b10abSAndroid Build Coastguard Worker }
87*fb1b10abSAndroid Build Coastguard Worker #endif
88*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->num_sbs = num_sbs;
89*fb1b10abSAndroid Build Coastguard Worker for (plane = 0; plane < 3; ++plane) {
90*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(&cm->error, row_mt_worker_data->dqcoeff[plane],
91*fb1b10abSAndroid Build Coastguard Worker vpx_memalign(32, dqcoeff_size));
92*fb1b10abSAndroid Build Coastguard Worker memset(row_mt_worker_data->dqcoeff[plane], 0, dqcoeff_size);
93*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(&cm->error, row_mt_worker_data->eob[plane],
94*fb1b10abSAndroid Build Coastguard Worker vpx_calloc(num_sbs << EOBS_PER_SB_LOG2,
95*fb1b10abSAndroid Build Coastguard Worker sizeof(*row_mt_worker_data->eob[plane])));
96*fb1b10abSAndroid Build Coastguard Worker }
97*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(&cm->error, row_mt_worker_data->partition,
98*fb1b10abSAndroid Build Coastguard Worker vpx_calloc(num_sbs * PARTITIONS_PER_SB,
99*fb1b10abSAndroid Build Coastguard Worker sizeof(*row_mt_worker_data->partition)));
100*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(&cm->error, row_mt_worker_data->recon_map,
101*fb1b10abSAndroid Build Coastguard Worker vpx_calloc(num_sbs, sizeof(*row_mt_worker_data->recon_map)));
102*fb1b10abSAndroid Build Coastguard Worker
103*fb1b10abSAndroid Build Coastguard Worker // allocate memory for thread_data
104*fb1b10abSAndroid Build Coastguard Worker if (row_mt_worker_data->thread_data == NULL) {
105*fb1b10abSAndroid Build Coastguard Worker const size_t thread_size =
106*fb1b10abSAndroid Build Coastguard Worker max_threads * sizeof(*row_mt_worker_data->thread_data);
107*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(&cm->error, row_mt_worker_data->thread_data,
108*fb1b10abSAndroid Build Coastguard Worker vpx_memalign(32, thread_size));
109*fb1b10abSAndroid Build Coastguard Worker }
110*fb1b10abSAndroid Build Coastguard Worker }
111*fb1b10abSAndroid Build Coastguard Worker
vp9_dec_free_row_mt_mem(RowMTWorkerData * row_mt_worker_data)112*fb1b10abSAndroid Build Coastguard Worker void vp9_dec_free_row_mt_mem(RowMTWorkerData *row_mt_worker_data) {
113*fb1b10abSAndroid Build Coastguard Worker if (row_mt_worker_data != NULL) {
114*fb1b10abSAndroid Build Coastguard Worker int plane;
115*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
116*fb1b10abSAndroid Build Coastguard Worker int i;
117*fb1b10abSAndroid Build Coastguard Worker if (row_mt_worker_data->recon_sync_mutex != NULL) {
118*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < row_mt_worker_data->num_jobs; ++i) {
119*fb1b10abSAndroid Build Coastguard Worker pthread_mutex_destroy(&row_mt_worker_data->recon_sync_mutex[i]);
120*fb1b10abSAndroid Build Coastguard Worker }
121*fb1b10abSAndroid Build Coastguard Worker vpx_free(row_mt_worker_data->recon_sync_mutex);
122*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->recon_sync_mutex = NULL;
123*fb1b10abSAndroid Build Coastguard Worker }
124*fb1b10abSAndroid Build Coastguard Worker if (row_mt_worker_data->recon_sync_cond != NULL) {
125*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < row_mt_worker_data->num_jobs; ++i) {
126*fb1b10abSAndroid Build Coastguard Worker pthread_cond_destroy(&row_mt_worker_data->recon_sync_cond[i]);
127*fb1b10abSAndroid Build Coastguard Worker }
128*fb1b10abSAndroid Build Coastguard Worker vpx_free(row_mt_worker_data->recon_sync_cond);
129*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->recon_sync_cond = NULL;
130*fb1b10abSAndroid Build Coastguard Worker }
131*fb1b10abSAndroid Build Coastguard Worker #endif
132*fb1b10abSAndroid Build Coastguard Worker for (plane = 0; plane < 3; ++plane) {
133*fb1b10abSAndroid Build Coastguard Worker vpx_free(row_mt_worker_data->eob[plane]);
134*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->eob[plane] = NULL;
135*fb1b10abSAndroid Build Coastguard Worker vpx_free(row_mt_worker_data->dqcoeff[plane]);
136*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->dqcoeff[plane] = NULL;
137*fb1b10abSAndroid Build Coastguard Worker }
138*fb1b10abSAndroid Build Coastguard Worker vpx_free(row_mt_worker_data->partition);
139*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->partition = NULL;
140*fb1b10abSAndroid Build Coastguard Worker vpx_free(row_mt_worker_data->recon_map);
141*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->recon_map = NULL;
142*fb1b10abSAndroid Build Coastguard Worker vpx_free(row_mt_worker_data->thread_data);
143*fb1b10abSAndroid Build Coastguard Worker row_mt_worker_data->thread_data = NULL;
144*fb1b10abSAndroid Build Coastguard Worker }
145*fb1b10abSAndroid Build Coastguard Worker }
146*fb1b10abSAndroid Build Coastguard Worker
vp9_dec_alloc_mi(VP9_COMMON * cm,int mi_size)147*fb1b10abSAndroid Build Coastguard Worker static int vp9_dec_alloc_mi(VP9_COMMON *cm, int mi_size) {
148*fb1b10abSAndroid Build Coastguard Worker cm->mip = vpx_calloc(mi_size, sizeof(*cm->mip));
149*fb1b10abSAndroid Build Coastguard Worker if (!cm->mip) return 1;
150*fb1b10abSAndroid Build Coastguard Worker cm->mi_alloc_size = mi_size;
151*fb1b10abSAndroid Build Coastguard Worker cm->mi_grid_base = (MODE_INFO **)vpx_calloc(mi_size, sizeof(MODE_INFO *));
152*fb1b10abSAndroid Build Coastguard Worker if (!cm->mi_grid_base) return 1;
153*fb1b10abSAndroid Build Coastguard Worker return 0;
154*fb1b10abSAndroid Build Coastguard Worker }
155*fb1b10abSAndroid Build Coastguard Worker
vp9_dec_free_mi(VP9_COMMON * cm)156*fb1b10abSAndroid Build Coastguard Worker static void vp9_dec_free_mi(VP9_COMMON *cm) {
157*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_POSTPROC
158*fb1b10abSAndroid Build Coastguard Worker // MFQE allocates an additional mip and swaps it with cm->mip.
159*fb1b10abSAndroid Build Coastguard Worker vpx_free(cm->postproc_state.prev_mip);
160*fb1b10abSAndroid Build Coastguard Worker cm->postproc_state.prev_mip = NULL;
161*fb1b10abSAndroid Build Coastguard Worker #endif
162*fb1b10abSAndroid Build Coastguard Worker vpx_free(cm->mip);
163*fb1b10abSAndroid Build Coastguard Worker cm->mip = NULL;
164*fb1b10abSAndroid Build Coastguard Worker vpx_free(cm->mi_grid_base);
165*fb1b10abSAndroid Build Coastguard Worker cm->mi_grid_base = NULL;
166*fb1b10abSAndroid Build Coastguard Worker cm->mi_alloc_size = 0;
167*fb1b10abSAndroid Build Coastguard Worker }
168*fb1b10abSAndroid Build Coastguard Worker
vp9_decoder_create(BufferPool * const pool)169*fb1b10abSAndroid Build Coastguard Worker VP9Decoder *vp9_decoder_create(BufferPool *const pool) {
170*fb1b10abSAndroid Build Coastguard Worker VP9Decoder *volatile const pbi = vpx_memalign(32, sizeof(*pbi));
171*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *volatile const cm = pbi ? &pbi->common : NULL;
172*fb1b10abSAndroid Build Coastguard Worker
173*fb1b10abSAndroid Build Coastguard Worker if (!cm) return NULL;
174*fb1b10abSAndroid Build Coastguard Worker
175*fb1b10abSAndroid Build Coastguard Worker vp9_zero(*pbi);
176*fb1b10abSAndroid Build Coastguard Worker
177*fb1b10abSAndroid Build Coastguard Worker if (setjmp(cm->error.jmp)) {
178*fb1b10abSAndroid Build Coastguard Worker cm->error.setjmp = 0;
179*fb1b10abSAndroid Build Coastguard Worker vp9_decoder_remove(pbi);
180*fb1b10abSAndroid Build Coastguard Worker return NULL;
181*fb1b10abSAndroid Build Coastguard Worker }
182*fb1b10abSAndroid Build Coastguard Worker
183*fb1b10abSAndroid Build Coastguard Worker cm->error.setjmp = 1;
184*fb1b10abSAndroid Build Coastguard Worker
185*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(&cm->error, cm->fc,
186*fb1b10abSAndroid Build Coastguard Worker (FRAME_CONTEXT *)vpx_calloc(1, sizeof(*cm->fc)));
187*fb1b10abSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
188*fb1b10abSAndroid Build Coastguard Worker &cm->error, cm->frame_contexts,
189*fb1b10abSAndroid Build Coastguard Worker (FRAME_CONTEXT *)vpx_calloc(FRAME_CONTEXTS, sizeof(*cm->frame_contexts)));
190*fb1b10abSAndroid Build Coastguard Worker
191*fb1b10abSAndroid Build Coastguard Worker pbi->need_resync = 1;
192*fb1b10abSAndroid Build Coastguard Worker once(initialize_dec);
193*fb1b10abSAndroid Build Coastguard Worker
194*fb1b10abSAndroid Build Coastguard Worker // Initialize the references to not point to any frame buffers.
195*fb1b10abSAndroid Build Coastguard Worker memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map));
196*fb1b10abSAndroid Build Coastguard Worker memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map));
197*fb1b10abSAndroid Build Coastguard Worker
198*fb1b10abSAndroid Build Coastguard Worker init_frame_indexes(cm);
199*fb1b10abSAndroid Build Coastguard Worker pbi->ready_for_new_data = 1;
200*fb1b10abSAndroid Build Coastguard Worker pbi->common.buffer_pool = pool;
201*fb1b10abSAndroid Build Coastguard Worker
202*fb1b10abSAndroid Build Coastguard Worker cm->bit_depth = VPX_BITS_8;
203*fb1b10abSAndroid Build Coastguard Worker cm->dequant_bit_depth = VPX_BITS_8;
204*fb1b10abSAndroid Build Coastguard Worker
205*fb1b10abSAndroid Build Coastguard Worker cm->alloc_mi = vp9_dec_alloc_mi;
206*fb1b10abSAndroid Build Coastguard Worker cm->free_mi = vp9_dec_free_mi;
207*fb1b10abSAndroid Build Coastguard Worker cm->setup_mi = vp9_dec_setup_mi;
208*fb1b10abSAndroid Build Coastguard Worker
209*fb1b10abSAndroid Build Coastguard Worker vp9_loop_filter_init(cm);
210*fb1b10abSAndroid Build Coastguard Worker
211*fb1b10abSAndroid Build Coastguard Worker cm->error.setjmp = 0;
212*fb1b10abSAndroid Build Coastguard Worker
213*fb1b10abSAndroid Build Coastguard Worker vpx_get_worker_interface()->init(&pbi->lf_worker);
214*fb1b10abSAndroid Build Coastguard Worker pbi->lf_worker.thread_name = "vpx lf worker";
215*fb1b10abSAndroid Build Coastguard Worker
216*fb1b10abSAndroid Build Coastguard Worker return pbi;
217*fb1b10abSAndroid Build Coastguard Worker }
218*fb1b10abSAndroid Build Coastguard Worker
vp9_decoder_remove(VP9Decoder * pbi)219*fb1b10abSAndroid Build Coastguard Worker void vp9_decoder_remove(VP9Decoder *pbi) {
220*fb1b10abSAndroid Build Coastguard Worker int i;
221*fb1b10abSAndroid Build Coastguard Worker
222*fb1b10abSAndroid Build Coastguard Worker if (!pbi) return;
223*fb1b10abSAndroid Build Coastguard Worker
224*fb1b10abSAndroid Build Coastguard Worker vpx_get_worker_interface()->end(&pbi->lf_worker);
225*fb1b10abSAndroid Build Coastguard Worker vpx_free(pbi->lf_worker.data1);
226*fb1b10abSAndroid Build Coastguard Worker
227*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < pbi->num_tile_workers; ++i) {
228*fb1b10abSAndroid Build Coastguard Worker VPxWorker *const worker = &pbi->tile_workers[i];
229*fb1b10abSAndroid Build Coastguard Worker vpx_get_worker_interface()->end(worker);
230*fb1b10abSAndroid Build Coastguard Worker }
231*fb1b10abSAndroid Build Coastguard Worker
232*fb1b10abSAndroid Build Coastguard Worker vpx_free(pbi->tile_worker_data);
233*fb1b10abSAndroid Build Coastguard Worker vpx_free(pbi->tile_workers);
234*fb1b10abSAndroid Build Coastguard Worker
235*fb1b10abSAndroid Build Coastguard Worker if (pbi->num_tile_workers > 0) {
236*fb1b10abSAndroid Build Coastguard Worker vp9_loop_filter_dealloc(&pbi->lf_row_sync);
237*fb1b10abSAndroid Build Coastguard Worker }
238*fb1b10abSAndroid Build Coastguard Worker
239*fb1b10abSAndroid Build Coastguard Worker if (pbi->row_mt == 1) {
240*fb1b10abSAndroid Build Coastguard Worker vp9_dec_free_row_mt_mem(pbi->row_mt_worker_data);
241*fb1b10abSAndroid Build Coastguard Worker if (pbi->row_mt_worker_data != NULL) {
242*fb1b10abSAndroid Build Coastguard Worker vp9_jobq_deinit(&pbi->row_mt_worker_data->jobq);
243*fb1b10abSAndroid Build Coastguard Worker vpx_free(pbi->row_mt_worker_data->jobq_buf);
244*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
245*fb1b10abSAndroid Build Coastguard Worker pthread_mutex_destroy(&pbi->row_mt_worker_data->recon_done_mutex);
246*fb1b10abSAndroid Build Coastguard Worker #endif
247*fb1b10abSAndroid Build Coastguard Worker }
248*fb1b10abSAndroid Build Coastguard Worker vpx_free(pbi->row_mt_worker_data);
249*fb1b10abSAndroid Build Coastguard Worker }
250*fb1b10abSAndroid Build Coastguard Worker
251*fb1b10abSAndroid Build Coastguard Worker vp9_remove_common(&pbi->common);
252*fb1b10abSAndroid Build Coastguard Worker vpx_free(pbi);
253*fb1b10abSAndroid Build Coastguard Worker }
254*fb1b10abSAndroid Build Coastguard Worker
equal_dimensions(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b)255*fb1b10abSAndroid Build Coastguard Worker static int equal_dimensions(const YV12_BUFFER_CONFIG *a,
256*fb1b10abSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *b) {
257*fb1b10abSAndroid Build Coastguard Worker return a->y_height == b->y_height && a->y_width == b->y_width &&
258*fb1b10abSAndroid Build Coastguard Worker a->uv_height == b->uv_height && a->uv_width == b->uv_width;
259*fb1b10abSAndroid Build Coastguard Worker }
260*fb1b10abSAndroid Build Coastguard Worker
vp9_copy_reference_dec(VP9Decoder * pbi,VP9_REFFRAME ref_frame_flag,YV12_BUFFER_CONFIG * sd)261*fb1b10abSAndroid Build Coastguard Worker vpx_codec_err_t vp9_copy_reference_dec(VP9Decoder *pbi,
262*fb1b10abSAndroid Build Coastguard Worker VP9_REFFRAME ref_frame_flag,
263*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *sd) {
264*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *cm = &pbi->common;
265*fb1b10abSAndroid Build Coastguard Worker
266*fb1b10abSAndroid Build Coastguard Worker /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
267*fb1b10abSAndroid Build Coastguard Worker * encoder is using the frame buffers for. This is just a stub to keep the
268*fb1b10abSAndroid Build Coastguard Worker * vpxenc --test-decode functionality working, and will be replaced in a
269*fb1b10abSAndroid Build Coastguard Worker * later commit that adds VP9-specific controls for this functionality.
270*fb1b10abSAndroid Build Coastguard Worker */
271*fb1b10abSAndroid Build Coastguard Worker if (ref_frame_flag == VP9_LAST_FLAG) {
272*fb1b10abSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *const cfg = get_ref_frame(cm, 0);
273*fb1b10abSAndroid Build Coastguard Worker if (cfg == NULL) {
274*fb1b10abSAndroid Build Coastguard Worker vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
275*fb1b10abSAndroid Build Coastguard Worker "No 'last' reference frame");
276*fb1b10abSAndroid Build Coastguard Worker return VPX_CODEC_ERROR;
277*fb1b10abSAndroid Build Coastguard Worker }
278*fb1b10abSAndroid Build Coastguard Worker if (!equal_dimensions(cfg, sd))
279*fb1b10abSAndroid Build Coastguard Worker vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
280*fb1b10abSAndroid Build Coastguard Worker "Incorrect buffer dimensions");
281*fb1b10abSAndroid Build Coastguard Worker else
282*fb1b10abSAndroid Build Coastguard Worker vpx_yv12_copy_frame(cfg, sd);
283*fb1b10abSAndroid Build Coastguard Worker } else {
284*fb1b10abSAndroid Build Coastguard Worker vpx_internal_error(&cm->error, VPX_CODEC_ERROR, "Invalid reference frame");
285*fb1b10abSAndroid Build Coastguard Worker }
286*fb1b10abSAndroid Build Coastguard Worker
287*fb1b10abSAndroid Build Coastguard Worker return cm->error.error_code;
288*fb1b10abSAndroid Build Coastguard Worker }
289*fb1b10abSAndroid Build Coastguard Worker
vp9_set_reference_dec(VP9_COMMON * cm,VP9_REFFRAME ref_frame_flag,YV12_BUFFER_CONFIG * sd)290*fb1b10abSAndroid Build Coastguard Worker vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
291*fb1b10abSAndroid Build Coastguard Worker VP9_REFFRAME ref_frame_flag,
292*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *sd) {
293*fb1b10abSAndroid Build Coastguard Worker int idx;
294*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *ref_buf = NULL;
295*fb1b10abSAndroid Build Coastguard Worker
296*fb1b10abSAndroid Build Coastguard Worker // TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
297*fb1b10abSAndroid Build Coastguard Worker // encoder is using the frame buffers for. This is just a stub to keep the
298*fb1b10abSAndroid Build Coastguard Worker // vpxenc --test-decode functionality working, and will be replaced in a
299*fb1b10abSAndroid Build Coastguard Worker // later commit that adds VP9-specific controls for this functionality.
300*fb1b10abSAndroid Build Coastguard Worker // (Yunqing) The set_reference control depends on the following setting in
301*fb1b10abSAndroid Build Coastguard Worker // encoder.
302*fb1b10abSAndroid Build Coastguard Worker // cpi->lst_fb_idx = 0;
303*fb1b10abSAndroid Build Coastguard Worker // cpi->gld_fb_idx = 1;
304*fb1b10abSAndroid Build Coastguard Worker // cpi->alt_fb_idx = 2;
305*fb1b10abSAndroid Build Coastguard Worker if (ref_frame_flag == VP9_LAST_FLAG) {
306*fb1b10abSAndroid Build Coastguard Worker idx = cm->ref_frame_map[0];
307*fb1b10abSAndroid Build Coastguard Worker } else if (ref_frame_flag == VP9_GOLD_FLAG) {
308*fb1b10abSAndroid Build Coastguard Worker idx = cm->ref_frame_map[1];
309*fb1b10abSAndroid Build Coastguard Worker } else if (ref_frame_flag == VP9_ALT_FLAG) {
310*fb1b10abSAndroid Build Coastguard Worker idx = cm->ref_frame_map[2];
311*fb1b10abSAndroid Build Coastguard Worker } else {
312*fb1b10abSAndroid Build Coastguard Worker vpx_internal_error(&cm->error, VPX_CODEC_ERROR, "Invalid reference frame");
313*fb1b10abSAndroid Build Coastguard Worker return cm->error.error_code;
314*fb1b10abSAndroid Build Coastguard Worker }
315*fb1b10abSAndroid Build Coastguard Worker
316*fb1b10abSAndroid Build Coastguard Worker if (idx < 0 || idx >= FRAME_BUFFERS) {
317*fb1b10abSAndroid Build Coastguard Worker vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
318*fb1b10abSAndroid Build Coastguard Worker "Invalid reference frame map");
319*fb1b10abSAndroid Build Coastguard Worker return cm->error.error_code;
320*fb1b10abSAndroid Build Coastguard Worker }
321*fb1b10abSAndroid Build Coastguard Worker
322*fb1b10abSAndroid Build Coastguard Worker // Get the destination reference buffer.
323*fb1b10abSAndroid Build Coastguard Worker ref_buf = &cm->buffer_pool->frame_bufs[idx].buf;
324*fb1b10abSAndroid Build Coastguard Worker
325*fb1b10abSAndroid Build Coastguard Worker if (!equal_dimensions(ref_buf, sd)) {
326*fb1b10abSAndroid Build Coastguard Worker vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
327*fb1b10abSAndroid Build Coastguard Worker "Incorrect buffer dimensions");
328*fb1b10abSAndroid Build Coastguard Worker } else {
329*fb1b10abSAndroid Build Coastguard Worker // Overwrite the reference frame buffer.
330*fb1b10abSAndroid Build Coastguard Worker vpx_yv12_copy_frame(sd, ref_buf);
331*fb1b10abSAndroid Build Coastguard Worker }
332*fb1b10abSAndroid Build Coastguard Worker
333*fb1b10abSAndroid Build Coastguard Worker return cm->error.error_code;
334*fb1b10abSAndroid Build Coastguard Worker }
335*fb1b10abSAndroid Build Coastguard Worker
336*fb1b10abSAndroid Build Coastguard Worker /* If any buffer updating is signaled it should be done here. */
swap_frame_buffers(VP9Decoder * pbi)337*fb1b10abSAndroid Build Coastguard Worker static void swap_frame_buffers(VP9Decoder *pbi) {
338*fb1b10abSAndroid Build Coastguard Worker int ref_index = 0, mask;
339*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *const cm = &pbi->common;
340*fb1b10abSAndroid Build Coastguard Worker BufferPool *const pool = cm->buffer_pool;
341*fb1b10abSAndroid Build Coastguard Worker RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
342*fb1b10abSAndroid Build Coastguard Worker
343*fb1b10abSAndroid Build Coastguard Worker for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
344*fb1b10abSAndroid Build Coastguard Worker const int old_idx = cm->ref_frame_map[ref_index];
345*fb1b10abSAndroid Build Coastguard Worker // Current thread releases the holding of reference frame.
346*fb1b10abSAndroid Build Coastguard Worker decrease_ref_count(old_idx, frame_bufs, pool);
347*fb1b10abSAndroid Build Coastguard Worker
348*fb1b10abSAndroid Build Coastguard Worker // Release the reference frame in reference map.
349*fb1b10abSAndroid Build Coastguard Worker if (mask & 1) {
350*fb1b10abSAndroid Build Coastguard Worker decrease_ref_count(old_idx, frame_bufs, pool);
351*fb1b10abSAndroid Build Coastguard Worker }
352*fb1b10abSAndroid Build Coastguard Worker cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
353*fb1b10abSAndroid Build Coastguard Worker ++ref_index;
354*fb1b10abSAndroid Build Coastguard Worker }
355*fb1b10abSAndroid Build Coastguard Worker
356*fb1b10abSAndroid Build Coastguard Worker // Current thread releases the holding of reference frame.
357*fb1b10abSAndroid Build Coastguard Worker for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
358*fb1b10abSAndroid Build Coastguard Worker const int old_idx = cm->ref_frame_map[ref_index];
359*fb1b10abSAndroid Build Coastguard Worker decrease_ref_count(old_idx, frame_bufs, pool);
360*fb1b10abSAndroid Build Coastguard Worker cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
361*fb1b10abSAndroid Build Coastguard Worker }
362*fb1b10abSAndroid Build Coastguard Worker pbi->hold_ref_buf = 0;
363*fb1b10abSAndroid Build Coastguard Worker cm->frame_to_show = get_frame_new_buffer(cm);
364*fb1b10abSAndroid Build Coastguard Worker
365*fb1b10abSAndroid Build Coastguard Worker --frame_bufs[cm->new_fb_idx].ref_count;
366*fb1b10abSAndroid Build Coastguard Worker
367*fb1b10abSAndroid Build Coastguard Worker // Invalidate these references until the next frame starts.
368*fb1b10abSAndroid Build Coastguard Worker for (ref_index = 0; ref_index < 3; ref_index++)
369*fb1b10abSAndroid Build Coastguard Worker cm->frame_refs[ref_index].idx = -1;
370*fb1b10abSAndroid Build Coastguard Worker }
371*fb1b10abSAndroid Build Coastguard Worker
release_fb_on_decoder_exit(VP9Decoder * pbi)372*fb1b10abSAndroid Build Coastguard Worker static void release_fb_on_decoder_exit(VP9Decoder *pbi) {
373*fb1b10abSAndroid Build Coastguard Worker const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
374*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *volatile const cm = &pbi->common;
375*fb1b10abSAndroid Build Coastguard Worker BufferPool *volatile const pool = cm->buffer_pool;
376*fb1b10abSAndroid Build Coastguard Worker RefCntBuffer *volatile const frame_bufs = cm->buffer_pool->frame_bufs;
377*fb1b10abSAndroid Build Coastguard Worker int i;
378*fb1b10abSAndroid Build Coastguard Worker
379*fb1b10abSAndroid Build Coastguard Worker // Synchronize all threads immediately as a subsequent decode call may
380*fb1b10abSAndroid Build Coastguard Worker // cause a resize invalidating some allocations.
381*fb1b10abSAndroid Build Coastguard Worker winterface->sync(&pbi->lf_worker);
382*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < pbi->num_tile_workers; ++i) {
383*fb1b10abSAndroid Build Coastguard Worker winterface->sync(&pbi->tile_workers[i]);
384*fb1b10abSAndroid Build Coastguard Worker }
385*fb1b10abSAndroid Build Coastguard Worker
386*fb1b10abSAndroid Build Coastguard Worker // Release all the reference buffers if worker thread is holding them.
387*fb1b10abSAndroid Build Coastguard Worker if (pbi->hold_ref_buf == 1) {
388*fb1b10abSAndroid Build Coastguard Worker int ref_index = 0, mask;
389*fb1b10abSAndroid Build Coastguard Worker for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
390*fb1b10abSAndroid Build Coastguard Worker const int old_idx = cm->ref_frame_map[ref_index];
391*fb1b10abSAndroid Build Coastguard Worker // Current thread releases the holding of reference frame.
392*fb1b10abSAndroid Build Coastguard Worker decrease_ref_count(old_idx, frame_bufs, pool);
393*fb1b10abSAndroid Build Coastguard Worker
394*fb1b10abSAndroid Build Coastguard Worker // Release the reference frame in reference map.
395*fb1b10abSAndroid Build Coastguard Worker if (mask & 1) {
396*fb1b10abSAndroid Build Coastguard Worker decrease_ref_count(old_idx, frame_bufs, pool);
397*fb1b10abSAndroid Build Coastguard Worker }
398*fb1b10abSAndroid Build Coastguard Worker ++ref_index;
399*fb1b10abSAndroid Build Coastguard Worker }
400*fb1b10abSAndroid Build Coastguard Worker
401*fb1b10abSAndroid Build Coastguard Worker // Current thread releases the holding of reference frame.
402*fb1b10abSAndroid Build Coastguard Worker for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
403*fb1b10abSAndroid Build Coastguard Worker const int old_idx = cm->ref_frame_map[ref_index];
404*fb1b10abSAndroid Build Coastguard Worker decrease_ref_count(old_idx, frame_bufs, pool);
405*fb1b10abSAndroid Build Coastguard Worker }
406*fb1b10abSAndroid Build Coastguard Worker pbi->hold_ref_buf = 0;
407*fb1b10abSAndroid Build Coastguard Worker }
408*fb1b10abSAndroid Build Coastguard Worker }
409*fb1b10abSAndroid Build Coastguard Worker
vp9_receive_compressed_data(VP9Decoder * pbi,size_t size,const uint8_t ** psource)410*fb1b10abSAndroid Build Coastguard Worker int vp9_receive_compressed_data(VP9Decoder *pbi, size_t size,
411*fb1b10abSAndroid Build Coastguard Worker const uint8_t **psource) {
412*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *volatile const cm = &pbi->common;
413*fb1b10abSAndroid Build Coastguard Worker BufferPool *volatile const pool = cm->buffer_pool;
414*fb1b10abSAndroid Build Coastguard Worker RefCntBuffer *volatile const frame_bufs = cm->buffer_pool->frame_bufs;
415*fb1b10abSAndroid Build Coastguard Worker const uint8_t *source = *psource;
416*fb1b10abSAndroid Build Coastguard Worker int retcode = 0;
417*fb1b10abSAndroid Build Coastguard Worker cm->error.error_code = VPX_CODEC_OK;
418*fb1b10abSAndroid Build Coastguard Worker
419*fb1b10abSAndroid Build Coastguard Worker if (size == 0) {
420*fb1b10abSAndroid Build Coastguard Worker // This is used to signal that we are missing frames.
421*fb1b10abSAndroid Build Coastguard Worker // We do not know if the missing frame(s) was supposed to update
422*fb1b10abSAndroid Build Coastguard Worker // any of the reference buffers, but we act conservative and
423*fb1b10abSAndroid Build Coastguard Worker // mark only the last buffer as corrupted.
424*fb1b10abSAndroid Build Coastguard Worker //
425*fb1b10abSAndroid Build Coastguard Worker // TODO(jkoleszar): Error concealment is undefined and non-normative
426*fb1b10abSAndroid Build Coastguard Worker // at this point, but if it becomes so, [0] may not always be the correct
427*fb1b10abSAndroid Build Coastguard Worker // thing to do here.
428*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_refs[0].idx > 0) {
429*fb1b10abSAndroid Build Coastguard Worker assert(cm->frame_refs[0].buf != NULL);
430*fb1b10abSAndroid Build Coastguard Worker cm->frame_refs[0].buf->corrupted = 1;
431*fb1b10abSAndroid Build Coastguard Worker }
432*fb1b10abSAndroid Build Coastguard Worker }
433*fb1b10abSAndroid Build Coastguard Worker
434*fb1b10abSAndroid Build Coastguard Worker pbi->ready_for_new_data = 0;
435*fb1b10abSAndroid Build Coastguard Worker
436*fb1b10abSAndroid Build Coastguard Worker // Check if the previous frame was a frame without any references to it.
437*fb1b10abSAndroid Build Coastguard Worker if (cm->new_fb_idx >= 0 && frame_bufs[cm->new_fb_idx].ref_count == 0 &&
438*fb1b10abSAndroid Build Coastguard Worker !frame_bufs[cm->new_fb_idx].released) {
439*fb1b10abSAndroid Build Coastguard Worker pool->release_fb_cb(pool->cb_priv,
440*fb1b10abSAndroid Build Coastguard Worker &frame_bufs[cm->new_fb_idx].raw_frame_buffer);
441*fb1b10abSAndroid Build Coastguard Worker frame_bufs[cm->new_fb_idx].released = 1;
442*fb1b10abSAndroid Build Coastguard Worker }
443*fb1b10abSAndroid Build Coastguard Worker
444*fb1b10abSAndroid Build Coastguard Worker // Find a free frame buffer. Return error if can not find any.
445*fb1b10abSAndroid Build Coastguard Worker cm->new_fb_idx = get_free_fb(cm);
446*fb1b10abSAndroid Build Coastguard Worker if (cm->new_fb_idx == INVALID_IDX) {
447*fb1b10abSAndroid Build Coastguard Worker pbi->ready_for_new_data = 1;
448*fb1b10abSAndroid Build Coastguard Worker release_fb_on_decoder_exit(pbi);
449*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
450*fb1b10abSAndroid Build Coastguard Worker vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
451*fb1b10abSAndroid Build Coastguard Worker "Unable to find free frame buffer");
452*fb1b10abSAndroid Build Coastguard Worker return cm->error.error_code;
453*fb1b10abSAndroid Build Coastguard Worker }
454*fb1b10abSAndroid Build Coastguard Worker
455*fb1b10abSAndroid Build Coastguard Worker // Assign a MV array to the frame buffer.
456*fb1b10abSAndroid Build Coastguard Worker cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
457*fb1b10abSAndroid Build Coastguard Worker
458*fb1b10abSAndroid Build Coastguard Worker pbi->hold_ref_buf = 0;
459*fb1b10abSAndroid Build Coastguard Worker pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
460*fb1b10abSAndroid Build Coastguard Worker
461*fb1b10abSAndroid Build Coastguard Worker if (setjmp(cm->error.jmp)) {
462*fb1b10abSAndroid Build Coastguard Worker cm->error.setjmp = 0;
463*fb1b10abSAndroid Build Coastguard Worker pbi->ready_for_new_data = 1;
464*fb1b10abSAndroid Build Coastguard Worker release_fb_on_decoder_exit(pbi);
465*fb1b10abSAndroid Build Coastguard Worker // Release current frame.
466*fb1b10abSAndroid Build Coastguard Worker decrease_ref_count(cm->new_fb_idx, frame_bufs, pool);
467*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
468*fb1b10abSAndroid Build Coastguard Worker return -1;
469*fb1b10abSAndroid Build Coastguard Worker }
470*fb1b10abSAndroid Build Coastguard Worker
471*fb1b10abSAndroid Build Coastguard Worker cm->error.setjmp = 1;
472*fb1b10abSAndroid Build Coastguard Worker vp9_decode_frame(pbi, source, source + size, psource);
473*fb1b10abSAndroid Build Coastguard Worker
474*fb1b10abSAndroid Build Coastguard Worker swap_frame_buffers(pbi);
475*fb1b10abSAndroid Build Coastguard Worker
476*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
477*fb1b10abSAndroid Build Coastguard Worker
478*fb1b10abSAndroid Build Coastguard Worker if (!cm->show_existing_frame) {
479*fb1b10abSAndroid Build Coastguard Worker cm->last_show_frame = cm->show_frame;
480*fb1b10abSAndroid Build Coastguard Worker cm->prev_frame = cm->cur_frame;
481*fb1b10abSAndroid Build Coastguard Worker if (cm->seg.enabled) vp9_swap_current_and_last_seg_map(cm);
482*fb1b10abSAndroid Build Coastguard Worker }
483*fb1b10abSAndroid Build Coastguard Worker
484*fb1b10abSAndroid Build Coastguard Worker if (cm->show_frame) cm->cur_show_frame_fb_idx = cm->new_fb_idx;
485*fb1b10abSAndroid Build Coastguard Worker
486*fb1b10abSAndroid Build Coastguard Worker // Update progress in frame parallel decode.
487*fb1b10abSAndroid Build Coastguard Worker cm->last_width = cm->width;
488*fb1b10abSAndroid Build Coastguard Worker cm->last_height = cm->height;
489*fb1b10abSAndroid Build Coastguard Worker if (cm->show_frame) {
490*fb1b10abSAndroid Build Coastguard Worker cm->current_video_frame++;
491*fb1b10abSAndroid Build Coastguard Worker }
492*fb1b10abSAndroid Build Coastguard Worker
493*fb1b10abSAndroid Build Coastguard Worker cm->error.setjmp = 0;
494*fb1b10abSAndroid Build Coastguard Worker return retcode;
495*fb1b10abSAndroid Build Coastguard Worker }
496*fb1b10abSAndroid Build Coastguard Worker
vp9_get_raw_frame(VP9Decoder * pbi,YV12_BUFFER_CONFIG * sd,vp9_ppflags_t * flags)497*fb1b10abSAndroid Build Coastguard Worker int vp9_get_raw_frame(VP9Decoder *pbi, YV12_BUFFER_CONFIG *sd,
498*fb1b10abSAndroid Build Coastguard Worker vp9_ppflags_t *flags) {
499*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *const cm = &pbi->common;
500*fb1b10abSAndroid Build Coastguard Worker int ret = -1;
501*fb1b10abSAndroid Build Coastguard Worker #if !CONFIG_VP9_POSTPROC
502*fb1b10abSAndroid Build Coastguard Worker (void)*flags;
503*fb1b10abSAndroid Build Coastguard Worker #endif
504*fb1b10abSAndroid Build Coastguard Worker
505*fb1b10abSAndroid Build Coastguard Worker if (pbi->ready_for_new_data == 1) return ret;
506*fb1b10abSAndroid Build Coastguard Worker
507*fb1b10abSAndroid Build Coastguard Worker pbi->ready_for_new_data = 1;
508*fb1b10abSAndroid Build Coastguard Worker
509*fb1b10abSAndroid Build Coastguard Worker /* no raw frame to show!!! */
510*fb1b10abSAndroid Build Coastguard Worker if (!cm->show_frame) return ret;
511*fb1b10abSAndroid Build Coastguard Worker
512*fb1b10abSAndroid Build Coastguard Worker pbi->ready_for_new_data = 1;
513*fb1b10abSAndroid Build Coastguard Worker
514*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_POSTPROC
515*fb1b10abSAndroid Build Coastguard Worker if (!cm->show_existing_frame) {
516*fb1b10abSAndroid Build Coastguard Worker ret = vp9_post_proc_frame(cm, sd, flags, cm->width);
517*fb1b10abSAndroid Build Coastguard Worker } else {
518*fb1b10abSAndroid Build Coastguard Worker *sd = *cm->frame_to_show;
519*fb1b10abSAndroid Build Coastguard Worker ret = 0;
520*fb1b10abSAndroid Build Coastguard Worker }
521*fb1b10abSAndroid Build Coastguard Worker #else
522*fb1b10abSAndroid Build Coastguard Worker *sd = *cm->frame_to_show;
523*fb1b10abSAndroid Build Coastguard Worker ret = 0;
524*fb1b10abSAndroid Build Coastguard Worker #endif /*!CONFIG_POSTPROC*/
525*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
526*fb1b10abSAndroid Build Coastguard Worker return ret;
527*fb1b10abSAndroid Build Coastguard Worker }
528*fb1b10abSAndroid Build Coastguard Worker
vp9_parse_superframe_index(const uint8_t * data,size_t data_sz,uint32_t sizes[8],int * count,vpx_decrypt_cb decrypt_cb,void * decrypt_state)529*fb1b10abSAndroid Build Coastguard Worker vpx_codec_err_t vp9_parse_superframe_index(const uint8_t *data, size_t data_sz,
530*fb1b10abSAndroid Build Coastguard Worker uint32_t sizes[8], int *count,
531*fb1b10abSAndroid Build Coastguard Worker vpx_decrypt_cb decrypt_cb,
532*fb1b10abSAndroid Build Coastguard Worker void *decrypt_state) {
533*fb1b10abSAndroid Build Coastguard Worker // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
534*fb1b10abSAndroid Build Coastguard Worker // it is a super frame index. If the last byte of real video compression
535*fb1b10abSAndroid Build Coastguard Worker // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
536*fb1b10abSAndroid Build Coastguard Worker // not the associated matching marker byte at the front of the index we have
537*fb1b10abSAndroid Build Coastguard Worker // an invalid bitstream and need to return an error.
538*fb1b10abSAndroid Build Coastguard Worker
539*fb1b10abSAndroid Build Coastguard Worker uint8_t marker;
540*fb1b10abSAndroid Build Coastguard Worker
541*fb1b10abSAndroid Build Coastguard Worker assert(data_sz);
542*fb1b10abSAndroid Build Coastguard Worker marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1);
543*fb1b10abSAndroid Build Coastguard Worker *count = 0;
544*fb1b10abSAndroid Build Coastguard Worker
545*fb1b10abSAndroid Build Coastguard Worker if ((marker & 0xe0) == 0xc0) {
546*fb1b10abSAndroid Build Coastguard Worker const uint32_t frames = (marker & 0x7) + 1;
547*fb1b10abSAndroid Build Coastguard Worker const uint32_t mag = ((marker >> 3) & 0x3) + 1;
548*fb1b10abSAndroid Build Coastguard Worker const size_t index_sz = 2 + mag * frames;
549*fb1b10abSAndroid Build Coastguard Worker
550*fb1b10abSAndroid Build Coastguard Worker // This chunk is marked as having a superframe index but doesn't have
551*fb1b10abSAndroid Build Coastguard Worker // enough data for it, thus it's an invalid superframe index.
552*fb1b10abSAndroid Build Coastguard Worker if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
553*fb1b10abSAndroid Build Coastguard Worker
554*fb1b10abSAndroid Build Coastguard Worker {
555*fb1b10abSAndroid Build Coastguard Worker const uint8_t marker2 =
556*fb1b10abSAndroid Build Coastguard Worker read_marker(decrypt_cb, decrypt_state, data + data_sz - index_sz);
557*fb1b10abSAndroid Build Coastguard Worker
558*fb1b10abSAndroid Build Coastguard Worker // This chunk is marked as having a superframe index but doesn't have
559*fb1b10abSAndroid Build Coastguard Worker // the matching marker byte at the front of the index therefore it's an
560*fb1b10abSAndroid Build Coastguard Worker // invalid chunk.
561*fb1b10abSAndroid Build Coastguard Worker if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
562*fb1b10abSAndroid Build Coastguard Worker }
563*fb1b10abSAndroid Build Coastguard Worker
564*fb1b10abSAndroid Build Coastguard Worker {
565*fb1b10abSAndroid Build Coastguard Worker // Found a valid superframe index.
566*fb1b10abSAndroid Build Coastguard Worker uint32_t i, j;
567*fb1b10abSAndroid Build Coastguard Worker const uint8_t *x = &data[data_sz - index_sz + 1];
568*fb1b10abSAndroid Build Coastguard Worker
569*fb1b10abSAndroid Build Coastguard Worker // Frames has a maximum of 8 and mag has a maximum of 4.
570*fb1b10abSAndroid Build Coastguard Worker uint8_t clear_buffer[32];
571*fb1b10abSAndroid Build Coastguard Worker assert(sizeof(clear_buffer) >= frames * mag);
572*fb1b10abSAndroid Build Coastguard Worker if (decrypt_cb) {
573*fb1b10abSAndroid Build Coastguard Worker decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
574*fb1b10abSAndroid Build Coastguard Worker x = clear_buffer;
575*fb1b10abSAndroid Build Coastguard Worker }
576*fb1b10abSAndroid Build Coastguard Worker
577*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < frames; ++i) {
578*fb1b10abSAndroid Build Coastguard Worker uint32_t this_sz = 0;
579*fb1b10abSAndroid Build Coastguard Worker
580*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < mag; ++j) this_sz |= ((uint32_t)(*x++)) << (j * 8);
581*fb1b10abSAndroid Build Coastguard Worker sizes[i] = this_sz;
582*fb1b10abSAndroid Build Coastguard Worker }
583*fb1b10abSAndroid Build Coastguard Worker *count = frames;
584*fb1b10abSAndroid Build Coastguard Worker }
585*fb1b10abSAndroid Build Coastguard Worker }
586*fb1b10abSAndroid Build Coastguard Worker return VPX_CODEC_OK;
587*fb1b10abSAndroid Build Coastguard Worker }
588