OLD | NEW |
(Empty) | |
| 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 |
| 12 #include "vp9/common/vp9_onyxc_int.h" |
| 13 #if CONFIG_POSTPROC |
| 14 #include "vp9/common/vp9_postproc.h" |
| 15 #endif |
| 16 #include "vp9/common/vp9_onyxd.h" |
| 17 #include "vp9/decoder/vp9_onyxd_int.h" |
| 18 #include "vpx_mem/vpx_mem.h" |
| 19 #include "vp9/common/vp9_alloccommon.h" |
| 20 #include "vp9/common/vp9_loopfilter.h" |
| 21 #include "vp9/common/vp9_swapyv12buffer.h" |
| 22 #include <stdio.h> |
| 23 #include <assert.h> |
| 24 |
| 25 #include "vp9/common/vp9_quant_common.h" |
| 26 #include "vpx_scale/vpxscale.h" |
| 27 #include "vp9/common/vp9_systemdependent.h" |
| 28 #include "vpx_ports/vpx_timer.h" |
| 29 #include "vp9/decoder/vp9_decodframe.h" |
| 30 #include "vp9/decoder/vp9_detokenize.h" |
| 31 #include "./vpx_scale_rtcd.h" |
| 32 |
| 33 static int get_free_fb(VP9_COMMON *cm); |
| 34 static void ref_cnt_fb(int *buf, int *idx, int new_idx); |
| 35 |
| 36 #define WRITE_RECON_BUFFER 0 |
| 37 #if WRITE_RECON_BUFFER == 1 |
| 38 static void recon_write_yuv_frame(char *name, YV12_BUFFER_CONFIG *s) { |
| 39 FILE *yuv_file = fopen((char *)name, "ab"); |
| 40 unsigned char *src = s->y_buffer; |
| 41 int h = s->y_height; |
| 42 |
| 43 do { |
| 44 fwrite(src, s->y_width, 1, yuv_file); |
| 45 src += s->y_stride; |
| 46 } while (--h); |
| 47 |
| 48 src = s->u_buffer; |
| 49 h = s->uv_height; |
| 50 |
| 51 do { |
| 52 fwrite(src, s->uv_width, 1, yuv_file); |
| 53 src += s->uv_stride; |
| 54 } while (--h); |
| 55 |
| 56 src = s->v_buffer; |
| 57 h = s->uv_height; |
| 58 |
| 59 do { |
| 60 fwrite(src, s->uv_width, 1, yuv_file); |
| 61 src += s->uv_stride; |
| 62 } while (--h); |
| 63 |
| 64 fclose(yuv_file); |
| 65 } |
| 66 #endif |
| 67 #if WRITE_RECON_BUFFER == 2 |
| 68 void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) { |
| 69 |
| 70 // write the frame |
| 71 FILE *yframe; |
| 72 int i; |
| 73 char filename[255]; |
| 74 |
| 75 sprintf(filename, "dx\\y%04d.raw", this_frame); |
| 76 yframe = fopen(filename, "wb"); |
| 77 |
| 78 for (i = 0; i < frame->y_height; i++) |
| 79 fwrite(frame->y_buffer + i * frame->y_stride, |
| 80 frame->y_width, 1, yframe); |
| 81 |
| 82 fclose(yframe); |
| 83 sprintf(filename, "dx\\u%04d.raw", this_frame); |
| 84 yframe = fopen(filename, "wb"); |
| 85 |
| 86 for (i = 0; i < frame->uv_height; i++) |
| 87 fwrite(frame->u_buffer + i * frame->uv_stride, |
| 88 frame->uv_width, 1, yframe); |
| 89 |
| 90 fclose(yframe); |
| 91 sprintf(filename, "dx\\v%04d.raw", this_frame); |
| 92 yframe = fopen(filename, "wb"); |
| 93 |
| 94 for (i = 0; i < frame->uv_height; i++) |
| 95 fwrite(frame->v_buffer + i * frame->uv_stride, |
| 96 frame->uv_width, 1, yframe); |
| 97 |
| 98 fclose(yframe); |
| 99 } |
| 100 #endif |
| 101 |
| 102 void vp9_initialize_dec(void) { |
| 103 static int init_done = 0; |
| 104 |
| 105 if (!init_done) { |
| 106 vp9_initialize_common(); |
| 107 vp9_init_quant_tables(); |
| 108 init_done = 1; |
| 109 } |
| 110 } |
| 111 |
| 112 VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) { |
| 113 VP9D_COMP *pbi = vpx_memalign(32, sizeof(VP9D_COMP)); |
| 114 |
| 115 if (!pbi) |
| 116 return NULL; |
| 117 |
| 118 vpx_memset(pbi, 0, sizeof(VP9D_COMP)); |
| 119 |
| 120 if (setjmp(pbi->common.error.jmp)) { |
| 121 pbi->common.error.setjmp = 0; |
| 122 vp9_remove_decompressor(pbi); |
| 123 return 0; |
| 124 } |
| 125 |
| 126 pbi->common.error.setjmp = 1; |
| 127 vp9_initialize_dec(); |
| 128 |
| 129 vp9_create_common(&pbi->common); |
| 130 |
| 131 pbi->common.current_video_frame = 0; |
| 132 pbi->ready_for_new_data = 1; |
| 133 |
| 134 /* vp9_init_de_quantizer() is first called here. Add check in |
| 135 * frame_init_dequantizer() to avoid unnecessary calling of |
| 136 * vp9_init_de_quantizer() for every frame. |
| 137 */ |
| 138 vp9_init_de_quantizer(pbi); |
| 139 |
| 140 vp9_loop_filter_init(&pbi->common); |
| 141 |
| 142 pbi->common.error.setjmp = 0; |
| 143 |
| 144 pbi->decoded_key_frame = 0; |
| 145 |
| 146 return (VP9D_PTR) pbi; |
| 147 } |
| 148 |
| 149 void vp9_remove_decompressor(VP9D_PTR ptr) { |
| 150 VP9D_COMP *pbi = (VP9D_COMP *) ptr; |
| 151 |
| 152 if (!pbi) |
| 153 return; |
| 154 |
| 155 // Delete sementation map |
| 156 if (pbi->common.last_frame_seg_map != 0) |
| 157 vpx_free(pbi->common.last_frame_seg_map); |
| 158 |
| 159 vp9_remove_common(&pbi->common); |
| 160 vpx_free(pbi->mbc); |
| 161 vpx_free(pbi); |
| 162 } |
| 163 |
| 164 |
| 165 vpx_codec_err_t vp9_get_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, |
| 166 YV12_BUFFER_CONFIG *sd) { |
| 167 VP9D_COMP *pbi = (VP9D_COMP *) ptr; |
| 168 VP9_COMMON *cm = &pbi->common; |
| 169 int ref_fb_idx; |
| 170 |
| 171 if (ref_frame_flag == VP9_LAST_FLAG) |
| 172 ref_fb_idx = cm->lst_fb_idx; |
| 173 else if (ref_frame_flag == VP9_GOLD_FLAG) |
| 174 ref_fb_idx = cm->gld_fb_idx; |
| 175 else if (ref_frame_flag == VP9_ALT_FLAG) |
| 176 ref_fb_idx = cm->alt_fb_idx; |
| 177 else { |
| 178 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, |
| 179 "Invalid reference frame"); |
| 180 return pbi->common.error.error_code; |
| 181 } |
| 182 |
| 183 if (cm->yv12_fb[ref_fb_idx].y_height != sd->y_height || |
| 184 cm->yv12_fb[ref_fb_idx].y_width != sd->y_width || |
| 185 cm->yv12_fb[ref_fb_idx].uv_height != sd->uv_height || |
| 186 cm->yv12_fb[ref_fb_idx].uv_width != sd->uv_width) { |
| 187 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, |
| 188 "Incorrect buffer dimensions"); |
| 189 } else |
| 190 vp8_yv12_copy_frame(&cm->yv12_fb[ref_fb_idx], sd); |
| 191 |
| 192 return pbi->common.error.error_code; |
| 193 } |
| 194 |
| 195 |
| 196 vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, |
| 197 YV12_BUFFER_CONFIG *sd) { |
| 198 VP9D_COMP *pbi = (VP9D_COMP *) ptr; |
| 199 VP9_COMMON *cm = &pbi->common; |
| 200 int *ref_fb_ptr = NULL; |
| 201 int free_fb; |
| 202 |
| 203 if (ref_frame_flag == VP9_LAST_FLAG) |
| 204 ref_fb_ptr = &cm->lst_fb_idx; |
| 205 else if (ref_frame_flag == VP9_GOLD_FLAG) |
| 206 ref_fb_ptr = &cm->gld_fb_idx; |
| 207 else if (ref_frame_flag == VP9_ALT_FLAG) |
| 208 ref_fb_ptr = &cm->alt_fb_idx; |
| 209 else { |
| 210 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, |
| 211 "Invalid reference frame"); |
| 212 return pbi->common.error.error_code; |
| 213 } |
| 214 |
| 215 if (cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height || |
| 216 cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width || |
| 217 cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height || |
| 218 cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width) { |
| 219 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, |
| 220 "Incorrect buffer dimensions"); |
| 221 } else { |
| 222 /* Find an empty frame buffer. */ |
| 223 free_fb = get_free_fb(cm); |
| 224 /* Decrease fb_idx_ref_cnt since it will be increased again in |
| 225 * ref_cnt_fb() below. */ |
| 226 cm->fb_idx_ref_cnt[free_fb]--; |
| 227 |
| 228 /* Manage the reference counters and copy image. */ |
| 229 ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb); |
| 230 vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]); |
| 231 } |
| 232 |
| 233 return pbi->common.error.error_code; |
| 234 } |
| 235 |
| 236 |
| 237 static int get_free_fb(VP9_COMMON *cm) { |
| 238 int i; |
| 239 for (i = 0; i < NUM_YV12_BUFFERS; i++) |
| 240 if (cm->fb_idx_ref_cnt[i] == 0) |
| 241 break; |
| 242 |
| 243 assert(i < NUM_YV12_BUFFERS); |
| 244 cm->fb_idx_ref_cnt[i] = 1; |
| 245 return i; |
| 246 } |
| 247 |
| 248 static void ref_cnt_fb(int *buf, int *idx, int new_idx) { |
| 249 if (buf[*idx] > 0) |
| 250 buf[*idx]--; |
| 251 |
| 252 *idx = new_idx; |
| 253 |
| 254 buf[new_idx]++; |
| 255 } |
| 256 |
| 257 /* If any buffer copy / swapping is signalled it should be done here. */ |
| 258 static int swap_frame_buffers(VP9_COMMON *cm) { |
| 259 int err = 0; |
| 260 |
| 261 /* The alternate reference frame or golden frame can be updated |
| 262 * using the new, last, or golden/alt ref frame. If it |
| 263 * is updated using the newly decoded frame it is a refresh. |
| 264 * An update using the last or golden/alt ref frame is a copy. |
| 265 */ |
| 266 if (cm->copy_buffer_to_arf) { |
| 267 int new_fb = 0; |
| 268 |
| 269 if (cm->copy_buffer_to_arf == 1) |
| 270 new_fb = cm->lst_fb_idx; |
| 271 else if (cm->copy_buffer_to_arf == 2) |
| 272 new_fb = cm->gld_fb_idx; |
| 273 else |
| 274 err = -1; |
| 275 |
| 276 ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb); |
| 277 } |
| 278 |
| 279 if (cm->copy_buffer_to_gf) { |
| 280 int new_fb = 0; |
| 281 |
| 282 if (cm->copy_buffer_to_gf == 1) |
| 283 new_fb = cm->lst_fb_idx; |
| 284 else if (cm->copy_buffer_to_gf == 2) |
| 285 new_fb = cm->alt_fb_idx; |
| 286 else |
| 287 err = -1; |
| 288 |
| 289 ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb); |
| 290 } |
| 291 |
| 292 if (cm->refresh_golden_frame) |
| 293 ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx); |
| 294 |
| 295 if (cm->refresh_alt_ref_frame) |
| 296 ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx); |
| 297 |
| 298 if (cm->refresh_last_frame) { |
| 299 ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx); |
| 300 |
| 301 cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx]; |
| 302 } else |
| 303 cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx]; |
| 304 |
| 305 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; |
| 306 |
| 307 return err; |
| 308 } |
| 309 |
| 310 int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size, |
| 311 const unsigned char **psource, |
| 312 int64_t time_stamp) { |
| 313 VP9D_COMP *pbi = (VP9D_COMP *) ptr; |
| 314 VP9_COMMON *cm = &pbi->common; |
| 315 const unsigned char *source = *psource; |
| 316 int retcode = 0; |
| 317 |
| 318 /*if(pbi->ready_for_new_data == 0) |
| 319 return -1;*/ |
| 320 |
| 321 if (ptr == 0) { |
| 322 return -1; |
| 323 } |
| 324 |
| 325 pbi->common.error.error_code = VPX_CODEC_OK; |
| 326 |
| 327 pbi->Source = source; |
| 328 pbi->source_sz = size; |
| 329 |
| 330 if (pbi->source_sz == 0) { |
| 331 /* This is used to signal that we are missing frames. |
| 332 * We do not know if the missing frame(s) was supposed to update |
| 333 * any of the reference buffers, but we act conservative and |
| 334 * mark only the last buffer as corrupted. |
| 335 */ |
| 336 cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; |
| 337 } |
| 338 |
| 339 cm->new_fb_idx = get_free_fb(cm); |
| 340 |
| 341 if (setjmp(pbi->common.error.jmp)) { |
| 342 pbi->common.error.setjmp = 0; |
| 343 |
| 344 /* We do not know if the missing frame(s) was supposed to update |
| 345 * any of the reference buffers, but we act conservative and |
| 346 * mark only the last buffer as corrupted. |
| 347 */ |
| 348 cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; |
| 349 |
| 350 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) |
| 351 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; |
| 352 return -1; |
| 353 } |
| 354 |
| 355 pbi->common.error.setjmp = 1; |
| 356 |
| 357 retcode = vp9_decode_frame(pbi, psource); |
| 358 |
| 359 if (retcode < 0) { |
| 360 pbi->common.error.error_code = VPX_CODEC_ERROR; |
| 361 pbi->common.error.setjmp = 0; |
| 362 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) |
| 363 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; |
| 364 return retcode; |
| 365 } |
| 366 |
| 367 { |
| 368 if (swap_frame_buffers(cm)) { |
| 369 pbi->common.error.error_code = VPX_CODEC_ERROR; |
| 370 pbi->common.error.setjmp = 0; |
| 371 return -1; |
| 372 } |
| 373 |
| 374 #if WRITE_RECON_BUFFER == 2 |
| 375 if (cm->show_frame) |
| 376 write_dx_frame_to_file(cm->frame_to_show, |
| 377 cm->current_video_frame); |
| 378 else |
| 379 write_dx_frame_to_file(cm->frame_to_show, |
| 380 cm->current_video_frame + 1000); |
| 381 #endif |
| 382 |
| 383 if (cm->filter_level) { |
| 384 /* Apply the loop filter if appropriate. */ |
| 385 vp9_loop_filter_frame(cm, &pbi->mb); |
| 386 } |
| 387 vp8_yv12_extend_frame_borders(cm->frame_to_show); |
| 388 } |
| 389 |
| 390 #if WRITE_RECON_BUFFER == 1 |
| 391 if (cm->show_frame) |
| 392 recon_write_yuv_frame("recon.yuv", cm->frame_to_show); |
| 393 #endif |
| 394 |
| 395 vp9_clear_system_state(); |
| 396 |
| 397 if (cm->show_frame) { |
| 398 vpx_memcpy(cm->prev_mip, cm->mip, |
| 399 (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO)); |
| 400 } else { |
| 401 vpx_memset(cm->prev_mip, 0, |
| 402 (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO)); |
| 403 } |
| 404 |
| 405 /*vp9_print_modes_and_motion_vectors(cm->mi, cm->mb_rows,cm->mb_cols, |
| 406 cm->current_video_frame);*/ |
| 407 |
| 408 if (cm->show_frame) |
| 409 cm->current_video_frame++; |
| 410 |
| 411 pbi->ready_for_new_data = 0; |
| 412 pbi->last_time_stamp = time_stamp; |
| 413 pbi->source_sz = 0; |
| 414 |
| 415 pbi->common.error.setjmp = 0; |
| 416 return retcode; |
| 417 } |
| 418 |
| 419 int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd, |
| 420 int64_t *time_stamp, int64_t *time_end_stamp, |
| 421 vp9_ppflags_t *flags) { |
| 422 int ret = -1; |
| 423 VP9D_COMP *pbi = (VP9D_COMP *) ptr; |
| 424 |
| 425 if (pbi->ready_for_new_data == 1) |
| 426 return ret; |
| 427 |
| 428 /* ie no raw frame to show!!! */ |
| 429 if (pbi->common.show_frame == 0) |
| 430 return ret; |
| 431 |
| 432 pbi->ready_for_new_data = 1; |
| 433 *time_stamp = pbi->last_time_stamp; |
| 434 *time_end_stamp = 0; |
| 435 |
| 436 sd->clrtype = pbi->common.clr_type; |
| 437 #if CONFIG_POSTPROC |
| 438 ret = vp9_post_proc_frame(&pbi->common, sd, flags); |
| 439 #else |
| 440 |
| 441 if (pbi->common.frame_to_show) { |
| 442 *sd = *pbi->common.frame_to_show; |
| 443 sd->y_width = pbi->common.Width; |
| 444 sd->y_height = pbi->common.Height; |
| 445 sd->uv_height = pbi->common.Height / 2; |
| 446 ret = 0; |
| 447 } else { |
| 448 ret = -1; |
| 449 } |
| 450 |
| 451 #endif /*!CONFIG_POSTPROC*/ |
| 452 vp9_clear_system_state(); |
| 453 return ret; |
| 454 } |
OLD | NEW |