---
 libavcodec/Makefile         |   3 +-
 libavcodec/vc1.h            |   5 +
 libavcodec/vc1_block.c      | 338 ++---------------------------------------
 libavcodec/vc1_loopfilter.c | 363 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 380 insertions(+), 329 deletions(-)
 create mode 100644 libavcodec/vc1_loopfilter.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 6aaf621..cda2426 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -390,7 +390,8 @@ OBJS-$(CONFIG_V410_ENCODER)            += v410enc.o
 OBJS-$(CONFIG_V210X_DECODER)           += v210x.o
 OBJS-$(CONFIG_VB_DECODER)              += vb.o
 OBJS-$(CONFIG_VBLE_DECODER)            += vble.o
-OBJS-$(CONFIG_VC1_DECODER)             += vc1dec.o vc1_block.o vc1.o vc1data.o 
vc1dsp.o \
+OBJS-$(CONFIG_VC1_DECODER)             += vc1dec.o vc1_block.o 
vc1_loopfilter.o \
+                                         vc1.o vc1data.o vc1dsp.o \
                                           msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_VCR1_DECODER)            += vcr1.o
 OBJS-$(CONFIG_VMDAUDIO_DECODER)        += vmdaudio.o
diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h
index 780344a..b26632d 100644
--- a/libavcodec/vc1.h
+++ b/libavcodec/vc1.h
@@ -400,4 +400,9 @@ void ff_vc1_init_transposed_scantables(VC1Context *v);
 int  ff_vc1_decode_end(AVCodecContext *avctx);
 void ff_vc1_decode_blocks(VC1Context *v);
 
+void ff_vc1_loop_filter_iblk(VC1Context *v, int pq);
+void ff_vc1_loop_filter_iblk_delayed(VC1Context *v, int pq);
+void ff_vc1_smooth_overlap_filter_iblk(VC1Context *v);
+void ff_vc1_apply_p_loop_filter(VC1Context *v);
+
 #endif /* AVCODEC_VC1_H */
diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c
index 28bc2e9..8b3ee21 100644
--- a/libavcodec/vc1_block.c
+++ b/libavcodec/vc1_block.c
@@ -167,178 +167,6 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v)
     inc_blk_idx(v->cur_blk_idx);
 }
 
