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"
29 #include "vp8/common/quant_common.h"
30 #include "vpx_scale/vpxscale.h"
31 #include "vp8/common/systemdependent.h"
32 #include "vpx_ports/vpx_timer.h"
33 #include "detokenize.h"
34 #if CONFIG_ERROR_CONCEALMENT
35 #include "error_concealment.h"
38 #include "vpx_ports/arm.h"
41 extern void vp8_init_loop_filter(VP8_COMMON
*cm
);
42 extern void vp8cx_init_de_quantizer(VP8D_COMP
*pbi
);
43 static int get_free_fb (VP8_COMMON
*cm
);
44 static void ref_cnt_fb (int *buf
, int *idx
, int new_idx
);
47 void vp8dx_initialize()
49 static int init_done
= 0;
53 vp8_initialize_common();
54 vp8_scale_machine_specific_config();
60 VP8D_PTR
vp8dx_create_decompressor(VP8D_CONFIG
*oxcf
)
62 VP8D_COMP
*pbi
= vpx_memalign(32, sizeof(VP8D_COMP
));
67 vpx_memset(pbi
, 0, sizeof(VP8D_COMP
));
69 if (setjmp(pbi
->common
.error
.jmp
))
71 pbi
->common
.error
.setjmp
= 0;
72 vp8dx_remove_decompressor(pbi
);
76 pbi
->common
.error
.setjmp
= 1;
79 vp8_create_common(&pbi
->common
);
80 vp8_dmachine_specific_config(pbi
);
82 pbi
->common
.current_video_frame
= 0;
83 pbi
->ready_for_new_data
= 1;
85 #if CONFIG_MULTITHREAD
86 pbi
->max_threads
= oxcf
->max_threads
;
87 vp8_decoder_create_threads(pbi
);
90 /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
91 * unnecessary calling of vp8cx_init_de_quantizer() for every frame.
93 vp8cx_init_de_quantizer(pbi
);
96 VP8_COMMON
*cm
= &pbi
->common
;
98 vp8_init_loop_filter(cm
);
99 cm
->last_frame_type
= KEY_FRAME
;
100 cm
->last_filter_type
= cm
->filter_type
;
101 cm
->last_sharpness_level
= cm
->sharpness_level
;
104 pbi
->common
.error
.setjmp
= 0;
106 #if CONFIG_ERROR_CONCEALMENT
107 pbi
->ec_enabled
= oxcf
->error_concealment
;
112 pbi
->input_partition
= oxcf
->input_partition
;
114 return (VP8D_PTR
) pbi
;
118 void vp8dx_remove_decompressor(VP8D_PTR ptr
)
120 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
125 #if CONFIG_MULTITHREAD
126 if (pbi
->b_multithreaded_rd
)
127 vp8mt_de_alloc_temp_buffers(pbi
, pbi
->common
.mb_rows
);
128 vp8_decoder_remove_threads(pbi
);
130 #if CONFIG_ERROR_CONCEALMENT
131 vp8_de_alloc_overlap_lists(pbi
);
133 vp8_remove_common(&pbi
->common
);
139 vpx_codec_err_t
vp8dx_get_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
141 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
142 VP8_COMMON
*cm
= &pbi
->common
;
145 if (ref_frame_flag
== VP8_LAST_FLAG
)
146 ref_fb_idx
= cm
->lst_fb_idx
;
147 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
148 ref_fb_idx
= cm
->gld_fb_idx
;
149 else if (ref_frame_flag
== VP8_ALT_FLAG
)
150 ref_fb_idx
= cm
->alt_fb_idx
;
152 vpx_internal_error(&pbi
->common
.error
, VPX_CODEC_ERROR
,
153 "Invalid reference frame");
154 return pbi
->common
.error
.error_code
;
157 if(cm
->yv12_fb
[ref_fb_idx
].y_height
!= sd
->y_height
||
158 cm
->yv12_fb
[ref_fb_idx
].y_width
!= sd
->y_width
||
159 cm
->yv12_fb
[ref_fb_idx
].uv_height
!= sd
->uv_height
||
160 cm
->yv12_fb
[ref_fb_idx
].uv_width
!= sd
->uv_width
){
161 vpx_internal_error(&pbi
->common
.error
, VPX_CODEC_ERROR
,
162 "Incorrect buffer dimensions");
165 vp8_yv12_copy_frame_ptr(&cm
->yv12_fb
[ref_fb_idx
], sd
);
167 return pbi
->common
.error
.error_code
;
171 vpx_codec_err_t
vp8dx_set_reference(VP8D_PTR ptr
, VP8_REFFRAME ref_frame_flag
, YV12_BUFFER_CONFIG
*sd
)
173 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
174 VP8_COMMON
*cm
= &pbi
->common
;
175 int *ref_fb_ptr
= NULL
;
178 if (ref_frame_flag
== VP8_LAST_FLAG
)
179 ref_fb_ptr
= &cm
->lst_fb_idx
;
180 else if (ref_frame_flag
== VP8_GOLD_FLAG
)
181 ref_fb_ptr
= &cm
->gld_fb_idx
;
182 else if (ref_frame_flag
== VP8_ALT_FLAG
)
183 ref_fb_ptr
= &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_ptr
].y_height
!= sd
->y_height
||
191 cm
->yv12_fb
[*ref_fb_ptr
].y_width
!= sd
->y_width
||
192 cm
->yv12_fb
[*ref_fb_ptr
].uv_height
!= sd
->uv_height
||
193 cm
->yv12_fb
[*ref_fb_ptr
].uv_width
!= sd
->uv_width
){
194 vpx_internal_error(&pbi
->common
.error
, VPX_CODEC_ERROR
,
195 "Incorrect buffer dimensions");
198 /* Find an empty frame buffer. */
199 free_fb
= get_free_fb(cm
);
200 /* Decrease fb_idx_ref_cnt since it will be increased again in
201 * ref_cnt_fb() below. */
202 cm
->fb_idx_ref_cnt
[free_fb
]--;
204 /* Manage the reference counters and copy image. */
205 ref_cnt_fb (cm
->fb_idx_ref_cnt
, ref_fb_ptr
, free_fb
);
206 vp8_yv12_copy_frame_ptr(sd
, &cm
->yv12_fb
[*ref_fb_ptr
]);
209 return pbi
->common
.error
.error_code
;
212 /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
214 extern void vp8_push_neon(INT64
*store
);
215 extern void vp8_pop_neon(INT64
*store
);
218 static int get_free_fb (VP8_COMMON
*cm
)
221 for (i
= 0; i
< NUM_YV12_BUFFERS
; i
++)
222 if (cm
->fb_idx_ref_cnt
[i
] == 0)
225 assert(i
< NUM_YV12_BUFFERS
);
226 cm
->fb_idx_ref_cnt
[i
] = 1;
230 static void ref_cnt_fb (int *buf
, int *idx
, int new_idx
)
240 /* If any buffer copy / swapping is signalled it should be done here. */
241 static int swap_frame_buffers (VP8_COMMON
*cm
)
245 /* The alternate reference frame or golden frame can be updated
246 * using the new, last, or golden/alt ref frame. If it
247 * is updated using the newly decoded frame it is a refresh.
248 * An update using the last or golden/alt ref frame is a copy.
250 if (cm
->copy_buffer_to_arf
)
254 if (cm
->copy_buffer_to_arf
== 1)
255 new_fb
= cm
->lst_fb_idx
;
256 else if (cm
->copy_buffer_to_arf
== 2)
257 new_fb
= cm
->gld_fb_idx
;
261 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, new_fb
);
264 if (cm
->copy_buffer_to_gf
)
268 if (cm
->copy_buffer_to_gf
== 1)
269 new_fb
= cm
->lst_fb_idx
;
270 else if (cm
->copy_buffer_to_gf
== 2)
271 new_fb
= cm
->alt_fb_idx
;
275 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, new_fb
);
278 if (cm
->refresh_golden_frame
)
279 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->gld_fb_idx
, cm
->new_fb_idx
);
281 if (cm
->refresh_alt_ref_frame
)
282 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->alt_fb_idx
, cm
->new_fb_idx
);
284 if (cm
->refresh_last_frame
)
286 ref_cnt_fb (cm
->fb_idx_ref_cnt
, &cm
->lst_fb_idx
, cm
->new_fb_idx
);
288 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->lst_fb_idx
];
291 cm
->frame_to_show
= &cm
->yv12_fb
[cm
->new_fb_idx
];
293 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
298 int vp8dx_receive_compressed_data(VP8D_PTR ptr
, unsigned long size
, const unsigned char *source
, INT64 time_stamp
)
301 INT64 dx_store_reg
[8];
303 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
304 VP8_COMMON
*cm
= &pbi
->common
;
307 /*if(pbi->ready_for_new_data == 0)
315 pbi
->common
.error
.error_code
= VPX_CODEC_OK
;
317 if (pbi
->input_partition
&& !(source
== NULL
&& size
== 0))
319 /* Store a pointer to this partition and return. We haven't
320 * received the complete frame yet, so we will wait with decoding.
322 pbi
->partitions
[pbi
->num_partitions
] = source
;
323 pbi
->partition_sizes
[pbi
->num_partitions
] = size
;
324 pbi
->source_sz
+= size
;
325 pbi
->num_partitions
++;
326 if (pbi
->num_partitions
> (1<<pbi
->common
.multi_token_partition
) + 1)
327 pbi
->common
.multi_token_partition
++;
328 if (pbi
->common
.multi_token_partition
> EIGHT_PARTITION
)
330 pbi
->common
.error
.error_code
= VPX_CODEC_UNSUP_BITSTREAM
;
331 pbi
->common
.error
.setjmp
= 0;
338 if (!pbi
->input_partition
)
340 pbi
->Source
= source
;
341 pbi
->source_sz
= size
;
344 if (pbi
->source_sz
== 0)
346 /* This is used to signal that we are missing frames.
347 * We do not know if the missing frame(s) was supposed to update
348 * any of the reference buffers, but we act conservative and
349 * mark only the last buffer as corrupted.
351 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
353 /* If error concealment is disabled we won't signal missing frames to
356 if (!pbi
->ec_enabled
)
358 /* Signal that we have no frame to show. */
361 /* Nothing more to do. */
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
))
380 #if CONFIG_RUNTIME_CPU_DETECT
381 if (cm
->rtcd
.flags
& HAS_NEON
)
384 vp8_pop_neon(dx_store_reg
);
387 pbi
->common
.error
.setjmp
= 0;
389 /* We do not know if the missing frame(s) was supposed to update
390 * any of the reference buffers, but we act conservative and
391 * mark only the last buffer as corrupted.
393 cm
->yv12_fb
[cm
->lst_fb_idx
].corrupted
= 1;
395 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
396 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
400 pbi
->common
.error
.setjmp
= 1;
403 retcode
= vp8_decode_frame(pbi
);
408 #if CONFIG_RUNTIME_CPU_DETECT
409 if (cm
->rtcd
.flags
& HAS_NEON
)
412 vp8_pop_neon(dx_store_reg
);
415 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
416 pbi
->common
.error
.setjmp
= 0;
417 if (cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
] > 0)
418 cm
->fb_idx_ref_cnt
[cm
->new_fb_idx
]--;
422 #if CONFIG_MULTITHREAD
423 if (pbi
->b_multithreaded_rd
&& cm
->multi_token_partition
!= ONE_PARTITION
)
425 if (swap_frame_buffers (cm
))
428 #if CONFIG_RUNTIME_CPU_DETECT
429 if (cm
->rtcd
.flags
& HAS_NEON
)
432 vp8_pop_neon(dx_store_reg
);
435 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
436 pbi
->common
.error
.setjmp
= 0;
442 if (swap_frame_buffers (cm
))
445 #if CONFIG_RUNTIME_CPU_DETECT
446 if (cm
->rtcd
.flags
& HAS_NEON
)
449 vp8_pop_neon(dx_store_reg
);
452 pbi
->common
.error
.error_code
= VPX_CODEC_ERROR
;
453 pbi
->common
.error
.setjmp
= 0;
457 if(pbi
->common
.filter_level
)
459 /* Apply the loop filter if appropriate. */
460 vp8_loop_filter_frame(cm
, &pbi
->mb
, cm
->filter_level
);
462 cm
->last_frame_type
= cm
->frame_type
;
463 cm
->last_filter_type
= cm
->filter_type
;
464 cm
->last_sharpness_level
= cm
->sharpness_level
;
466 vp8_yv12_extend_frame_borders_ptr(cm
->frame_to_show
);
470 vp8_clear_system_state();
472 #if CONFIG_ERROR_CONCEALMENT
473 /* swap the mode infos to storage for future error concealment */
474 if (pbi
->ec_enabled
&& pbi
->common
.prev_mi
)
476 const MODE_INFO
* tmp
= pbi
->common
.prev_mi
;
478 pbi
->common
.prev_mi
= pbi
->common
.mi
;
479 pbi
->common
.mi
= tmp
;
481 /* Propagate the segment_ids to the next frame */
482 for (row
= 0; row
< pbi
->common
.mb_rows
; ++row
)
484 for (col
= 0; col
< pbi
->common
.mb_cols
; ++col
)
486 const int i
= row
*pbi
->common
.mode_info_stride
+ col
;
487 pbi
->common
.mi
[i
].mbmi
.segment_id
=
488 pbi
->common
.prev_mi
[i
].mbmi
.segment_id
;
494 /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
497 cm
->current_video_frame
++;
499 pbi
->ready_for_new_data
= 0;
500 pbi
->last_time_stamp
= time_stamp
;
501 pbi
->num_partitions
= 0;
502 if (pbi
->input_partition
)
503 pbi
->common
.multi_token_partition
= 0;
509 INT64 earliest_time
= pbi
->dr
[0].time_stamp
;
510 INT64 latest_time
= pbi
->dr
[0].time_stamp
;
514 pbi
->dr
[pbi
->common
.current_video_frame
&0xf].size
= pbi
->bc
.pos
+ pbi
->bc2
.pos
+ 4;;
515 pbi
->dr
[pbi
->common
.current_video_frame
&0xf].time_stamp
= time_stamp
;
517 for (i
= 0; i
< 16; i
++)
520 bytes
+= pbi
->dr
[i
].size
;
522 if (pbi
->dr
[i
].time_stamp
< earliest_time
)
523 earliest_time
= pbi
->dr
[i
].time_stamp
;
525 if (pbi
->dr
[i
].time_stamp
> latest_time
)
526 latest_time
= pbi
->dr
[i
].time_stamp
;
529 time_diff
= latest_time
- earliest_time
;
533 pbi
->common
.bitrate
= 80000.00 * bytes
/ time_diff
;
534 pbi
->common
.framerate
= 160000000.00 / time_diff
;
541 #if CONFIG_RUNTIME_CPU_DETECT
542 if (cm
->rtcd
.flags
& HAS_NEON
)
545 vp8_pop_neon(dx_store_reg
);
548 pbi
->common
.error
.setjmp
= 0;
551 int vp8dx_get_raw_frame(VP8D_PTR ptr
, YV12_BUFFER_CONFIG
*sd
, INT64
*time_stamp
, INT64
*time_end_stamp
, vp8_ppflags_t
*flags
)
554 VP8D_COMP
*pbi
= (VP8D_COMP
*) ptr
;
556 if (pbi
->ready_for_new_data
== 1)
559 /* ie no raw frame to show!!! */
560 if (pbi
->common
.show_frame
== 0)
563 pbi
->ready_for_new_data
= 1;
564 *time_stamp
= pbi
->last_time_stamp
;
567 sd
->clrtype
= pbi
->common
.clr_type
;
569 ret
= vp8_post_proc_frame(&pbi
->common
, sd
, flags
);
572 if (pbi
->common
.frame_to_show
)
574 *sd
= *pbi
->common
.frame_to_show
;
575 sd
->y_width
= pbi
->common
.Width
;
576 sd
->y_height
= pbi
->common
.Height
;
577 sd
->uv_height
= pbi
->common
.Height
/ 2;
585 #endif /*!CONFIG_POSTPROC*/
586 vp8_clear_system_state();