| Index: source/libvpx/vp8/decoder/onyxd_if.c
|
| ===================================================================
|
| --- source/libvpx/vp8/decoder/onyxd_if.c (revision 96967)
|
| +++ source/libvpx/vp8/decoder/onyxd_if.c (working copy)
|
| @@ -24,18 +24,24 @@
|
| #include "vp8/common/threading.h"
|
| #include "decoderthreading.h"
|
| #include <stdio.h>
|
| +#include <assert.h>
|
|
|
| #include "vp8/common/quant_common.h"
|
| #include "vpx_scale/vpxscale.h"
|
| #include "vp8/common/systemdependent.h"
|
| #include "vpx_ports/vpx_timer.h"
|
| #include "detokenize.h"
|
| +#if CONFIG_ERROR_CONCEALMENT
|
| +#include "error_concealment.h"
|
| +#endif
|
| #if ARCH_ARM
|
| #include "vpx_ports/arm.h"
|
| #endif
|
|
|
| extern void vp8_init_loop_filter(VP8_COMMON *cm);
|
| extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
|
| +static int get_free_fb (VP8_COMMON *cm);
|
| +static void ref_cnt_fb (int *buf, int *idx, int new_idx);
|
|
|
|
|
| void vp8dx_initialize()
|
| @@ -76,7 +82,6 @@
|
| pbi->common.current_video_frame = 0;
|
| pbi->ready_for_new_data = 1;
|
|
|
| - pbi->CPUFreq = 0; /*vp8_get_processor_freq();*/
|
| #if CONFIG_MULTITHREAD
|
| pbi->max_threads = oxcf->max_threads;
|
| vp8_decoder_create_threads(pbi);
|
| @@ -87,16 +92,30 @@
|
| */
|
| vp8cx_init_de_quantizer(pbi);
|
|
|
| - {
|
| - VP8_COMMON *cm = &pbi->common;
|
| + vp8_loop_filter_init(&pbi->common);
|
|
|
| - vp8_init_loop_filter(cm);
|
| - cm->last_frame_type = KEY_FRAME;
|
| - cm->last_filter_type = cm->filter_type;
|
| - cm->last_sharpness_level = cm->sharpness_level;
|
| - }
|
| + pbi->common.error.setjmp = 0;
|
|
|
| - pbi->common.error.setjmp = 0;
|
| +#if CONFIG_ERROR_CONCEALMENT
|
| + pbi->ec_enabled = oxcf->error_concealment;
|
| +#else
|
| + pbi->ec_enabled = 0;
|
| +#endif
|
| + /* Error concealment is activated after a key frame has been
|
| + * decoded without errors when error concealment is enabled.
|
| + */
|
| + pbi->ec_active = 0;
|
| +
|
| + pbi->decoded_key_frame = 0;
|
| +
|
| + pbi->input_partition = oxcf->input_partition;
|
| +
|
| + /* Independent partitions is activated when a frame updates the
|
| + * token probability table to have equal probabilities over the
|
| + * PREV_COEF context.
|
| + */
|
| + pbi->independent_partitions = 0;
|
| +
|
| return (VP8D_PTR) pbi;
|
| }
|
|
|
| @@ -113,12 +132,16 @@
|
| vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows);
|
| vp8_decoder_remove_threads(pbi);
|
| #endif
|
| +#if CONFIG_ERROR_CONCEALMENT
|
| + vp8_de_alloc_overlap_lists(pbi);
|
| +#endif
|
| vp8_remove_common(&pbi->common);
|
| + vpx_free(pbi->mbc);
|
| vpx_free(pbi);
|
| }
|
|
|
|
|
| -int vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
|
| +vpx_codec_err_t vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
|
| {
|
| VP8D_COMP *pbi = (VP8D_COMP *) ptr;
|
| VP8_COMMON *cm = &pbi->common;
|
| @@ -130,39 +153,71 @@
|
| ref_fb_idx = cm->gld_fb_idx;
|
| else if (ref_frame_flag == VP8_ALT_FLAG)
|
| ref_fb_idx = cm->alt_fb_idx;
|
| + else{
|
| + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
|
| + "Invalid reference frame");
|
| + return pbi->common.error.error_code;
|
| + }
|
| +
|
| + if(cm->yv12_fb[ref_fb_idx].y_height != sd->y_height ||
|
| + cm->yv12_fb[ref_fb_idx].y_width != sd->y_width ||
|
| + cm->yv12_fb[ref_fb_idx].uv_height != sd->uv_height ||
|
| + cm->yv12_fb[ref_fb_idx].uv_width != sd->uv_width){
|
| + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
|
| + "Incorrect buffer dimensions");
|
| + }
|
| else
|
| - return -1;
|
| + vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd);
|
|
|
| - vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd);
|
| -
|
| - return 0;
|
| + return pbi->common.error.error_code;
|
| }
|
|
|
|
|
| -int vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
|
| +vpx_codec_err_t vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
|
| {
|
| VP8D_COMP *pbi = (VP8D_COMP *) ptr;
|
| VP8_COMMON *cm = &pbi->common;
|
| - int ref_fb_idx;
|
| + int *ref_fb_ptr = NULL;
|
| + int free_fb;
|
|
|
| if (ref_frame_flag == VP8_LAST_FLAG)
|
| - ref_fb_idx = cm->lst_fb_idx;
|
| + ref_fb_ptr = &cm->lst_fb_idx;
|
| else if (ref_frame_flag == VP8_GOLD_FLAG)
|
| - ref_fb_idx = cm->gld_fb_idx;
|
| + ref_fb_ptr = &cm->gld_fb_idx;
|
| else if (ref_frame_flag == VP8_ALT_FLAG)
|
| - ref_fb_idx = cm->alt_fb_idx;
|
| - else
|
| - return -1;
|
| + ref_fb_ptr = &cm->alt_fb_idx;
|
| + else{
|
| + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
|
| + "Invalid reference frame");
|
| + return pbi->common.error.error_code;
|
| + }
|
|
|
| - vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[ref_fb_idx]);
|
| + if(cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height ||
|
| + cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width ||
|
| + cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height ||
|
| + cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width){
|
| + vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
|
| + "Incorrect buffer dimensions");
|
| + }
|
| + else{
|
| + /* Find an empty frame buffer. */
|
| + free_fb = get_free_fb(cm);
|
| + /* Decrease fb_idx_ref_cnt since it will be increased again in
|
| + * ref_cnt_fb() below. */
|
| + cm->fb_idx_ref_cnt[free_fb]--;
|
|
|
| - return 0;
|
| + /* Manage the reference counters and copy image. */
|
| + ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
|
| + vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[*ref_fb_ptr]);
|
| + }
|
| +
|
| + return pbi->common.error.error_code;
|
| }
|
|
|
| /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
|
| #if HAVE_ARMV7
|
| -extern void vp8_push_neon(INT64 *store);
|
| -extern void vp8_pop_neon(INT64 *store);
|
| +extern void vp8_push_neon(int64_t *store);
|
| +extern void vp8_pop_neon(int64_t *store);
|
| #endif
|
|
|
| static int get_free_fb (VP8_COMMON *cm)
|
| @@ -172,6 +227,7 @@
|
| if (cm->fb_idx_ref_cnt[i] == 0)
|
| break;
|
|
|
| + assert(i < NUM_YV12_BUFFERS);
|
| cm->fb_idx_ref_cnt[i] = 1;
|
| return i;
|
| }
|
| @@ -244,15 +300,14 @@
|
| return err;
|
| }
|
|
|
| -int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsigned char *source, INT64 time_stamp)
|
| +int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsigned char *source, int64_t time_stamp)
|
| {
|
| #if HAVE_ARMV7
|
| - INT64 dx_store_reg[8];
|
| + int64_t dx_store_reg[8];
|
| #endif
|
| VP8D_COMP *pbi = (VP8D_COMP *) ptr;
|
| VP8_COMMON *cm = &pbi->common;
|
| int retcode = 0;
|
| - struct vpx_usec_timer timer;
|
|
|
| /*if(pbi->ready_for_new_data == 0)
|
| return -1;*/
|
| @@ -264,65 +319,100 @@
|
|
|
| pbi->common.error.error_code = VPX_CODEC_OK;
|
|
|
| - if (size == 0)
|
| + if (pbi->input_partition && !(source == NULL && size == 0))
|
| {
|
| - /* This is used to signal that we are missing frames.
|
| - * We do not know if the missing frame(s) was supposed to update
|
| - * any of the reference buffers, but we act conservative and
|
| - * mark only the last buffer as corrupted.
|
| - */
|
| - cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
|
| -
|
| - /* Signal that we have no frame to show. */
|
| - cm->show_frame = 0;
|
| -
|
| - /* Nothing more to do. */
|
| + /* Store a pointer to this partition and return. We haven't
|
| + * received the complete frame yet, so we will wait with decoding.
|
| + */
|
| + pbi->partitions[pbi->num_partitions] = source;
|
| + pbi->partition_sizes[pbi->num_partitions] = size;
|
| + pbi->source_sz += size;
|
| + pbi->num_partitions++;
|
| + if (pbi->num_partitions > (1<<pbi->common.multi_token_partition) + 1)
|
| + pbi->common.multi_token_partition++;
|
| + if (pbi->common.multi_token_partition > EIGHT_PARTITION)
|
| + {
|
| + pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
|
| + pbi->common.error.setjmp = 0;
|
| + return -1;
|
| + }
|
| return 0;
|
| }
|
| + else
|
| + {
|
| + if (!pbi->input_partition)
|
| + {
|
| + pbi->Source = source;
|
| + pbi->source_sz = size;
|
| + }
|
|
|
| + if (pbi->source_sz == 0)
|
| + {
|
| + /* This is used to signal that we are missing frames.
|
| + * We do not know if the missing frame(s) was supposed to update
|
| + * any of the reference buffers, but we act conservative and
|
| + * mark only the last buffer as corrupted.
|
| + */
|
| + cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
|
|
|
| + /* If error concealment is disabled we won't signal missing frames to
|
| + * the decoder.
|
| + */
|
| + if (!pbi->ec_active)
|
| + {
|
| + /* Signal that we have no frame to show. */
|
| + cm->show_frame = 0;
|
| +
|
| + pbi->num_partitions = 0;
|
| + if (pbi->input_partition)
|
| + pbi->common.multi_token_partition = 0;
|
| +
|
| + /* Nothing more to do. */
|
| + return 0;
|
| + }
|
| + }
|
| +
|
| #if HAVE_ARMV7
|
| #if CONFIG_RUNTIME_CPU_DETECT
|
| - if (cm->rtcd.flags & HAS_NEON)
|
| + if (cm->rtcd.flags & HAS_NEON)
|
| #endif
|
| - {
|
| - vp8_push_neon(dx_store_reg);
|
| - }
|
| + {
|
| + vp8_push_neon(dx_store_reg);
|
| + }
|
| #endif
|
|
|
| - cm->new_fb_idx = get_free_fb (cm);
|
| + cm->new_fb_idx = get_free_fb (cm);
|
|
|
| - if (setjmp(pbi->common.error.jmp))
|
| - {
|
| + if (setjmp(pbi->common.error.jmp))
|
| + {
|
| #if HAVE_ARMV7
|
| #if CONFIG_RUNTIME_CPU_DETECT
|
| - if (cm->rtcd.flags & HAS_NEON)
|
| + if (cm->rtcd.flags & HAS_NEON)
|
| #endif
|
| - {
|
| - vp8_pop_neon(dx_store_reg);
|
| - }
|
| + {
|
| + vp8_pop_neon(dx_store_reg);
|
| + }
|
| #endif
|
| - pbi->common.error.setjmp = 0;
|
| + pbi->common.error.setjmp = 0;
|
|
|
| - /* We do not know if the missing frame(s) was supposed to update
|
| - * any of the reference buffers, but we act conservative and
|
| - * mark only the last buffer as corrupted.
|
| - */
|
| - cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
|
| + pbi->num_partitions = 0;
|
| + if (pbi->input_partition)
|
| + pbi->common.multi_token_partition = 0;
|
|
|
| - if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
|
| - cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
|
| - return -1;
|
| - }
|
| + /* We do not know if the missing frame(s) was supposed to update
|
| + * any of the reference buffers, but we act conservative and
|
| + * mark only the last buffer as corrupted.
|
| + */
|
| + cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
|
|
|
| - pbi->common.error.setjmp = 1;
|
| + if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
|
| + cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
|
| + return -1;
|
| + }
|
|
|
| - vpx_usec_timer_start(&timer);
|
| + pbi->common.error.setjmp = 1;
|
| + }
|
|
|
| - /*cm->current_video_frame++;*/
|
| - pbi->Source = source;
|
| - pbi->source_sz = size;
|
| -
|
| retcode = vp8_decode_frame(pbi);
|
|
|
| if (retcode < 0)
|
| @@ -377,20 +467,10 @@
|
| return -1;
|
| }
|
|
|
| - if(pbi->common.filter_level)
|
| + if(cm->filter_level)
|
| {
|
| - struct vpx_usec_timer lpftimer;
|
| - vpx_usec_timer_start(&lpftimer);
|
| /* Apply the loop filter if appropriate. */
|
| -
|
| - vp8_loop_filter_frame(cm, &pbi->mb, cm->filter_level);
|
| -
|
| - vpx_usec_timer_mark(&lpftimer);
|
| - pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);
|
| -
|
| - cm->last_frame_type = cm->frame_type;
|
| - cm->last_filter_type = cm->filter_type;
|
| - cm->last_sharpness_level = cm->sharpness_level;
|
| + vp8_loop_filter_frame(cm, &pbi->mb);
|
| }
|
| vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
|
| }
|
| @@ -398,10 +478,27 @@
|
|
|
| vp8_clear_system_state();
|
|
|
| - vpx_usec_timer_mark(&timer);
|
| - pbi->decode_microseconds = vpx_usec_timer_elapsed(&timer);
|
| +#if CONFIG_ERROR_CONCEALMENT
|
| + /* swap the mode infos to storage for future error concealment */
|
| + if (pbi->ec_enabled && pbi->common.prev_mi)
|
| + {
|
| + const MODE_INFO* tmp = pbi->common.prev_mi;
|
| + int row, col;
|
| + pbi->common.prev_mi = pbi->common.mi;
|
| + pbi->common.mi = tmp;
|
|
|
| - pbi->time_decoding += pbi->decode_microseconds;
|
| + /* Propagate the segment_ids to the next frame */
|
| + for (row = 0; row < pbi->common.mb_rows; ++row)
|
| + {
|
| + for (col = 0; col < pbi->common.mb_cols; ++col)
|
| + {
|
| + const int i = row*pbi->common.mode_info_stride + col;
|
| + pbi->common.mi[i].mbmi.segment_id =
|
| + pbi->common.prev_mi[i].mbmi.segment_id;
|
| + }
|
| + }
|
| + }
|
| +#endif
|
|
|
| /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
|
|
|
| @@ -410,13 +507,17 @@
|
|
|
| pbi->ready_for_new_data = 0;
|
| pbi->last_time_stamp = time_stamp;
|
| + pbi->num_partitions = 0;
|
| + if (pbi->input_partition)
|
| + pbi->common.multi_token_partition = 0;
|
| + pbi->source_sz = 0;
|
|
|
| #if 0
|
| {
|
| int i;
|
| - INT64 earliest_time = pbi->dr[0].time_stamp;
|
| - INT64 latest_time = pbi->dr[0].time_stamp;
|
| - INT64 time_diff = 0;
|
| + int64_t earliest_time = pbi->dr[0].time_stamp;
|
| + int64_t latest_time = pbi->dr[0].time_stamp;
|
| + int64_t time_diff = 0;
|
| int bytes = 0;
|
|
|
| pbi->dr[pbi->common.current_video_frame&0xf].size = pbi->bc.pos + pbi->bc2.pos + 4;;
|
| @@ -456,7 +557,7 @@
|
| pbi->common.error.setjmp = 0;
|
| return retcode;
|
| }
|
| -int vp8dx_get_raw_frame(VP8D_PTR ptr, YV12_BUFFER_CONFIG *sd, INT64 *time_stamp, INT64 *time_end_stamp, vp8_ppflags_t *flags)
|
| +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)
|
| {
|
| int ret = -1;
|
| VP8D_COMP *pbi = (VP8D_COMP *) ptr;
|
|
|