-static void vc1_loop_filter_iblk(VC1Context *v, int pq)
-{
-    MpegEncContext *s = &v->s;
-    int j;
-    if (!s->first_slice_line) {
-        v->vc1dsp.vc1_v_loop_filter16(s->dest[0], s->linesize, pq);
-        if (s->mb_x)
-            v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, 
s->linesize, pq);
-        v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, 
s->linesize, pq);
-        for (j = 0; j < 2; j++) {
-            v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1], s->uvlinesize, pq);
-            if (s->mb_x)
-                v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize, s->uvlinesize, pq);
-        }
-    }
-    v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8 * s->linesize, s->linesize, 
pq);
-
-    if (s->mb_y == s->end_mb_y - 1) {
-        if (s->mb_x) {
-            v->vc1dsp.vc1_h_loop_filter16(s->dest[0], s->linesize, pq);
-            v->vc1dsp.vc1_h_loop_filter8(s->dest[1], s->uvlinesize, pq);
-            v->vc1dsp.vc1_h_loop_filter8(s->dest[2], s->uvlinesize, pq);
-        }
-        v->vc1dsp.vc1_h_loop_filter16(s->dest[0] + 8, s->linesize, pq);
-    }
-}
-
-static void vc1_loop_filter_iblk_delayed(VC1Context *v, int pq)
-{
-    MpegEncContext *s = &v->s;
-    int j;
-
-    /* The loopfilter runs 1 row and 1 column behind the overlap filter, which
-     * means it runs two rows/cols behind the decoding loop. */
-    if (!s->first_slice_line) {
-        if (s->mb_x) {
-            if (s->mb_y >= s->start_mb_y + 2) {
-                v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize - 
16, s->linesize, pq);
-
-                if (s->mb_x >= 2)
-                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * 
s->linesize - 16, s->linesize, pq);
-                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 
8, s->linesize, pq);
-                for (j = 0; j < 2; j++) {
-                    v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize - 8, s->uvlinesize, pq);
-                    if (s->mb_x >= 2) {
-                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * 
s->uvlinesize - 8, s->uvlinesize, pq);
-                    }
-                }
-            }
-            v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize - 16, 
s->linesize, pq);
-        }
-
-        if (s->mb_x == s->mb_width - 1) {
-            if (s->mb_y >= s->start_mb_y + 2) {
-                v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize, 
s->linesize, pq);
-
-                if (s->mb_x)
-                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * 
s->linesize, s->linesize, pq);
-                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize + 
8, s->linesize, pq);
-                for (j = 0; j < 2; j++) {
-                    v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize, s->uvlinesize, pq);
-                    if (s->mb_x >= 2) {
-                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * 
s->uvlinesize, s->uvlinesize, pq);
-                    }
-                }
-            }
-            v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize, 
s->linesize, pq);
-        }
-
-        if (s->mb_y == s->end_mb_y) {
-            if (s->mb_x) {
-                if (s->mb_x >= 2)
-                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * 
s->linesize - 16, s->linesize, pq);
-                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 
8, s->linesize, pq);
-                if (s->mb_x >= 2) {
-                    for (j = 0; j < 2; j++) {
-                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize - 8, s->uvlinesize, pq);
-                    }
-                }
-            }
-
-            if (s->mb_x == s->mb_width - 1) {
-                if (s->mb_x)
-                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * 
s->linesize, s->linesize, pq);
-                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 
8, s->linesize, pq);
-                if (s->mb_x) {
-                    for (j = 0; j < 2; j++) {
-                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize, s->uvlinesize, pq);
-                    }
-                }
-            }
-        }
-    }
-}
-
-static void vc1_smooth_overlap_filter_iblk(VC1Context *v)
-{
-    MpegEncContext *s = &v->s;
-    int mb_pos;
-
-    if (v->condover == CONDOVER_NONE)
-        return;
-
-    mb_pos = s->mb_x + s->mb_y * s->mb_stride;
-
-    /* Within a MB, the horizontal overlap always runs before the vertical.
-     * To accomplish that, we run the H on left and internal borders of the
-     * currently decoded MB. Then, we wait for the next overlap iteration
-     * to do H overlap on the right edge of this MB, before moving over and
-     * running the V overlap. Therefore, the V overlap makes us trail by one
-     * MB col and the H overlap filter makes us trail by one MB row. This
-     * is reflected in the time at which we run the put_pixels loop. */
-    if (v->condover == CONDOVER_ALL || v->pq >= 9 || 
v->over_flags_plane[mb_pos]) {
-        if (s->mb_x && (v->condover == CONDOVER_ALL || v->pq >= 9 ||
-                        v->over_flags_plane[mb_pos - 1])) {
-            v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][1],
-                                      v->block[v->cur_blk_idx][0]);
-            v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][3],
-                                      v->block[v->cur_blk_idx][2]);
-            if (!(s->flags & CODEC_FLAG_GRAY)) {
-                v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][4],
-                                          v->block[v->cur_blk_idx][4]);
-                v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][5],
-                                          v->block[v->cur_blk_idx][5]);
-            }
-        }
-        v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][0],
-                                  v->block[v->cur_blk_idx][1]);
-        v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][2],
-                                  v->block[v->cur_blk_idx][3]);
-
-        if (s->mb_x == s->mb_width - 1) {
-            if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq 
>= 9 ||
-                                         v->over_flags_plane[mb_pos - 
s->mb_stride])) {
-                v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][2],
-                                          v->block[v->cur_blk_idx][0]);
-                v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][3],
-                                          v->block[v->cur_blk_idx][1]);
-                if (!(s->flags & CODEC_FLAG_GRAY)) {
-                    v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][4],
-                                              v->block[v->cur_blk_idx][4]);
-                    v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][5],
-                                              v->block[v->cur_blk_idx][5]);
-                }
-            }
-            v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][0],
-                                      v->block[v->cur_blk_idx][2]);
-            v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][1],
-                                      v->block[v->cur_blk_idx][3]);
-        }
-    }
-    if (s->mb_x && (v->condover == CONDOVER_ALL || v->over_flags_plane[mb_pos 
- 1])) {
-        if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 
||
-                                     v->over_flags_plane[mb_pos - s->mb_stride 
- 1])) {
-            v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][2],
-                                      v->block[v->left_blk_idx][0]);
-            v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][3],
-                                      v->block[v->left_blk_idx][1]);
-            if (!(s->flags & CODEC_FLAG_GRAY)) {
-                v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][4],
-                                          v->block[v->left_blk_idx][4]);
-                v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][5],
-                                          v->block[v->left_blk_idx][5]);
-            }
-        }
-        v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][0],
-                                  v->block[v->left_blk_idx][2]);
-        v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][1],
-                                  v->block[v->left_blk_idx][3]);
-    }
-}
-
 /** Do motion compensation over 1 macroblock
  * Mostly adapted hpel_motion and qpel_motion from mpegvideo.c
  */
