1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

vc1: make P-frame deblock filter bit-exact.

This commit is contained in:
Ronald S. Bultje 2011-03-21 21:26:26 -04:00
parent 77e41e047d
commit c47d383502
3 changed files with 217 additions and 105 deletions

View File

@ -236,7 +236,7 @@ typedef struct VC1Context{
//@} //@}
int ttfrm; ///< Transform type info present at frame level int ttfrm; ///< Transform type info present at frame level
uint8_t ttmbf; ///< Transform type flag uint8_t ttmbf; ///< Transform type flag
uint8_t ttblk4x4; ///< Value of ttblk which indicates a 4x4 transform int *ttblk_base, *ttblk; ///< Transform type at the block level
int codingset; ///< index of current table set from 11.8 to use for luma block decoding int codingset; ///< index of current table set from 11.8 to use for luma block decoding
int codingset2; ///< index of current table set from 11.8 to use for chroma block decoding int codingset2; ///< index of current table set from 11.8 to use for chroma block decoding
int pqindex; ///< raw pqindex used in coding set selection int pqindex; ///< raw pqindex used in coding set selection
@ -311,6 +311,8 @@ typedef struct VC1Context{
int x8_type; int x8_type;
uint32_t *cbp_base, *cbp; uint32_t *cbp_base, *cbp;
uint8_t *is_intra_base, *is_intra;
int16_t (*luma_mv_base)[2], (*luma_mv)[2];
uint8_t bfraction_lut_index;///< Index for BFRACTION value (see Table 40, reproduced into ff_vc1_bfraction_lut[]) uint8_t bfraction_lut_index;///< Index for BFRACTION value (see Table 40, reproduced into ff_vc1_bfraction_lut[])
uint8_t broken_link; ///< Broken link flag (BROKEN_LINK syntax element) uint8_t broken_link; ///< Broken link flag (BROKEN_LINK syntax element)
uint8_t closed_entry; ///< Closed entry point flag (CLOSED_ENTRY syntax element) uint8_t closed_entry; ///< Closed entry point flag (CLOSED_ENTRY syntax element)

View File

@ -209,6 +209,8 @@ static void vc1_mc_1mv(VC1Context *v, int dir)
} }
uvmx = (mx + ((mx & 3) == 3)) >> 1; uvmx = (mx + ((mx & 3) == 3)) >> 1;
uvmy = (my + ((my & 3) == 3)) >> 1; uvmy = (my + ((my & 3) == 3)) >> 1;
v->luma_mv[s->mb_x][0] = uvmx;
v->luma_mv[s->mb_x][1] = uvmy;
if(v->fastuvmc) { if(v->fastuvmc) {
uvmx = uvmx + ((uvmx<0)?(uvmx&1):-(uvmx&1)); uvmx = uvmx + ((uvmx<0)?(uvmx&1):-(uvmx&1));
uvmy = uvmy + ((uvmy<0)?(uvmy&1):-(uvmy&1)); uvmy = uvmy + ((uvmy<0)?(uvmy&1):-(uvmy&1));
@ -477,6 +479,7 @@ static void vc1_mc_4mv_chroma(VC1Context *v)
} else { } else {
s->current_picture.motion_val[1][s->block_index[0]][0] = 0; s->current_picture.motion_val[1][s->block_index[0]][0] = 0;
s->current_picture.motion_val[1][s->block_index[0]][1] = 0; s->current_picture.motion_val[1][s->block_index[0]][1] = 0;
v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;
return; //no need to do MC for inter blocks return; //no need to do MC for inter blocks
} }
@ -484,6 +487,8 @@ static void vc1_mc_4mv_chroma(VC1Context *v)
s->current_picture.motion_val[1][s->block_index[0]][1] = ty; s->current_picture.motion_val[1][s->block_index[0]][1] = ty;
uvmx = (tx + ((tx&3) == 3)) >> 1; uvmx = (tx + ((tx&3) == 3)) >> 1;
uvmy = (ty + ((ty&3) == 3)) >> 1; uvmy = (ty + ((ty&3) == 3)) >> 1;
v->luma_mv[s->mb_x][0] = uvmx;
v->luma_mv[s->mb_x][1] = uvmy;
if(v->fastuvmc) { if(v->fastuvmc) {
uvmx = uvmx + ((uvmx<0)?(uvmx&1):-(uvmx&1)); uvmx = uvmx + ((uvmx<0)?(uvmx&1):-(uvmx&1));
uvmy = uvmy + ((uvmy<0)?(uvmy&1):-(uvmy&1)); uvmy = uvmy + ((uvmy<0)?(uvmy&1):-(uvmy&1));
@ -652,8 +657,9 @@ static void vc1_mc_4mv_chroma(VC1Context *v)
/** Predict and set motion vector /** Predict and set motion vector
*/ */
static inline void vc1_pred_mv(MpegEncContext *s, int n, int dmv_x, int dmv_y, int mv1, int r_x, int r_y, uint8_t* is_intra) static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, int mv1, int r_x, int r_y, uint8_t* is_intra)
{ {
MpegEncContext *s = &v->s;
int xy, wrap, off = 0; int xy, wrap, off = 0;
int16_t *A, *B, *C; int16_t *A, *B, *C;
int px, py; int px, py;
@ -678,6 +684,7 @@ static inline void vc1_pred_mv(MpegEncContext *s, int n, int dmv_x, int dmv_y, i
s->current_picture.motion_val[0][xy + wrap][1] = 0; s->current_picture.motion_val[0][xy + wrap][1] = 0;
s->current_picture.motion_val[0][xy + wrap + 1][0] = 0; s->current_picture.motion_val[0][xy + wrap + 1][0] = 0;
s->current_picture.motion_val[0][xy + wrap + 1][1] = 0; s->current_picture.motion_val[0][xy + wrap + 1][1] = 0;
v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;
s->current_picture.motion_val[1][xy + 1][0] = 0; s->current_picture.motion_val[1][xy + 1][0] = 0;
s->current_picture.motion_val[1][xy + 1][1] = 0; s->current_picture.motion_val[1][xy + 1][1] = 0;
s->current_picture.motion_val[1][xy + wrap][0] = 0; s->current_picture.motion_val[1][xy + wrap][0] = 0;
@ -1953,7 +1960,7 @@ static int vc1_decode_intra_block(VC1Context *v, DCTELEM block[64], int n, int c
/** Decode P block /** Decode P block
*/ */
static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquant, int ttmb, int first_block, static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquant, int ttmb, int first_block,
uint8_t *dst, int linesize, int skip_block, int apply_filter, int cbp_top, int cbp_left) uint8_t *dst, int linesize, int skip_block, int *ttmb_out)
{ {
MpegEncContext *s = &v->s; MpegEncContext *s = &v->s;
GetBitContext *gb = &s->gb; GetBitContext *gb = &s->gb;
@ -2011,10 +2018,6 @@ static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquan
else{ else{
v->vc1dsp.vc1_inv_trans_8x8_add(dst, linesize, block); v->vc1dsp.vc1_inv_trans_8x8_add(dst, linesize, block);
} }
if(apply_filter && cbp_top & 0xC)
v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq);
if(apply_filter && cbp_left & 0xA)
v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq);
} }
break; break;
case TT_4X4: case TT_4X4:
@ -2038,10 +2041,6 @@ static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquan
v->vc1dsp.vc1_inv_trans_4x4_dc(dst + (j&1)*4 + (j&2)*2*linesize, linesize, block + off); v->vc1dsp.vc1_inv_trans_4x4_dc(dst + (j&1)*4 + (j&2)*2*linesize, linesize, block + off);
else else
v->vc1dsp.vc1_inv_trans_4x4(dst + (j&1)*4 + (j&2)*2*linesize, linesize, block + off); v->vc1dsp.vc1_inv_trans_4x4(dst + (j&1)*4 + (j&2)*2*linesize, linesize, block + off);
if(apply_filter && (j&2 ? pat & (1<<(j-2)) : (cbp_top & (1 << (j + 2)))))
v->vc1dsp.vc1_v_loop_filter4(dst + (j&1)*4 + (j&2)*2*linesize, linesize, v->pq);
if(apply_filter && (j&1 ? pat & (1<<(j-1)) : (cbp_left & (1 << (j + 1)))))
v->vc1dsp.vc1_h_loop_filter4(dst + (j&1)*4 + (j&2)*2*linesize, linesize, v->pq);
} }
} }
break; break;
@ -2066,10 +2065,6 @@ static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquan
v->vc1dsp.vc1_inv_trans_8x4_dc(dst + j*4*linesize, linesize, block + off); v->vc1dsp.vc1_inv_trans_8x4_dc(dst + j*4*linesize, linesize, block + off);
else else
v->vc1dsp.vc1_inv_trans_8x4(dst + j*4*linesize, linesize, block + off); v->vc1dsp.vc1_inv_trans_8x4(dst + j*4*linesize, linesize, block + off);
if(apply_filter && j ? pat & 0x3 : (cbp_top & 0xC))
v->vc1dsp.vc1_v_loop_filter8(dst + j*4*linesize, linesize, v->pq);
if(apply_filter && cbp_left & (2 << j))
v->vc1dsp.vc1_h_loop_filter4(dst + j*4*linesize, linesize, v->pq);
} }
} }
break; break;
@ -2094,14 +2089,12 @@ static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquan
v->vc1dsp.vc1_inv_trans_4x8_dc(dst + j*4, linesize, block + off); v->vc1dsp.vc1_inv_trans_4x8_dc(dst + j*4, linesize, block + off);
else else
v->vc1dsp.vc1_inv_trans_4x8(dst + j*4, linesize, block + off); v->vc1dsp.vc1_inv_trans_4x8(dst + j*4, linesize, block + off);
if(apply_filter && cbp_top & (2 << j))
v->vc1dsp.vc1_v_loop_filter4(dst + j*4, linesize, v->pq);
if(apply_filter && j ? pat & 0x5 : (cbp_left & 0xA))
v->vc1dsp.vc1_h_loop_filter8(dst + j*4, linesize, v->pq);
} }
} }
break; break;
} }
if (ttmb_out)
*ttmb_out |= ttblk << (n * 4);
return pat; return pat;
} }
@ -2110,6 +2103,155 @@ static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquan
static const int size_table [6] = { 0, 2, 3, 4, 5, 8 }; static const int size_table [6] = { 0, 2, 3, 4, 5, 8 };
static const int offset_table[6] = { 0, 1, 3, 7, 15, 31 }; static const int offset_table[6] = { 0, 1, 3, 7, 15, 31 };
static av_always_inline void vc1_apply_p_v_loop_filter(VC1Context *v, int block_num)
{
MpegEncContext *s = &v->s;
int mb_cbp = v->cbp[s->mb_x - s->mb_stride],
block_cbp = mb_cbp >> (block_num * 4), bottom_cbp,
mb_is_intra = v->is_intra[s->mb_x - s->mb_stride],
block_is_intra = mb_is_intra >> (block_num * 4), bottom_is_intra;
int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk;
uint8_t *dst;
if(block_num > 3) {
dst = s->dest[block_num - 3];
} else {
dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 8) * linesize;
}
if (s->mb_y != s->mb_height || block_num < 2) {
int16_t (*mv)[2];
int mv_stride;
if(block_num > 3) {
bottom_cbp = v->cbp[s->mb_x] >> (block_num * 4);
bottom_is_intra = v->is_intra[s->mb_x] >> (block_num * 4);
mv = &v->luma_mv[s->mb_x - s->mb_stride];
mv_stride = s->mb_stride;
} else {
bottom_cbp = (block_num < 2) ? (mb_cbp >> ((block_num + 2) * 4)) :
(v->cbp[s->mb_x] >> ((block_num - 2) * 4));
bottom_is_intra = (block_num < 2) ? (mb_is_intra >> ((block_num + 2) * 4)) :
(v->is_intra[s->mb_x] >> ((block_num - 2) * 4));
mv_stride = s->b8_stride;
mv = &s->current_picture.motion_val[0][s->block_index[block_num] - 2 * mv_stride];
}
if (bottom_is_intra & 1 || block_is_intra & 1 ||
mv[0][0] != mv[mv_stride][0] || mv[0][1] != mv[mv_stride][1]) {
v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq);
} else {
idx = ((bottom_cbp >> 2) | block_cbp) & 3;
if(idx == 3) {
v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq);
} else if (idx) {
if (idx == 1)
v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq);
else
v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq);
}
}
}
dst -= 4 * linesize;
ttblk = (v->ttblk[s->mb_x - s->mb_stride] >> (block_num * 4)) & 0xf;
if (ttblk == TT_4X4 || ttblk == TT_8X4) {
idx = (block_cbp | (block_cbp >> 2)) & 3;
if (idx == 3) {
v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq);
} else if (idx) {
if (idx == 1)
v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq);
else
v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq);
}
}
}
static av_always_inline void vc1_apply_p_h_loop_filter(VC1Context *v, int block_num)
{
MpegEncContext *s = &v->s;
int mb_cbp = v->cbp[s->mb_x - 1 - s->mb_stride],
block_cbp = mb_cbp >> (block_num * 4), right_cbp,
mb_is_intra = v->is_intra[s->mb_x - 1 - s->mb_stride],
block_is_intra = mb_is_intra >> (block_num * 4), right_is_intra;
int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk;
uint8_t *dst;
if (block_num > 3) {
dst = s->dest[block_num - 3] - 8 * linesize;
} else {
dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 16) * linesize - 8;
}
if (s->mb_x != s->mb_width || !(block_num & 5)) {
int16_t (*mv)[2];
if(block_num > 3) {
right_cbp = v->cbp[s->mb_x - s->mb_stride] >> (block_num * 4);
right_is_intra = v->is_intra[s->mb_x - s->mb_stride] >> (block_num * 4);
mv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
}else{
right_cbp = (block_num & 1) ? (v->cbp[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4)) :
(mb_cbp >> ((block_num + 1) * 4));
right_is_intra = (block_num & 1) ? (v->is_intra[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4)) :
(mb_is_intra >> ((block_num + 1) * 4));
mv = &s->current_picture.motion_val[0][s->block_index[block_num] - s->b8_stride * 2 - 2];
}
if (block_is_intra & 1 || right_is_intra & 1 || mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1]) {
v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq);
} else {
idx = ((right_cbp >> 1) | block_cbp) & 5; // FIXME check
if (idx == 5) {
v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq);
} else if (idx) {
if (idx == 1)
v->vc1dsp.vc1_h_loop_filter4(dst+4*linesize, linesize, v->pq);
else
v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq);
}
}
}
dst -= 4;
ttblk = (v->ttblk[s->mb_x - s->mb_stride - 1] >> (block_num * 4)) & 0xf;
if (ttblk == TT_4X4 || ttblk == TT_4X8) {
idx = (block_cbp | (block_cbp >> 1)) & 5;
if (idx == 5) {
v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq);
} else if (idx) {
if (idx == 1)
v->vc1dsp.vc1_h_loop_filter4(dst + linesize*4, linesize, v->pq);
else
v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq);
}
}
}
static void vc1_apply_p_loop_filter(VC1Context *v)
{
MpegEncContext *s = &v->s;
int i;
for (i = 0; i < 6; i++) {
vc1_apply_p_v_loop_filter(v, i);
}
/* V always preceedes H, therefore we run H one MB before V;
* at the end of a row, we catch up to complete the row */
if (s->mb_x) {
for (i = 0; i < 6; i++) {
vc1_apply_p_h_loop_filter(v, i);
}
if (s->mb_x == s->mb_width - 1) {
s->mb_x++;
ff_update_block_index(s);
for (i = 0; i < 6; i++) {
vc1_apply_p_h_loop_filter(v, i);
}
}
}
}
/** Decode one P-frame MB (in Simple/Main profile) /** Decode one P-frame MB (in Simple/Main profile)
*/ */
static int vc1_decode_p_mb(VC1Context *v) static int vc1_decode_p_mb(VC1Context *v)
@ -2129,8 +2271,7 @@ static int vc1_decode_p_mb(VC1Context *v)
int first_block = 1; int first_block = 1;
int dst_idx, off; int dst_idx, off;
int skipped, fourmv; int skipped, fourmv;
int block_cbp = 0, pat; int block_cbp = 0, pat, block_tt = 0, block_intra = 0;
int apply_loop_filter;
mquant = v->pq; /* Loosy initialization */ mquant = v->pq; /* Loosy initialization */
@ -2143,7 +2284,6 @@ static int vc1_decode_p_mb(VC1Context *v)
else else
skipped = v->s.mbskip_table[mb_pos]; skipped = v->s.mbskip_table[mb_pos];
apply_loop_filter = s->loop_filter && !(s->avctx->skip_loop_filter >= AVDISCARD_NONKEY);
if (!fourmv) /* 1MV mode */ if (!fourmv) /* 1MV mode */
{ {
if (!skipped) if (!skipped)
@ -2157,7 +2297,7 @@ static int vc1_decode_p_mb(VC1Context *v)
s->current_picture.motion_val[1][s->block_index[0]][1] = 0; s->current_picture.motion_val[1][s->block_index[0]][1] = 0;
} }
s->current_picture.mb_type[mb_pos] = s->mb_intra ? MB_TYPE_INTRA : MB_TYPE_16x16; s->current_picture.mb_type[mb_pos] = s->mb_intra ? MB_TYPE_INTRA : MB_TYPE_16x16;
vc1_pred_mv(s, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0]); vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0]);
/* FIXME Set DC val for inter block ? */ /* FIXME Set DC val for inter block ? */
if (s->mb_intra && !mb_has_coeffs) if (s->mb_intra && !mb_has_coeffs)
@ -2211,38 +2351,10 @@ static int vc1_decode_p_mb(VC1Context *v)
if(v->a_avail) if(v->a_avail)
v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize);
} }
if(apply_loop_filter && s->mb_x && s->mb_x != (s->mb_width - 1) && s->mb_y && s->mb_y != (s->mb_height - 1)){
int left_cbp, top_cbp;
if(i & 4){
left_cbp = v->cbp[s->mb_x - 1] >> (i * 4);
top_cbp = v->cbp[s->mb_x - s->mb_stride] >> (i * 4);
}else{
left_cbp = (i & 1) ? (cbp >> ((i-1)*4)) : (v->cbp[s->mb_x - 1] >> ((i+1)*4));
top_cbp = (i & 2) ? (cbp >> ((i-2)*4)) : (v->cbp[s->mb_x - s->mb_stride] >> ((i+2)*4));
}
if(left_cbp & 0xC)
v->vc1dsp.vc1_v_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
if(top_cbp & 0xA)
v->vc1dsp.vc1_h_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
}
block_cbp |= 0xF << (i << 2); block_cbp |= 0xF << (i << 2);
block_intra |= 1 << i;
} else if(val) { } else if(val) {
int left_cbp = 0, top_cbp = 0, filter = 0; pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY), &block_tt);
if(apply_loop_filter && s->mb_x && s->mb_x != (s->mb_width - 1) && s->mb_y && s->mb_y != (s->mb_height - 1)){
filter = 1;
if(i & 4){
left_cbp = v->cbp[s->mb_x - 1] >> (i * 4);
top_cbp = v->cbp[s->mb_x - s->mb_stride] >> (i * 4);
}else{
left_cbp = (i & 1) ? (cbp >> ((i-1)*4)) : (v->cbp[s->mb_x - 1] >> ((i+1)*4));
top_cbp = (i & 2) ? (cbp >> ((i-2)*4)) : (v->cbp[s->mb_x - s->mb_stride] >> ((i+2)*4));
}
if(left_cbp & 0xC)
v->vc1dsp.vc1_v_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
if(top_cbp & 0xA)
v->vc1dsp.vc1_h_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
}
pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY), filter, left_cbp, top_cbp);
block_cbp |= pat << (i << 2); block_cbp |= pat << (i << 2);
if(!v->ttmbf && ttmb < 8) ttmb = -1; if(!v->ttmbf && ttmb < 8) ttmb = -1;
first_block = 0; first_block = 0;
@ -2258,9 +2370,8 @@ static int vc1_decode_p_mb(VC1Context *v)
} }
s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP;
s->current_picture.qscale_table[mb_pos] = 0; s->current_picture.qscale_table[mb_pos] = 0;
vc1_pred_mv(s, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0]); vc1_pred_mv(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0]);
vc1_mc_1mv(v, 0); vc1_mc_1mv(v, 0);
return 0;
} }
} //1MV mode } //1MV mode
else //4MV mode else //4MV mode
@ -2284,7 +2395,7 @@ static int vc1_decode_p_mb(VC1Context *v)
if(val) { if(val) {
GET_MVDATA(dmv_x, dmv_y); GET_MVDATA(dmv_x, dmv_y);
} }
vc1_pred_mv(s, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0]); vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0]);
if(!s->mb_intra) vc1_mc_4mv_luma(v, i); if(!s->mb_intra) vc1_mc_4mv_luma(v, i);
intra_count += s->mb_intra; intra_count += s->mb_intra;
is_intra[i] = s->mb_intra; is_intra[i] = s->mb_intra;
@ -2299,8 +2410,9 @@ static int vc1_decode_p_mb(VC1Context *v)
if(!coded_inter) coded_inter = !is_intra[i] & is_coded[i]; if(!coded_inter) coded_inter = !is_intra[i] & is_coded[i];
} }
// if there are no coded blocks then don't do anything more // if there are no coded blocks then don't do anything more
if(!intra_count && !coded_inter) return 0;
dst_idx = 0; dst_idx = 0;
if(!intra_count && !coded_inter)
goto end;
GET_MQUANT(); GET_MQUANT();
s->current_picture.qscale_table[mb_pos] = mquant; s->current_picture.qscale_table[mb_pos] = mquant;
/* test if block is intra and has pred */ /* test if block is intra and has pred */
@ -2344,44 +2456,15 @@ static int vc1_decode_p_mb(VC1Context *v)
if(v->a_avail) if(v->a_avail)
v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize);
} }
if(v->s.loop_filter && s->mb_x && s->mb_x != (s->mb_width - 1) && s->mb_y && s->mb_y != (s->mb_height - 1)){
int left_cbp, top_cbp;
if(i & 4){
left_cbp = v->cbp[s->mb_x - 1] >> (i * 4);
top_cbp = v->cbp[s->mb_x - s->mb_stride] >> (i * 4);
}else{
left_cbp = (i & 1) ? (cbp >> ((i-1)*4)) : (v->cbp[s->mb_x - 1] >> ((i+1)*4));
top_cbp = (i & 2) ? (cbp >> ((i-2)*4)) : (v->cbp[s->mb_x - s->mb_stride] >> ((i+2)*4));
}
if(left_cbp & 0xC)
v->vc1dsp.vc1_v_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
if(top_cbp & 0xA)
v->vc1dsp.vc1_h_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
}
block_cbp |= 0xF << (i << 2); block_cbp |= 0xF << (i << 2);
block_intra |= 1 << i;
} else if(is_coded[i]) { } else if(is_coded[i]) {
int left_cbp = 0, top_cbp = 0, filter = 0; pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY), &block_tt);
if(v->s.loop_filter && s->mb_x && s->mb_x != (s->mb_width - 1) && s->mb_y && s->mb_y != (s->mb_height - 1)){
filter = 1;
if(i & 4){
left_cbp = v->cbp[s->mb_x - 1] >> (i * 4);
top_cbp = v->cbp[s->mb_x - s->mb_stride] >> (i * 4);
}else{
left_cbp = (i & 1) ? (cbp >> ((i-1)*4)) : (v->cbp[s->mb_x - 1] >> ((i+1)*4));
top_cbp = (i & 2) ? (cbp >> ((i-2)*4)) : (v->cbp[s->mb_x - s->mb_stride] >> ((i+2)*4));
}
if(left_cbp & 0xC)
v->vc1dsp.vc1_v_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
if(top_cbp & 0xA)
v->vc1dsp.vc1_h_loop_filter8(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize, v->pq);
}
pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY), filter, left_cbp, top_cbp);
block_cbp |= pat << (i << 2); block_cbp |= pat << (i << 2);
if(!v->ttmbf && ttmb < 8) ttmb = -1; if(!v->ttmbf && ttmb < 8) ttmb = -1;
first_block = 0; first_block = 0;
} }
} }
return 0;
} }
else //Skipped MB else //Skipped MB
{ {
@ -2393,18 +2476,19 @@ static int vc1_decode_p_mb(VC1Context *v)
} }
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
vc1_pred_mv(s, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0]); vc1_pred_mv(v, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0]);
vc1_mc_4mv_luma(v, i); vc1_mc_4mv_luma(v, i);
} }
vc1_mc_4mv_chroma(v); vc1_mc_4mv_chroma(v);
s->current_picture.qscale_table[mb_pos] = 0; s->current_picture.qscale_table[mb_pos] = 0;
return 0;
} }
} }
end:
v->cbp[s->mb_x] = block_cbp; v->cbp[s->mb_x] = block_cbp;
v->ttblk[s->mb_x] = block_tt;
v->is_intra[s->mb_x] = block_intra;
/* Should never happen */ return 0;
return -1;
} }
/** Decode one B-frame MB (in Main profile) /** Decode one B-frame MB (in Main profile)
@ -2546,7 +2630,7 @@ static void vc1_decode_b_mb(VC1Context *v)
i & 4 ? s->uvlinesize : s->linesize, i & 4 ? s->uvlinesize : s->linesize,
s->block[i]); s->block[i]);
} else if(val) { } else if(val) {
vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY), 0, 0, 0); vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY), NULL);
if(!v->ttmbf && ttmb < 8) ttmb = -1; if(!v->ttmbf && ttmb < 8) ttmb = -1;
first_block = 0; first_block = 0;
} }
@ -2841,6 +2925,7 @@ static void vc1_decode_i_blocks_adv(VC1Context *v, int mby_start, int mby_end)
static void vc1_decode_p_blocks(VC1Context *v, int mby_start, int mby_end) static void vc1_decode_p_blocks(VC1Context *v, int mby_start, int mby_end)
{ {
MpegEncContext *s = &v->s; MpegEncContext *s = &v->s;
int apply_loop_filter;
/* select codingmode used for VLC tables selection */ /* select codingmode used for VLC tables selection */
switch(v->c_ac_table_index){ switch(v->c_ac_table_index){
@ -2867,6 +2952,7 @@ static void vc1_decode_p_blocks(VC1Context *v, int mby_start, int mby_end)
break; break;
} }
apply_loop_filter = s->loop_filter && !(s->avctx->skip_loop_filter >= AVDISCARD_NONKEY);
s->first_slice_line = 1; s->first_slice_line = 1;
memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride); memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride);
for(s->mb_y = mby_start; s->mb_y < mby_end; s->mb_y++) { for(s->mb_y = mby_start; s->mb_y < mby_end; s->mb_y++) {
@ -2876,6 +2962,8 @@ static void vc1_decode_p_blocks(VC1Context *v, int mby_start, int mby_end)
ff_update_block_index(s); ff_update_block_index(s);
vc1_decode_p_mb(v); vc1_decode_p_mb(v);
if (s->mb_y != mby_start && apply_loop_filter)
vc1_apply_p_loop_filter(v);
if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
ff_er_add_slice(s, 0, mby_start, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)); ff_er_add_slice(s, 0, mby_start, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END));
av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y);
@ -2883,9 +2971,22 @@ static void vc1_decode_p_blocks(VC1Context *v, int mby_start, int mby_end)
} }
} }
memmove(v->cbp_base, v->cbp, sizeof(v->cbp_base[0])*s->mb_stride); memmove(v->cbp_base, v->cbp, sizeof(v->cbp_base[0])*s->mb_stride);
ff_draw_horiz_band(s, s->mb_y * 16, 16); memmove(v->ttblk_base, v->ttblk, sizeof(v->ttblk_base[0])*s->mb_stride);
memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0])*s->mb_stride);
memmove(v->luma_mv_base, v->luma_mv, sizeof(v->luma_mv_base[0])*s->mb_stride);
if (s->mb_y != mby_start) ff_draw_horiz_band(s, (s->mb_y-1) * 16, 16);
s->first_slice_line = 0; s->first_slice_line = 0;
} }
if (apply_loop_filter) {
s->mb_x = 0;
ff_init_block_index(s);
for (; s->mb_x < s->mb_width; s->mb_x++) {
ff_update_block_index(s);
vc1_apply_p_loop_filter(v);
}
}
if (mby_end >= mby_start)
ff_draw_horiz_band(s, (mby_end-1) * 16, 16);
ff_er_add_slice(s, 0, mby_start, s->mb_width - 1, mby_end - 1, (AC_END|DC_END|MV_END)); ff_er_add_slice(s, 0, mby_start, s->mb_width - 1, mby_end - 1, (AC_END|DC_END|MV_END));
} }
@ -3122,6 +3223,12 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
v->cbp_base = av_malloc(sizeof(v->cbp_base[0]) * 2 * s->mb_stride); v->cbp_base = av_malloc(sizeof(v->cbp_base[0]) * 2 * s->mb_stride);
v->cbp = v->cbp_base + s->mb_stride; v->cbp = v->cbp_base + s->mb_stride;
v->ttblk_base = av_malloc(sizeof(v->ttblk_base[0]) * 2 * s->mb_stride);
v->ttblk = v->ttblk_base + s->mb_stride;
v->is_intra_base = av_malloc(sizeof(v->is_intra_base[0]) * 2 * s->mb_stride);
v->is_intra = v->is_intra_base + s->mb_stride;
v->luma_mv_base = av_malloc(sizeof(v->luma_mv_base[0]) * 2 * s->mb_stride);
v->luma_mv = v->luma_mv_base + s->mb_stride;
/* allocate block type info in that way so it could be used with s->block_index[] */ /* allocate block type info in that way so it could be used with s->block_index[] */
v->mb_type_base = av_malloc(s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); v->mb_type_base = av_malloc(s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2);
@ -3375,6 +3482,9 @@ static av_cold int vc1_decode_end(AVCodecContext *avctx)
av_freep(&v->over_flags_plane); av_freep(&v->over_flags_plane);
av_freep(&v->mb_type_base); av_freep(&v->mb_type_base);
av_freep(&v->cbp_base); av_freep(&v->cbp_base);
av_freep(&v->ttblk_base);
av_freep(&v->is_intra_base); // FIXME use v->mb_type[]
av_freep(&v->luma_mv_base);
ff_intrax8_common_end(&v->x8); ff_intrax8_common_end(&v->x8);
return 0; return 0;
} }

