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/common/vp9_onyxc_int.h" 16 #if CONFIG_VP9_POSTPROC 17 #include "vp9/common/vp9_postproc.h" 18 #endif 19 #include "vp9/decoder/vp9_onyxd.h" 20 #include "vp9/decoder/vp9_onyxd_int.h" 21 #include "vpx_mem/vpx_mem.h" 22 #include "vp9/common/vp9_alloccommon.h" 23 #include "vp9/common/vp9_loopfilter.h" 24 #include "vp9/common/vp9_quant_common.h" 25 #include "vpx_scale/vpx_scale.h" 26 #include "vp9/common/vp9_systemdependent.h" 27 #include "vpx_ports/vpx_timer.h" 28 #include "vp9/decoder/vp9_decodframe.h" 29 #include "vp9/decoder/vp9_detokenize.h" 30 #include "./vpx_scale_rtcd.h" 31 32 #define WRITE_RECON_BUFFER 0 33 #if WRITE_RECON_BUFFER == 1 34 static void recon_write_yuv_frame(const char *name, 35 const YV12_BUFFER_CONFIG *s, 36 int w, int _h) { 37 FILE *yuv_file = fopen(name, "ab"); 38 const uint8_t *src = s->y_buffer; 39 int h = _h; 40 41 do { 42 fwrite(src, w, 1, yuv_file); 43 src += s->y_stride; 44 } while (--h); 45 46 src = s->u_buffer; 47 h = (_h + 1) >> 1; 48 w = (w + 1) >> 1; 49 50 do { 51 fwrite(src, w, 1, yuv_file); 52 src += s->uv_stride; 53 } while (--h); 54 55 src = s->v_buffer; 56 h = (_h + 1) >> 1; 57 58 do { 59 fwrite(src, w, 1, yuv_file); 60 src += s->uv_stride; 61 } while (--h); 62 63 fclose(yuv_file); 64 } 65 #endif 66 #if WRITE_RECON_BUFFER == 2 67 void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) { 68 // write the frame 69 FILE *yframe; 70 int i; 71 char filename[255]; 72 73 snprintf(filename, sizeof(filename)-1, "dx\\y%04d.raw", this_frame); 74 yframe = fopen(filename, "wb"); 75 76 for (i = 0; i < frame->y_height; i++) 77 fwrite(frame->y_buffer + i * frame->y_stride, 78 frame->y_width, 1, yframe); 79 80 fclose(yframe); 81 snprintf(filename, sizeof(filename)-1, "dx\\u%04d.raw", this_frame); 82 yframe = fopen(filename, "wb"); 83 84 for (i = 0; i < frame->uv_height; i++) 85 fwrite(frame->u_buffer + i * frame->uv_stride, 86 frame->uv_width, 1, yframe); 87 88 fclose(yframe); 89 snprintf(filename, sizeof(filename)-1, "dx\\v%04d.raw", this_frame); 90 yframe = fopen(filename, "wb"); 91 92 for (i = 0; i < frame->uv_height; i++) 93 fwrite(frame->v_buffer + i * frame->uv_stride, 94 frame->uv_width, 1, yframe); 95 96 fclose(yframe); 97 } 98 #endif 99 100 void vp9_initialize_dec() { 101 static int init_done = 0; 102 103 if (!init_done) { 104 vp9_initialize_common(); 105 vp9_init_quant_tables(); 106 init_done = 1; 107 } 108 } 109 110 static void init_macroblockd(VP9D_COMP *const pbi) { 111 MACROBLOCKD *xd = &pbi->mb; 112 struct macroblockd_plane *const pd = xd->plane; 113 int i; 114 115 for (i = 0; i < MAX_MB_PLANE; ++i) { 116 pd[i].qcoeff = pbi->qcoeff[i]; 117 pd[i].dqcoeff = pbi->dqcoeff[i]; 118 pd[i].eobs = pbi->eobs[i]; 119 } 120 } 121 122 VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) { 123 VP9D_COMP *const pbi = vpx_memalign(32, sizeof(VP9D_COMP)); 124 VP9_COMMON *const cm = pbi ? &pbi->common : NULL; 125 126 if (!cm) 127 return NULL; 128 129 vp9_zero(*pbi); 130 131 if (setjmp(cm->error.jmp)) { 132 cm->error.setjmp = 0; 133 vp9_remove_decompressor(pbi); 134 return NULL; 135 } 136 137 cm->error.setjmp = 1; 138 vp9_initialize_dec(); 139 140 vp9_create_common(cm); 141 142 pbi->oxcf = *oxcf; 143 pbi->ready_for_new_data = 1; 144 cm->current_video_frame = 0; 145 146 // vp9_init_dequantizer() is first called here. Add check in 147 // frame_init_dequantizer() to avoid unnecessary calling of 148 // vp9_init_dequantizer() for every frame. 149 vp9_init_dequantizer(cm); 150 151 vp9_loop_filter_init(cm); 152 153 cm->error.setjmp = 0; 154 pbi->decoded_key_frame = 0; 155 156 init_macroblockd(pbi); 157 158 vp9_worker_init(&pbi->lf_worker); 159 160 return pbi; 161 } 162 163 void vp9_remove_decompressor(VP9D_PTR ptr) { 164 int i; 165 VP9D_COMP *const pbi = (VP9D_COMP *)ptr; 166 167 if (!pbi) 168 return; 169 170 vp9_remove_common(&pbi->common); 171 vp9_worker_end(&pbi->lf_worker); 172 vpx_free(pbi->lf_worker.data1); 173 for (i = 0; i < pbi->num_tile_workers; ++i) { 174 VP9Worker *const worker = &pbi->tile_workers[i]; 175 vp9_worker_end(worker); 176 vpx_free(worker->data1); 177 vpx_free(worker->data2); 178 } 179 vpx_free(pbi->tile_workers); 180 vpx_free(pbi->mi_streams); 181 vpx_free(pbi->above_context[0]); 182 vpx_free(pbi->above_seg_context); 183 vpx_free(pbi); 184 } 185 186 static int equal_dimensions(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) { 187 return a->y_height == b->y_height && a->y_width == b->y_width && 188 a->uv_height == b->uv_height && a->uv_width == b->uv_width; 189 } 190 191 vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR ptr, 192 VP9_REFFRAME ref_frame_flag, 193 YV12_BUFFER_CONFIG *sd) { 194 VP9D_COMP *pbi = (VP9D_COMP *) ptr; 195 VP9_COMMON *cm = &pbi->common; 196 197 /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the 198 * encoder is using the frame buffers for. This is just a stub to keep the 199 * vpxenc --test-decode functionality working, and will be replaced in a 200 * later commit that adds VP9-specific controls for this functionality. 201 */ 202 if (ref_frame_flag == VP9_LAST_FLAG) { 203 YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[0]]; 204 if (!equal_dimensions(cfg, sd)) 205 vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 206 "Incorrect buffer dimensions"); 207 else 208 vp8_yv12_copy_frame(cfg, sd); 209 } else { 210 vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 211 "Invalid reference frame"); 212 } 213 214 return cm->error.error_code; 215 } 216 217 218 vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, 219 YV12_BUFFER_CONFIG *sd) { 220 VP9D_COMP *pbi = (VP9D_COMP *) ptr; 221 VP9_COMMON *cm = &pbi->common; 222 int *ref_fb_ptr = NULL; 223 224 /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the 225 * encoder is using the frame buffers for. This is just a stub to keep the 226 * vpxenc --test-decode functionality working, and will be replaced in a 227 * later commit that adds VP9-specific controls for this functionality. 228 */ 229 if (ref_frame_flag == VP9_LAST_FLAG) { 230 ref_fb_ptr = &pbi->common.active_ref_idx[0]; 231 } else if (ref_frame_flag == VP9_GOLD_FLAG) { 232 ref_fb_ptr = &pbi->common.active_ref_idx[1]; 233 } else if (ref_frame_flag == VP9_ALT_FLAG) { 234 ref_fb_ptr = &pbi->common.active_ref_idx[2]; 235 } else { 236 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 237 "Invalid reference frame"); 238 return pbi->common.error.error_code; 239 } 240 241 if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) { 242 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, 243 "Incorrect buffer dimensions"); 244 } else { 245 // Find an empty frame buffer. 246 const int free_fb = get_free_fb(cm); 247 // Decrease fb_idx_ref_cnt since it will be increased again in 248 // ref_cnt_fb() below. 249 cm->fb_idx_ref_cnt[free_fb]--; 250 251 // Manage the reference counters and copy image. 252 ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb); 253 vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]); 254 } 255 256 return pbi->common.error.error_code; 257 } 258 259 260 int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) { 261 VP9D_COMP *pbi = (VP9D_COMP *) ptr; 262 VP9_COMMON *cm = &pbi->common; 263 264 if (index < 0 || index >= NUM_REF_FRAMES) 265 return -1; 266 267 *fb = &cm->yv12_fb[cm->ref_frame_map[index]]; 268 return 0; 269 } 270 271 /* If any buffer updating is signaled it should be done here. */ 272 static void swap_frame_buffers(VP9D_COMP *pbi) { 273 int ref_index = 0, mask; 274 VP9_COMMON *const cm = &pbi->common; 275 276 for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { 277 if (mask & 1) 278 ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index], 279 cm->new_fb_idx); 280 ++ref_index; 281 } 282 283 cm->frame_to_show = get_frame_new_buffer(cm); 284 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 285 286 // Invalidate these references until the next frame starts. 287 for (ref_index = 0; ref_index < 3; ref_index++) 288 cm->active_ref_idx[ref_index] = INT_MAX; 289 } 290 291 int vp9_receive_compressed_data(VP9D_PTR ptr, 292 size_t size, const uint8_t **psource, 293 int64_t time_stamp) { 294 VP9D_COMP *pbi = (VP9D_COMP *) ptr; 295 VP9_COMMON *cm = &pbi->common; 296 const uint8_t *source = *psource; 297 int retcode = 0; 298 299 /*if(pbi->ready_for_new_data == 0) 300 return -1;*/ 301 302 if (ptr == 0) 303 return -1; 304 305 cm->error.error_code = VPX_CODEC_OK; 306 307 pbi->source = source; 308 pbi->source_sz = size; 309 310 if (pbi->source_sz == 0) { 311 /* This is used to signal that we are missing frames. 312 * We do not know if the missing frame(s) was supposed to update 313 * any of the reference buffers, but we act conservative and 314 * mark only the last buffer as corrupted. 315 * 316 * TODO(jkoleszar): Error concealment is undefined and non-normative 317 * at this point, but if it becomes so, [0] may not always be the correct 318 * thing to do here. 319 */ 320 if (cm->active_ref_idx[0] != INT_MAX) 321 get_frame_ref_buffer(cm, 0)->corrupted = 1; 322 } 323 324 cm->new_fb_idx = get_free_fb(cm); 325 326 if (setjmp(cm->error.jmp)) { 327 cm->error.setjmp = 0; 328 329 /* We do not know if the missing frame(s) was supposed to update 330 * any of the reference buffers, but we act conservative and 331 * mark only the last buffer as corrupted. 332 * 333 * TODO(jkoleszar): Error concealment is undefined and non-normative 334 * at this point, but if it becomes so, [0] may not always be the correct 335 * thing to do here. 336 */ 337 if (cm->active_ref_idx[0] != INT_MAX) 338 get_frame_ref_buffer(cm, 0)->corrupted = 1; 339 340 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 341 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 342 343 return -1; 344 } 345 346 cm->error.setjmp = 1; 347 348 retcode = vp9_decode_frame(pbi, psource); 349 350 if (retcode < 0) { 351 cm->error.error_code = VPX_CODEC_ERROR; 352 cm->error.setjmp = 0; 353 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 354 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 355 return retcode; 356 } 357 358 swap_frame_buffers(pbi); 359 360 #if WRITE_RECON_BUFFER == 2 361 if (cm->show_frame) 362 write_dx_frame_to_file(cm->frame_to_show, 363 cm->current_video_frame); 364 else 365 write_dx_frame_to_file(cm->frame_to_show, 366 cm->current_video_frame + 1000); 367 #endif 368 369 if (!pbi->do_loopfilter_inline) { 370 vp9_loop_filter_frame(cm, &pbi->mb, pbi->common.lf.filter_level, 0, 0); 371 } 372 373 #if WRITE_RECON_BUFFER == 2 374 if (cm->show_frame) 375 write_dx_frame_to_file(cm->frame_to_show, 376 cm->current_video_frame + 2000); 377 else 378 write_dx_frame_to_file(cm->frame_to_show, 379 cm->current_video_frame + 3000); 380 #endif 381 382 vp9_extend_frame_inner_borders(cm->frame_to_show, 383 cm->subsampling_x, 384 cm->subsampling_y); 385 386 #if WRITE_RECON_BUFFER == 1 387 if (cm->show_frame) 388 recon_write_yuv_frame("recon.yuv", cm->frame_to_show, 389 cm->width, cm->height); 390 #endif 391 392 vp9_clear_system_state(); 393 394 cm->last_show_frame = cm->show_frame; 395 if (cm->show_frame) { 396 // current mip will be the prev_mip for the next frame 397 MODE_INFO *temp = cm->prev_mip; 398 MODE_INFO **temp2 = cm->prev_mi_grid_base; 399 cm->prev_mip = cm->mip; 400 cm->mip = temp; 401 cm->prev_mi_grid_base = cm->mi_grid_base; 402 cm->mi_grid_base = temp2; 403 404 // update the upper left visible macroblock ptrs 405 cm->mi = cm->mip + cm->mode_info_stride + 1; 406 cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1; 407 cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1; 408 cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1; 409 410 pbi->mb.mi_8x8 = cm->mi_grid_visible; 411 pbi->mb.mi_8x8[0] = cm->mi; 412 413 cm->current_video_frame++; 414 } 415 416 pbi->ready_for_new_data = 0; 417 pbi->last_time_stamp = time_stamp; 418 pbi->source_sz = 0; 419 420 cm->error.setjmp = 0; 421 return retcode; 422 } 423 424 int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd, 425 int64_t *time_stamp, int64_t *time_end_stamp, 426 vp9_ppflags_t *flags) { 427 int ret = -1; 428 VP9D_COMP *pbi = (VP9D_COMP *) ptr; 429 430 if (pbi->ready_for_new_data == 1) 431 return ret; 432 433 /* ie no raw frame to show!!! */ 434 if (pbi->common.show_frame == 0) 435 return ret; 436 437 pbi->ready_for_new_data = 1; 438 *time_stamp = pbi->last_time_stamp; 439 *time_end_stamp = 0; 440 441 #if CONFIG_VP9_POSTPROC 442 ret = vp9_post_proc_frame(&pbi->common, sd, flags); 443 #else 444 445 if (pbi->common.frame_to_show) { 446 *sd = *pbi->common.frame_to_show; 447 sd->y_width = pbi->common.width; 448 sd->y_height = pbi->common.height; 449 sd->uv_width = sd->y_width >> pbi->common.subsampling_x; 450 sd->uv_height = sd->y_height >> pbi->common.subsampling_y; 451 452 ret = 0; 453 } else { 454 ret = -1; 455 } 456 457 #endif /*!CONFIG_POSTPROC*/ 458 vp9_clear_system_state(); 459 return ret; 460 } 461