@@ -3376,155 +3204,6 @@ static int vc1_decode_p_block(VC1Context *v, int16_t 
block[64], int n,
 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 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->end_mb_y || 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 precedes 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
  */
 static int vc1_decode_p_mb(VC1Context *v)
@@ -4881,7 +4560,8 @@ static void vc1_decode_i_blocks(VC1Context *v)
                 v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, 
s->linesize);
                 v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, 
s->linesize);
             }
-            if (v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq);
+            if (v->s.loop_filter)
+                ff_vc1_loop_filter_iblk(v, v->pq);
 
             if (get_bits_count(&s->gb) > v->bits) {
                 ff_er_add_slice(&s->er, 0, 0, s->mb_x, s->mb_y, ER_MB_ERROR);
@@ -5006,9 +4686,10 @@ static void vc1_decode_i_blocks_adv(VC1Context *v)
                 v->vc1dsp.vc1_inv_trans_8x8(block[k]);
             }
 
-            vc1_smooth_overlap_filter_iblk(v);
+            ff_vc1_smooth_overlap_filter_iblk(v);
             vc1_put_signed_blocks_clamped(v);
-            if (v->s.loop_filter) vc1_loop_filter_iblk_delayed(v, v->pq);
+            if (v->s.loop_filter)
+                ff_vc1_loop_filter_iblk_delayed(v, v->pq);
 
             if (get_bits_count(&s->gb) > v->bits) {
                 // TODO: may need modification to handle slice coding
@@ -5033,7 +4714,7 @@ static void vc1_decode_i_blocks_adv(VC1Context *v)
         ff_update_block_index(s);
         vc1_put_signed_blocks_clamped(v);
         if (v->s.loop_filter)
-            vc1_loop_filter_iblk_delayed(v, v->pq);
+            ff_vc1_loop_filter_iblk_delayed(v, v->pq);
     }
     if (v->s.loop_filter)
         ff_mpeg_draw_horiz_band(s, (s->end_mb_y-1)*16, 16);
@@ -5087,7 +4768,7 @@ static void vc1_decode_p_blocks(VC1Context *v)
                 vc1_decode_p_mb_intfr(v);
             else vc1_decode_p_mb(v);
             if (s->mb_y != s->start_mb_y && apply_loop_filter)
-                vc1_apply_p_loop_filter(v);
+                ff_vc1_apply_p_loop_filter(v);
             if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 
0) {
                 // TODO: may need modification to handle slice coding
                 ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, 
ER_MB_ERROR);
@@ -5108,7 +4789,7 @@ static void vc1_decode_p_blocks(VC1Context *v)
         init_block_index(v);
         for (; s->mb_x < s->mb_width; s->mb_x++) {
             ff_update_block_index(s);
-            vc1_apply_p_loop_filter(v);
+            ff_vc1_apply_p_loop_filter(v);
         }
     }
     if (s->end_mb_y >= s->start_mb_y)
@@ -5166,7 +4847,8 @@ static void vc1_decode_b_blocks(VC1Context *v)
                        get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y);
                 return;
             }
