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 "vp8/common/onyxc_int.h" 13 #if CONFIG_POSTPROC 14 #include "vp8/common/postproc.h" 15 #endif 16 #include "vp8/common/onyxd.h" 17 #include "onyxd_int.h" 18 #include "vpx_mem/vpx_mem.h" 19 #include "vp8/common/alloccommon.h" 20 #include "vpx_scale/yv12extend.h" 21 #include "vp8/common/loopfilter.h" 22 #include "vp8/common/swapyv12buffer.h" 23 #include "vp8/common/g_common.h" 24 #include "vp8/common/threading.h" 25 #include "decoderthreading.h" 26 #include <stdio.h> 27 28 #include "vp8/common/quant_common.h" 29 #include "vpx_scale/vpxscale.h" 30 #include "vp8/common/systemdependent.h" 31 #include "vpx_ports/vpx_timer.h" 32 #include "detokenize.h" 33 #if ARCH_ARM 34 #include "vpx_ports/arm.h" 35 #endif 36 37 extern void vp8_init_loop_filter(VP8_COMMON *cm); 38 extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi); 39 40 41 void vp8dx_initialize() 42 { 43 static int init_done = 0; 44 45 if (!init_done) 46 { 47 vp8_initialize_common(); 48 vp8_scale_machine_specific_config(); 49 init_done = 1; 50 } 51 } 52 53 54 VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf) 55 { 56 VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP)); 57 58 if (!pbi) 59 return NULL; 60 61 vpx_memset(pbi, 0, sizeof(VP8D_COMP)); 62 63 if (setjmp(pbi->common.error.jmp)) 64 { 65 pbi->common.error.setjmp = 0; 66 vp8dx_remove_decompressor(pbi); 67 return 0; 68 } 69 70 pbi->common.error.setjmp = 1; 71 vp8dx_initialize(); 72 73 vp8_create_common(&pbi->common); 74 vp8_dmachine_specific_config(pbi); 75 76 pbi->common.current_video_frame = 0; 77 pbi->ready_for_new_data = 1; 78 79 pbi->CPUFreq = 0; /*vp8_get_processor_freq();*/ 80 #if CONFIG_MULTITHREAD 81 pbi->max_threads = oxcf->max_threads; 82 vp8_decoder_create_threads(pbi); 83 #endif 84 85 /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid 86 * unnecessary calling of vp8cx_init_de_quantizer() for every frame. 87 */ 88 vp8cx_init_de_quantizer(pbi); 89 90 { 91 VP8_COMMON *cm = &pbi->common; 92 93 vp8_init_loop_filter(cm); 94 cm->last_frame_type = KEY_FRAME; 95 cm->last_filter_type = cm->filter_type; 96 cm->last_sharpness_level = cm->sharpness_level; 97 } 98 99 pbi->common.error.setjmp = 0; 100 return (VP8D_PTR) pbi; 101 } 102 103 104 void vp8dx_remove_decompressor(VP8D_PTR ptr) 105 { 106 VP8D_COMP *pbi = (VP8D_COMP *) ptr; 107 108 if (!pbi) 109 return; 110 111 #if CONFIG_MULTITHREAD 112 if (pbi->b_multithreaded_rd) 113 vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows); 114 vp8_decoder_remove_threads(pbi); 115 #endif 116 vp8_remove_common(&pbi->common); 117 vpx_free(pbi); 118 } 119 120 121 int vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd) 122 { 123 VP8D_COMP *pbi = (VP8D_COMP *) ptr; 124 VP8_COMMON *cm = &pbi->common; 125 int ref_fb_idx; 126 127 if (ref_frame_flag == VP8_LAST_FLAG) 128 ref_fb_idx = cm->lst_fb_idx; 129 else if (ref_frame_flag == VP8_GOLD_FLAG) 130 ref_fb_idx = cm->gld_fb_idx; 131 else if (ref_frame_flag == VP8_ALT_FLAG) 132 ref_fb_idx = cm->alt_fb_idx; 133 else 134 return -1; 135 136 vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd); 137 138 return 0; 139 } 140 141 142 int vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd) 143 { 144 VP8D_COMP *pbi = (VP8D_COMP *) ptr; 145 VP8_COMMON *cm = &pbi->common; 146 int ref_fb_idx; 147 148 if (ref_frame_flag == VP8_LAST_FLAG) 149 ref_fb_idx = cm->lst_fb_idx; 150 else if (ref_frame_flag == VP8_GOLD_FLAG) 151 ref_fb_idx = cm->gld_fb_idx; 152 else if (ref_frame_flag == VP8_ALT_FLAG) 153 ref_fb_idx = cm->alt_fb_idx; 154 else 155 return -1; 156 157 vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[ref_fb_idx]); 158 159 return 0; 160 } 161 162 /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/ 163 #if HAVE_ARMV7 164 extern void vp8_push_neon(INT64 *store); 165 extern void vp8_pop_neon(INT64 *store); 166 #endif 167 168 static int get_free_fb (VP8_COMMON *cm) 169 { 170 int i; 171 for (i = 0; i < NUM_YV12_BUFFERS; i++) 172 if (cm->fb_idx_ref_cnt[i] == 0) 173 break; 174 175 cm->fb_idx_ref_cnt[i] = 1; 176 return i; 177 } 178 179 static void ref_cnt_fb (int *buf, int *idx, int new_idx) 180 { 181 if (buf[*idx] > 0) 182 buf[*idx]--; 183 184 *idx = new_idx; 185 186 buf[new_idx]++; 187 } 188 189 /* If any buffer copy / swapping is signalled it should be done here. */ 190 static int swap_frame_buffers (VP8_COMMON *cm) 191 { 192 int err = 0; 193 194 /* The alternate reference frame or golden frame can be updated 195 * using the new, last, or golden/alt ref frame. If it 196 * is updated using the newly decoded frame it is a refresh. 197 * An update using the last or golden/alt ref frame is a copy. 198 */ 199 if (cm->copy_buffer_to_arf) 200 { 201 int new_fb = 0; 202 203 if (cm->copy_buffer_to_arf == 1) 204 new_fb = cm->lst_fb_idx; 205 else if (cm->copy_buffer_to_arf == 2) 206 new_fb = cm->gld_fb_idx; 207 else 208 err = -1; 209 210 ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb); 211 } 212 213 if (cm->copy_buffer_to_gf) 214 { 215 int new_fb = 0; 216 217 if (cm->copy_buffer_to_gf == 1) 218 new_fb = cm->lst_fb_idx; 219 else if (cm->copy_buffer_to_gf == 2) 220 new_fb = cm->alt_fb_idx; 221 else 222 err = -1; 223 224 ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb); 225 } 226 227 if (cm->refresh_golden_frame) 228 ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx); 229 230 if (cm->refresh_alt_ref_frame) 231 ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx); 232 233 if (cm->refresh_last_frame) 234 { 235 ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx); 236 237 cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx]; 238 } 239 else 240 cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx]; 241 242 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 243 244 return err; 245 } 246 247 int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsigned char *source, INT64 time_stamp) 248 { 249 #if HAVE_ARMV7 250 INT64 dx_store_reg[8]; 251 #endif 252 VP8D_COMP *pbi = (VP8D_COMP *) ptr; 253 VP8_COMMON *cm = &pbi->common; 254 int retcode = 0; 255 struct vpx_usec_timer timer; 256 257 /*if(pbi->ready_for_new_data == 0) 258 return -1;*/ 259 260 if (ptr == 0) 261 { 262 return -1; 263 } 264 265 pbi->common.error.error_code = VPX_CODEC_OK; 266 267 if (size == 0) 268 { 269 /* This is used to signal that we are missing frames. 270 * We do not know if the missing frame(s) was supposed to update 271 * any of the reference buffers, but we act conservative and 272 * mark only the last buffer as corrupted. 273 */ 274 cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; 275 276 /* Signal that we have no frame to show. */ 277 cm->show_frame = 0; 278 279 /* Nothing more to do. */ 280 return 0; 281 } 282 283 284 #if HAVE_ARMV7 285 #if CONFIG_RUNTIME_CPU_DETECT 286 if (cm->rtcd.flags & HAS_NEON) 287 #endif 288 { 289 vp8_push_neon(dx_store_reg); 290 } 291 #endif 292 293 cm->new_fb_idx = get_free_fb (cm); 294 295 if (setjmp(pbi->common.error.jmp)) 296 { 297 #if HAVE_ARMV7 298 #if CONFIG_RUNTIME_CPU_DETECT 299 if (cm->rtcd.flags & HAS_NEON) 300 #endif 301 { 302 vp8_pop_neon(dx_store_reg); 303 } 304 #endif 305 pbi->common.error.setjmp = 0; 306 307 /* We do not know if the missing frame(s) was supposed to update 308 * any of the reference buffers, but we act conservative and 309 * mark only the last buffer as corrupted. 310 */ 311 cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; 312 313 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 314 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 315 return -1; 316 } 317 318 pbi->common.error.setjmp = 1; 319 320 vpx_usec_timer_start(&timer); 321 322 /*cm->current_video_frame++;*/ 323 pbi->Source = source; 324 pbi->source_sz = size; 325 326 retcode = vp8_decode_frame(pbi); 327 328 if (retcode < 0) 329 { 330 #if HAVE_ARMV7 331 #if CONFIG_RUNTIME_CPU_DETECT 332 if (cm->rtcd.flags & HAS_NEON) 333 #endif 334 { 335 vp8_pop_neon(dx_store_reg); 336 } 337 #endif 338 pbi->common.error.error_code = VPX_CODEC_ERROR; 339 pbi->common.error.setjmp = 0; 340 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) 341 cm->fb_idx_ref_cnt[cm->new_fb_idx]--; 342 return retcode; 343 } 344 345 #if CONFIG_MULTITHREAD 346 if (pbi->b_multithreaded_rd && cm->multi_token_partition != ONE_PARTITION) 347 { 348 if (swap_frame_buffers (cm)) 349 { 350 #if HAVE_ARMV7 351 #if CONFIG_RUNTIME_CPU_DETECT 352 if (cm->rtcd.flags & HAS_NEON) 353 #endif 354 { 355 vp8_pop_neon(dx_store_reg); 356 } 357 #endif 358 pbi->common.error.error_code = VPX_CODEC_ERROR; 359 pbi->common.error.setjmp = 0; 360 return -1; 361 } 362 } else 363 #endif 364 { 365 if (swap_frame_buffers (cm)) 366 { 367 #if HAVE_ARMV7 368 #if CONFIG_RUNTIME_CPU_DETECT 369 if (cm->rtcd.flags & HAS_NEON) 370 #endif 371 { 372 vp8_pop_neon(dx_store_reg); 373 } 374 #endif 375 pbi->common.error.error_code = VPX_CODEC_ERROR; 376 pbi->common.error.setjmp = 0; 377 return -1; 378 } 379 380 if(pbi->common.filter_level) 381 { 382 struct vpx_usec_timer lpftimer; 383 vpx_usec_timer_start(&lpftimer); 384 /* Apply the loop filter if appropriate. */ 385 386 vp8_loop_filter_frame(cm, &pbi->mb, cm->filter_level); 387 388 vpx_usec_timer_mark(&lpftimer); 389 pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer); 390 391 cm->last_frame_type = cm->frame_type; 392 cm->last_filter_type = cm->filter_type; 393 cm->last_sharpness_level = cm->sharpness_level; 394 } 395 vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show); 396 } 397 398 399 vp8_clear_system_state(); 400 401 vpx_usec_timer_mark(&timer); 402 pbi->decode_microseconds = vpx_usec_timer_elapsed(&timer); 403 404 pbi->time_decoding += pbi->decode_microseconds; 405 406 /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, 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 414 #if 0 415 { 416 int i; 417 INT64 earliest_time = pbi->dr[0].time_stamp; 418 INT64 latest_time = pbi->dr[0].time_stamp; 419 INT64 time_diff = 0; 420 int bytes = 0; 421 422 pbi->dr[pbi->common.current_video_frame&0xf].size = pbi->bc.pos + pbi->bc2.pos + 4;; 423 pbi->dr[pbi->common.current_video_frame&0xf].time_stamp = time_stamp; 424 425 for (i = 0; i < 16; i++) 426 { 427 428 bytes += pbi->dr[i].size; 429 430 if (pbi->dr[i].time_stamp < earliest_time) 431 earliest_time = pbi->dr[i].time_stamp; 432 433 if (pbi->dr[i].time_stamp > latest_time) 434 latest_time = pbi->dr[i].time_stamp; 435 } 436 437 time_diff = latest_time - earliest_time; 438 439 if (time_diff > 0) 440 { 441 pbi->common.bitrate = 80000.00 * bytes / time_diff ; 442 pbi->common.framerate = 160000000.00 / time_diff ; 443 } 444 445 } 446 #endif 447 448 #if HAVE_ARMV7 449 #if CONFIG_RUNTIME_CPU_DETECT 450 if (cm->rtcd.flags & HAS_NEON) 451 #endif 452 { 453 vp8_pop_neon(dx_store_reg); 454 } 455 #endif 456 pbi->common.error.setjmp = 0; 457 return retcode; 458 } 459 int vp8dx_get_raw_frame(VP8D_PTR ptr, YV12_BUFFER_CONFIG *sd, INT64 *time_stamp, INT64 *time_end_stamp, vp8_ppflags_t *flags) 460 { 461 int ret = -1; 462 VP8D_COMP *pbi = (VP8D_COMP *) ptr; 463 464 if (pbi->ready_for_new_data == 1) 465 return ret; 466 467 /* ie no raw frame to show!!! */ 468 if (pbi->common.show_frame == 0) 469 return ret; 470 471 pbi->ready_for_new_data = 1; 472 *time_stamp = pbi->last_time_stamp; 473 *time_end_stamp = 0; 474 475 sd->clrtype = pbi->common.clr_type; 476 #if CONFIG_POSTPROC 477 ret = vp8_post_proc_frame(&pbi->common, sd, flags); 478 #else 479 480 if (pbi->common.frame_to_show) 481 { 482 *sd = *pbi->common.frame_to_show; 483 sd->y_width = pbi->common.Width; 484 sd->y_height = pbi->common.Height; 485 sd->uv_height = pbi->common.Height / 2; 486 ret = 0; 487 } 488 else 489 { 490 ret = -1; 491 } 492 493 #endif /*!CONFIG_POSTPROC*/ 494 vp8_clear_system_state(); 495 return ret; 496 } 497