View File

@ -2,14 +2,14 @@
0, 3600, 38016, 0xf4715db5 0, 3600, 38016, 0xf4715db5
0, 7200, 38016, 0xf4715db5 0, 7200, 38016, 0xf4715db5
0, 10800, 38016, 0xf46af0e1 0, 10800, 38016, 0xf46af0e1
0, 14400, 38016, 0x96992cf1 0, 14400, 38016, 0x9c1c2cf1
0, 18000, 38016, 0xbaadd874 0, 18000, 38016, 0xff12d87f
0, 21600, 38016, 0x751f4328 0, 21600, 38016, 0x7408432b
0, 25200, 38016, 0x751f4328 0, 25200, 38016, 0x7408432b
0, 28800, 38016, 0xf7294772 0, 28800, 38016, 0x8d11479a
0, 32400, 38016, 0xf7294772 0, 32400, 38016, 0x8d11479a
0, 36000, 38016, 0xf1d12133 0, 36000, 38016, 0xc4a121ab
0, 39600, 38016, 0xf1d12133 0, 39600, 38016, 0xc4a121ab
0, 43200, 38016, 0xf1d12133 0, 43200, 38016, 0xc4a121ab
0, 46800, 38016, 0xf1d12133 0, 46800, 38016, 0xc4a121ab
0, 50400, 38016, 0xf1d12133 0, 50400, 38016, 0xc4a121ab