Added a first simple version of error-concealment
Added a first very simple version of error-concealment which simply repeats the last decoded motion vector for corrupt MBs. Change-Id: Ia83e111649afe11870c3c66065977bd0610c4fa1
This commit is contained in:
@@ -251,6 +251,7 @@ void vp8_mb_mode_mv_init(VP8D_COMP *pbi)
|
||||
vp8_reader *const bc = & pbi->bc;
|
||||
MV_CONTEXT *const mvc = pbi->common.fc.mvc;
|
||||
|
||||
pbi->mvs_corrupt_from_mb = -1;
|
||||
pbi->prob_skip_false = 0;
|
||||
if (pbi->common.mb_no_coeff_skip)
|
||||
pbi->prob_skip_false = (vp8_prob)vp8_read_literal(bc, 8);
|
||||
@@ -543,12 +544,18 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
|
||||
|
||||
while (++mb_col < pbi->common.mb_cols)
|
||||
{
|
||||
int mb_num = mb_row * pbi->common.mb_cols + mb_col;
|
||||
/*vp8_read_mb_modes_mv(pbi, xd->mode_info_context, &xd->mode_info_context->mbmi, mb_row, mb_col);*/
|
||||
if(pbi->common.frame_type == KEY_FRAME)
|
||||
vp8_kfread_modes(pbi, mi, mb_row, mb_col);
|
||||
else
|
||||
vp8_read_mb_modes_mv(pbi, mi, &mi->mbmi, mb_row, mb_col);
|
||||
|
||||
/* look for corruption */
|
||||
if (vp8dx_bool_error(&pbi->bc) && mb_num < pbi->mvs_corrupt_from_mb)
|
||||
pbi->mvs_corrupt_from_mb = mb_num;
|
||||
|
||||
|
||||
mi++; /* next macroblock */
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "decodemv.h"
|
||||
#include "extend.h"
|
||||
#include "error_concealment.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#include "idct.h"
|
||||
#include "dequantize.h"
|
||||
@@ -176,7 +177,7 @@ void clamp_mvs(MACROBLOCKD *xd)
|
||||
|
||||
}
|
||||
|
||||
void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd)
|
||||
void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, unsigned int mb_idx)
|
||||
{
|
||||
int eobtotal = 0;
|
||||
int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
|
||||
@@ -225,6 +226,14 @@ void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd)
|
||||
vp8_build_inter_predictors_mb(xd);
|
||||
}
|
||||
|
||||
/* TODO(holmer): change when we have MB level error tracking */
|
||||
if (xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME &&
|
||||
(xd->corrupted || mb_idx >= pbi->mvs_corrupt_from_mb))
|
||||
{
|
||||
vp8_conceal_corrupt_block(xd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* dequantization and idct */
|
||||
if (xd->mode_info_context->mbmi.mode != B_PRED && xd->mode_info_context->mbmi.mode != SPLITMV)
|
||||
{
|
||||
@@ -395,7 +404,7 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
|
||||
else
|
||||
pbi->debugoutput =0;
|
||||
*/
|
||||
vp8_decode_macroblock(pbi, xd);
|
||||
vp8_decode_macroblock(pbi, xd, mb_row * pc->mb_cols + mb_col);
|
||||
|
||||
/* check if the boolean decoder has suffered an error */
|
||||
xd->corrupted |= vp8dx_bool_error(xd->current_bc);
|
||||
@@ -469,8 +478,8 @@ static void setup_token_decoder(VP8D_COMP *pbi,
|
||||
partition_size = user_data_end - partition;
|
||||
}
|
||||
|
||||
if (partition + partition_size > user_data_end
|
||||
|| partition + partition_size < partition)
|
||||
if (!pbi->ec_enabled && (partition + partition_size > user_data_end
|
||||
|| partition + partition_size < partition))
|
||||
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
||||
"Truncated packet or corrupt partition "
|
||||
"%d length", i + 1);
|
||||
@@ -584,8 +593,25 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
|
||||
|
||||
if (data_end - data < 3)
|
||||
{
|
||||
if (pbi->ec_enabled)
|
||||
{
|
||||
/* Declare the missing frame as an inter frame since it will
|
||||
be handled as an inter frame when we have estimated its
|
||||
motion vectors. */
|
||||
pc->frame_type = INTER_FRAME;
|
||||
pc->version = 0;
|
||||
pc->show_frame = 1;
|
||||
first_partition_length_in_bytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
||||
"Truncated packet");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pc->frame_type = (FRAME_TYPE)(data[0] & 1);
|
||||
pc->version = (data[0] >> 1) & 7;
|
||||
pc->show_frame = (data[0] >> 4) & 1;
|
||||
@@ -593,8 +619,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
(data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
|
||||
data += 3;
|
||||
|
||||
if (data + first_partition_length_in_bytes > data_end
|
||||
|| data + first_partition_length_in_bytes < data)
|
||||
if (!pbi->ec_enabled && (data + first_partition_length_in_bytes > data_end
|
||||
|| data + first_partition_length_in_bytes < data))
|
||||
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
||||
"Truncated packet or corrupt partition 0 length");
|
||||
vp8_setup_version(pc);
|
||||
@@ -605,7 +631,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
const int Height = pc->Height;
|
||||
|
||||
/* vet via sync code */
|
||||
if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
|
||||
if (!pbi->ec_enabled &&
|
||||
(data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a))
|
||||
vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
|
||||
"Invalid frame sync code");
|
||||
|
||||
@@ -643,6 +670,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pc->Width == 0 || pc->Height == 0)
|
||||
{
|
||||
@@ -862,6 +890,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
|
||||
vp8_decode_mode_mvs(pbi);
|
||||
|
||||
if (pbi->ec_enabled && pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
|
||||
{
|
||||
vp8_estimate_missing_mvs(pbi);
|
||||
}
|
||||
|
||||
vpx_memset(pc->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) * pc->mb_cols);
|
||||
|
||||
vpx_memcpy(&xd->block[0].bmi, &xd->mode_info_context->bmi[0], sizeof(B_MODE_INFO));
|
||||
|
72
vp8/decoder/error_concealment.c
Normal file
72
vp8/decoder/error_concealment.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "error_concealment.h"
|
||||
#include "onyxd_int.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
|
||||
void vp8_estimate_missing_mvs(VP8D_COMP *pbi)
|
||||
{
|
||||
VP8_COMMON *const pc = &pbi->common;
|
||||
unsigned int first_corrupt = pbi->mvs_corrupt_from_mb;
|
||||
const unsigned int num_mbs = pc->mb_rows * pc->mb_cols;
|
||||
if (first_corrupt < num_mbs)
|
||||
{
|
||||
MODE_INFO *mi = pc->mi;
|
||||
MODE_INFO *correct_mi;
|
||||
const int num_corrupt = num_mbs - first_corrupt;
|
||||
int i;
|
||||
int mb_row, mb_col;
|
||||
if (first_corrupt == 0)
|
||||
{
|
||||
/* if the first MB is corrupt we just copy from it
|
||||
the previous frame */
|
||||
mi[0].mbmi.mv.as_int = 0;
|
||||
mi[0].mbmi.mode = ZEROMV;
|
||||
mi[0].mbmi.uv_mode = ZEROMV;
|
||||
mi[0].mbmi.ref_frame = LAST_FRAME;
|
||||
first_corrupt = 1;
|
||||
correct_mi = mi + 1;
|
||||
}
|
||||
for (mb_row = 0; mb_row < pc->mb_rows; ++mb_row)
|
||||
{
|
||||
for (mb_col = 0; mb_col < pc->mb_cols; ++mb_col)
|
||||
{
|
||||
int mb_idx = mb_row * pc->mb_cols + mb_col;
|
||||
if (mb_idx >= first_corrupt)
|
||||
{
|
||||
*mi = *correct_mi;
|
||||
}
|
||||
else if (mb_idx == first_corrupt - 1)
|
||||
{
|
||||
correct_mi = mi;
|
||||
}
|
||||
++mi;
|
||||
}
|
||||
++mi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vp8_conceal_corrupt_block(MACROBLOCKD *xd)
|
||||
{
|
||||
/* this macroblock has corrupt residual, use the motion compensated
|
||||
image for concealment */
|
||||
int i;
|
||||
for (i=0; i < 16; i++)
|
||||
vpx_memcpy(xd->dst.y_buffer + i*xd->dst.y_stride,
|
||||
xd->predictor + i*16, 16);
|
||||
for (i=0; i < 8; i++)
|
||||
vpx_memcpy(xd->dst.u_buffer + i*xd->dst.uv_stride,
|
||||
xd->predictor + 256 + i*8, 8);
|
||||
for (i=0; i < 8; i++)
|
||||
vpx_memcpy(xd->dst.v_buffer + i*xd->dst.uv_stride,
|
||||
xd->predictor + 320 + i*8, 8);
|
||||
}
|
20
vp8/decoder/error_concealment.h
Normal file
20
vp8/decoder/error_concealment.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ERROR_CONCEALMENT_H
|
||||
#define ERROR_CONCEALMENT_H
|
||||
|
||||
#include "onyxd_int.h"
|
||||
|
||||
void vp8_estimate_missing_mvs(VP8D_COMP *);
|
||||
void vp8_conceal_corrupt_block(MACROBLOCKD *);
|
||||
|
||||
#endif
|
@@ -319,6 +319,8 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
|
||||
int retcode = 0;
|
||||
struct vpx_usec_timer timer;
|
||||
|
||||
pbi->ec_enabled = 1;
|
||||
|
||||
/*if(pbi->ready_for_new_data == 0)
|
||||
return -1;*/
|
||||
|
||||
@@ -338,12 +340,15 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
|
||||
*/
|
||||
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
|
||||
|
||||
if (!pbi->ec_enabled)
|
||||
{
|
||||
/* Signal that we have no frame to show. */
|
||||
cm->show_frame = 0;
|
||||
|
||||
/* Nothing more to do. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_ARMV7
|
||||
|
@@ -134,6 +134,9 @@ typedef struct VP8Decompressor
|
||||
vp8_prob prob_gf;
|
||||
vp8_prob prob_skip_false;
|
||||
|
||||
unsigned int mvs_corrupt_from_mb;
|
||||
int ec_enabled;
|
||||
|
||||
} VP8D_COMP;
|
||||
|
||||
int vp8_decode_frame(VP8D_COMP *cpi);
|
||||
|
@@ -56,12 +56,14 @@ VP8_DX_SRCS-yes += decoder/decodemv.c
|
||||
VP8_DX_SRCS-yes += decoder/decodframe.c
|
||||
VP8_DX_SRCS-yes += decoder/dequantize.c
|
||||
VP8_DX_SRCS-yes += decoder/detokenize.c
|
||||
VP8_DX_SRCS-yes += decoder/error_concealment.c
|
||||
VP8_DX_SRCS-yes += decoder/generic/dsystemdependent.c
|
||||
VP8_DX_SRCS-yes += decoder/dboolhuff.h
|
||||
VP8_DX_SRCS-yes += decoder/decodemv.h
|
||||
VP8_DX_SRCS-yes += decoder/decoderthreading.h
|
||||
VP8_DX_SRCS-yes += decoder/dequantize.h
|
||||
VP8_DX_SRCS-yes += decoder/detokenize.h
|
||||
VP8_DX_SRCS-yes += decoder/error_concealment.h
|
||||
VP8_DX_SRCS-yes += decoder/onyxd_int.h
|
||||
VP8_DX_SRCS-yes += decoder/treereader.h
|
||||
VP8_DX_SRCS-yes += decoder/onyxd_if.c
|
||||
|
Reference in New Issue
Block a user