summaryrefslogtreecommitdiff
path: root/libavcodec/vc1_loopfilter.c
diff options
context:
space:
mode:
authorJerome Borsboom <jerome.borsboom@carpalis.nl>2018-06-20 13:11:07 +0200
committerCarl Eugen Hoyos <ceffmpeg@gmail.com>2018-06-29 01:18:44 +0200
commit975a1a81b28dc632d7c4bee99d5eccf09b9603d8 (patch)
treece277ae7d5fa07da76935cb4a8cb8096b8889457 /libavcodec/vc1_loopfilter.c
parentf92e95e9b5afd7d4a28db53d086876aa0df8625b (diff)
avcodec/vc1: fix overlap filter for frame interlaced pictures
The overlap filter is not correct for vertical edges in frame interlaced I and P pictures. When filtering macroblocks with different FIELDTX values, we have to match the lines at both sides of the vertical border. In addition, we have to use the correct rounding values, depending on the line we are filtering. Signed-off-by: Jerome Borsboom <jerome.borsboom@carpalis.nl>
Diffstat (limited to 'libavcodec/vc1_loopfilter.c')
-rw-r--r--libavcodec/vc1_loopfilter.c86
1 files changed, 72 insertions, 14 deletions
diff --git a/libavcodec/vc1_loopfilter.c b/libavcodec/vc1_loopfilter.c
index 5d5630db67..d43fa5b3ae 100644
--- a/libavcodec/vc1_loopfilter.c
+++ b/libavcodec/vc1_loopfilter.c
@@ -32,25 +32,74 @@
#include "vc1dsp.h"
static av_always_inline void vc1_h_overlap_filter(VC1Context *v, int16_t (*left_block)[64],
- int16_t (*right_block)[64], int block_num)
+ int16_t (*right_block)[64], int left_fieldtx,
+ int right_fieldtx, int block_num)
{
- if (block_num > 3)
- v->vc1dsp.vc1_h_s_overlap(left_block[block_num], right_block[block_num]);
- else if (block_num & 1)
- v->vc1dsp.vc1_h_s_overlap(right_block[block_num - 1], right_block[block_num]);
- else
- v->vc1dsp.vc1_h_s_overlap(left_block[block_num + 1], right_block[block_num]);
+ switch (block_num) {
+ case 0:
+ v->vc1dsp.vc1_h_s_overlap(left_block[2],
+ right_block[0],
+ left_fieldtx ^ right_fieldtx ? 16 - 8 * left_fieldtx : 8,
+ left_fieldtx ^ right_fieldtx ? 16 - 8 * right_fieldtx : 8,
+ left_fieldtx || right_fieldtx ? 0 : 1);
+ break;
+
+ case 1:
+ v->vc1dsp.vc1_h_s_overlap(right_block[0],
+ right_block[2],
+ 8,
+ 8,
+ right_fieldtx ? 0 : 1);
+ break;
+
+ case 2:
+ v->vc1dsp.vc1_h_s_overlap(!left_fieldtx && right_fieldtx ? left_block[2] + 8 : left_block[3],
+ left_fieldtx && !right_fieldtx ? right_block[0] + 8 : right_block[1],
+ left_fieldtx ^ right_fieldtx ? 16 - 8 * left_fieldtx : 8,
+ left_fieldtx ^ right_fieldtx ? 16 - 8 * right_fieldtx : 8,
+ left_fieldtx || right_fieldtx ? 2 : 1);
+ break;
+
+ case 3:
+ v->vc1dsp.vc1_h_s_overlap(right_block[1],
+ right_block[3],
+ 8,
+ 8,
+ right_fieldtx ? 2 : 1);
+ break;
+
+ case 4:
+ case 5:
+ v->vc1dsp.vc1_h_s_overlap(left_block[block_num], right_block[block_num], 8, 8, 1);
+ break;
+ }
}
static av_always_inline void vc1_v_overlap_filter(VC1Context *v, int16_t (*top_block)[64],
int16_t (*bottom_block)[64], int block_num)
{
- if (block_num > 3)
+ switch (block_num) {
+ case 0:
+ v->vc1dsp.vc1_v_s_overlap(top_block[1], bottom_block[0]);
+ break;
+
+ case 1:
+ v->vc1dsp.vc1_v_s_overlap(top_block[3], bottom_block[2]);
+ break;
+
+ case 2:
+ v->vc1dsp.vc1_v_s_overlap(bottom_block[0], bottom_block[1]);
+ break;
+
+ case 3:
+ v->vc1dsp.vc1_v_s_overlap(bottom_block[2], bottom_block[3]);
+ break;
+
+ case 4:
+ case 5:
v->vc1dsp.vc1_v_s_overlap(top_block[block_num], bottom_block[block_num]);
- else if (block_num & 2)
- v->vc1dsp.vc1_v_s_overlap(bottom_block[block_num - 2], bottom_block[block_num]);
- else
- v->vc1dsp.vc1_v_s_overlap(top_block[block_num + 2], bottom_block[block_num]);
+ break;
+ }
}
void ff_vc1_i_overlap_filter(VC1Context *v)
@@ -82,7 +131,11 @@ void ff_vc1_i_overlap_filter(VC1Context *v)
(v->condover == CONDOVER_ALL ||
(v->over_flags_plane[mb_pos] &&
((i & 5) == 1 || v->over_flags_plane[mb_pos - 1])))))
- vc1_h_overlap_filter(v, s->mb_x ? left_blk : cur_blk, cur_blk, i);
+ vc1_h_overlap_filter(v,
+ s->mb_x ? left_blk : cur_blk, cur_blk,
+ v->fcm == ILACE_FRAME && s->mb_x && v->fieldtx_plane[mb_pos - 1],
+ v->fcm == ILACE_FRAME && v->fieldtx_plane[mb_pos],
+ i);
}
if (v->fcm != ILACE_FRAME)
@@ -110,6 +163,7 @@ void ff_vc1_p_overlap_filter(VC1Context *v)
MpegEncContext *s = &v->s;
int16_t (*topleft_blk)[64], (*top_blk)[64], (*left_blk)[64], (*cur_blk)[64];
int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
+ int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
int i;
topleft_blk = v->block[v->topleft_blk_idx];
@@ -122,7 +176,11 @@ void ff_vc1_p_overlap_filter(VC1Context *v)
continue;
if (v->mb_type[0][s->block_index[i]] && v->mb_type[0][s->block_index[i] - 1])
- vc1_h_overlap_filter(v, s->mb_x ? left_blk : cur_blk, cur_blk, i);
+ vc1_h_overlap_filter(v,
+ s->mb_x ? left_blk : cur_blk, cur_blk,
+ v->fcm == ILACE_FRAME && s->mb_x && v->fieldtx_plane[mb_pos - 1],
+ v->fcm == ILACE_FRAME && v->fieldtx_plane[mb_pos],
+ i);
}
if (v->fcm != ILACE_FRAME)