1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp9/decoder/vp9_onyxd_if.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,460 @@ 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 +#include <assert.h> 1.15 +#include <limits.h> 1.16 +#include <stdio.h> 1.17 + 1.18 +#include "vp9/common/vp9_onyxc_int.h" 1.19 +#if CONFIG_VP9_POSTPROC 1.20 +#include "vp9/common/vp9_postproc.h" 1.21 +#endif 1.22 +#include "vp9/decoder/vp9_onyxd.h" 1.23 +#include "vp9/decoder/vp9_onyxd_int.h" 1.24 +#include "vpx_mem/vpx_mem.h" 1.25 +#include "vp9/common/vp9_alloccommon.h" 1.26 +#include "vp9/common/vp9_loopfilter.h" 1.27 +#include "vp9/common/vp9_quant_common.h" 1.28 +#include "vpx_scale/vpx_scale.h" 1.29 +#include "vp9/common/vp9_systemdependent.h" 1.30 +#include "vpx_ports/vpx_timer.h" 1.31 +#include "vp9/decoder/vp9_decodframe.h" 1.32 +#include "vp9/decoder/vp9_detokenize.h" 1.33 +#include "./vpx_scale_rtcd.h" 1.34 + 1.35 +#define WRITE_RECON_BUFFER 0 1.36 +#if WRITE_RECON_BUFFER == 1 1.37 +static void recon_write_yuv_frame(const char *name, 1.38 + const YV12_BUFFER_CONFIG *s, 1.39 + int w, int _h) { 1.40 + FILE *yuv_file = fopen(name, "ab"); 1.41 + const uint8_t *src = s->y_buffer; 1.42 + int h = _h; 1.43 + 1.44 + do { 1.45 + fwrite(src, w, 1, yuv_file); 1.46 + src += s->y_stride; 1.47 + } while (--h); 1.48 + 1.49 + src = s->u_buffer; 1.50 + h = (_h + 1) >> 1; 1.51 + w = (w + 1) >> 1; 1.52 + 1.53 + do { 1.54 + fwrite(src, w, 1, yuv_file); 1.55 + src += s->uv_stride; 1.56 + } while (--h); 1.57 + 1.58 + src = s->v_buffer; 1.59 + h = (_h + 1) >> 1; 1.60 + 1.61 + do { 1.62 + fwrite(src, w, 1, yuv_file); 1.63 + src += s->uv_stride; 1.64 + } while (--h); 1.65 + 1.66 + fclose(yuv_file); 1.67 +} 1.68 +#endif 1.69 +#if WRITE_RECON_BUFFER == 2 1.70 +void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) { 1.71 + // write the frame 1.72 + FILE *yframe; 1.73 + int i; 1.74 + char filename[255]; 1.75 + 1.76 + snprintf(filename, sizeof(filename)-1, "dx\\y%04d.raw", this_frame); 1.77 + yframe = fopen(filename, "wb"); 1.78 + 1.79 + for (i = 0; i < frame->y_height; i++) 1.80 + fwrite(frame->y_buffer + i * frame->y_stride, 1.81 + frame->y_width, 1, yframe); 1.82 + 1.83 + fclose(yframe); 1.84 + snprintf(filename, sizeof(filename)-1, "dx\\u%04d.raw", this_frame); 1.85 + yframe = fopen(filename, "wb"); 1.86 + 1.87 + for (i = 0; i < frame->uv_height; i++) 1.88 + fwrite(frame->u_buffer + i * frame->uv_stride, 1.89 + frame->uv_width, 1, yframe); 1.90 + 1.91 + fclose(yframe); 1.92 + snprintf(filename, sizeof(filename)-1, "dx\\v%04d.raw", this_frame); 1.93 + yframe = fopen(filename, "wb"); 1.94 + 1.95 + for (i = 0; i < frame->uv_height; i++) 1.96 + fwrite(frame->v_buffer + i * frame->uv_stride, 1.97 + frame->uv_width, 1, yframe); 1.98 + 1.99 + fclose(yframe); 1.100 +} 1.101 +#endif 1.102 + 1.103 +void vp9_initialize_dec() { 1.104 + static int init_done = 0; 1.105 + 1.106 + if (!init_done) { 1.107 + vp9_initialize_common(); 1.108 + vp9_init_quant_tables(); 1.109 + init_done = 1; 1.110 + } 1.111 +} 1.112 + 1.113 +static void init_macroblockd(VP9D_COMP *const pbi) { 1.114 + MACROBLOCKD *xd = &pbi->mb; 1.115 + struct macroblockd_plane *const pd = xd->plane; 1.116 + int i; 1.117 + 1.118 + for (i = 0; i < MAX_MB_PLANE; ++i) { 1.119 + pd[i].qcoeff = pbi->qcoeff[i]; 1.120 + pd[i].dqcoeff = pbi->dqcoeff[i]; 1.121 + pd[i].eobs = pbi->eobs[i]; 1.122 + } 1.123 +} 1.124 + 1.125 +VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) { 1.126 + VP9D_COMP *const pbi = vpx_memalign(32, sizeof(VP9D_COMP)); 1.127 + VP9_COMMON *const cm = pbi ? &pbi->common : NULL; 1.128 + 1.129 + if (!cm) 1.130 + return NULL; 1.131 + 1.132 + vp9_zero(*pbi); 1.133 + 1.134 + if (setjmp(cm->error.jmp)) { 1.135 + cm->error.setjmp = 0; 1.136 + vp9_remove_decompressor(pbi); 1.137 + return NULL; 1.138 + } 1.139 + 1.140 + cm->error.setjmp = 1; 1.141 + vp9_initialize_dec(); 1.142 + 1.143 + vp9_create_common(cm); 1.144 + 1.145 + pbi->oxcf = *oxcf; 1.146 + pbi->ready_for_new_data = 1; 1.147 + cm->current_video_frame = 0; 1.148 + 1.149 + // vp9_init_dequantizer() is first called here. Add check in 1.150 + // frame_init_dequantizer() to avoid unnecessary calling of 1.151 + // vp9_init_dequantizer() for every frame. 1.152 + vp9_init_dequantizer(cm); 1.153 + 1.154 + vp9_loop_filter_init(cm); 1.155 + 1.156 + cm->error.setjmp = 0; 1.157 + pbi->decoded_key_frame = 0; 1.158 + 1.159 + init_macroblockd(pbi); 1.160 + 1.161 + vp9_worker_init(&pbi->lf_worker); 1.162 + 1.163 + return pbi; 1.164 +} 1.165 + 1.166 +void vp9_remove_decompressor(VP9D_PTR ptr) { 1.167 + int i; 1.168 + VP9D_COMP *const pbi = (VP9D_COMP *)ptr; 1.169 + 1.170 + if (!pbi) 1.171 + return; 1.172 + 1.173 + vp9_remove_common(&pbi->common); 1.174 + vp9_worker_end(&pbi->lf_worker); 1.175 + vpx_free(pbi->lf_worker.data1); 1.176 + for (i = 0; i < pbi->num_tile_workers; ++i) { 1.177 + VP9Worker *const worker = &pbi->tile_workers[i]; 1.178 + vp9_worker_end(worker); 1.179 + vpx_free(worker->data1); 1.180 + vpx_free(worker->data2); 1.181 + } 1.182 + vpx_free(pbi->tile_workers); 1.183 + vpx_free(pbi->mi_streams); 1.184 + vpx_free(pbi->above_context[0]); 1.185 + vpx_free(pbi->above_seg_context); 1.186 + vpx_free(pbi); 1.187 +} 1.188 + 1.189 +static int equal_dimensions(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) { 1.190 + return a->y_height == b->y_height && a->y_width == b->y_width && 1.191 + a->uv_height == b->uv_height && a->uv_width == b->uv_width; 1.192 +} 1.193 + 1.194 +vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR ptr, 1.195 + VP9_REFFRAME ref_frame_flag, 1.196 + YV12_BUFFER_CONFIG *sd) { 1.197 + VP9D_COMP *pbi = (VP9D_COMP *) ptr; 1.198 + VP9_COMMON *cm = &pbi->common; 1.199 + 1.200 + /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the 1.201 + * encoder is using the frame buffers for. This is just a stub to keep the 1.202 + * vpxenc --test-decode functionality working, and will be replaced in a 1.203 + * later commit that adds VP9-specific controls for this functionality. 1.204 + */ 1.205 + if (ref_frame_flag == VP9_LAST_FLAG) { 1.206 + YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[0]]; 1.207 + if (!equal_dimensions(cfg, sd)) 1.208 + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 1.209 + "Incorrect buffer dimensions"); 1.210 + else 1.211 + vp8_yv12_copy_frame(cfg, sd); 1.212 + } else { 1.213 + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 1.214 + "Invalid reference frame"); 1.215 + } 1.216 + 1.217 + return cm->error.error_code; 1.218 +} 1.219 + 1.220 + 1.221 +vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, 1.222 + YV12_BUFFER_CONFIG *sd) { 1.223 + VP9D_COMP *pbi = (VP9D_COMP *) ptr; 1.224 + VP9_COMMON *cm = &pbi->common; 1.225 + int *ref_fb_ptr = NULL; 1.226 + 1.227 + /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the 1.228 + * encoder is using the frame buffers for. This is just a stub to keep the 1.229 + * vpxenc --test-decode functionality working, and will be replaced in a 1.230 + * later commit that adds VP9-specific controls for this functionality. 1.231 + */ 1.232 + if (ref_frame_flag == VP9_LAST_FLAG) { 1.233 + ref_fb_ptr = &pbi->common.active_ref_idx[0]; 1.234 + } else if (ref_frame_flag == VP9_GOLD_FLAG) { 1.235 + ref_fb_ptr = &pbi->common.active_ref_idx[1]; 1.236 + } else if (ref_frame_flag == VP9_ALT_FLAG) { 1.237 + ref_fb_ptr = &pbi->common.active_ref_idx[2]; 1.238 + } else { 1.239 + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 1.240 + "Invalid reference frame"); 1.241 + return pbi->common.error.error_code; 1.242 + } 1.243 + 1.244 + if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) { 1.245 + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 1.246 + "Incorrect buffer dimensions"); 1.247 + } else { 1.248 + // Find an empty frame buffer. 1.249 + const int free_fb = get_free_fb(cm); 1.250 + // Decrease fb_idx_ref_cnt since it will be increased again in 1.251 + // ref_cnt_fb() below. 1.252 + cm->fb_idx_ref_cnt[free_fb]--; 1.253 + 1.254 + // Manage the reference counters and copy image. 1.255 + ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb); 1.256 + vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]); 1.257 + } 1.258 + 1.259 + return pbi->common.error.error_code; 1.260 +} 1.261 + 1.262 + 1.263 +int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) { 1.264 + VP9D_COMP *pbi = (VP9D_COMP *) ptr; 1.265 + VP9_COMMON *cm = &pbi->common; 1.266 + 1.267 + if (index < 0 || index >= NUM_REF_FRAMES) 1.268 + return -1; 1.269 + 1.270 + *fb = &cm->yv12_fb[cm->ref_frame_map[index]]; 1.271 + return 0; 1.272 +} 1.273 + 1.274 +/* If any buffer updating is signaled it should be done here. */ 1.275 +static void swap_frame_buffers(VP9D_COMP *pbi) { 1.276 + int ref_index = 0, mask; 1.277 + VP9_COMMON *const cm = &pbi->common; 1.278 + 1.279 + for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { 1.280 + if (mask & 1) 1.281 + ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index], 1.282 + cm->new_fb_idx); 1.283 + ++ref_index; 1.284 + } 1.285 + 1.286 + cm->frame_to_show = get_frame_new_buffer(cm); 1.287 + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 1.288 + 1.289 + // Invalidate these references until the next frame starts. 1.290 + for (ref_index = 0; ref_index < 3; ref_index++) 1.291 + cm->active_ref_idx[ref_index] = INT_MAX; 1.292 +} 1.293 + 1.294 +int vp9_receive_compressed_data(VP9D_PTR ptr, 1.295 + size_t size, const uint8_t **psource, 1.296 + int64_t time_stamp) { 1.297 + VP9D_COMP *pbi = (VP9D_COMP *) ptr; 1.298 + VP9_COMMON *cm = &pbi->common; 1.299 + const uint8_t *source = *psource; 1.300 + int retcode = 0; 1.301 + 1.302 + /*if(pbi->ready_for_new_data == 0) 1.303 + return -1;*/ 1.304 + 1.305 + if (ptr == 0) 1.306 + return -1; 1.307 + 1.308 + cm->error.error_code = VPX_CODEC_OK; 1.309 + 1.310 + pbi->source = source; 1.311 + pbi->source_sz = size; 1.312 + 1.313 + if (pbi->source_sz == 0) { 1.314 + /* This is used to signal that we are missing frames. 1.315 + * We do not know if the missing frame(s) was supposed to update 1.316 + * any of the reference buffers, but we act conservative and 1.317 + * mark only the last buffer as corrupted. 1.318 + * 1.319 + * TODO(jkoleszar): Error concealment is undefined and non-normative 1.320 + * at this point, but if it becomes so, [0] may not always be the correct 1.321 + * thing to do here. 1.322 + */ 1.323 + if (cm->active_ref_idx[0] != INT_MAX) 1.324 + get_frame_ref_buffer(cm, 0)->corrupted = 1; 1.325 + } 1.326 + 1.327 + cm->new_fb_idx = get_free_fb(cm); 1.328 + 1.329 + if (setjmp(cm->error.jmp)) { 1.330 + cm->error.setjmp = 0; 1.331 + 1.332 + /* We do not know if the missing frame(s) was supposed to update 1.333 + * any of the reference buffers, but we act conservative and 1.334 + * mark only the last buffer as corrupted. 1.335 + * 1.336 + * TODO(jkoleszar): Error concealment is undefined and non-normative 1.337 + * at this point, but if it becomes so, [0] may not always be the correct 1.338 + * thing to do here. 1.339 + */ 1.340 + if (cm->active_ref_idx[0] != INT_MAX) 1.341 + get_frame_ref_buffer(cm, 0)->corrupted = 1; 1.342 + 1.343 + if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 1.344 + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 1.345 + 1.346 + return -1; 1.347 + } 1.348 + 1.349 + cm->error.setjmp = 1; 1.350 + 1.351 + retcode = vp9_decode_frame(pbi, psource); 1.352 + 1.353 + if (retcode < 0) { 1.354 + cm->error.error_code = VPX_CODEC_ERROR; 1.355 + cm->error.setjmp = 0; 1.356 + if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 1.357 + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 1.358 + return retcode; 1.359 + } 1.360 + 1.361 + swap_frame_buffers(pbi); 1.362 + 1.363 +#if WRITE_RECON_BUFFER == 2 1.364 + if (cm->show_frame) 1.365 + write_dx_frame_to_file(cm->frame_to_show, 1.366 + cm->current_video_frame); 1.367 + else 1.368 + write_dx_frame_to_file(cm->frame_to_show, 1.369 + cm->current_video_frame + 1000); 1.370 +#endif 1.371 + 1.372 + if (!pbi->do_loopfilter_inline) { 1.373 + vp9_loop_filter_frame(cm, &pbi->mb, pbi->common.lf.filter_level, 0, 0); 1.374 + } 1.375 + 1.376 +#if WRITE_RECON_BUFFER == 2 1.377 + if (cm->show_frame) 1.378 + write_dx_frame_to_file(cm->frame_to_show, 1.379 + cm->current_video_frame + 2000); 1.380 + else 1.381 + write_dx_frame_to_file(cm->frame_to_show, 1.382 + cm->current_video_frame + 3000); 1.383 +#endif 1.384 + 1.385 + vp9_extend_frame_inner_borders(cm->frame_to_show, 1.386 + cm->subsampling_x, 1.387 + cm->subsampling_y); 1.388 + 1.389 +#if WRITE_RECON_BUFFER == 1 1.390 + if (cm->show_frame) 1.391 + recon_write_yuv_frame("recon.yuv", cm->frame_to_show, 1.392 + cm->width, cm->height); 1.393 +#endif 1.394 + 1.395 + vp9_clear_system_state(); 1.396 + 1.397 + cm->last_show_frame = cm->show_frame; 1.398 + if (cm->show_frame) { 1.399 + // current mip will be the prev_mip for the next frame 1.400 + MODE_INFO *temp = cm->prev_mip; 1.401 + MODE_INFO **temp2 = cm->prev_mi_grid_base; 1.402 + cm->prev_mip = cm->mip; 1.403 + cm->mip = temp; 1.404 + cm->prev_mi_grid_base = cm->mi_grid_base; 1.405 + cm->mi_grid_base = temp2; 1.406 + 1.407 + // update the upper left visible macroblock ptrs 1.408 + cm->mi = cm->mip + cm->mode_info_stride + 1; 1.409 + cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1; 1.410 + cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1; 1.411 + cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1; 1.412 + 1.413 + pbi->mb.mi_8x8 = cm->mi_grid_visible; 1.414 + pbi->mb.mi_8x8[0] = cm->mi; 1.415 + 1.416 + cm->current_video_frame++; 1.417 + } 1.418 + 1.419 + pbi->ready_for_new_data = 0; 1.420 + pbi->last_time_stamp = time_stamp; 1.421 + pbi->source_sz = 0; 1.422 + 1.423 + cm->error.setjmp = 0; 1.424 + return retcode; 1.425 +} 1.426 + 1.427 +int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd, 1.428 + int64_t *time_stamp, int64_t *time_end_stamp, 1.429 + vp9_ppflags_t *flags) { 1.430 + int ret = -1; 1.431 + VP9D_COMP *pbi = (VP9D_COMP *) ptr; 1.432 + 1.433 + if (pbi->ready_for_new_data == 1) 1.434 + return ret; 1.435 + 1.436 + /* ie no raw frame to show!!! */ 1.437 + if (pbi->common.show_frame == 0) 1.438 + return ret; 1.439 + 1.440 + pbi->ready_for_new_data = 1; 1.441 + *time_stamp = pbi->last_time_stamp; 1.442 + *time_end_stamp = 0; 1.443 + 1.444 +#if CONFIG_VP9_POSTPROC 1.445 + ret = vp9_post_proc_frame(&pbi->common, sd, flags); 1.446 +#else 1.447 + 1.448 + if (pbi->common.frame_to_show) { 1.449 + *sd = *pbi->common.frame_to_show; 1.450 + sd->y_width = pbi->common.width; 1.451 + sd->y_height = pbi->common.height; 1.452 + sd->uv_width = sd->y_width >> pbi->common.subsampling_x; 1.453 + sd->uv_height = sd->y_height >> pbi->common.subsampling_y; 1.454 + 1.455 + ret = 0; 1.456 + } else { 1.457 + ret = -1; 1.458 + } 1.459 + 1.460 +#endif /*!CONFIG_POSTPROC*/ 1.461 + vp9_clear_system_state(); 1.462 + return ret; 1.463 +}