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