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 pbi
->common
.error
.setjmp
= 0;
137 return (VP8D_PTR
) pbi
;
141 void vp8dx_remove_decompressor(VP8D_PTR ptr
)
143 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
148 #if CONFIG_MULTITHREAD
149 if (pbi
->b_multithreaded_rd
)
150 vp8mt_de_alloc_temp_buffers(pbi
, pbi
->common
.mb_rows
);
151 vp8_decoder_remove_threads(pbi
);
153 vp8_remove_common(&pbi
->common
);
158 void vp8dx_set_setting(VP8D_PTR comp
, VP8D_SETTING oxst
, int x
)
160 VP8D_COMP
*pbi
= (VP8D_COMP
*) comp
;
172 int vp8dx_get_setting(VP8D_PTR comp
, VP8D_SETTING oxst
)
174 VP8D_COMP
*pbi
= (VP8D_COMP
*) comp
;
187 int vp8dx_get_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
189 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
190 VP8_COMMON
*cm
= &pbi
->common
;
193 if (ref_frame_flag
== VP8_LAST_FLAG
)
194 ref_fb_idx
= cm
->lst_fb_idx
;
195 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
196 ref_fb_idx
= cm
->gld_fb_idx
;
197 else if (ref_frame_flag
== VP8_ALT_FLAG
)
198 ref_fb_idx
= cm
->alt_fb_idx
;
202 vp8_yv12_copy_frame_ptr(&cm
->yv12_fb
[ref_fb_idx
], sd
);
206 int vp8dx_set_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
208 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
209 VP8_COMMON
*cm
= &pbi
->common
;
212 if (ref_frame_flag
== VP8_LAST_FLAG
)
213 ref_fb_idx
= cm
->lst_fb_idx
;
214 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
215 ref_fb_idx
= cm
->gld_fb_idx
;
216 else if (ref_frame_flag
== VP8_ALT_FLAG
)
217 ref_fb_idx
= cm
->alt_fb_idx
;
221 vp8_yv12_copy_frame_ptr(sd
, &cm
->yv12_fb
[ref_fb_idx
]);
226 /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
228 extern void vp8_push_neon(INT64
*store
);
229 extern void vp8_pop_neon(INT64
*store
);
232 static int get_free_fb (VP8_COMMON
*cm
)
235 for (i
= 0; i
< NUM_YV12_BUFFERS
; i
++)
236 if (cm
->fb_idx_ref_cnt
[i
] == 0)
239 cm
->fb_idx_ref_cnt
[i
] = 1;
243 static void ref_cnt_fb (int *buf
, int *idx
, int new_idx
)
253 /* If any buffer copy / swapping is signalled it should be done here. */
254 static int swap_frame_buffers (VP8_COMMON
*cm
)
258 /* The alternate reference frame or golden frame can be updated
259 * using the new, last, or golden/alt ref frame. If it
260 * is updated using the newly decoded frame it is a refresh.
261 * An update using the last or golden/alt ref frame is a copy.
263 if (cm
->copy_buffer_to_arf
)
267 if (cm
->copy_buffer_to_arf
== 1)
268 new_fb
= cm
->lst_fb_idx
;
269 else if (cm
->copy_buffer_to_arf
== 2)
270 new_fb
= cm
->gld_fb_idx
;
274 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, new_fb
);
277 if (cm
->copy_buffer_to_gf
)
281 if (cm
->copy_buffer_to_gf
== 1)
282 new_fb
= cm
->lst_fb_idx
;
283 else if (cm
->copy_buffer_to_gf
== 2)
284 new_fb
= cm
->alt_fb_idx
;
288 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, new_fb
);
291 if (cm
->refresh_golden_frame
)
292 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, cm
->new_fb_idx
);
294 if (cm
->refresh_alt_ref_frame
)
295 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, cm
->new_fb_idx
);
297 if (cm
->refresh_last_frame
)
299 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->lst_fb_idx
, cm
->new_fb_idx
);
301 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->lst_fb_idx
];
304 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->new_fb_idx
];
306 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
311 int vp8dx_receive_compressed_data(VP8D_PTR ptr
, unsigned long size
, const unsigned char *source
, INT64 time_stamp
)
314 INT64 dx_store_reg
[8];
316 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
317 VP8_COMMON
*cm
= &pbi
->common
;
319 struct vpx_usec_timer timer
;
321 /*if(pbi->ready_for_new_data == 0)
329 pbi
->common
.error
.error_code
= VPX_CODEC_OK
;
333 /* This is used to signal that we are missing frames.
334 * We do not know if the missing frame(s) was supposed to update
335 * any of the reference buffers, but we act conservative and
336 * mark only the last buffer as corrupted.
338 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
340 /* Signal that we have no frame to show. */
343 /* Nothing more to do. */
349 #if CONFIG_RUNTIME_CPU_DETECT
350 if (cm
->rtcd
.flags
& HAS_NEON
)
353 vp8_push_neon(dx_store_reg
);
357 cm
->new_fb_idx
= get_free_fb (cm
);
359 if (setjmp(pbi
->common
.error
.jmp
))
362 #if CONFIG_RUNTIME_CPU_DETECT
363 if (cm
->rtcd
.flags
& HAS_NEON
)
366 vp8_pop_neon(dx_store_reg
);
369 pbi
->common
.error
.setjmp
= 0;
371 /* We do not know if the missing frame(s) was supposed to update
372 * any of the reference buffers, but we act conservative and
373 * mark only the last buffer as corrupted.
375 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
377 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
378 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
382 pbi
->common
.error
.setjmp
= 1;
384 vpx_usec_timer_start(&timer
);
386 /*cm->current_video_frame++;*/
387 pbi
->Source
= source
;
388 pbi
->source_sz
= size
;
390 retcode
= vp8_decode_frame(pbi
);
395 #if CONFIG_RUNTIME_CPU_DETECT
396 if (cm
->rtcd
.flags
& HAS_NEON
)
399 vp8_pop_neon(dx_store_reg
);
402 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
403 pbi
->common
.error
.setjmp
= 0;
404 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
405 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
409 #if CONFIG_MULTITHREAD
410 if (pbi
->b_multithreaded_rd
&& cm
->multi_token_partition
!= ONE_PARTITION
)
412 if (swap_frame_buffers (cm
))
415 #if CONFIG_RUNTIME_CPU_DETECT
416 if (cm
->rtcd
.flags
& HAS_NEON
)
419 vp8_pop_neon(dx_store_reg
);
422 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
423 pbi
->common
.error
.setjmp
= 0;
429 if (swap_frame_buffers (cm
))
432 #if CONFIG_RUNTIME_CPU_DETECT
433 if (cm
->rtcd
.flags
& HAS_NEON
)
436 vp8_pop_neon(dx_store_reg
);
439 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
440 pbi
->common
.error
.setjmp
= 0;
444 if(pbi
->common
.filter_level
)
446 struct vpx_usec_timer lpftimer
;
447 vpx_usec_timer_start(&lpftimer
);
448 /* Apply the loop filter if appropriate. */
450 vp8_loop_filter_frame(cm
, &pbi
->mb
, cm
->filter_level
);
452 vpx_usec_timer_mark(&lpftimer
);
453 pbi
->time_loop_filtering
+= vpx_usec_timer_elapsed(&lpftimer
);
455 cm
->last_frame_type
= cm
->frame_type
;
456 cm
->last_filter_type
= cm
->filter_type
;
457 cm
->last_sharpness_level
= cm
->sharpness_level
;
459 vp8_yv12_extend_frame_borders_ptr(cm
->frame_to_show
);
464 /*vp8_recon_write_yuv_frame("recon.yuv", cm->frame_to_show);*/
465 if (cm
->current_video_frame
<= 5)
466 write_dx_frame_to_file(cm
->frame_to_show
, cm
->current_video_frame
);
469 vp8_clear_system_state();
471 vpx_usec_timer_mark(&timer
);
472 pbi
->decode_microseconds
= vpx_usec_timer_elapsed(&timer
);
474 pbi
->time_decoding
+= pbi
->decode_microseconds
;
476 /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
479 cm
->current_video_frame
++;
481 pbi
->ready_for_new_data
= 0;
482 pbi
->last_time_stamp
= time_stamp
;
487 INT64 earliest_time
= pbi
->dr
[0].time_stamp
;
488 INT64 latest_time
= pbi
->dr
[0].time_stamp
;
492 pbi
->dr
[pbi
->common
.current_video_frame
&0xf].size
= pbi
->bc
.pos
+ pbi
->bc2
.pos
+ 4;;
493 pbi
->dr
[pbi
->common
.current_video_frame
&0xf].time_stamp
= time_stamp
;
495 for (i
= 0; i
< 16; i
++)
498 bytes
+= pbi
->dr
[i
].size
;
500 if (pbi
->dr
[i
].time_stamp
< earliest_time
)
501 earliest_time
= pbi
->dr
[i
].time_stamp
;
503 if (pbi
->dr
[i
].time_stamp
> latest_time
)
504 latest_time
= pbi
->dr
[i
].time_stamp
;
507 time_diff
= latest_time
- earliest_time
;
511 pbi
->common
.bitrate
= 80000.00 * bytes
/ time_diff
;
512 pbi
->common
.framerate
= 160000000.00 / time_diff
;
519 #if CONFIG_RUNTIME_CPU_DETECT
520 if (cm
->rtcd
.flags
& HAS_NEON
)
523 vp8_pop_neon(dx_store_reg
);
526 pbi
->common
.error
.setjmp
= 0;
529 int vp8dx_get_raw_frame(VP8D_PTR ptr
, YV12_BUFFER_CONFIG
*sd
, INT64
*time_stamp
, INT64
*time_end_stamp
, vp8_ppflags_t
*flags
)
532 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
534 if (pbi
->ready_for_new_data
== 1)
537 /* ie no raw frame to show!!! */
538 if (pbi
->common
.show_frame
== 0)
541 pbi
->ready_for_new_data
= 1;
542 *time_stamp
= pbi
->last_time_stamp
;
545 sd
->clrtype
= pbi
->common
.clr_type
;
547 ret
= vp8_post_proc_frame(&pbi
->common
, sd
, flags
);
550 if (pbi
->common
.frame_to_show
)
552 *sd
= *pbi
->common
.frame_to_show
;
553 sd
->y_width
= pbi
->common
.Width
;
554 sd
->y_height
= pbi
->common
.Height
;
555 sd
->uv_height
= pbi
->common
.Height
/ 2;
563 #endif /*!CONFIG_POSTPROC*/
564 vp8_clear_system_state();