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"
27 #include "vp8/common/quant_common.h"
28 #include "vpx_scale/vpxscale.h"
29 #include "vp8/common/systemdependent.h"
30 #include "vpx_ports/vpx_timer.h"
31 #include "detokenize.h"
33 #include "vpx_ports/arm.h"
36 extern void vp8_init_loop_filter(VP8_COMMON
*cm
);
37 extern void vp8cx_init_de_quantizer(VP8D_COMP
*pbi
);
38 static int get_free_fb(VP8_COMMON
*cm
);
39 static void ref_cnt_fb(int *buf
, int *idx
, int new_idx
);
42 void vp8_recon_write_yuv_frame(char *name
, YV12_BUFFER_CONFIG
*s
) {
43 FILE *yuv_file
= fopen((char *)name
, "ab");
44 unsigned char *src
= s
->y_buffer
;
48 fwrite(src
, s
->y_width
, 1, yuv_file
);
56 fwrite(src
, s
->uv_width
, 1, yuv_file
);
64 fwrite(src
, s
->uv_width
, 1, yuv_file
);
71 #define WRITE_RECON_BUFFER 0
72 #if WRITE_RECON_BUFFER
73 void write_dx_frame_to_file(YV12_BUFFER_CONFIG
*frame
, int this_frame
) {
80 sprintf(filename
, "dx\\y%04d.raw", this_frame
);
81 yframe
= fopen(filename
, "wb");
83 for (i
= 0; i
< frame
->y_height
; i
++)
84 fwrite(frame
->y_buffer
+ i
* frame
->y_stride
,
85 frame
->y_width
, 1, yframe
);
88 sprintf(filename
, "dx\\u%04d.raw", this_frame
);
89 yframe
= fopen(filename
, "wb");
91 for (i
= 0; i
< frame
->uv_height
; i
++)
92 fwrite(frame
->u_buffer
+ i
* frame
->uv_stride
,
93 frame
->uv_width
, 1, yframe
);
96 sprintf(filename
, "dx\\v%04d.raw", this_frame
);
97 yframe
= fopen(filename
, "wb");
99 for (i
= 0; i
< frame
->uv_height
; i
++)
100 fwrite(frame
->v_buffer
+ i
* frame
->uv_stride
,
101 frame
->uv_width
, 1, yframe
);
107 void vp8dx_initialize() {
108 static int init_done
= 0;
111 vp8_initialize_common();
112 vp8_init_quant_tables();
113 vp8_scale_machine_specific_config();
118 VP8D_PTR
vp8dx_create_decompressor(VP8D_CONFIG
*oxcf
) {
119 VP8D_COMP
*pbi
= vpx_memalign(32, sizeof(VP8D_COMP
));
124 vpx_memset(pbi
, 0, sizeof(VP8D_COMP
));
126 if (setjmp(pbi
->common
.error
.jmp
)) {
127 pbi
->common
.error
.setjmp
= 0;
128 vp8dx_remove_decompressor(pbi
);
132 pbi
->common
.error
.setjmp
= 1;
135 vp8_create_common(&pbi
->common
);
136 vp8_dmachine_specific_config(pbi
);
138 pbi
->common
.current_video_frame
= 0;
139 pbi
->ready_for_new_data
= 1;
141 /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
142 * unnecessary calling of vp8cx_init_de_quantizer() for every frame.
144 vp8cx_init_de_quantizer(pbi
);
146 vp8_loop_filter_init(&pbi
->common
);
148 pbi
->common
.error
.setjmp
= 0;
150 pbi
->decoded_key_frame
= 0;
152 pbi
->interleaved_decoding
= CONFIG_NEWBESTREFMV
|| CONFIG_SUPERBLOCKS
;
154 return (VP8D_PTR
) pbi
;
157 void vp8dx_remove_decompressor(VP8D_PTR ptr
) {
158 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
163 // Delete sementation map
164 if (pbi
->common
.last_frame_seg_map
!= 0)
165 vpx_free(pbi
->common
.last_frame_seg_map
);
167 vp8_remove_common(&pbi
->common
);
173 vpx_codec_err_t
vp8dx_get_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
) {
174 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
175 VP8_COMMON
*cm
= &pbi
->common
;
178 if (ref_frame_flag
== VP8_LAST_FLAG
)
179 ref_fb_idx
= cm
->lst_fb_idx
;
180 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
181 ref_fb_idx
= cm
->gld_fb_idx
;
182 else if (ref_frame_flag
== VP8_ALT_FLAG
)
183 ref_fb_idx
= cm
->alt_fb_idx
;
185 vpx_internal_error(&pbi
->common
.error
, VPX_CODEC_ERROR
,
186 "Invalid reference frame");
187 return pbi
->common
.error
.error_code
;
190 if (cm
->yv12_fb
[ref_fb_idx
].y_height
!= sd
->y_height
||
191 cm
->yv12_fb
[ref_fb_idx
].y_width
!= sd
->y_width
||
192 cm
->yv12_fb
[ref_fb_idx
].uv_height
!= sd
->uv_height
||
193 cm
->yv12_fb
[ref_fb_idx
].uv_width
!= sd
->uv_width
) {
194 vpx_internal_error(&pbi
->common
.error
, VPX_CODEC_ERROR
,
195 "Incorrect buffer dimensions");
197 vp8_yv12_copy_frame_ptr(&cm
->yv12_fb
[ref_fb_idx
], sd
);
199 return pbi
->common
.error
.error_code
;
203 vpx_codec_err_t
vp8dx_set_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
) {
204 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
205 VP8_COMMON
*cm
= &pbi
->common
;
206 int *ref_fb_ptr
= NULL
;
209 if (ref_frame_flag
== VP8_LAST_FLAG
)
210 ref_fb_ptr
= &cm
->lst_fb_idx
;
211 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
212 ref_fb_ptr
= &cm
->gld_fb_idx
;
213 else if (ref_frame_flag
== VP8_ALT_FLAG
)
214 ref_fb_ptr
= &cm
->alt_fb_idx
;
216 vpx_internal_error(&pbi
->common
.error
, VPX_CODEC_ERROR
,
217 "Invalid reference frame");
218 return pbi
->common
.error
.error_code
;
221 if (cm
->yv12_fb
[*ref_fb_ptr
].y_height
!= sd
->y_height
||
222 cm
->yv12_fb
[*ref_fb_ptr
].y_width
!= sd
->y_width
||
223 cm
->yv12_fb
[*ref_fb_ptr
].uv_height
!= sd
->uv_height
||
224 cm
->yv12_fb
[*ref_fb_ptr
].uv_width
!= sd
->uv_width
) {
225 vpx_internal_error(&pbi
->common
.error
, VPX_CODEC_ERROR
,
226 "Incorrect buffer dimensions");
228 /* Find an empty frame buffer. */
229 free_fb
= get_free_fb(cm
);
230 /* Decrease fb_idx_ref_cnt since it will be increased again in
231 * ref_cnt_fb() below. */
232 cm
->fb_idx_ref_cnt
[free_fb
]--;
234 /* Manage the reference counters and copy image. */
235 ref_cnt_fb(cm
->fb_idx_ref_cnt
, ref_fb_ptr
, free_fb
);
236 vp8_yv12_copy_frame_ptr(sd
, &cm
->yv12_fb
[*ref_fb_ptr
]);
239 return pbi
->common
.error
.error_code
;
242 /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
244 extern void vp8_push_neon(int64_t *store
);
245 extern void vp8_pop_neon(int64_t *store
);
248 static int get_free_fb(VP8_COMMON
*cm
) {
250 for (i
= 0; i
< NUM_YV12_BUFFERS
; i
++)
251 if (cm
->fb_idx_ref_cnt
[i
] == 0)
254 assert(i
< NUM_YV12_BUFFERS
);
255 cm
->fb_idx_ref_cnt
[i
] = 1;
259 static void ref_cnt_fb(int *buf
, int *idx
, int new_idx
) {
268 /* If any buffer copy / swapping is signalled it should be done here. */
269 static int swap_frame_buffers(VP8_COMMON
*cm
) {
272 /* The alternate reference frame or golden frame can be updated
273 * using the new, last, or golden/alt ref frame. If it
274 * is updated using the newly decoded frame it is a refresh.
275 * An update using the last or golden/alt ref frame is a copy.
277 if (cm
->copy_buffer_to_arf
) {
280 if (cm
->copy_buffer_to_arf
== 1)
281 new_fb
= cm
->lst_fb_idx
;
282 else if (cm
->copy_buffer_to_arf
== 2)
283 new_fb
= cm
->gld_fb_idx
;
287 ref_cnt_fb(cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, new_fb
);
290 if (cm
->copy_buffer_to_gf
) {
293 if (cm
->copy_buffer_to_gf
== 1)
294 new_fb
= cm
->lst_fb_idx
;
295 else if (cm
->copy_buffer_to_gf
== 2)
296 new_fb
= cm
->alt_fb_idx
;
300 ref_cnt_fb(cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, new_fb
);
303 if (cm
->refresh_golden_frame
)
304 ref_cnt_fb(cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, cm
->new_fb_idx
);
306 if (cm
->refresh_alt_ref_frame
)
307 ref_cnt_fb(cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, cm
->new_fb_idx
);
309 if (cm
->refresh_last_frame
) {
310 ref_cnt_fb(cm
->fb_idx_ref_cnt
, &cm
->lst_fb_idx
, cm
->new_fb_idx
);
312 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->lst_fb_idx
];
314 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->new_fb_idx
];
316 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
322 static void vp8_print_yuv_rec_mb(VP8_COMMON *cm, int mb_row, int mb_col)
324 YV12_BUFFER_CONFIG *s = cm->frame_to_show;
325 unsigned char *src = s->y_buffer;
328 printf("After loop filter\n");
331 printf("%3d ", src[(mb_row*16+i)*s->y_stride + mb_col*16+j]);
337 int vp8dx_receive_compressed_data(VP8D_PTR ptr
, unsigned long size
, const unsigned char *source
, int64_t time_stamp
) {
339 int64_t dx_store_reg
[8];
341 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
342 VP8_COMMON
*cm
= &pbi
->common
;
345 /*if(pbi->ready_for_new_data == 0)
352 pbi
->common
.error
.error_code
= VPX_CODEC_OK
;
354 pbi
->Source
= source
;
355 pbi
->source_sz
= size
;
357 if (pbi
->source_sz
== 0) {
358 /* This is used to signal that we are missing frames.
359 * We do not know if the missing frame(s) was supposed to update
360 * any of the reference buffers, but we act conservative and
361 * mark only the last buffer as corrupted.
363 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
367 #if CONFIG_RUNTIME_CPU_DETECT
368 if (cm
->rtcd
.flags
& HAS_NEON
)
371 vp8_push_neon(dx_store_reg
);
375 cm
->new_fb_idx
= get_free_fb(cm
);
377 if (setjmp(pbi
->common
.error
.jmp
)) {
379 #if CONFIG_RUNTIME_CPU_DETECT
380 if (cm
->rtcd
.flags
& HAS_NEON
)
383 vp8_pop_neon(dx_store_reg
);
386 pbi
->common
.error
.setjmp
= 0;
388 /* We do not know if the missing frame(s) was supposed to update
389 * any of the reference buffers, but we act conservative and
390 * mark only the last buffer as corrupted.
392 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
394 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
395 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
399 pbi
->common
.error
.setjmp
= 1;
401 retcode
= vp8_decode_frame(pbi
);
405 #if CONFIG_RUNTIME_CPU_DETECT
406 if (cm
->rtcd
.flags
& HAS_NEON
)
409 vp8_pop_neon(dx_store_reg
);
412 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
413 pbi
->common
.error
.setjmp
= 0;
414 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
415 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
420 if (swap_frame_buffers(cm
)) {
422 #if CONFIG_RUNTIME_CPU_DETECT
423 if (cm
->rtcd
.flags
& HAS_NEON
)
426 vp8_pop_neon(dx_store_reg
);
429 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
430 pbi
->common
.error
.setjmp
= 0;
434 #if WRITE_RECON_BUFFER
436 write_dx_frame_to_file(cm
->frame_to_show
,
437 cm
->current_video_frame
);
439 write_dx_frame_to_file(cm
->frame_to_show
,
440 cm
->current_video_frame
+ 1000);
443 if (cm
->filter_level
) {
444 /* Apply the loop filter if appropriate. */
445 vp8_loop_filter_frame(cm
, &pbi
->mb
);
447 vp8_yv12_extend_frame_borders_ptr(cm
->frame_to_show
);
452 vp8_recon_write_yuv_frame("recon.yuv", cm
->frame_to_show
);
455 vp8_clear_system_state();
457 if (cm
->show_frame
) {
458 vpx_memcpy(cm
->prev_mip
, cm
->mip
,
459 (cm
->mb_cols
+ 1) * (cm
->mb_rows
+ 1)* sizeof(MODE_INFO
));
461 vpx_memset(cm
->prev_mip
, 0,
462 (cm
->mb_cols
+ 1) * (cm
->mb_rows
+ 1)* sizeof(MODE_INFO
));
465 /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
468 cm
->current_video_frame
++;
470 pbi
->ready_for_new_data
= 0;
471 pbi
->last_time_stamp
= time_stamp
;
475 #if CONFIG_RUNTIME_CPU_DETECT
476 if (cm
->rtcd
.flags
& HAS_NEON
)
479 vp8_pop_neon(dx_store_reg
);
482 pbi
->common
.error
.setjmp
= 0;
485 int vp8dx_get_raw_frame(VP8D_PTR ptr
, YV12_BUFFER_CONFIG
*sd
, int64_t *time_stamp
, int64_t *time_end_stamp
, vp8_ppflags_t
*flags
) {
487 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
489 if (pbi
->ready_for_new_data
== 1)
492 /* ie no raw frame to show!!! */
493 if (pbi
->common
.show_frame
== 0)
496 pbi
->ready_for_new_data
= 1;
497 *time_stamp
= pbi
->last_time_stamp
;
500 sd
->clrtype
= pbi
->common
.clr_type
;
502 ret
= vp8_post_proc_frame(&pbi
->common
, sd
, flags
);
505 if (pbi
->common
.frame_to_show
) {
506 *sd
= *pbi
->common
.frame_to_show
;
507 sd
->y_width
= pbi
->common
.Width
;
508 sd
->y_height
= pbi
->common
.Height
;
509 sd
->uv_height
= pbi
->common
.Height
/ 2;
515 #endif /*!CONFIG_POSTPROC*/
516 vp8_clear_system_state();