-            if (v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq);
+            if (v->s.loop_filter)
+                ff_vc1_loop_filter_iblk(v, v->pq);
         }
         if (!v->s.loop_filter)
             ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16);
diff --git a/libavcodec/vc1_loopfilter.c b/libavcodec/vc1_loopfilter.c
new file mode 100644
index 0000000..f2a90ac
--- /dev/null
+++ b/libavcodec/vc1_loopfilter.c
@@ -0,0 +1,363 @@
+/*
+ * VC-1 and WMV3 decoder
+ * Copyright (c) 2011 Mashiat Sarker Shakkhar
+ * Copyright (c) 2006-2007 Konstantin Shishkov
+ * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael 
Niedermayer
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * VC-1 and WMV3 loopfilter
+ */
+
+#include "internal.h"
+#include "avcodec.h"
+#include "error_resilience.h"
+#include "mpegutils.h"
+#include "mpegvideo.h"
+#include "h263.h"
+#include "h264chroma.h"
+#include "qpeldsp.h"
+#include "vc1.h"
+#include "vc1data.h"
+#include "vc1acdata.h"
+#include "msmpeg4data.h"
+#include "unary.h"
+#include "mathops.h"
+
+void ff_vc1_loop_filter_iblk(VC1Context *v, int pq)
+{
+    MpegEncContext *s = &v->s;
+    int j;
+    if (!s->first_slice_line) {
+        v->vc1dsp.vc1_v_loop_filter16(s->dest[0], s->linesize, pq);
+        if (s->mb_x)
+            v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, 
s->linesize, pq);
+        v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, 
s->linesize, pq);
+        for (j = 0; j < 2; j++) {
+            v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1], s->uvlinesize, pq);
+            if (s->mb_x)
+                v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize, s->uvlinesize, pq);
+        }
+    }
+    v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8 * s->linesize, s->linesize, 
pq);
+
+    if (s->mb_y == s->end_mb_y - 1) {
+        if (s->mb_x) {
+            v->vc1dsp.vc1_h_loop_filter16(s->dest[0], s->linesize, pq);
+            v->vc1dsp.vc1_h_loop_filter8(s->dest[1], s->uvlinesize, pq);
+            v->vc1dsp.vc1_h_loop_filter8(s->dest[2], s->uvlinesize, pq);
+        }
+        v->vc1dsp.vc1_h_loop_filter16(s->dest[0] + 8, s->linesize, pq);
+    }
+}
+
+void ff_vc1_loop_filter_iblk_delayed(VC1Context *v, int pq)
+{
+    MpegEncContext *s = &v->s;
+    int j;
+
+    /* The loopfilter runs 1 row and 1 column behind the overlap filter, which
+     * means it runs two rows/cols behind the decoding loop. */
+    if (!s->first_slice_line) {
+        if (s->mb_x) {
+            if (s->mb_y >= s->start_mb_y + 2) {
+                v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize - 
16, s->linesize, pq);
+
+                if (s->mb_x >= 2)
+                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * 
s->linesize - 16, s->linesize, pq);
+                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 
8, s->linesize, pq);
+                for (j = 0; j < 2; j++) {
+                    v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize - 8, s->uvlinesize, pq);
+                    if (s->mb_x >= 2) {
+                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * 
s->uvlinesize - 8, s->uvlinesize, pq);
+                    }
+                }
+            }
+            v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize - 16, 
s->linesize, pq);
+        }
+
+        if (s->mb_x == s->mb_width - 1) {
+            if (s->mb_y >= s->start_mb_y + 2) {
+                v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize, 
s->linesize, pq);
+
+                if (s->mb_x)
+                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * 
s->linesize, s->linesize, pq);
+                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize + 
8, s->linesize, pq);
+                for (j = 0; j < 2; j++) {
+                    v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize, s->uvlinesize, pq);
+                    if (s->mb_x >= 2) {
+                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * 
s->uvlinesize, s->uvlinesize, pq);
+                    }
+                }
+            }
+            v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize, 
s->linesize, pq);
+        }
+
+        if (s->mb_y == s->end_mb_y) {
+            if (s->mb_x) {
+                if (s->mb_x >= 2)
+                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * 
s->linesize - 16, s->linesize, pq);
+                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 
8, s->linesize, pq);
+                if (s->mb_x >= 2) {
+                    for (j = 0; j < 2; j++) {
+                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize - 8, s->uvlinesize, pq);
+                    }
+                }
+            }
+
+            if (s->mb_x == s->mb_width - 1) {
+                if (s->mb_x)
+                    v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * 
s->linesize, s->linesize, pq);
+                v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 
8, s->linesize, pq);
+                if (s->mb_x) {
+                    for (j = 0; j < 2; j++) {
+                        v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * 
s->uvlinesize, s->uvlinesize, pq);
+                    }
+                }
+            }
+        }
+    }
+}
+
+void ff_vc1_smooth_overlap_filter_iblk(VC1Context *v)
+{
+    MpegEncContext *s = &v->s;
+    int mb_pos;
+
+    if (v->condover == CONDOVER_NONE)
+        return;
+
+    mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+
+    /* Within a MB, the horizontal overlap always runs before the vertical.
+     * To accomplish that, we run the H on left and internal borders of the
+     * currently decoded MB. Then, we wait for the next overlap iteration
+     * to do H overlap on the right edge of this MB, before moving over and
+     * running the V overlap. Therefore, the V overlap makes us trail by one
+     * MB col and the H overlap filter makes us trail by one MB row. This
+     * is reflected in the time at which we run the put_pixels loop. */
+    if (v->condover == CONDOVER_ALL || v->pq >= 9 || 
v->over_flags_plane[mb_pos]) {
+        if (s->mb_x && (v->condover == CONDOVER_ALL || v->pq >= 9 ||
+                        v->over_flags_plane[mb_pos - 1])) {
+            v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][1],
+                                      v->block[v->cur_blk_idx][0]);
+            v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][3],
+                                      v->block[v->cur_blk_idx][2]);
+            if (!(s->flags & CODEC_FLAG_GRAY)) {
+                v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][4],
+                                          v->block[v->cur_blk_idx][4]);
+                v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][5],
+                                          v->block[v->cur_blk_idx][5]);
+            }
+        }
+        v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][0],
+                                  v->block[v->cur_blk_idx][1]);
+        v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][2],
+                                  v->block[v->cur_blk_idx][3]);
+
+        if (s->mb_x == s->mb_width - 1) {
+            if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq 
>= 9 ||
+                                         v->over_flags_plane[mb_pos - 
s->mb_stride])) {
+                v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][2],
+                                          v->block[v->cur_blk_idx][0]);
+                v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][3],
+                                          v->block[v->cur_blk_idx][1]);
+                if (!(s->flags & CODEC_FLAG_GRAY)) {
+                    v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][4],
+                                              v->block[v->cur_blk_idx][4]);
+                    v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][5],
+                                              v->block[v->cur_blk_idx][5]);
+                }
+            }
+            v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][0],
+                                      v->block[v->cur_blk_idx][2]);
+            v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][1],
+                                      v->block[v->cur_blk_idx][3]);
+        }
+    }
+    if (s->mb_x && (v->condover == CONDOVER_ALL || v->over_flags_plane[mb_pos 
- 1])) {
+        if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 
||
+                                     v->over_flags_plane[mb_pos - s->mb_stride 
- 1])) {
+            v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][2],
+                                      v->block[v->left_blk_idx][0]);
+            v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][3],
+                                      v->block[v->left_blk_idx][1]);
+            if (!(s->flags & CODEC_FLAG_GRAY)) {
+                v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][4],
+                                          v->block[v->left_blk_idx][4]);
+                v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][5],
+                                          v->block[v->left_blk_idx][5]);
+            }
+        }
+        v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][0],
+                                  v->block[v->left_blk_idx][2]);
+        v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][1],
+                                  v->block[v->left_blk_idx][3]);
+    }
+}
+
+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->end_mb_y || 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);
+        }
+    }
+}
+
+void ff_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 precedes 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);
+            }
+        }
+    }
+}
-- 
2.1.0

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to