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