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 vp8dx_initialize()
43 static int init_done
= 0;
47 vp8_initialize_common();
48 vp8_scale_machine_specific_config();
54 VP8D_PTR
vp8dx_create_decompressor(VP8D_CONFIG
*oxcf
)
56 VP8D_COMP
*pbi
= vpx_memalign(32, sizeof(VP8D_COMP
));
61 vpx_memset(pbi
, 0, sizeof(VP8D_COMP
));
63 if (setjmp(pbi
->common
.error
.jmp
))
65 pbi
->common
.error
.setjmp
= 0;
66 vp8dx_remove_decompressor(pbi
);
70 pbi
->common
.error
.setjmp
= 1;
73 vp8_create_common(&pbi
->common
);
74 vp8_dmachine_specific_config(pbi
);
76 pbi
->common
.current_video_frame
= 0;
77 pbi
->ready_for_new_data
= 1;
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
);
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.
88 vp8cx_init_de_quantizer(pbi
);
91 VP8_COMMON
*cm
= &pbi
->common
;
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
;
99 pbi
->common
.error
.setjmp
= 0;
100 return (VP8D_PTR
) pbi
;
104 void vp8dx_remove_decompressor(VP8D_PTR ptr
)
106 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
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
);
116 vp8_remove_common(&pbi
->common
);
121 int vp8dx_get_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
123 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
124 VP8_COMMON
*cm
= &pbi
->common
;
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
;
136 vp8_yv12_copy_frame_ptr(&cm
->yv12_fb
[ref_fb_idx
], sd
);
142 int vp8dx_set_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
144 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
145 VP8_COMMON
*cm
= &pbi
->common
;
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
;
157 vp8_yv12_copy_frame_ptr(sd
, &cm
->yv12_fb
[ref_fb_idx
]);
162 /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
164 extern void vp8_push_neon(INT64
*store
);
165 extern void vp8_pop_neon(INT64
*store
);
168 static int get_free_fb (VP8_COMMON
*cm
)
171 for (i
= 0; i
< NUM_YV12_BUFFERS
; i
++)
172 if (cm
->fb_idx_ref_cnt
[i
] == 0)
175 cm
->fb_idx_ref_cnt
[i
] = 1;
179 static void ref_cnt_fb (int *buf
, int *idx
, int new_idx
)
189 /* If any buffer copy / swapping is signalled it should be done here. */
190 static int swap_frame_buffers (VP8_COMMON
*cm
)
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.
199 if (cm
->copy_buffer_to_arf
)
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
;
210 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, new_fb
);
213 if (cm
->copy_buffer_to_gf
)
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
;
224 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, new_fb
);
227 if (cm
->refresh_golden_frame
)
228 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, cm
->new_fb_idx
);
230 if (cm
->refresh_alt_ref_frame
)
231 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, cm
->new_fb_idx
);
233 if (cm
->refresh_last_frame
)
235 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->lst_fb_idx
, cm
->new_fb_idx
);
237 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->lst_fb_idx
];
240 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->new_fb_idx
];
242 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
247 int vp8dx_receive_compressed_data(VP8D_PTR ptr
, unsigned long size
, const unsigned char *source
, INT64 time_stamp
)
250 INT64 dx_store_reg
[8];
252 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
253 VP8_COMMON
*cm
= &pbi
->common
;
255 struct vpx_usec_timer timer
;
257 /*if(pbi->ready_for_new_data == 0)
265 pbi
->common
.error
.error_code
= VPX_CODEC_OK
;
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.
274 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
276 /* Signal that we have no frame to show. */
279 /* Nothing more to do. */
285 #if CONFIG_RUNTIME_CPU_DETECT
286 if (cm
->rtcd
.flags
& HAS_NEON
)
289 vp8_push_neon(dx_store_reg
);
293 cm
->new_fb_idx
= get_free_fb (cm
);
295 if (setjmp(pbi
->common
.error
.jmp
))
298 #if CONFIG_RUNTIME_CPU_DETECT
299 if (cm
->rtcd
.flags
& HAS_NEON
)
302 vp8_pop_neon(dx_store_reg
);
305 pbi
->common
.error
.setjmp
= 0;
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.
311 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
313 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
314 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
318 pbi
->common
.error
.setjmp
= 1;
320 vpx_usec_timer_start(&timer
);
322 /*cm->current_video_frame++;*/
323 pbi
->Source
= source
;
324 pbi
->source_sz
= size
;
326 retcode
= vp8_decode_frame(pbi
);
331 #if CONFIG_RUNTIME_CPU_DETECT
332 if (cm
->rtcd
.flags
& HAS_NEON
)
335 vp8_pop_neon(dx_store_reg
);
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
]--;
345 #if CONFIG_MULTITHREAD
346 if (pbi
->b_multithreaded_rd
&& cm
->multi_token_partition
!= ONE_PARTITION
)
348 if (swap_frame_buffers (cm
))
351 #if CONFIG_RUNTIME_CPU_DETECT
352 if (cm
->rtcd
.flags
& HAS_NEON
)
355 vp8_pop_neon(dx_store_reg
);
358 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
359 pbi
->common
.error
.setjmp
= 0;
365 if (swap_frame_buffers (cm
))
368 #if CONFIG_RUNTIME_CPU_DETECT
369 if (cm
->rtcd
.flags
& HAS_NEON
)
372 vp8_pop_neon(dx_store_reg
);
375 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
376 pbi
->common
.error
.setjmp
= 0;
380 if(pbi
->common
.filter_level
)
382 struct vpx_usec_timer lpftimer
;
383 vpx_usec_timer_start(&lpftimer
);
384 /* Apply the loop filter if appropriate. */
386 vp8_loop_filter_frame(cm
, &pbi
->mb
, cm
->filter_level
);
388 vpx_usec_timer_mark(&lpftimer
);
389 pbi
->time_loop_filtering
+= vpx_usec_timer_elapsed(&lpftimer
);
391 cm
->last_frame_type
= cm
->frame_type
;
392 cm
->last_filter_type
= cm
->filter_type
;
393 cm
->last_sharpness_level
= cm
->sharpness_level
;
395 vp8_yv12_extend_frame_borders_ptr(cm
->frame_to_show
);
399 vp8_clear_system_state();
401 vpx_usec_timer_mark(&timer
);
402 pbi
->decode_microseconds
= vpx_usec_timer_elapsed(&timer
);
404 pbi
->time_decoding
+= pbi
->decode_microseconds
;
406 /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
409 cm
->current_video_frame
++;
411 pbi
->ready_for_new_data
= 0;
412 pbi
->last_time_stamp
= time_stamp
;
417 INT64 earliest_time
= pbi
->dr
[0].time_stamp
;
418 INT64 latest_time
= pbi
->dr
[0].time_stamp
;
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
;
425 for (i
= 0; i
< 16; i
++)
428 bytes
+= pbi
->dr
[i
].size
;
430 if (pbi
->dr
[i
].time_stamp
< earliest_time
)
431 earliest_time
= pbi
->dr
[i
].time_stamp
;
433 if (pbi
->dr
[i
].time_stamp
> latest_time
)
434 latest_time
= pbi
->dr
[i
].time_stamp
;
437 time_diff
= latest_time
- earliest_time
;
441 pbi
->common
.bitrate
= 80000.00 * bytes
/ time_diff
;
442 pbi
->common
.framerate
= 160000000.00 / time_diff
;
449 #if CONFIG_RUNTIME_CPU_DETECT
450 if (cm
->rtcd
.flags
& HAS_NEON
)
453 vp8_pop_neon(dx_store_reg
);
456 pbi
->common
.error
.setjmp
= 0;
459 int vp8dx_get_raw_frame(VP8D_PTR ptr
, YV12_BUFFER_CONFIG
*sd
, INT64
*time_stamp
, INT64
*time_end_stamp
, vp8_ppflags_t
*flags
)
462 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
464 if (pbi
->ready_for_new_data
== 1)
467 /* ie no raw frame to show!!! */
468 if (pbi
->common
.show_frame
== 0)
471 pbi
->ready_for_new_data
= 1;
472 *time_stamp
= pbi
->last_time_stamp
;
475 sd
->clrtype
= pbi
->common
.clr_type
;
477 ret
= vp8_post_proc_frame(&pbi
->common
, sd
, flags
);
480 if (pbi
->common
.frame_to_show
)
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;
493 #endif /*!CONFIG_POSTPROC*/
494 vp8_clear_system_state();