1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp8/decoder/onyxd_if.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,527 @@ 1.4 +/* 1.5 + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license 1.8 + * that can be found in the LICENSE file in the root of the source 1.9 + * tree. An additional intellectual property rights grant can be found 1.10 + * in the file PATENTS. All contributing project authors may 1.11 + * be found in the AUTHORS file in the root of the source tree. 1.12 + */ 1.13 + 1.14 + 1.15 +#include "vp8/common/onyxc_int.h" 1.16 +#if CONFIG_POSTPROC 1.17 +#include "vp8/common/postproc.h" 1.18 +#endif 1.19 +#include "vp8/common/onyxd.h" 1.20 +#include "onyxd_int.h" 1.21 +#include "vpx_mem/vpx_mem.h" 1.22 +#include "vp8/common/alloccommon.h" 1.23 +#include "vp8/common/loopfilter.h" 1.24 +#include "vp8/common/swapyv12buffer.h" 1.25 +#include "vp8/common/threading.h" 1.26 +#include "decoderthreading.h" 1.27 +#include <stdio.h> 1.28 +#include <assert.h> 1.29 + 1.30 +#include "vp8/common/quant_common.h" 1.31 +#include "./vpx_scale_rtcd.h" 1.32 +#include "vpx_scale/vpx_scale.h" 1.33 +#include "vp8/common/systemdependent.h" 1.34 +#include "vpx_ports/vpx_timer.h" 1.35 +#include "detokenize.h" 1.36 +#if CONFIG_ERROR_CONCEALMENT 1.37 +#include "error_concealment.h" 1.38 +#endif 1.39 +#if ARCH_ARM 1.40 +#include "vpx_ports/arm.h" 1.41 +#endif 1.42 + 1.43 +extern void vp8_init_loop_filter(VP8_COMMON *cm); 1.44 +extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi); 1.45 +static int get_free_fb (VP8_COMMON *cm); 1.46 +static void ref_cnt_fb (int *buf, int *idx, int new_idx); 1.47 + 1.48 +static void remove_decompressor(VP8D_COMP *pbi) 1.49 +{ 1.50 +#if CONFIG_ERROR_CONCEALMENT 1.51 + vp8_de_alloc_overlap_lists(pbi); 1.52 +#endif 1.53 + vp8_remove_common(&pbi->common); 1.54 + vpx_free(pbi); 1.55 +} 1.56 + 1.57 +static struct VP8D_COMP * create_decompressor(VP8D_CONFIG *oxcf) 1.58 +{ 1.59 + VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP)); 1.60 + 1.61 + if (!pbi) 1.62 + return NULL; 1.63 + 1.64 + vpx_memset(pbi, 0, sizeof(VP8D_COMP)); 1.65 + 1.66 + if (setjmp(pbi->common.error.jmp)) 1.67 + { 1.68 + pbi->common.error.setjmp = 0; 1.69 + remove_decompressor(pbi); 1.70 + return 0; 1.71 + } 1.72 + 1.73 + pbi->common.error.setjmp = 1; 1.74 + 1.75 + vp8_create_common(&pbi->common); 1.76 + 1.77 + pbi->common.current_video_frame = 0; 1.78 + pbi->ready_for_new_data = 1; 1.79 + 1.80 + /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid 1.81 + * unnecessary calling of vp8cx_init_de_quantizer() for every frame. 1.82 + */ 1.83 + vp8cx_init_de_quantizer(pbi); 1.84 + 1.85 + vp8_loop_filter_init(&pbi->common); 1.86 + 1.87 + pbi->common.error.setjmp = 0; 1.88 + 1.89 +#if CONFIG_ERROR_CONCEALMENT 1.90 + pbi->ec_enabled = oxcf->error_concealment; 1.91 + pbi->overlaps = NULL; 1.92 +#else 1.93 + pbi->ec_enabled = 0; 1.94 +#endif 1.95 + /* Error concealment is activated after a key frame has been 1.96 + * decoded without errors when error concealment is enabled. 1.97 + */ 1.98 + pbi->ec_active = 0; 1.99 + 1.100 + pbi->decoded_key_frame = 0; 1.101 + 1.102 + /* Independent partitions is activated when a frame updates the 1.103 + * token probability table to have equal probabilities over the 1.104 + * PREV_COEF context. 1.105 + */ 1.106 + pbi->independent_partitions = 0; 1.107 + 1.108 + vp8_setup_block_dptrs(&pbi->mb); 1.109 + 1.110 + return pbi; 1.111 +} 1.112 + 1.113 +vpx_codec_err_t vp8dx_get_reference(VP8D_COMP *pbi, enum vpx_ref_frame_type ref_frame_flag, YV12_BUFFER_CONFIG *sd) 1.114 +{ 1.115 + VP8_COMMON *cm = &pbi->common; 1.116 + int ref_fb_idx; 1.117 + 1.118 + if (ref_frame_flag == VP8_LAST_FRAME) 1.119 + ref_fb_idx = cm->lst_fb_idx; 1.120 + else if (ref_frame_flag == VP8_GOLD_FRAME) 1.121 + ref_fb_idx = cm->gld_fb_idx; 1.122 + else if (ref_frame_flag == VP8_ALTR_FRAME) 1.123 + ref_fb_idx = cm->alt_fb_idx; 1.124 + else{ 1.125 + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 1.126 + "Invalid reference frame"); 1.127 + return pbi->common.error.error_code; 1.128 + } 1.129 + 1.130 + if(cm->yv12_fb[ref_fb_idx].y_height != sd->y_height || 1.131 + cm->yv12_fb[ref_fb_idx].y_width != sd->y_width || 1.132 + cm->yv12_fb[ref_fb_idx].uv_height != sd->uv_height || 1.133 + cm->yv12_fb[ref_fb_idx].uv_width != sd->uv_width){ 1.134 + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 1.135 + "Incorrect buffer dimensions"); 1.136 + } 1.137 + else 1.138 + vp8_yv12_copy_frame(&cm->yv12_fb[ref_fb_idx], sd); 1.139 + 1.140 + return pbi->common.error.error_code; 1.141 +} 1.142 + 1.143 + 1.144 +vpx_codec_err_t vp8dx_set_reference(VP8D_COMP *pbi, enum vpx_ref_frame_type ref_frame_flag, YV12_BUFFER_CONFIG *sd) 1.145 +{ 1.146 + VP8_COMMON *cm = &pbi->common; 1.147 + int *ref_fb_ptr = NULL; 1.148 + int free_fb; 1.149 + 1.150 + if (ref_frame_flag == VP8_LAST_FRAME) 1.151 + ref_fb_ptr = &cm->lst_fb_idx; 1.152 + else if (ref_frame_flag == VP8_GOLD_FRAME) 1.153 + ref_fb_ptr = &cm->gld_fb_idx; 1.154 + else if (ref_frame_flag == VP8_ALTR_FRAME) 1.155 + ref_fb_ptr = &cm->alt_fb_idx; 1.156 + else{ 1.157 + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 1.158 + "Invalid reference frame"); 1.159 + return pbi->common.error.error_code; 1.160 + } 1.161 + 1.162 + if(cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height || 1.163 + cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width || 1.164 + cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height || 1.165 + cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width){ 1.166 + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 1.167 + "Incorrect buffer dimensions"); 1.168 + } 1.169 + else{ 1.170 + /* Find an empty frame buffer. */ 1.171 + free_fb = get_free_fb(cm); 1.172 + /* Decrease fb_idx_ref_cnt since it will be increased again in 1.173 + * ref_cnt_fb() below. */ 1.174 + cm->fb_idx_ref_cnt[free_fb]--; 1.175 + 1.176 + /* Manage the reference counters and copy image. */ 1.177 + ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb); 1.178 + vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]); 1.179 + } 1.180 + 1.181 + return pbi->common.error.error_code; 1.182 +} 1.183 + 1.184 +/*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/ 1.185 +#if HAVE_NEON 1.186 +extern void vp8_push_neon(int64_t *store); 1.187 +extern void vp8_pop_neon(int64_t *store); 1.188 +#endif 1.189 + 1.190 +static int get_free_fb (VP8_COMMON *cm) 1.191 +{ 1.192 + int i; 1.193 + for (i = 0; i < NUM_YV12_BUFFERS; i++) 1.194 + if (cm->fb_idx_ref_cnt[i] == 0) 1.195 + break; 1.196 + 1.197 + assert(i < NUM_YV12_BUFFERS); 1.198 + cm->fb_idx_ref_cnt[i] = 1; 1.199 + return i; 1.200 +} 1.201 + 1.202 +static void ref_cnt_fb (int *buf, int *idx, int new_idx) 1.203 +{ 1.204 + if (buf[*idx] > 0) 1.205 + buf[*idx]--; 1.206 + 1.207 + *idx = new_idx; 1.208 + 1.209 + buf[new_idx]++; 1.210 +} 1.211 + 1.212 +/* If any buffer copy / swapping is signalled it should be done here. */ 1.213 +static int swap_frame_buffers (VP8_COMMON *cm) 1.214 +{ 1.215 + int err = 0; 1.216 + 1.217 + /* The alternate reference frame or golden frame can be updated 1.218 + * using the new, last, or golden/alt ref frame. If it 1.219 + * is updated using the newly decoded frame it is a refresh. 1.220 + * An update using the last or golden/alt ref frame is a copy. 1.221 + */ 1.222 + if (cm->copy_buffer_to_arf) 1.223 + { 1.224 + int new_fb = 0; 1.225 + 1.226 + if (cm->copy_buffer_to_arf == 1) 1.227 + new_fb = cm->lst_fb_idx; 1.228 + else if (cm->copy_buffer_to_arf == 2) 1.229 + new_fb = cm->gld_fb_idx; 1.230 + else 1.231 + err = -1; 1.232 + 1.233 + ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb); 1.234 + } 1.235 + 1.236 + if (cm->copy_buffer_to_gf) 1.237 + { 1.238 + int new_fb = 0; 1.239 + 1.240 + if (cm->copy_buffer_to_gf == 1) 1.241 + new_fb = cm->lst_fb_idx; 1.242 + else if (cm->copy_buffer_to_gf == 2) 1.243 + new_fb = cm->alt_fb_idx; 1.244 + else 1.245 + err = -1; 1.246 + 1.247 + ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb); 1.248 + } 1.249 + 1.250 + if (cm->refresh_golden_frame) 1.251 + ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx); 1.252 + 1.253 + if (cm->refresh_alt_ref_frame) 1.254 + ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx); 1.255 + 1.256 + if (cm->refresh_last_frame) 1.257 + { 1.258 + ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx); 1.259 + 1.260 + cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx]; 1.261 + } 1.262 + else 1.263 + cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx]; 1.264 + 1.265 + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 1.266 + 1.267 + return err; 1.268 +} 1.269 + 1.270 +int check_fragments_for_errors(VP8D_COMP *pbi) 1.271 +{ 1.272 + if (!pbi->ec_active && 1.273 + pbi->fragments.count <= 1 && pbi->fragments.sizes[0] == 0) 1.274 + { 1.275 + VP8_COMMON *cm = &pbi->common; 1.276 + 1.277 + /* If error concealment is disabled we won't signal missing frames 1.278 + * to the decoder. 1.279 + */ 1.280 + if (cm->fb_idx_ref_cnt[cm->lst_fb_idx] > 1) 1.281 + { 1.282 + /* The last reference shares buffer with another reference 1.283 + * buffer. Move it to its own buffer before setting it as 1.284 + * corrupt, otherwise we will make multiple buffers corrupt. 1.285 + */ 1.286 + const int prev_idx = cm->lst_fb_idx; 1.287 + cm->fb_idx_ref_cnt[prev_idx]--; 1.288 + cm->lst_fb_idx = get_free_fb(cm); 1.289 + vp8_yv12_copy_frame(&cm->yv12_fb[prev_idx], 1.290 + &cm->yv12_fb[cm->lst_fb_idx]); 1.291 + } 1.292 + /* This is used to signal that we are missing frames. 1.293 + * We do not know if the missing frame(s) was supposed to update 1.294 + * any of the reference buffers, but we act conservative and 1.295 + * mark only the last buffer as corrupted. 1.296 + */ 1.297 + cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; 1.298 + 1.299 + /* Signal that we have no frame to show. */ 1.300 + cm->show_frame = 0; 1.301 + 1.302 + /* Nothing more to do. */ 1.303 + return 0; 1.304 + } 1.305 + 1.306 + return 1; 1.307 +} 1.308 + 1.309 +int vp8dx_receive_compressed_data(VP8D_COMP *pbi, size_t size, 1.310 + const uint8_t *source, 1.311 + int64_t time_stamp) 1.312 +{ 1.313 +#if HAVE_NEON 1.314 + int64_t dx_store_reg[8]; 1.315 +#endif 1.316 + VP8_COMMON *cm = &pbi->common; 1.317 + int retcode = -1; 1.318 + 1.319 + pbi->common.error.error_code = VPX_CODEC_OK; 1.320 + 1.321 + retcode = check_fragments_for_errors(pbi); 1.322 + if(retcode <= 0) 1.323 + return retcode; 1.324 + 1.325 +#if HAVE_NEON 1.326 +#if CONFIG_RUNTIME_CPU_DETECT 1.327 + if (cm->cpu_caps & HAS_NEON) 1.328 +#endif 1.329 + { 1.330 + vp8_push_neon(dx_store_reg); 1.331 + } 1.332 +#endif 1.333 + 1.334 + cm->new_fb_idx = get_free_fb (cm); 1.335 + 1.336 + /* setup reference frames for vp8_decode_frame */ 1.337 + pbi->dec_fb_ref[INTRA_FRAME] = &cm->yv12_fb[cm->new_fb_idx]; 1.338 + pbi->dec_fb_ref[LAST_FRAME] = &cm->yv12_fb[cm->lst_fb_idx]; 1.339 + pbi->dec_fb_ref[GOLDEN_FRAME] = &cm->yv12_fb[cm->gld_fb_idx]; 1.340 + pbi->dec_fb_ref[ALTREF_FRAME] = &cm->yv12_fb[cm->alt_fb_idx]; 1.341 + 1.342 + if (setjmp(pbi->common.error.jmp)) 1.343 + { 1.344 + /* We do not know if the missing frame(s) was supposed to update 1.345 + * any of the reference buffers, but we act conservative and 1.346 + * mark only the last buffer as corrupted. 1.347 + */ 1.348 + cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; 1.349 + 1.350 + if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 1.351 + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 1.352 + 1.353 + goto decode_exit; 1.354 + } 1.355 + 1.356 + pbi->common.error.setjmp = 1; 1.357 + 1.358 + retcode = vp8_decode_frame(pbi); 1.359 + 1.360 + if (retcode < 0) 1.361 + { 1.362 + if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 1.363 + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 1.364 + 1.365 + pbi->common.error.error_code = VPX_CODEC_ERROR; 1.366 + goto decode_exit; 1.367 + } 1.368 + 1.369 + if (swap_frame_buffers (cm)) 1.370 + { 1.371 + pbi->common.error.error_code = VPX_CODEC_ERROR; 1.372 + goto decode_exit; 1.373 + } 1.374 + 1.375 + vp8_clear_system_state(); 1.376 + 1.377 + if (cm->show_frame) 1.378 + { 1.379 + cm->current_video_frame++; 1.380 + cm->show_frame_mi = cm->mi; 1.381 + } 1.382 + 1.383 + #if CONFIG_ERROR_CONCEALMENT 1.384 + /* swap the mode infos to storage for future error concealment */ 1.385 + if (pbi->ec_enabled && pbi->common.prev_mi) 1.386 + { 1.387 + MODE_INFO* tmp = pbi->common.prev_mi; 1.388 + int row, col; 1.389 + pbi->common.prev_mi = pbi->common.mi; 1.390 + pbi->common.mi = tmp; 1.391 + 1.392 + /* Propagate the segment_ids to the next frame */ 1.393 + for (row = 0; row < pbi->common.mb_rows; ++row) 1.394 + { 1.395 + for (col = 0; col < pbi->common.mb_cols; ++col) 1.396 + { 1.397 + const int i = row*pbi->common.mode_info_stride + col; 1.398 + pbi->common.mi[i].mbmi.segment_id = 1.399 + pbi->common.prev_mi[i].mbmi.segment_id; 1.400 + } 1.401 + } 1.402 + } 1.403 +#endif 1.404 + 1.405 + pbi->ready_for_new_data = 0; 1.406 + pbi->last_time_stamp = time_stamp; 1.407 + 1.408 +decode_exit: 1.409 +#if HAVE_NEON 1.410 +#if CONFIG_RUNTIME_CPU_DETECT 1.411 + if (cm->cpu_caps & HAS_NEON) 1.412 +#endif 1.413 + { 1.414 + vp8_pop_neon(dx_store_reg); 1.415 + } 1.416 +#endif 1.417 + 1.418 + pbi->common.error.setjmp = 0; 1.419 + return retcode; 1.420 +} 1.421 +int vp8dx_get_raw_frame(VP8D_COMP *pbi, YV12_BUFFER_CONFIG *sd, int64_t *time_stamp, int64_t *time_end_stamp, vp8_ppflags_t *flags) 1.422 +{ 1.423 + int ret = -1; 1.424 + 1.425 + if (pbi->ready_for_new_data == 1) 1.426 + return ret; 1.427 + 1.428 + /* ie no raw frame to show!!! */ 1.429 + if (pbi->common.show_frame == 0) 1.430 + return ret; 1.431 + 1.432 + pbi->ready_for_new_data = 1; 1.433 + *time_stamp = pbi->last_time_stamp; 1.434 + *time_end_stamp = 0; 1.435 + 1.436 +#if CONFIG_POSTPROC 1.437 + ret = vp8_post_proc_frame(&pbi->common, sd, flags); 1.438 +#else 1.439 + 1.440 + if (pbi->common.frame_to_show) 1.441 + { 1.442 + *sd = *pbi->common.frame_to_show; 1.443 + sd->y_width = pbi->common.Width; 1.444 + sd->y_height = pbi->common.Height; 1.445 + sd->uv_height = pbi->common.Height / 2; 1.446 + ret = 0; 1.447 + } 1.448 + else 1.449 + { 1.450 + ret = -1; 1.451 + } 1.452 + 1.453 +#endif /*!CONFIG_POSTPROC*/ 1.454 + vp8_clear_system_state(); 1.455 + return ret; 1.456 +} 1.457 + 1.458 + 1.459 +/* This function as written isn't decoder specific, but the encoder has 1.460 + * much faster ways of computing this, so it's ok for it to live in a 1.461 + * decode specific file. 1.462 + */ 1.463 +int vp8dx_references_buffer( VP8_COMMON *oci, int ref_frame ) 1.464 +{ 1.465 + const MODE_INFO *mi = oci->mi; 1.466 + int mb_row, mb_col; 1.467 + 1.468 + for (mb_row = 0; mb_row < oci->mb_rows; mb_row++) 1.469 + { 1.470 + for (mb_col = 0; mb_col < oci->mb_cols; mb_col++,mi++) 1.471 + { 1.472 + if( mi->mbmi.ref_frame == ref_frame) 1.473 + return 1; 1.474 + } 1.475 + mi++; 1.476 + } 1.477 + return 0; 1.478 + 1.479 +} 1.480 + 1.481 +int vp8_create_decoder_instances(struct frame_buffers *fb, VP8D_CONFIG *oxcf) 1.482 +{ 1.483 + if(!fb->use_frame_threads) 1.484 + { 1.485 + /* decoder instance for single thread mode */ 1.486 + fb->pbi[0] = create_decompressor(oxcf); 1.487 + if(!fb->pbi[0]) 1.488 + return VPX_CODEC_ERROR; 1.489 + 1.490 +#if CONFIG_MULTITHREAD 1.491 + /* enable row-based threading only when use_frame_threads 1.492 + * is disabled */ 1.493 + fb->pbi[0]->max_threads = oxcf->max_threads; 1.494 + vp8_decoder_create_threads(fb->pbi[0]); 1.495 +#endif 1.496 + } 1.497 + else 1.498 + { 1.499 + /* TODO : create frame threads and decoder instances for each 1.500 + * thread here */ 1.501 + } 1.502 + 1.503 + return VPX_CODEC_OK; 1.504 +} 1.505 + 1.506 +int vp8_remove_decoder_instances(struct frame_buffers *fb) 1.507 +{ 1.508 + if(!fb->use_frame_threads) 1.509 + { 1.510 + VP8D_COMP *pbi = fb->pbi[0]; 1.511 + 1.512 + if (!pbi) 1.513 + return VPX_CODEC_ERROR; 1.514 +#if CONFIG_MULTITHREAD 1.515 + if (pbi->b_multithreaded_rd) 1.516 + vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows); 1.517 + vp8_decoder_remove_threads(pbi); 1.518 +#endif 1.519 + 1.520 + /* decoder instance for single thread mode */ 1.521 + remove_decompressor(pbi); 1.522 + } 1.523 + else 1.524 + { 1.525 + /* TODO : remove frame threads and decoder instances for each 1.526 + * thread here */ 1.527 + } 1.528 + 1.529 + return VPX_CODEC_OK; 1.530 +}