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