2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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.
12 #include "vp8/common/onyxc_int.h"
14 #include "vp8/common/postproc.h"
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"
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"
34 #include "vpx_ports/arm.h"
37 extern void vp8_init_loop_filter(VP8_COMMON
*cm
);
38 extern void vp8cx_init_de_quantizer(VP8D_COMP
*pbi
);
41 void vp8_recon_write_yuv_frame(unsigned char *name
, YV12_BUFFER_CONFIG
*s
)
43 FILE *yuv_file
= fopen((char *)name
, "ab");
44 unsigned char *src
= s
->y_buffer
;
49 fwrite(src
, s
->y_width
, 1, yuv_file
);
59 fwrite(src
, s
->uv_width
, 1, yuv_file
);
69 fwrite(src
, s
->uv_width
, 1, yuv_file
);
78 void vp8dx_initialize()
80 static int init_done
= 0;
84 vp8_initialize_common();
85 vp8_scale_machine_specific_config();
91 VP8D_PTR
vp8dx_create_decompressor(VP8D_CONFIG
*oxcf
)
93 VP8D_COMP
*pbi
= vpx_memalign(32, sizeof(VP8D_COMP
));
98 vpx_memset(pbi
, 0, sizeof(VP8D_COMP
));
100 if (setjmp(pbi
->common
.error
.jmp
))
102 pbi
->common
.error
.setjmp
= 0;
103 vp8dx_remove_decompressor(pbi
);
107 pbi
->common
.error
.setjmp
= 1;
110 vp8_create_common(&pbi
->common
);
111 vp8_dmachine_specific_config(pbi
);
113 pbi
->common
.current_video_frame
= 0;
114 pbi
->ready_for_new_data
= 1;
116 pbi
->CPUFreq
= 0; /*vp8_get_processor_freq();*/
117 #if CONFIG_MULTITHREAD
118 pbi
->max_threads
= oxcf
->max_threads
;
119 vp8_decoder_create_threads(pbi
);
122 /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
123 * unnecessary calling of vp8cx_init_de_quantizer() for every frame.
125 vp8cx_init_de_quantizer(pbi
);
128 VP8_COMMON
*cm
= &pbi
->common
;
130 vp8_init_loop_filter(cm
);
131 cm
->last_frame_type
= KEY_FRAME
;
132 cm
->last_filter_type
= cm
->filter_type
;
133 cm
->last_sharpness_level
= cm
->sharpness_level
;
136 #if CONFIG_ARM_ASM_DETOK
137 vp8_init_detokenizer(pbi
);
139 pbi
->common
.error
.setjmp
= 0;
140 return (VP8D_PTR
) pbi
;
144 void vp8dx_remove_decompressor(VP8D_PTR ptr
)
146 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
151 #if CONFIG_MULTITHREAD
152 if (pbi
->b_multithreaded_rd
)
153 vp8mt_de_alloc_temp_buffers(pbi
, pbi
->common
.mb_rows
);
154 vp8_decoder_remove_threads(pbi
);
156 vp8_remove_common(&pbi
->common
);
161 void vp8dx_set_setting(VP8D_PTR comp
, VP8D_SETTING oxst
, int x
)
163 VP8D_COMP
*pbi
= (VP8D_COMP
*) comp
;
175 int vp8dx_get_setting(VP8D_PTR comp
, VP8D_SETTING oxst
)
177 VP8D_COMP
*pbi
= (VP8D_COMP
*) comp
;
190 int vp8dx_get_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
192 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
193 VP8_COMMON
*cm
= &pbi
->common
;
196 if (ref_frame_flag
== VP8_LAST_FLAG
)
197 ref_fb_idx
= cm
->lst_fb_idx
;
198 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
199 ref_fb_idx
= cm
->gld_fb_idx
;
200 else if (ref_frame_flag
== VP8_ALT_FLAG
)
201 ref_fb_idx
= cm
->alt_fb_idx
;
205 vp8_yv12_copy_frame_ptr(&cm
->yv12_fb
[ref_fb_idx
], sd
);
209 int vp8dx_set_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
211 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
212 VP8_COMMON
*cm
= &pbi
->common
;
215 if (ref_frame_flag
== VP8_LAST_FLAG
)
216 ref_fb_idx
= cm
->lst_fb_idx
;
217 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
218 ref_fb_idx
= cm
->gld_fb_idx
;
219 else if (ref_frame_flag
== VP8_ALT_FLAG
)
220 ref_fb_idx
= cm
->alt_fb_idx
;
224 vp8_yv12_copy_frame_ptr(sd
, &cm
->yv12_fb
[ref_fb_idx
]);
229 /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
231 extern void vp8_push_neon(INT64
*store
);
232 extern void vp8_pop_neon(INT64
*store
);
235 static int get_free_fb (VP8_COMMON
*cm
)
238 for (i
= 0; i
< NUM_YV12_BUFFERS
; i
++)
239 if (cm
->fb_idx_ref_cnt
[i
] == 0)
242 cm
->fb_idx_ref_cnt
[i
] = 1;
246 static void ref_cnt_fb (int *buf
, int *idx
, int new_idx
)
256 /* If any buffer copy / swapping is signalled it should be done here. */
257 static int swap_frame_buffers (VP8_COMMON
*cm
)
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.
266 if (cm
->copy_buffer_to_arf
)
270 if (cm
->copy_buffer_to_arf
== 1)
271 new_fb
= cm
->lst_fb_idx
;
272 else if (cm
->copy_buffer_to_arf
== 2)
273 new_fb
= cm
->gld_fb_idx
;
277 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, new_fb
);
280 if (cm
->copy_buffer_to_gf
)
284 if (cm
->copy_buffer_to_gf
== 1)
285 new_fb
= cm
->lst_fb_idx
;
286 else if (cm
->copy_buffer_to_gf
== 2)
287 new_fb
= cm
->alt_fb_idx
;
291 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, new_fb
);
294 if (cm
->refresh_golden_frame
)
295 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, cm
->new_fb_idx
);
297 if (cm
->refresh_alt_ref_frame
)
298 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, cm
->new_fb_idx
);
300 if (cm
->refresh_last_frame
)
302 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->lst_fb_idx
, cm
->new_fb_idx
);
304 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->lst_fb_idx
];
307 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->new_fb_idx
];
309 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
314 int vp8dx_receive_compressed_data(VP8D_PTR ptr
, unsigned long size
, const unsigned char *source
, INT64 time_stamp
)
317 INT64 dx_store_reg
[8];
319 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
320 VP8_COMMON
*cm
= &pbi
->common
;
322 struct vpx_usec_timer timer
;
324 /*if(pbi->ready_for_new_data == 0)
332 pbi
->common
.error
.error_code
= VPX_CODEC_OK
;
336 /* This is used to signal that we are missing frames.
337 * We do not know if the missing frame(s) was supposed to update
338 * any of the reference buffers, but we act conservative and
339 * mark only the last buffer as corrupted.
341 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
343 /* Signal that we have no frame to show. */
346 /* Nothing more to do. */
352 #if CONFIG_RUNTIME_CPU_DETECT
353 if (cm
->rtcd
.flags
& HAS_NEON
)
356 vp8_push_neon(dx_store_reg
);
360 cm
->new_fb_idx
= get_free_fb (cm
);
362 if (setjmp(pbi
->common
.error
.jmp
))
365 #if CONFIG_RUNTIME_CPU_DETECT
366 if (cm
->rtcd
.flags
& HAS_NEON
)
369 vp8_pop_neon(dx_store_reg
);
372 pbi
->common
.error
.setjmp
= 0;
374 /* We do not know if the missing frame(s) was supposed to update
375 * any of the reference buffers, but we act conservative and
376 * mark only the last buffer as corrupted.
378 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
380 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
381 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
385 pbi
->common
.error
.setjmp
= 1;
387 vpx_usec_timer_start(&timer
);
389 /*cm->current_video_frame++;*/
390 pbi
->Source
= source
;
391 pbi
->source_sz
= size
;
393 retcode
= vp8_decode_frame(pbi
);
398 #if CONFIG_RUNTIME_CPU_DETECT
399 if (cm
->rtcd
.flags
& HAS_NEON
)
402 vp8_pop_neon(dx_store_reg
);
405 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
406 pbi
->common
.error
.setjmp
= 0;
407 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
408 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
412 #if CONFIG_MULTITHREAD
413 if (pbi
->b_multithreaded_rd
&& cm
->multi_token_partition
!= ONE_PARTITION
)
415 if (swap_frame_buffers (cm
))
418 #if CONFIG_RUNTIME_CPU_DETECT
419 if (cm
->rtcd
.flags
& HAS_NEON
)
422 vp8_pop_neon(dx_store_reg
);
425 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
426 pbi
->common
.error
.setjmp
= 0;
432 if (swap_frame_buffers (cm
))
435 #if CONFIG_RUNTIME_CPU_DETECT
436 if (cm
->rtcd
.flags
& HAS_NEON
)
439 vp8_pop_neon(dx_store_reg
);
442 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
443 pbi
->common
.error
.setjmp
= 0;
447 if(pbi
->common
.filter_level
)
449 struct vpx_usec_timer lpftimer
;
450 vpx_usec_timer_start(&lpftimer
);
451 /* Apply the loop filter if appropriate. */
453 vp8_loop_filter_frame(cm
, &pbi
->mb
, cm
->filter_level
);
455 vpx_usec_timer_mark(&lpftimer
);
456 pbi
->time_loop_filtering
+= vpx_usec_timer_elapsed(&lpftimer
);
458 cm
->last_frame_type
= cm
->frame_type
;
459 cm
->last_filter_type
= cm
->filter_type
;
460 cm
->last_sharpness_level
= cm
->sharpness_level
;
462 vp8_yv12_extend_frame_borders_ptr(cm
->frame_to_show
);
467 /*vp8_recon_write_yuv_frame("recon.yuv", cm->frame_to_show);*/
468 if (cm
->current_video_frame
<= 5)
469 write_dx_frame_to_file(cm
->frame_to_show
, cm
->current_video_frame
);
472 vp8_clear_system_state();
474 vpx_usec_timer_mark(&timer
);
475 pbi
->decode_microseconds
= vpx_usec_timer_elapsed(&timer
);
477 pbi
->time_decoding
+= pbi
->decode_microseconds
;
479 /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
482 cm
->current_video_frame
++;
484 pbi
->ready_for_new_data
= 0;
485 pbi
->last_time_stamp
= time_stamp
;
490 INT64 earliest_time
= pbi
->dr
[0].time_stamp
;
491 INT64 latest_time
= pbi
->dr
[0].time_stamp
;
495 pbi
->dr
[pbi
->common
.current_video_frame
&0xf].size
= pbi
->bc
.pos
+ pbi
->bc2
.pos
+ 4;;
496 pbi
->dr
[pbi
->common
.current_video_frame
&0xf].time_stamp
= time_stamp
;
498 for (i
= 0; i
< 16; i
++)
501 bytes
+= pbi
->dr
[i
].size
;
503 if (pbi
->dr
[i
].time_stamp
< earliest_time
)
504 earliest_time
= pbi
->dr
[i
].time_stamp
;
506 if (pbi
->dr
[i
].time_stamp
> latest_time
)
507 latest_time
= pbi
->dr
[i
].time_stamp
;
510 time_diff
= latest_time
- earliest_time
;
514 pbi
->common
.bitrate
= 80000.00 * bytes
/ time_diff
;
515 pbi
->common
.framerate
= 160000000.00 / time_diff
;
522 #if CONFIG_RUNTIME_CPU_DETECT
523 if (cm
->rtcd
.flags
& HAS_NEON
)
526 vp8_pop_neon(dx_store_reg
);
529 pbi
->common
.error
.setjmp
= 0;
532 int vp8dx_get_raw_frame(VP8D_PTR ptr
, YV12_BUFFER_CONFIG
*sd
, INT64
*time_stamp
, INT64
*time_end_stamp
, vp8_ppflags_t
*flags
)
535 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
537 if (pbi
->ready_for_new_data
== 1)
540 /* ie no raw frame to show!!! */
541 if (pbi
->common
.show_frame
== 0)
544 pbi
->ready_for_new_data
= 1;
545 *time_stamp
= pbi
->last_time_stamp
;
548 sd
->clrtype
= pbi
->common
.clr_type
;
550 ret
= vp8_post_proc_frame(&pbi
->common
, sd
, flags
);
553 if (pbi
->common
.frame_to_show
)
555 *sd
= *pbi
->common
.frame_to_show
;
556 sd
->y_width
= pbi
->common
.Width
;
557 sd
->y_height
= pbi
->common
.Height
;
558 sd
->uv_height
= pbi
->common
.Height
/ 2;
566 #endif /*!CONFIG_POSTPROC*/
567 vp8_clear_system_state();