---
 libavcodec/Makefile    |    3 +-
 libavcodec/vc1.h       |    1 -
 libavcodec/vc1_block.c | 1015 ++----------------------------------------------
 libavcodec/vc1_pred.c  |  969 +++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/vc1_pred.h  |   59 +++
 libavcodec/vc1data.h   |    2 -
 6 files changed, 1066 insertions(+), 983 deletions(-)
 create mode 100644 libavcodec/vc1_pred.c
 create mode 100644 libavcodec/vc1_pred.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 53e84f9..1b3db07 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -391,7 +391,8 @@ 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_loopfilter.o \
-                                         vc1_mc.o vc1.o vc1data.o vc1dsp.o \
+                                         vc1_mc.o vc1_pred.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 b4acc06..0c4958c 100644
--- a/libavcodec/vc1.h
+++ b/libavcodec/vc1.h
@@ -412,5 +412,4 @@ void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int 
dir2, int avg);
 
 void ff_vc1_interp_mc(VC1Context *v);
 
-
 #endif /* AVCODEC_VC1_H */
diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c
index dc9cd97..00c3948 100644
--- a/libavcodec/vc1_block.c
+++ b/libavcodec/vc1_block.c
@@ -36,6 +36,7 @@
 #include "h264chroma.h"
 #include "qpeldsp.h"
 #include "vc1.h"
+#include "vc1_pred.h"
 #include "vc1data.h"
 #include "vc1acdata.h"
 #include "msmpeg4data.h"
@@ -327,679 +328,6 @@ static av_always_inline void 
get_mvdata_interlaced(VC1Context *v, int *dmv_x,
     }
 }
 
-static av_always_inline int scaleforsame_x(VC1Context *v, int n /* MV */, int 
dir)
-{
-    int scaledvalue, refdist;
-    int scalesame1, scalesame2;
-    int scalezone1_x, zone1offset_x;
-    int table_index = dir ^ v->second_field;
-
-    if (v->s.pict_type != AV_PICTURE_TYPE_B)
-        refdist = v->refdist;
-    else
-        refdist = dir ? v->brfd : v->frfd;
-    if (refdist > 3)
-        refdist = 3;
-    scalesame1    = ff_vc1_field_mvpred_scales[table_index][1][refdist];
-    scalesame2    = ff_vc1_field_mvpred_scales[table_index][2][refdist];
-    scalezone1_x  = ff_vc1_field_mvpred_scales[table_index][3][refdist];
-    zone1offset_x = ff_vc1_field_mvpred_scales[table_index][5][refdist];
-
-    if (FFABS(n) > 255)
-        scaledvalue = n;
-    else {
-        if (FFABS(n) < scalezone1_x)
-            scaledvalue = (n * scalesame1) >> 8;
-        else {
-            if (n < 0)
-                scaledvalue = ((n * scalesame2) >> 8) - zone1offset_x;
-            else
-                scaledvalue = ((n * scalesame2) >> 8) + zone1offset_x;
-        }
-    }
-    return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
-}
-
-static av_always_inline int scaleforsame_y(VC1Context *v, int i, int n /* MV 
*/, int dir)
-{
-    int scaledvalue, refdist;
-    int scalesame1, scalesame2;
-    int scalezone1_y, zone1offset_y;
-    int table_index = dir ^ v->second_field;
-
-    if (v->s.pict_type != AV_PICTURE_TYPE_B)
-        refdist = v->refdist;
-    else
-        refdist = dir ? v->brfd : v->frfd;
-    if (refdist > 3)
-        refdist = 3;
-    scalesame1    = ff_vc1_field_mvpred_scales[table_index][1][refdist];
-    scalesame2    = ff_vc1_field_mvpred_scales[table_index][2][refdist];
-    scalezone1_y  = ff_vc1_field_mvpred_scales[table_index][4][refdist];
-    zone1offset_y = ff_vc1_field_mvpred_scales[table_index][6][refdist];
-
-    if (FFABS(n) > 63)
-        scaledvalue = n;
-    else {
-        if (FFABS(n) < scalezone1_y)
-            scaledvalue = (n * scalesame1) >> 8;
-        else {
-            if (n < 0)
-                scaledvalue = ((n * scalesame2) >> 8) - zone1offset_y;
-            else
-                scaledvalue = ((n * scalesame2) >> 8) + zone1offset_y;
-        }
-    }
-
-    if (v->cur_field_type && !v->ref_field_type[dir])
-        return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
-    else
-        return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
-}
-
-static av_always_inline int scaleforopp_x(VC1Context *v, int n /* MV */)
-{
-    int scalezone1_x, zone1offset_x;
-    int scaleopp1, scaleopp2, brfd;
-    int scaledvalue;
-
-    brfd = FFMIN(v->brfd, 3);
-    scalezone1_x  = ff_vc1_b_field_mvpred_scales[3][brfd];
-    zone1offset_x = ff_vc1_b_field_mvpred_scales[5][brfd];
-    scaleopp1     = ff_vc1_b_field_mvpred_scales[1][brfd];
-    scaleopp2     = ff_vc1_b_field_mvpred_scales[2][brfd];
-
-    if (FFABS(n) > 255)
-        scaledvalue = n;
-    else {
-        if (FFABS(n) < scalezone1_x)
-            scaledvalue = (n * scaleopp1) >> 8;
-        else {
-            if (n < 0)
-                scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_x;
-            else
-                scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_x;
-        }
-    }
-    return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
-}
-
-static av_always_inline int scaleforopp_y(VC1Context *v, int n /* MV */, int 
dir)
-{
-    int scalezone1_y, zone1offset_y;
-    int scaleopp1, scaleopp2, brfd;
-    int scaledvalue;
-
-    brfd = FFMIN(v->brfd, 3);
-    scalezone1_y  = ff_vc1_b_field_mvpred_scales[4][brfd];
-    zone1offset_y = ff_vc1_b_field_mvpred_scales[6][brfd];
-    scaleopp1     = ff_vc1_b_field_mvpred_scales[1][brfd];
-    scaleopp2     = ff_vc1_b_field_mvpred_scales[2][brfd];
-
-    if (FFABS(n) > 63)
-        scaledvalue = n;
-    else {
-        if (FFABS(n) < scalezone1_y)
-            scaledvalue = (n * scaleopp1) >> 8;
-        else {
-            if (n < 0)
-                scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_y;
-            else
-                scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_y;
-        }
-    }
-    if (v->cur_field_type && !v->ref_field_type[dir]) {
-        return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
-    } else {
-        return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
-    }
-}
-
-static av_always_inline int scaleforsame(VC1Context *v, int i, int n /* MV */,
-                                         int dim, int dir)
-{
-    int brfd, scalesame;
-    int hpel = 1 - v->s.quarter_sample;
-
-    n >>= hpel;
-    if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) {
-        if (dim)
-            n = scaleforsame_y(v, i, n, dir) << hpel;
-        else
-            n = scaleforsame_x(v, n, dir) << hpel;
-        return n;
-    }
-    brfd      = FFMIN(v->brfd, 3);
-    scalesame = ff_vc1_b_field_mvpred_scales[0][brfd];
-
-    n = (n * scalesame >> 8) << hpel;
-    return n;
-}
-
-static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */,
-                                        int dim, int dir)
-{
-    int refdist, scaleopp;
-    int hpel = 1 - v->s.quarter_sample;
-
-    n >>= hpel;
-    if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) {
-        if (dim)
-            n = scaleforopp_y(v, n, dir) << hpel;
-        else
-            n = scaleforopp_x(v, n) << hpel;
-        return n;
-    }
-    if (v->s.pict_type != AV_PICTURE_TYPE_B)
-        refdist = FFMIN(v->refdist, 3);
-    else
-        refdist = dir ? v->brfd : v->frfd;
-    scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist];
-
-    n = (n * scaleopp >> 8) << hpel;
-    return n;
-}
-
-/** Predict and set motion vector
- */
-static 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,
-                        int pred_flag, int dir)
-{
-    MpegEncContext *s = &v->s;
-    int xy, wrap, off = 0;
-    int16_t *A, *B, *C;
-    int px, py;
-    int sum;
-    int mixedmv_pic, num_samefield = 0, num_oppfield = 0;
-    int opposite, a_f, b_f, c_f;
-    int16_t field_predA[2];
-    int16_t field_predB[2];
-    int16_t field_predC[2];
-    int a_valid, b_valid, c_valid;
-    int hybridmv_thresh, y_bias = 0;
-
-    if (v->mv_mode == MV_PMODE_MIXED_MV ||
-        ((v->mv_mode == MV_PMODE_INTENSITY_COMP) && (v->mv_mode2 == 
MV_PMODE_MIXED_MV)))
-        mixedmv_pic = 1;
-    else
-        mixedmv_pic = 0;
-    /* scale MV difference to be quad-pel */
-    dmv_x <<= 1 - s->quarter_sample;
-    dmv_y <<= 1 - s->quarter_sample;
-
-    wrap = s->b8_stride;
-    xy   = s->block_index[n];
-
-    if (s->mb_intra) {
-        s->mv[0][n][0] = s->current_picture.motion_val[0][xy + 
v->blocks_off][0] = 0;
-        s->mv[0][n][1] = s->current_picture.motion_val[0][xy + 
v->blocks_off][1] = 0;
-        s->current_picture.motion_val[1][xy + v->blocks_off][0] = 0;
-        s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0;
-        if (mv1) { /* duplicate motion data for 1-MV block */
-            s->current_picture.motion_val[0][xy + 1 + v->blocks_off][0]        
= 0;
-            s->current_picture.motion_val[0][xy + 1 + v->blocks_off][1]        
= 0;
-            s->current_picture.motion_val[0][xy + wrap + v->blocks_off][0]     
= 0;
-            s->current_picture.motion_val[0][xy + wrap + v->blocks_off][1]     
= 0;
-            s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][0] 
= 0;
-            s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][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 + v->blocks_off][0]        
= 0;
-            s->current_picture.motion_val[1][xy + 1 + v->blocks_off][1]        
= 0;
-            s->current_picture.motion_val[1][xy + wrap][0]                     
= 0;
-            s->current_picture.motion_val[1][xy + wrap + v->blocks_off][1]     
= 0;
-            s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][0] 
= 0;
-            s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][1] 
= 0;
-        }
-        return;
-    }
-
-    C = s->current_picture.motion_val[dir][xy -    1 + v->blocks_off];
-    A = s->current_picture.motion_val[dir][xy - wrap + v->blocks_off];
-    if (mv1) {
-        if (v->field_mode && mixedmv_pic)
-            off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
-        else
-            off = (s->mb_x == (s->mb_width - 1)) ? -1 : 2;
-    } else {
-        //in 4-MV mode different blocks have different B predictor position
-        switch (n) {
-        case 0:
-            off = (s->mb_x > 0) ? -1 : 1;
-            break;
-        case 1:
-            off = (s->mb_x == (s->mb_width - 1)) ? -1 : 1;
-            break;
-        case 2:
-            off = 1;
-            break;
-        case 3:
-            off = -1;
-        }
-    }
-    B = s->current_picture.motion_val[dir][xy - wrap + off + v->blocks_off];
-
-    a_valid = !s->first_slice_line || (n == 2 || n == 3);
-    b_valid = a_valid && (s->mb_width > 1);
-    c_valid = s->mb_x || (n == 1 || n == 3);
-    if (v->field_mode) {
-        a_valid = a_valid && !is_intra[xy - wrap];
-        b_valid = b_valid && !is_intra[xy - wrap + off];
-        c_valid = c_valid && !is_intra[xy - 1];
-    }
-
-    if (a_valid) {
-        a_f = v->mv_f[dir][xy - wrap + v->blocks_off];
-        num_oppfield  += a_f;
-        num_samefield += 1 - a_f;
-        field_predA[0] = A[0];
-        field_predA[1] = A[1];
-    } else {
-        field_predA[0] = field_predA[1] = 0;
-        a_f = 0;
-    }
-    if (b_valid) {
-        b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off];
-        num_oppfield  += b_f;
-        num_samefield += 1 - b_f;
-        field_predB[0] = B[0];
-        field_predB[1] = B[1];
-    } else {
-        field_predB[0] = field_predB[1] = 0;
-        b_f = 0;
-    }
-    if (c_valid) {
-        c_f = v->mv_f[dir][xy - 1 + v->blocks_off];
-        num_oppfield  += c_f;
-        num_samefield += 1 - c_f;
-        field_predC[0] = C[0];
-        field_predC[1] = C[1];
-    } else {
-        field_predC[0] = field_predC[1] = 0;
-        c_f = 0;
-    }
-
-    if (v->field_mode) {
-        if (!v->numref)
-            // REFFIELD determines if the last field or the second-last field 
is
-            // to be used as reference
-            opposite = 1 - v->reffield;
-        else {
-            if (num_samefield <= num_oppfield)
-                opposite = 1 - pred_flag;
-            else
-                opposite = pred_flag;
-        }
-    } else
-        opposite = 0;
-    if (opposite) {
-        if (a_valid && !a_f) {
-            field_predA[0] = scaleforopp(v, field_predA[0], 0, dir);
-            field_predA[1] = scaleforopp(v, field_predA[1], 1, dir);
-        }
-        if (b_valid && !b_f) {
-            field_predB[0] = scaleforopp(v, field_predB[0], 0, dir);
-            field_predB[1] = scaleforopp(v, field_predB[1], 1, dir);
-        }
-        if (c_valid && !c_f) {
-            field_predC[0] = scaleforopp(v, field_predC[0], 0, dir);
-            field_predC[1] = scaleforopp(v, field_predC[1], 1, dir);
-        }
-        v->mv_f[dir][xy + v->blocks_off] = 1;
-        v->ref_field_type[dir] = !v->cur_field_type;
-    } else {
-        if (a_valid && a_f) {
-            field_predA[0] = scaleforsame(v, n, field_predA[0], 0, dir);
-            field_predA[1] = scaleforsame(v, n, field_predA[1], 1, dir);
-        }
-        if (b_valid && b_f) {
-            field_predB[0] = scaleforsame(v, n, field_predB[0], 0, dir);
-            field_predB[1] = scaleforsame(v, n, field_predB[1], 1, dir);
-        }
-        if (c_valid && c_f) {
-            field_predC[0] = scaleforsame(v, n, field_predC[0], 0, dir);
-            field_predC[1] = scaleforsame(v, n, field_predC[1], 1, dir);
-        }
-        v->mv_f[dir][xy + v->blocks_off] = 0;
-        v->ref_field_type[dir] = v->cur_field_type;
-    }
-
-    if (a_valid) {
-        px = field_predA[0];
-        py = field_predA[1];
-    } else if (c_valid) {
-        px = field_predC[0];
-        py = field_predC[1];
-    } else if (b_valid) {
-        px = field_predB[0];
-        py = field_predB[1];
-    } else {
-        px = 0;
-        py = 0;
-    }
-
-    if (num_samefield + num_oppfield > 1) {
-        px = mid_pred(field_predA[0], field_predB[0], field_predC[0]);
-        py = mid_pred(field_predA[1], field_predB[1], field_predC[1]);
-    }
-
-    /* Pullback MV as specified in 8.3.5.3.4 */
-    if (!v->field_mode) {
-        int qx, qy, X, Y;
-        qx = (s->mb_x << 6) + ((n == 1 || n == 3) ? 32 : 0);
-        qy = (s->mb_y << 6) + ((n == 2 || n == 3) ? 32 : 0);
-        X  = (s->mb_width  << 6) - 4;
-        Y  = (s->mb_height << 6) - 4;
-        if (mv1) {
-            if (qx + px < -60) px = -60 - qx;
-            if (qy + py < -60) py = -60 - qy;
-        } else {
-            if (qx + px < -28) px = -28 - qx;
-            if (qy + py < -28) py = -28 - qy;
-        }
-        if (qx + px > X) px = X - qx;
-        if (qy + py > Y) py = Y - qy;
-    }
-
-    if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) {
-        /* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 
10.3.5.4.3.5) */
-        hybridmv_thresh = 32;
-        if (a_valid && c_valid) {
-            if (is_intra[xy - wrap])
-                sum = FFABS(px) + FFABS(py);
-            else
-                sum = FFABS(px - field_predA[0]) + FFABS(py - field_predA[1]);
-            if (sum > hybridmv_thresh) {
-                if (get_bits1(&s->gb)) {     // read HYBRIDPRED bit
-                    px = field_predA[0];
-                    py = field_predA[1];
-                } else {
-                    px = field_predC[0];
-                    py = field_predC[1];
-                }
-            } else {
-                if (is_intra[xy - 1])
-                    sum = FFABS(px) + FFABS(py);
-                else
-                    sum = FFABS(px - field_predC[0]) + FFABS(py - 
field_predC[1]);
-                if (sum > hybridmv_thresh) {
-                    if (get_bits1(&s->gb)) {
-                        px = field_predA[0];
-                        py = field_predA[1];
-                    } else {
-                        px = field_predC[0];
-                        py = field_predC[1];
-                    }
-                }
-            }
-        }
-    }
-
-    if (v->field_mode && v->numref)
-        r_y >>= 1;
-    if (v->field_mode && v->cur_field_type && v->ref_field_type[dir] == 0)
-        y_bias = 1;
-    /* store MV using signed modulus of MV range defined in 4.11 */
-    s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy + 
v->blocks_off][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
-    s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy + 
v->blocks_off][1] = ((py + dmv_y + r_y - y_bias) & ((r_y << 1) - 1)) - r_y + 
y_bias;
-    if (mv1) { /* duplicate motion data for 1-MV block */
-        s->current_picture.motion_val[dir][xy +    1 +     v->blocks_off][0] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][0];
-        s->current_picture.motion_val[dir][xy +    1 +     v->blocks_off][1] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][1];
-        s->current_picture.motion_val[dir][xy + wrap +     v->blocks_off][0] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][0];
-        s->current_picture.motion_val[dir][xy + wrap +     v->blocks_off][1] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][1];
-        s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][0] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][0];
-        s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][1] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][1];
-        v->mv_f[dir][xy +    1 + v->blocks_off] = v->mv_f[dir][xy +            
v->blocks_off];
-        v->mv_f[dir][xy + wrap + v->blocks_off] = v->mv_f[dir][xy + wrap + 1 + 
v->blocks_off] = v->mv_f[dir][xy + v->blocks_off];
-    }
-}
-
-/** Predict and set motion vector for interlaced frame picture MBs
- */
-static void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,
-                              int mvn, int r_x, int r_y, uint8_t* is_intra, 
int dir)
-{
-    MpegEncContext *s = &v->s;
-    int xy, wrap, off = 0;
-    int A[2], B[2], C[2];
-    int px, py;
-    int a_valid = 0, b_valid = 0, c_valid = 0;
-    int field_a, field_b, field_c; // 0: same, 1: opposit
-    int total_valid, num_samefield, num_oppfield;
-    int pos_c, pos_b, n_adj;
-
-    wrap = s->b8_stride;
-    xy = s->block_index[n];
-
-    if (s->mb_intra) {
-        s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0;
-        s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0;
-        s->current_picture.motion_val[1][xy][0] = 0;
-        s->current_picture.motion_val[1][xy][1] = 0;
-        if (mvn == 1) { /* duplicate motion data for 1-MV block */
-            s->current_picture.motion_val[0][xy + 1][0]        = 0;
-            s->current_picture.motion_val[0][xy + 1][1]        = 0;
-            s->current_picture.motion_val[0][xy + wrap][0]     = 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][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][1]        = 0;
-            s->current_picture.motion_val[1][xy + wrap][0]     = 0;
-            s->current_picture.motion_val[1][xy + wrap][1]     = 0;
-            s->current_picture.motion_val[1][xy + wrap + 1][0] = 0;
-            s->current_picture.motion_val[1][xy + wrap + 1][1] = 0;
-        }
-        return;
-    }
-
-    off = ((n == 0) || (n == 1)) ? 1 : -1;
-    /* predict A */
-    if (s->mb_x || (n == 1) || (n == 3)) {
-        if ((v->blk_mv_type[xy]) // current block (MB) has a field MV
-            || (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both 
have frame MV
-            A[0] = s->current_picture.motion_val[dir][xy - 1][0];
-            A[1] = s->current_picture.motion_val[dir][xy - 1][1];
-            a_valid = 1;
-        } else { // current block has frame mv and cand. has field MV (so 
average)
-            A[0] = (s->current_picture.motion_val[dir][xy - 1][0]
-                    + s->current_picture.motion_val[dir][xy - 1 + off * 
wrap][0] + 1) >> 1;
-            A[1] = (s->current_picture.motion_val[dir][xy - 1][1]
-                    + s->current_picture.motion_val[dir][xy - 1 + off * 
wrap][1] + 1) >> 1;
-            a_valid = 1;
-        }
-        if (!(n & 1) && v->is_intra[s->mb_x - 1]) {
-            a_valid = 0;
-            A[0] = A[1] = 0;
-        }
-    } else
-        A[0] = A[1] = 0;
-    /* Predict B and C */
-    B[0] = B[1] = C[0] = C[1] = 0;
-    if (n == 0 || n == 1 || v->blk_mv_type[xy]) {
-        if (!s->first_slice_line) {
-            if (!v->is_intra[s->mb_x - s->mb_stride]) {
-                b_valid = 1;
-                n_adj   = n | 2;
-                pos_b   = s->block_index[n_adj] - 2 * wrap;
-                if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) {
-                    n_adj = (n & 2) | (n & 1);
-                }
-                B[0] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0];
-                B[1] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1];
-                if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) {
-                    B[0] = (B[0] + 
s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 
1) >> 1;
-                    B[1] = (B[1] + 
s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 
1) >> 1;
-                }
-            }
-            if (s->mb_width > 1) {
-                if (!v->is_intra[s->mb_x - s->mb_stride + 1]) {
-                    c_valid = 1;
-                    n_adj   = 2;
-                    pos_c   = s->block_index[2] - 2 * wrap + 2;
-                    if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
-                        n_adj = n & 2;
-                    }
-                    C[0] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0];
-                    C[1] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1];
-                    if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
-                        C[0] = (1 + C[0] + 
(s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 
2][0])) >> 1;
-                        C[1] = (1 + C[1] + 
(s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 
2][1])) >> 1;
-                    }
-                    if (s->mb_x == s->mb_width - 1) {
-                        if (!v->is_intra[s->mb_x - s->mb_stride - 1]) {
-                            c_valid = 1;
-                            n_adj   = 3;
-                            pos_c   = s->block_index[3] - 2 * wrap - 2;
-                            if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
-                                n_adj = n | 1;
-                            }
-                            C[0] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0];
-                            C[1] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1];
-                            if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
-                                C[0] = (1 + C[0] + 
s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1;
-                                C[1] = (1 + C[1] + 
s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1;
-                            }
-                        } else
-                            c_valid = 0;
-                    }
-                }
-            }
-        }
-    } else {
-        pos_b   = s->block_index[1];
-        b_valid = 1;
-        B[0]    = s->current_picture.motion_val[dir][pos_b][0];
-        B[1]    = s->current_picture.motion_val[dir][pos_b][1];
-        pos_c   = s->block_index[0];
-        c_valid = 1;
-        C[0]    = s->current_picture.motion_val[dir][pos_c][0];
-        C[1]    = s->current_picture.motion_val[dir][pos_c][1];
-    }
-
-    total_valid = a_valid + b_valid + c_valid;
-    // check if predictor A is out of bounds
-    if (!s->mb_x && !(n == 1 || n == 3)) {
-        A[0] = A[1] = 0;
-    }
-    // check if predictor B is out of bounds
-    if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && 
!(n & 2))) {
-        B[0] = B[1] = C[0] = C[1] = 0;
-    }
-    if (!v->blk_mv_type[xy]) {
-        if (s->mb_width == 1) {
-            px = B[0];
-            py = B[1];
-        } else {
-            if (total_valid >= 2) {
-                px = mid_pred(A[0], B[0], C[0]);
-                py = mid_pred(A[1], B[1], C[1]);
-            } else if (total_valid) {
-                if (a_valid) { px = A[0]; py = A[1]; }
-                if (b_valid) { px = B[0]; py = B[1]; }
-                if (c_valid) { px = C[0]; py = C[1]; }
-            } else
-                px = py = 0;
-        }
-    } else {
-        if (a_valid)
-            field_a = (A[1] & 4) ? 1 : 0;
-        else
-            field_a = 0;
-        if (b_valid)
-            field_b = (B[1] & 4) ? 1 : 0;
-        else
-            field_b = 0;
-        if (c_valid)
-            field_c = (C[1] & 4) ? 1 : 0;
-        else
-            field_c = 0;
-
-        num_oppfield  = field_a + field_b + field_c;
-        num_samefield = total_valid - num_oppfield;
-        if (total_valid == 3) {
-            if ((num_samefield == 3) || (num_oppfield == 3)) {
-                px = mid_pred(A[0], B[0], C[0]);
-                py = mid_pred(A[1], B[1], C[1]);
-            } else if (num_samefield >= num_oppfield) {
-                /* take one MV from same field set depending on priority
-                the check for B may not be necessary */
-                px = !field_a ? A[0] : B[0];
-                py = !field_a ? A[1] : B[1];
-            } else {
-                px =  field_a ? A[0] : B[0];
-                py =  field_a ? A[1] : B[1];
-            }
-        } else if (total_valid == 2) {
-            if (num_samefield >= num_oppfield) {
-                if (!field_a && a_valid) {
-                    px = A[0];
-                    py = A[1];
-                } else if (!field_b && b_valid) {
-                    px = B[0];
-                    py = B[1];
-                } else if (c_valid) {
-                    px = C[0];
-                    py = C[1];
-                } else px = py = 0;
-            } else {
-                if (field_a && a_valid) {
-                    px = A[0];
-                    py = A[1];
-                } else if (field_b && b_valid) {
-                    px = B[0];
-                    py = B[1];
-                } else if (c_valid) {
-                    px = C[0];
-                    py = C[1];
-                } else
-                    px = py = 0;
-            }
-        } else if (total_valid == 1) {
-            px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]);
-            py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]);
-        } else
-            px = py = 0;
-    }
-
-    /* store MV using signed modulus of MV range defined in 4.11 */
-    s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy][0] = ((px + 
dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
-    s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy][1] = ((py + 
dmv_y + r_y) & ((r_y << 1) - 1)) - r_y;
-    if (mvn == 1) { /* duplicate motion data for 1-MV block */
-        s->current_picture.motion_val[dir][xy +    1    ][0] = 
s->current_picture.motion_val[dir][xy][0];
-        s->current_picture.motion_val[dir][xy +    1    ][1] = 
s->current_picture.motion_val[dir][xy][1];
-        s->current_picture.motion_val[dir][xy + wrap    ][0] = 
s->current_picture.motion_val[dir][xy][0];
-        s->current_picture.motion_val[dir][xy + wrap    ][1] = 
s->current_picture.motion_val[dir][xy][1];
-        s->current_picture.motion_val[dir][xy + wrap + 1][0] = 
s->current_picture.motion_val[dir][xy][0];
-        s->current_picture.motion_val[dir][xy + wrap + 1][1] = 
s->current_picture.motion_val[dir][xy][1];
-    } else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */
-        s->current_picture.motion_val[dir][xy + 1][0] = 
s->current_picture.motion_val[dir][xy][0];
-        s->current_picture.motion_val[dir][xy + 1][1] = 
s->current_picture.motion_val[dir][xy][1];
-        s->mv[dir][n + 1][0] = s->mv[dir][n][0];
-        s->mv[dir][n + 1][1] = s->mv[dir][n][1];
-    }
-}
-
-static av_always_inline int scale_mv(int value, int bfrac, int inv, int qs)
-{
-    int n = bfrac;
-
-#if B_FRACTION_DEN==256
-    if (inv)
-        n -= 256;
-    if (!qs)
-        return 2 * ((value * n + 255) >> 9);
-    return (value * n + 128) >> 8;
-#else
-    if (inv)
-        n -= B_FRACTION_DEN;
-    if (!qs)
-        return 2 * ((value * n + B_FRACTION_DEN - 1) / (2 * B_FRACTION_DEN));
-    return (value * n + B_FRACTION_DEN/2) / B_FRACTION_DEN;
-#endif
-}
-
 /** Reconstruct motion vector for B-frame and do motion compensation
  */
 static inline void vc1_b_mc(VC1Context *v, int dmv_x[2], int dmv_y[2],
@@ -1019,277 +347,6 @@ static inline void vc1_b_mc(VC1Context *v, int dmv_x[2], 
int dmv_y[2],
     ff_vc1_mc_1mv(v, (mode == BMV_TYPE_BACKWARD));
 }
 
-static void vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2],
-                          int direct, int mvtype)
-{
-    MpegEncContext *s = &v->s;
-    int xy, wrap, off = 0;
-    int16_t *A, *B, *C;
-    int px, py;
-    int sum;
-    int r_x, r_y;
-    const uint8_t *is_intra = v->mb_type[0];
-
-    r_x = v->range_x;
-    r_y = v->range_y;
-    /* scale MV difference to be quad-pel */
-    dmv_x[0] <<= 1 - s->quarter_sample;
-    dmv_y[0] <<= 1 - s->quarter_sample;
-    dmv_x[1] <<= 1 - s->quarter_sample;
-    dmv_y[1] <<= 1 - s->quarter_sample;
-
-    wrap = s->b8_stride;
-    xy = s->block_index[0];
-
-    if (s->mb_intra) {
-        s->current_picture.motion_val[0][xy + v->blocks_off][0] =
-        s->current_picture.motion_val[0][xy + v->blocks_off][1] =
-        s->current_picture.motion_val[1][xy + v->blocks_off][0] =
-        s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0;
-        return;
-    }
-    if (!v->field_mode) {
-        s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], 
v->bfraction, 0, s->quarter_sample);
-        s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], 
v->bfraction, 0, s->quarter_sample);
-        s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], 
v->bfraction, 1, s->quarter_sample);
-        s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], 
v->bfraction, 1, s->quarter_sample);
-
-        /* Pullback predicted motion vectors as specified in 8.4.5.4 */
-        s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), 
(s->mb_width  << 6) - 4 - (s->mb_x << 6));
-        s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), 
(s->mb_height << 6) - 4 - (s->mb_y << 6));
-        s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), 
(s->mb_width  << 6) - 4 - (s->mb_x << 6));
-        s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), 
(s->mb_height << 6) - 4 - (s->mb_y << 6));
-    }
-    if (direct) {
-        s->current_picture.motion_val[0][xy + v->blocks_off][0] = 
s->mv[0][0][0];
-        s->current_picture.motion_val[0][xy + v->blocks_off][1] = 
s->mv[0][0][1];
-        s->current_picture.motion_val[1][xy + v->blocks_off][0] = 
s->mv[1][0][0];
-        s->current_picture.motion_val[1][xy + v->blocks_off][1] = 
s->mv[1][0][1];
-        return;
-    }
-
-    if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
-        C   = s->current_picture.motion_val[0][xy - 2];
-        A   = s->current_picture.motion_val[0][xy - wrap * 2];
-        off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
-        B   = s->current_picture.motion_val[0][xy - wrap * 2 + off];
-
-        if (!s->mb_x) C[0] = C[1] = 0;
-        if (!s->first_slice_line) { // predictor A is not out of bounds
-            if (s->mb_width == 1) {
-                px = A[0];
-                py = A[1];
-            } else {
-                px = mid_pred(A[0], B[0], C[0]);
-                py = mid_pred(A[1], B[1], C[1]);
-            }
-        } else if (s->mb_x) { // predictor C is not out of bounds
-            px = C[0];
-            py = C[1];
-        } else {
-            px = py = 0;
-        }
-        /* Pullback MV as specified in 8.3.5.3.4 */
-        {
-            int qx, qy, X, Y;
-            if (v->profile < PROFILE_ADVANCED) {
-                qx = (s->mb_x << 5);
-                qy = (s->mb_y << 5);
-                X  = (s->mb_width  << 5) - 4;
-                Y  = (s->mb_height << 5) - 4;
-                if (qx + px < -28) px = -28 - qx;
-                if (qy + py < -28) py = -28 - qy;
-                if (qx + px > X) px = X - qx;
-                if (qy + py > Y) py = Y - qy;
-            } else {
-                qx = (s->mb_x << 6);
-                qy = (s->mb_y << 6);
-                X  = (s->mb_width  << 6) - 4;
-                Y  = (s->mb_height << 6) - 4;
-                if (qx + px < -60) px = -60 - qx;
-                if (qy + py < -60) py = -60 - qy;
-                if (qx + px > X) px = X - qx;
-                if (qy + py > Y) py = Y - qy;
-            }
-        }
-        /* Calculate hybrid prediction as specified in 8.3.5.3.5 */
-        if (0 && !s->first_slice_line && s->mb_x) {
-            if (is_intra[xy - wrap])
-                sum = FFABS(px) + FFABS(py);
-            else
-                sum = FFABS(px - A[0]) + FFABS(py - A[1]);
-            if (sum > 32) {
-                if (get_bits1(&s->gb)) {
-                    px = A[0];
-                    py = A[1];
-                } else {
-                    px = C[0];
-                    py = C[1];
-                }
-            } else {
-                if (is_intra[xy - 2])
-                    sum = FFABS(px) + FFABS(py);
-                else
-                    sum = FFABS(px - C[0]) + FFABS(py - C[1]);
-                if (sum > 32) {
-                    if (get_bits1(&s->gb)) {
-                        px = A[0];
-                        py = A[1];
-                    } else {
-                        px = C[0];
-                        py = C[1];
-                    }
-                }
-            }
-        }
-        /* store MV using signed modulus of MV range defined in 4.11 */
-        s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x;
-        s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y;
-    }
-    if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
-        C   = s->current_picture.motion_val[1][xy - 2];
-        A   = s->current_picture.motion_val[1][xy - wrap * 2];
-        off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
-        B   = s->current_picture.motion_val[1][xy - wrap * 2 + off];
-
-        if (!s->mb_x)
-            C[0] = C[1] = 0;
-        if (!s->first_slice_line) { // predictor A is not out of bounds
-            if (s->mb_width == 1) {
-                px = A[0];
-                py = A[1];
-            } else {
-                px = mid_pred(A[0], B[0], C[0]);
-                py = mid_pred(A[1], B[1], C[1]);
-            }
-        } else if (s->mb_x) { // predictor C is not out of bounds
-            px = C[0];
-            py = C[1];
-        } else {
-            px = py = 0;
-        }
-        /* Pullback MV as specified in 8.3.5.3.4 */
-        {
-            int qx, qy, X, Y;
-            if (v->profile < PROFILE_ADVANCED) {
-                qx = (s->mb_x << 5);
-                qy = (s->mb_y << 5);
-                X  = (s->mb_width  << 5) - 4;
-                Y  = (s->mb_height << 5) - 4;
-                if (qx + px < -28) px = -28 - qx;
-                if (qy + py < -28) py = -28 - qy;
-                if (qx + px > X) px = X - qx;
-                if (qy + py > Y) py = Y - qy;
-            } else {
-                qx = (s->mb_x << 6);
-                qy = (s->mb_y << 6);
-                X  = (s->mb_width  << 6) - 4;
-                Y  = (s->mb_height << 6) - 4;
-                if (qx + px < -60) px = -60 - qx;
-                if (qy + py < -60) py = -60 - qy;
-                if (qx + px > X) px = X - qx;
-                if (qy + py > Y) py = Y - qy;
-            }
-        }
-        /* Calculate hybrid prediction as specified in 8.3.5.3.5 */
-        if (0 && !s->first_slice_line && s->mb_x) {
-            if (is_intra[xy - wrap])
-                sum = FFABS(px) + FFABS(py);
-            else
-                sum = FFABS(px - A[0]) + FFABS(py - A[1]);
-            if (sum > 32) {
-                if (get_bits1(&s->gb)) {
-                    px = A[0];
-                    py = A[1];
-                } else {
-                    px = C[0];
-                    py = C[1];
-                }
-            } else {
-                if (is_intra[xy - 2])
-                    sum = FFABS(px) + FFABS(py);
-                else
-                    sum = FFABS(px - C[0]) + FFABS(py - C[1]);
-                if (sum > 32) {
-                    if (get_bits1(&s->gb)) {
-                        px = A[0];
-                        py = A[1];
-                    } else {
-                        px = C[0];
-                        py = C[1];
-                    }
-                }
-            }
-        }
-        /* store MV using signed modulus of MV range defined in 4.11 */
-
-        s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x;
-        s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y;
-    }
-    s->current_picture.motion_val[0][xy][0] = s->mv[0][0][0];
-    s->current_picture.motion_val[0][xy][1] = s->mv[0][0][1];
-    s->current_picture.motion_val[1][xy][0] = s->mv[1][0][0];
-    s->current_picture.motion_val[1][xy][1] = s->mv[1][0][1];
-}
-
-static void vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y,
-                                int mv1, int *pred_flag)
-{
-    int dir = (v->bmvtype == BMV_TYPE_BACKWARD) ? 1 : 0;
-    MpegEncContext *s = &v->s;
-    int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
-
-    if (v->bmvtype == BMV_TYPE_DIRECT) {
-        int total_opp, k, f;
-        if (s->next_picture.mb_type[mb_pos + v->mb_off] != MB_TYPE_INTRA) {
-            s->mv[0][0][0] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0],
-                                      v->bfraction, 0, s->quarter_sample);
-            s->mv[0][0][1] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1],
-                                      v->bfraction, 0, s->quarter_sample);
-            s->mv[1][0][0] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0],
-                                      v->bfraction, 1, s->quarter_sample);
-            s->mv[1][0][1] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1],
-                                      v->bfraction, 1, s->quarter_sample);
-
-            total_opp = v->mv_f_next[0][s->block_index[0] + v->blocks_off]
-                      + v->mv_f_next[0][s->block_index[1] + v->blocks_off]
-                      + v->mv_f_next[0][s->block_index[2] + v->blocks_off]
-                      + v->mv_f_next[0][s->block_index[3] + v->blocks_off];
-            f = (total_opp > 2) ? 1 : 0;
-        } else {
-            s->mv[0][0][0] = s->mv[0][0][1] = 0;
-            s->mv[1][0][0] = s->mv[1][0][1] = 0;
-            f = 0;
-        }
-        v->ref_field_type[0] = v->ref_field_type[1] = v->cur_field_type ^ f;
-        for (k = 0; k < 4; k++) {
-            s->current_picture.motion_val[0][s->block_index[k] + 
v->blocks_off][0] = s->mv[0][0][0];
-            s->current_picture.motion_val[0][s->block_index[k] + 
v->blocks_off][1] = s->mv[0][0][1];
-            s->current_picture.motion_val[1][s->block_index[k] + 
v->blocks_off][0] = s->mv[1][0][0];
-            s->current_picture.motion_val[1][s->block_index[k] + 
v->blocks_off][1] = s->mv[1][0][1];
-            v->mv_f[0][s->block_index[k] + v->blocks_off] = f;
-            v->mv_f[1][s->block_index[k] + v->blocks_off] = f;
-        }
-        return;
-    }
-    if (v->bmvtype == BMV_TYPE_INTERPOLATED) {
-        vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0],   1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[0], 0);
-        vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1],   1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[1], 1);
-        return;
-    }
-    if (dir) { // backward
-        vc1_pred_mv(v, n, dmv_x[1], dmv_y[1], mv1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[1], 1);
-        if (n == 3 || mv1) {
-            vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0],   1, v->range_x, v->range_y, 
v->mb_type[0], 0, 0);
-        }
-    } else { // forward
-        vc1_pred_mv(v, n, dmv_x[0], dmv_y[0], mv1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[0], 0);
-        if (n == 3 || mv1) {
-            vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1],   1, v->range_x, v->range_y, 
v->mb_type[0], 0, 1);
-        }
-    }
-}
-
 /** Get predicted DC value for I-frames only
  * prediction dir: left=0, top=1
  * @param s MpegEncContext
@@ -1364,7 +421,7 @@ static inline int vc1_i_pred_dc(MpegEncContext *s, int 
overlap, int pq, int n,
  * @param dc_val_ptr Pointer to DC predictor
  * @param dir_ptr Prediction direction for use in AC prediction
  */
-static inline int vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n,
+static inline int ff_vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n,
                               int a_avail, int c_avail,
                               int16_t **dc_val_ptr, int *dir_ptr)
 {
@@ -1749,7 +806,7 @@ static int vc1_decode_i_block_adv(VC1Context *v, int16_t 
block[64], int n,
     }
 
     /* Prediction */
-    dcdiff += vc1_pred_dc(&v->s, v->overlap, mquant, n, v->a_avail, 
v->c_avail, &dc_val, &dc_pred_dir);
+    dcdiff += ff_vc1_pred_dc(&v->s, v->overlap, mquant, n, v->a_avail, 
v->c_avail, &dc_val, &dc_pred_dir);
     *dc_val = dcdiff;
 
     /* Store the quantized DC coeff, used for prediction */
@@ -1970,7 +1027,7 @@ static int vc1_decode_intra_block(VC1Context *v, int16_t 
block[64], int n,
     }
 
     /* Prediction */
-    dcdiff += vc1_pred_dc(&v->s, v->overlap, mquant, n, a_avail, c_avail, 
&dc_val, &dc_pred_dir);
+    dcdiff += ff_vc1_pred_dc(&v->s, v->overlap, mquant, n, a_avail, c_avail, 
&dc_val, &dc_pred_dir);
     *dc_val = dcdiff;
 
     /* Store the quantized DC coeff, used for prediction */
@@ -2331,7 +1388,7 @@ static int vc1_decode_p_mb(VC1Context *v)
                 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;
-            vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, 
v->mb_type[0], 0, 0);
+            ff_vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, 
v->mb_type[0], 0, 0);
 
             /* FIXME Set DC val for inter block ? */
             if (s->mb_intra && !mb_has_coeffs) {
@@ -2406,7 +1463,7 @@ static int vc1_decode_p_mb(VC1Context *v)
             }
             s->current_picture.mb_type[mb_pos]      = MB_TYPE_SKIP;
             s->current_picture.qscale_table[mb_pos] = 0;
-            vc1_pred_mv(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 
0, 0);
+            ff_vc1_pred_mv(v, 0, 0, 0, 1, v->range_x, v->range_y, 
v->mb_type[0], 0, 0);
             ff_vc1_mc_1mv(v, 0);
         }
     } else { // 4MV mode
@@ -2426,7 +1483,7 @@ static int vc1_decode_p_mb(VC1Context *v)
                     if (val) {
                         GET_MVDATA(dmv_x, dmv_y);
                     }
-                    vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, 
v->mb_type[0], 0, 0);
+                    ff_vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, 
v->range_y, v->mb_type[0], 0, 0);
                     if (!s->mb_intra)
                         ff_vc1_mc_4mv_luma(v, i, 0, 0);
                     intra_count += s->mb_intra;
@@ -2519,7 +1576,7 @@ static int vc1_decode_p_mb(VC1Context *v)
                 s->dc_val[0][s->block_index[i]]  = 0;
             }
             for (i = 0; i < 4; i++) {
-                vc1_pred_mv(v, i, 0, 0, 0, v->range_x, v->range_y, 
v->mb_type[0], 0, 0);
+                ff_vc1_pred_mv(v, i, 0, 0, 0, v->range_x, v->range_y, 
v->mb_type[0], 0, 0);
                 ff_vc1_mc_4mv_luma(v, i, 0, 0);
             }
             ff_vc1_mc_4mv_chroma(v, 0);
@@ -2672,7 +1729,7 @@ static int vc1_decode_p_mb_intfr(VC1Context *v)
                         if (val) {
                             get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
                         }
-                        vc1_pred_mv_intfr(v, i, dmv_x, dmv_y, 0, v->range_x, 
v->range_y, v->mb_type[0], 0);
+                        ff_vc1_pred_mv_intfr(v, i, dmv_x, dmv_y, 0, 
v->range_x, v->range_y, v->mb_type[0], 0);
                         ff_vc1_mc_4mv_luma(v, i, 0, 0);
                     } else if (i == 4) {
                         ff_vc1_mc_4mv_chroma4(v, 0, 0, 0);
@@ -2684,14 +1741,14 @@ static int vc1_decode_p_mb_intfr(VC1Context *v)
                 if (mvbp & 2) {
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
                 }
-                vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], 0);
+                ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], 0);
                 ff_vc1_mc_4mv_luma(v, 0, 0, 0);
                 ff_vc1_mc_4mv_luma(v, 1, 0, 0);
                 dmv_x = dmv_y = 0;
                 if (mvbp & 1) {
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
                 }
-                vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], 0);
+                ff_vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], 0);
                 ff_vc1_mc_4mv_luma(v, 2, 0, 0);
                 ff_vc1_mc_4mv_luma(v, 3, 0, 0);
                 ff_vc1_mc_4mv_chroma4(v, 0, 0, 0);
@@ -2701,7 +1758,7 @@ static int vc1_decode_p_mb_intfr(VC1Context *v)
                 if (mvbp) {
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
                 }
-                vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], 0);
+                ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], 0);
                 ff_vc1_mc_1mv(v, 0);
             }
             if (cbp)
@@ -2741,7 +1798,7 @@ static int vc1_decode_p_mb_intfr(VC1Context *v)
         v->blk_mv_type[s->block_index[1]] = 0;
         v->blk_mv_type[s->block_index[2]] = 0;
         v->blk_mv_type[s->block_index[3]] = 0;
-        vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, 
v->mb_type[0], 0);
+        ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, 
v->mb_type[0], 0);
         ff_vc1_mc_1mv(v, 0);
     }
     if (s->mb_x == s->mb_width - 1)
@@ -2818,7 +1875,7 @@ static int vc1_decode_p_mb_intfi(VC1Context *v)
             if (idx_mbmode & 1) {
                 get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag);
             }
-            vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag, 0);
+            ff_vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag, 0);
             ff_vc1_mc_1mv(v, 0);
             mb_has_coeffs = !(idx_mbmode & 2);
         } else { // 4-MV
@@ -2830,7 +1887,7 @@ static int vc1_decode_p_mb_intfi(VC1Context *v)
                     if (val) {
                         get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag);
                     }
-                    vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, 
v->mb_type[0], pred_flag, 0);
+                    ff_vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, 
v->range_y, v->mb_type[0], pred_flag, 0);
                     ff_vc1_mc_4mv_luma(v, i, 0, 0);
                 } else if (i == 4)
                     ff_vc1_mc_4mv_chroma(v, 0);
@@ -2935,7 +1992,7 @@ static void vc1_decode_b_mb(VC1Context *v)
     if (skipped) {
         if (direct)
             bmvtype = BMV_TYPE_INTERPOLATED;
-        vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
+        ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
         vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
         return;
     }
@@ -2947,12 +2004,12 @@ static void vc1_decode_b_mb(VC1Context *v)
         if (!v->ttmbf)
             ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, 
VC1_TTMB_VLC_BITS, 2);
         dmv_x[0] = dmv_y[0] = dmv_x[1] = dmv_y[1] = 0;
-        vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
+        ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
         vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
     } else {
         if (!mb_has_coeffs && !s->mb_intra) {
             /* no coded blocks - effectively skipped */
-            vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
+            ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
             vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
             return;
         }
@@ -2961,18 +2018,18 @@ static void vc1_decode_b_mb(VC1Context *v)
             s->current_picture.qscale_table[mb_pos] = mquant;
             s->ac_pred = get_bits1(gb);
             cbp = 0;
-            vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
+            ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
         } else {
             if (bmvtype == BMV_TYPE_INTERPOLATED) {
                 GET_MVDATA(dmv_x[0], dmv_y[0]);
                 if (!mb_has_coeffs) {
                     /* interpolated skipped block */
-                    vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
+                    ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
                     vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
                     return;
                 }
             }
-            vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
+            ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
             if (!s->mb_intra) {
                 vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
             }
@@ -3127,7 +2184,7 @@ static void vc1_decode_b_mb_intfi(VC1Context *v)
                 dmv_x[0] = dmv_y[0] = pred_flag[0] = 0;
                 dmv_x[1] = dmv_y[1] = pred_flag[0] = 0;
             }
-            vc1_pred_b_mv_intfi(v, 0, dmv_x, dmv_y, 1, pred_flag);
+            ff_vc1_pred_b_mv_intfi(v, 0, dmv_x, dmv_y, 1, pred_flag);
             vc1_b_mc(v, dmv_x, dmv_y, (bmvtype == BMV_TYPE_DIRECT), bmvtype);
             mb_has_coeffs = !(idx_mbmode & 2);
         } else { // 4-MV
@@ -3145,7 +2202,7 @@ static void vc1_decode_b_mb_intfi(VC1Context *v)
                                                  &dmv_y[bmvtype == 
BMV_TYPE_BACKWARD],
                                              &pred_flag[bmvtype == 
BMV_TYPE_BACKWARD]);
                     }
-                    vc1_pred_b_mv_intfi(v, i, dmv_x, dmv_y, 0, pred_flag);
+                    ff_vc1_pred_b_mv_intfi(v, i, dmv_x, dmv_y, 0, pred_flag);
                     ff_vc1_mc_4mv_luma(v, i, bmvtype == BMV_TYPE_BACKWARD, 0);
                 } else if (i == 4)
                     ff_vc1_mc_4mv_chroma(v, bmvtype == BMV_TYPE_BACKWARD);
@@ -3368,7 +2425,7 @@ static int vc1_decode_b_mb_intfr(VC1Context *v)
                     if (val)
                         get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
                     j = i > 1 ? 2 : 0;
-                    vc1_pred_mv_intfr(v, j, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], dir);
+                    ff_vc1_pred_mv_intfr(v, j, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], dir);
                     ff_vc1_mc_4mv_luma(v, j, dir, dir);
                     ff_vc1_mc_4mv_luma(v, j+1, dir, dir);
                 }
@@ -3381,14 +2438,14 @@ static int vc1_decode_b_mb_intfr(VC1Context *v)
                 if (mvbp & 2)
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
 
-                vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], 0);
+                ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], 0);
                 ff_vc1_mc_1mv(v, 0);
 
                 dmv_x = dmv_y = 0;
                 if (mvbp & 1)
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
 
-                vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], 1);
+                ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], 1);
                 ff_vc1_interp_mc(v);
             } else if (twomv) {
                 dir = bmvtype == BMV_TYPE_BACKWARD;
@@ -3399,12 +2456,12 @@ static int vc1_decode_b_mb_intfr(VC1Context *v)
                 dmv_x = dmv_y = 0;
                 if (mvbp & 2)
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
-                vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], dir);
+                ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], dir);
 
                 dmv_x = dmv_y = 0;
                 if (mvbp & 1)
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
-                vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], dir2);
+                ff_vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, 
v->range_y, v->mb_type[0], dir2);
 
                 if (mvsw) {
                     for (i = 0; i < 2; i++) {
@@ -3414,8 +2471,8 @@ static int vc1_decode_b_mb_intfr(VC1Context *v)
                         s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = 
s->current_picture.motion_val[dir2][s->block_index[i]][1] = 
s->current_picture.motion_val[dir2][s->block_index[i+2]][1];
                     }
                 } else {
-                    vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 
v->mb_type[0], !dir);
-                    vc1_pred_mv_intfr(v, 2, 0, 0, 2, v->range_x, v->range_y, 
v->mb_type[0], !dir);
+                    ff_vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, 
v->range_y, v->mb_type[0], !dir);
+                    ff_vc1_pred_mv_intfr(v, 2, 0, 0, 2, v->range_x, 
v->range_y, v->mb_type[0], !dir);
                 }
 
                 ff_vc1_mc_4mv_luma(v, 0, dir, 0);
@@ -3431,12 +2488,12 @@ static int vc1_decode_b_mb_intfr(VC1Context *v)
                 if (mvbp)
                     get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0);
 
-                vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], dir);
+                ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, 
v->range_y, v->mb_type[0], dir);
                 v->blk_mv_type[s->block_index[0]] = 1;
                 v->blk_mv_type[s->block_index[1]] = 1;
                 v->blk_mv_type[s->block_index[2]] = 1;
                 v->blk_mv_type[s->block_index[3]] = 1;
-                vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, 
!dir);
+                ff_vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, 
!dir);
                 for (i = 0; i < 2; i++) {
                     s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = 
s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = 
s->current_picture.motion_val[!dir][s->block_index[i]][0];
                     s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = 
s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = 
s->current_picture.motion_val[!dir][s->block_index[i]][1];
@@ -3484,11 +2541,11 @@ static int vc1_decode_b_mb_intfr(VC1Context *v)
 
             if (!direct) {
                 if (bmvtype == BMV_TYPE_INTERPOLATED) {
-                    vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, 
v->mb_type[0], 0);
-                    vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, 
v->mb_type[0], 1);
+                    ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, 
v->range_y, v->mb_type[0], 0);
+                    ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, 
v->range_y, v->mb_type[0], 1);
                 } else {
                     dir = bmvtype == BMV_TYPE_BACKWARD;
-                    vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, 
v->mb_type[0], dir);
+                    ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, 
v->range_y, v->mb_type[0], dir);
                     if (mvsw) {
                         int dir2 = dir;
                         if (mvsw)
@@ -3504,7 +2561,7 @@ static int vc1_decode_b_mb_intfr(VC1Context *v)
                         v->blk_mv_type[s->block_index[1]] = 1;
                         v->blk_mv_type[s->block_index[2]] = 1;
                         v->blk_mv_type[s->block_index[3]] = 1;
-                        vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, 
v->range_y, 0, !dir);
+                        ff_vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, 
v->range_y, 0, !dir);
                         for (i = 0; i < 2; i++) {
                             s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = 
s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = 
s->current_picture.motion_val[!dir][s->block_index[i]][0];
                             s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = 
s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = 
s->current_picture.motion_val[!dir][s->block_index[i]][1];
diff --git a/libavcodec/vc1_pred.c b/libavcodec/vc1_pred.c
new file mode 100644
index 0000000..ce22e1f
--- /dev/null
+++ b/libavcodec/vc1_pred.c
@@ -0,0 +1,969 @@
+/*
+ * 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 block decoding routines
+ */
+
+#include "internal.h"
+#include "avcodec.h"
+#include "error_resilience.h"
+#include "mpeg_er.h"
+#include "mpegutils.h"
+#include "mpegvideo.h"
+#include "h263.h"
+#include "h264chroma.h"
+#include "qpeldsp.h"
+#include "vc1.h"
+#include "vc1_pred.h"
+#include "vc1data.h"
+#include "vc1acdata.h"
+#include "msmpeg4data.h"
+#include "unary.h"
+#include "mathops.h"
+
+static av_always_inline int scaleforsame_x(VC1Context *v, int n /* MV */, int 
dir)
+{
+    int scaledvalue, refdist;
+    int scalesame1, scalesame2;
+    int scalezone1_x, zone1offset_x;
+    int table_index = dir ^ v->second_field;
+
+    if (v->s.pict_type != AV_PICTURE_TYPE_B)
+        refdist = v->refdist;
+    else
+        refdist = dir ? v->brfd : v->frfd;
+    if (refdist > 3)
+        refdist = 3;
+    scalesame1    = ff_vc1_field_mvpred_scales[table_index][1][refdist];
+    scalesame2    = ff_vc1_field_mvpred_scales[table_index][2][refdist];
+    scalezone1_x  = ff_vc1_field_mvpred_scales[table_index][3][refdist];
+    zone1offset_x = ff_vc1_field_mvpred_scales[table_index][5][refdist];
+
+    if (FFABS(n) > 255)
+        scaledvalue = n;
+    else {
+        if (FFABS(n) < scalezone1_x)
+            scaledvalue = (n * scalesame1) >> 8;
+        else {
+            if (n < 0)
+                scaledvalue = ((n * scalesame2) >> 8) - zone1offset_x;
+            else
+                scaledvalue = ((n * scalesame2) >> 8) + zone1offset_x;
+        }
+    }
+    return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
+}
+
+static av_always_inline int scaleforsame_y(VC1Context *v, int i, int n /* MV 
*/, int dir)
+{
+    int scaledvalue, refdist;
+    int scalesame1, scalesame2;
+    int scalezone1_y, zone1offset_y;
+    int table_index = dir ^ v->second_field;
+
+    if (v->s.pict_type != AV_PICTURE_TYPE_B)
+        refdist = v->refdist;
+    else
+        refdist = dir ? v->brfd : v->frfd;
+    if (refdist > 3)
+        refdist = 3;
+    scalesame1    = ff_vc1_field_mvpred_scales[table_index][1][refdist];
+    scalesame2    = ff_vc1_field_mvpred_scales[table_index][2][refdist];
+    scalezone1_y  = ff_vc1_field_mvpred_scales[table_index][4][refdist];
+    zone1offset_y = ff_vc1_field_mvpred_scales[table_index][6][refdist];
+
+    if (FFABS(n) > 63)
+        scaledvalue = n;
+    else {
+        if (FFABS(n) < scalezone1_y)
+            scaledvalue = (n * scalesame1) >> 8;
+        else {
+            if (n < 0)
+                scaledvalue = ((n * scalesame2) >> 8) - zone1offset_y;
+            else
+                scaledvalue = ((n * scalesame2) >> 8) + zone1offset_y;
+        }
+    }
+
+    if (v->cur_field_type && !v->ref_field_type[dir])
+        return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
+    else
+        return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
+}
+
+static av_always_inline int scaleforopp_x(VC1Context *v, int n /* MV */)
+{
+    int scalezone1_x, zone1offset_x;
+    int scaleopp1, scaleopp2, brfd;
+    int scaledvalue;
+
+    brfd = FFMIN(v->brfd, 3);
+    scalezone1_x  = ff_vc1_b_field_mvpred_scales[3][brfd];
+    zone1offset_x = ff_vc1_b_field_mvpred_scales[5][brfd];
+    scaleopp1     = ff_vc1_b_field_mvpred_scales[1][brfd];
+    scaleopp2     = ff_vc1_b_field_mvpred_scales[2][brfd];
+
+    if (FFABS(n) > 255)
+        scaledvalue = n;
+    else {
+        if (FFABS(n) < scalezone1_x)
+            scaledvalue = (n * scaleopp1) >> 8;
+        else {
+            if (n < 0)
+                scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_x;
+            else
+                scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_x;
+        }
+    }
+    return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
+}
+
+static av_always_inline int scaleforopp_y(VC1Context *v, int n /* MV */, int 
dir)
+{
+    int scalezone1_y, zone1offset_y;
+    int scaleopp1, scaleopp2, brfd;
+    int scaledvalue;
+
+    brfd = FFMIN(v->brfd, 3);
+    scalezone1_y  = ff_vc1_b_field_mvpred_scales[4][brfd];
+    zone1offset_y = ff_vc1_b_field_mvpred_scales[6][brfd];
+    scaleopp1     = ff_vc1_b_field_mvpred_scales[1][brfd];
+    scaleopp2     = ff_vc1_b_field_mvpred_scales[2][brfd];
+
+    if (FFABS(n) > 63)
+        scaledvalue = n;
+    else {
+        if (FFABS(n) < scalezone1_y)
+            scaledvalue = (n * scaleopp1) >> 8;
+        else {
+            if (n < 0)
+                scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_y;
+            else
+                scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_y;
+        }
+    }
+    if (v->cur_field_type && !v->ref_field_type[dir]) {
+        return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
+    } else {
+        return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
+    }
+}
+
+static av_always_inline int scaleforsame(VC1Context *v, int i, int n /* MV */,
+                                         int dim, int dir)
+{
+    int brfd, scalesame;
+    int hpel = 1 - v->s.quarter_sample;
+
+    n >>= hpel;
+    if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) {
+        if (dim)
+            n = scaleforsame_y(v, i, n, dir) << hpel;
+        else
+            n = scaleforsame_x(v, n, dir) << hpel;
+        return n;
+    }
+    brfd      = FFMIN(v->brfd, 3);
+    scalesame = ff_vc1_b_field_mvpred_scales[0][brfd];
+
+    n = (n * scalesame >> 8) << hpel;
+    return n;
+}
+
+static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */,
+                                        int dim, int dir)
+{
+    int refdist, scaleopp;
+    int hpel = 1 - v->s.quarter_sample;
+
+    n >>= hpel;
+    if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) {
+        if (dim)
+            n = scaleforopp_y(v, n, dir) << hpel;
+        else
+            n = scaleforopp_x(v, n) << hpel;
+        return n;
+    }
+    if (v->s.pict_type != AV_PICTURE_TYPE_B)
+        refdist = FFMIN(v->refdist, 3);
+    else
+        refdist = dir ? v->brfd : v->frfd;
+    scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist];
+
+    n = (n * scaleopp >> 8) << hpel;
+    return n;
+}
+
+/** Predict and set motion vector
+ */
+void ff_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,
+                    int pred_flag, int dir)
+{
+    MpegEncContext *s = &v->s;
+    int xy, wrap, off = 0;
+    int16_t *A, *B, *C;
+    int px, py;
+    int sum;
+    int mixedmv_pic, num_samefield = 0, num_oppfield = 0;
+    int opposite, a_f, b_f, c_f;
+    int16_t field_predA[2];
+    int16_t field_predB[2];
+    int16_t field_predC[2];
+    int a_valid, b_valid, c_valid;
+    int hybridmv_thresh, y_bias = 0;
+
+    if (v->mv_mode == MV_PMODE_MIXED_MV ||
+        ((v->mv_mode == MV_PMODE_INTENSITY_COMP) && (v->mv_mode2 == 
MV_PMODE_MIXED_MV)))
+        mixedmv_pic = 1;
+    else
+        mixedmv_pic = 0;
+    /* scale MV difference to be quad-pel */
+    dmv_x <<= 1 - s->quarter_sample;
+    dmv_y <<= 1 - s->quarter_sample;
+
+    wrap = s->b8_stride;
+    xy   = s->block_index[n];
+
+    if (s->mb_intra) {
+        s->mv[0][n][0] = s->current_picture.motion_val[0][xy + 
v->blocks_off][0] = 0;
+        s->mv[0][n][1] = s->current_picture.motion_val[0][xy + 
v->blocks_off][1] = 0;
+        s->current_picture.motion_val[1][xy + v->blocks_off][0] = 0;
+        s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0;
+        if (mv1) { /* duplicate motion data for 1-MV block */
+            s->current_picture.motion_val[0][xy + 1 + v->blocks_off][0]        
= 0;
+            s->current_picture.motion_val[0][xy + 1 + v->blocks_off][1]        
= 0;
+            s->current_picture.motion_val[0][xy + wrap + v->blocks_off][0]     
= 0;
+            s->current_picture.motion_val[0][xy + wrap + v->blocks_off][1]     
= 0;
+            s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][0] 
= 0;
+            s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][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 + v->blocks_off][0]        
= 0;
+            s->current_picture.motion_val[1][xy + 1 + v->blocks_off][1]        
= 0;
+            s->current_picture.motion_val[1][xy + wrap][0]                     
= 0;
+            s->current_picture.motion_val[1][xy + wrap + v->blocks_off][1]     
= 0;
+            s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][0] 
= 0;
+            s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][1] 
= 0;
+        }
+        return;
+    }
+
+    C = s->current_picture.motion_val[dir][xy -    1 + v->blocks_off];
+    A = s->current_picture.motion_val[dir][xy - wrap + v->blocks_off];
+    if (mv1) {
+        if (v->field_mode && mixedmv_pic)
+            off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
+        else
+            off = (s->mb_x == (s->mb_width - 1)) ? -1 : 2;
+    } else {
+        //in 4-MV mode different blocks have different B predictor position
+        switch (n) {
+        case 0:
+            off = (s->mb_x > 0) ? -1 : 1;
+            break;
+        case 1:
+            off = (s->mb_x == (s->mb_width - 1)) ? -1 : 1;
+            break;
+        case 2:
+            off = 1;
+            break;
+        case 3:
+            off = -1;
+        }
+    }
+    B = s->current_picture.motion_val[dir][xy - wrap + off + v->blocks_off];
+
+    a_valid = !s->first_slice_line || (n == 2 || n == 3);
+    b_valid = a_valid && (s->mb_width > 1);
+    c_valid = s->mb_x || (n == 1 || n == 3);
+    if (v->field_mode) {
+        a_valid = a_valid && !is_intra[xy - wrap];
+        b_valid = b_valid && !is_intra[xy - wrap + off];
+        c_valid = c_valid && !is_intra[xy - 1];
+    }
+
+    if (a_valid) {
+        a_f = v->mv_f[dir][xy - wrap + v->blocks_off];
+        num_oppfield  += a_f;
+        num_samefield += 1 - a_f;
+        field_predA[0] = A[0];
+        field_predA[1] = A[1];
+    } else {
+        field_predA[0] = field_predA[1] = 0;
+        a_f = 0;
+    }
+    if (b_valid) {
+        b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off];
+        num_oppfield  += b_f;
+        num_samefield += 1 - b_f;
+        field_predB[0] = B[0];
+        field_predB[1] = B[1];
+    } else {
+        field_predB[0] = field_predB[1] = 0;
+        b_f = 0;
+    }
+    if (c_valid) {
+        c_f = v->mv_f[dir][xy - 1 + v->blocks_off];
+        num_oppfield  += c_f;
+        num_samefield += 1 - c_f;
+        field_predC[0] = C[0];
+        field_predC[1] = C[1];
+    } else {
+        field_predC[0] = field_predC[1] = 0;
+        c_f = 0;
+    }
+
+    if (v->field_mode) {
+        if (!v->numref)
+            // REFFIELD determines if the last field or the second-last field 
is
+            // to be used as reference
+            opposite = 1 - v->reffield;
+        else {
+            if (num_samefield <= num_oppfield)
+                opposite = 1 - pred_flag;
+            else
+                opposite = pred_flag;
+        }
+    } else
+        opposite = 0;
+    if (opposite) {
+        if (a_valid && !a_f) {
+            field_predA[0] = scaleforopp(v, field_predA[0], 0, dir);
+            field_predA[1] = scaleforopp(v, field_predA[1], 1, dir);
+        }
+        if (b_valid && !b_f) {
+            field_predB[0] = scaleforopp(v, field_predB[0], 0, dir);
+            field_predB[1] = scaleforopp(v, field_predB[1], 1, dir);
+        }
+        if (c_valid && !c_f) {
+            field_predC[0] = scaleforopp(v, field_predC[0], 0, dir);
+            field_predC[1] = scaleforopp(v, field_predC[1], 1, dir);
+        }
+        v->mv_f[dir][xy + v->blocks_off] = 1;
+        v->ref_field_type[dir] = !v->cur_field_type;
+    } else {
+        if (a_valid && a_f) {
+            field_predA[0] = scaleforsame(v, n, field_predA[0], 0, dir);
+            field_predA[1] = scaleforsame(v, n, field_predA[1], 1, dir);
+        }
+        if (b_valid && b_f) {
+            field_predB[0] = scaleforsame(v, n, field_predB[0], 0, dir);
+            field_predB[1] = scaleforsame(v, n, field_predB[1], 1, dir);
+        }
+        if (c_valid && c_f) {
+            field_predC[0] = scaleforsame(v, n, field_predC[0], 0, dir);
+            field_predC[1] = scaleforsame(v, n, field_predC[1], 1, dir);
+        }
+        v->mv_f[dir][xy + v->blocks_off] = 0;
+        v->ref_field_type[dir] = v->cur_field_type;
+    }
+
+    if (a_valid) {
+        px = field_predA[0];
+        py = field_predA[1];
+    } else if (c_valid) {
+        px = field_predC[0];
+        py = field_predC[1];
+    } else if (b_valid) {
+        px = field_predB[0];
+        py = field_predB[1];
+    } else {
+        px = 0;
+        py = 0;
+    }
+
+    if (num_samefield + num_oppfield > 1) {
+        px = mid_pred(field_predA[0], field_predB[0], field_predC[0]);
+        py = mid_pred(field_predA[1], field_predB[1], field_predC[1]);
+    }
+
+    /* Pullback MV as specified in 8.3.5.3.4 */
+    if (!v->field_mode) {
+        int qx, qy, X, Y;
+        qx = (s->mb_x << 6) + ((n == 1 || n == 3) ? 32 : 0);
+        qy = (s->mb_y << 6) + ((n == 2 || n == 3) ? 32 : 0);
+        X  = (s->mb_width  << 6) - 4;
+        Y  = (s->mb_height << 6) - 4;
+        if (mv1) {
+            if (qx + px < -60) px = -60 - qx;
+            if (qy + py < -60) py = -60 - qy;
+        } else {
+            if (qx + px < -28) px = -28 - qx;
+            if (qy + py < -28) py = -28 - qy;
+        }
+        if (qx + px > X) px = X - qx;
+        if (qy + py > Y) py = Y - qy;
+    }
+
+    if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) {
+        /* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 
10.3.5.4.3.5) */
+        hybridmv_thresh = 32;
+        if (a_valid && c_valid) {
+            if (is_intra[xy - wrap])
+                sum = FFABS(px) + FFABS(py);
+            else
+                sum = FFABS(px - field_predA[0]) + FFABS(py - field_predA[1]);
+            if (sum > hybridmv_thresh) {
+                if (get_bits1(&s->gb)) {     // read HYBRIDPRED bit
+                    px = field_predA[0];
+                    py = field_predA[1];
+                } else {
+                    px = field_predC[0];
+                    py = field_predC[1];
+                }
+            } else {
+                if (is_intra[xy - 1])
+                    sum = FFABS(px) + FFABS(py);
+                else
+                    sum = FFABS(px - field_predC[0]) + FFABS(py - 
field_predC[1]);
+                if (sum > hybridmv_thresh) {
+                    if (get_bits1(&s->gb)) {
+                        px = field_predA[0];
+                        py = field_predA[1];
+                    } else {
+                        px = field_predC[0];
+                        py = field_predC[1];
+                    }
+                }
+            }
+        }
+    }
+
+    if (v->field_mode && v->numref)
+        r_y >>= 1;
+    if (v->field_mode && v->cur_field_type && v->ref_field_type[dir] == 0)
+        y_bias = 1;
+    /* store MV using signed modulus of MV range defined in 4.11 */
+    s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy + 
v->blocks_off][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
+    s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy + 
v->blocks_off][1] = ((py + dmv_y + r_y - y_bias) & ((r_y << 1) - 1)) - r_y + 
y_bias;
+    if (mv1) { /* duplicate motion data for 1-MV block */
+        s->current_picture.motion_val[dir][xy +    1 +     v->blocks_off][0] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][0];
+        s->current_picture.motion_val[dir][xy +    1 +     v->blocks_off][1] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][1];
+        s->current_picture.motion_val[dir][xy + wrap +     v->blocks_off][0] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][0];
+        s->current_picture.motion_val[dir][xy + wrap +     v->blocks_off][1] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][1];
+        s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][0] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][0];
+        s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][1] = 
s->current_picture.motion_val[dir][xy + v->blocks_off][1];
+        v->mv_f[dir][xy +    1 + v->blocks_off] = v->mv_f[dir][xy +            
v->blocks_off];
+        v->mv_f[dir][xy + wrap + v->blocks_off] = v->mv_f[dir][xy + wrap + 1 + 
v->blocks_off] = v->mv_f[dir][xy + v->blocks_off];
+    }
+}
+
+/** Predict and set motion vector for interlaced frame picture MBs
+ */
+void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,
+                          int mvn, int r_x, int r_y, uint8_t* is_intra, int 
dir)
+{
+    MpegEncContext *s = &v->s;
+    int xy, wrap, off = 0;
+    int A[2], B[2], C[2];
+    int px, py;
+    int a_valid = 0, b_valid = 0, c_valid = 0;
+    int field_a, field_b, field_c; // 0: same, 1: opposit
+    int total_valid, num_samefield, num_oppfield;
+    int pos_c, pos_b, n_adj;
+
+    wrap = s->b8_stride;
+    xy = s->block_index[n];
+
+    if (s->mb_intra) {
+        s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0;
+        s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0;
+        s->current_picture.motion_val[1][xy][0] = 0;
+        s->current_picture.motion_val[1][xy][1] = 0;
+        if (mvn == 1) { /* duplicate motion data for 1-MV block */
+            s->current_picture.motion_val[0][xy + 1][0]        = 0;
+            s->current_picture.motion_val[0][xy + 1][1]        = 0;
+            s->current_picture.motion_val[0][xy + wrap][0]     = 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][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][1]        = 0;
+            s->current_picture.motion_val[1][xy + wrap][0]     = 0;
+            s->current_picture.motion_val[1][xy + wrap][1]     = 0;
+            s->current_picture.motion_val[1][xy + wrap + 1][0] = 0;
+            s->current_picture.motion_val[1][xy + wrap + 1][1] = 0;
+        }
+        return;
+    }
+
+    off = ((n == 0) || (n == 1)) ? 1 : -1;
+    /* predict A */
+    if (s->mb_x || (n == 1) || (n == 3)) {
+        if ((v->blk_mv_type[xy]) // current block (MB) has a field MV
+            || (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both 
have frame MV
+            A[0] = s->current_picture.motion_val[dir][xy - 1][0];
+            A[1] = s->current_picture.motion_val[dir][xy - 1][1];
+            a_valid = 1;
+        } else { // current block has frame mv and cand. has field MV (so 
average)
+            A[0] = (s->current_picture.motion_val[dir][xy - 1][0]
+                    + s->current_picture.motion_val[dir][xy - 1 + off * 
wrap][0] + 1) >> 1;
+            A[1] = (s->current_picture.motion_val[dir][xy - 1][1]
+                    + s->current_picture.motion_val[dir][xy - 1 + off * 
wrap][1] + 1) >> 1;
+            a_valid = 1;
+        }
+        if (!(n & 1) && v->is_intra[s->mb_x - 1]) {
+            a_valid = 0;
+            A[0] = A[1] = 0;
+        }
+    } else
+        A[0] = A[1] = 0;
+    /* Predict B and C */
+    B[0] = B[1] = C[0] = C[1] = 0;
+    if (n == 0 || n == 1 || v->blk_mv_type[xy]) {
+        if (!s->first_slice_line) {
+            if (!v->is_intra[s->mb_x - s->mb_stride]) {
+                b_valid = 1;
+                n_adj   = n | 2;
+                pos_b   = s->block_index[n_adj] - 2 * wrap;
+                if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) {
+                    n_adj = (n & 2) | (n & 1);
+                }
+                B[0] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0];
+                B[1] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1];
+                if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) {
+                    B[0] = (B[0] + 
s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 
1) >> 1;
+                    B[1] = (B[1] + 
s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 
1) >> 1;
+                }
+            }
+            if (s->mb_width > 1) {
+                if (!v->is_intra[s->mb_x - s->mb_stride + 1]) {
+                    c_valid = 1;
+                    n_adj   = 2;
+                    pos_c   = s->block_index[2] - 2 * wrap + 2;
+                    if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
+                        n_adj = n & 2;
+                    }
+                    C[0] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0];
+                    C[1] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1];
+                    if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
+                        C[0] = (1 + C[0] + 
(s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 
2][0])) >> 1;
+                        C[1] = (1 + C[1] + 
(s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 
2][1])) >> 1;
+                    }
+                    if (s->mb_x == s->mb_width - 1) {
+                        if (!v->is_intra[s->mb_x - s->mb_stride - 1]) {
+                            c_valid = 1;
+                            n_adj   = 3;
+                            pos_c   = s->block_index[3] - 2 * wrap - 2;
+                            if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
+                                n_adj = n | 1;
+                            }
+                            C[0] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0];
+                            C[1] = 
s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1];
+                            if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
+                                C[0] = (1 + C[0] + 
s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1;
+                                C[1] = (1 + C[1] + 
s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1;
+                            }
+                        } else
+                            c_valid = 0;
+                    }
+                }
+            }
+        }
+    } else {
+        pos_b   = s->block_index[1];
+        b_valid = 1;
+        B[0]    = s->current_picture.motion_val[dir][pos_b][0];
+        B[1]    = s->current_picture.motion_val[dir][pos_b][1];
+        pos_c   = s->block_index[0];
+        c_valid = 1;
+        C[0]    = s->current_picture.motion_val[dir][pos_c][0];
+        C[1]    = s->current_picture.motion_val[dir][pos_c][1];
+    }
+
+    total_valid = a_valid + b_valid + c_valid;
+    // check if predictor A is out of bounds
+    if (!s->mb_x && !(n == 1 || n == 3)) {
+        A[0] = A[1] = 0;
+    }
+    // check if predictor B is out of bounds
+    if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && 
!(n & 2))) {
+        B[0] = B[1] = C[0] = C[1] = 0;
+    }
+    if (!v->blk_mv_type[xy]) {
+        if (s->mb_width == 1) {
+            px = B[0];
+            py = B[1];
+        } else {
+            if (total_valid >= 2) {
+                px = mid_pred(A[0], B[0], C[0]);
+                py = mid_pred(A[1], B[1], C[1]);
+            } else if (total_valid) {
+                if (a_valid) { px = A[0]; py = A[1]; }
+                if (b_valid) { px = B[0]; py = B[1]; }
+                if (c_valid) { px = C[0]; py = C[1]; }
+            } else
+                px = py = 0;
+        }
+    } else {
+        if (a_valid)
+            field_a = (A[1] & 4) ? 1 : 0;
+        else
+            field_a = 0;
+        if (b_valid)
+            field_b = (B[1] & 4) ? 1 : 0;
+        else
+            field_b = 0;
+        if (c_valid)
+            field_c = (C[1] & 4) ? 1 : 0;
+        else
+            field_c = 0;
+
+        num_oppfield  = field_a + field_b + field_c;
+        num_samefield = total_valid - num_oppfield;
+        if (total_valid == 3) {
+            if ((num_samefield == 3) || (num_oppfield == 3)) {
+                px = mid_pred(A[0], B[0], C[0]);
+                py = mid_pred(A[1], B[1], C[1]);
+            } else if (num_samefield >= num_oppfield) {
+                /* take one MV from same field set depending on priority
+                the check for B may not be necessary */
+                px = !field_a ? A[0] : B[0];
+                py = !field_a ? A[1] : B[1];
+            } else {
+                px =  field_a ? A[0] : B[0];
+                py =  field_a ? A[1] : B[1];
+            }
+        } else if (total_valid == 2) {
+            if (num_samefield >= num_oppfield) {
+                if (!field_a && a_valid) {
+                    px = A[0];
+                    py = A[1];
+                } else if (!field_b && b_valid) {
+                    px = B[0];
+                    py = B[1];
+                } else if (c_valid) {
+                    px = C[0];
+                    py = C[1];
+                } else px = py = 0;
+            } else {
+                if (field_a && a_valid) {
+                    px = A[0];
+                    py = A[1];
+                } else if (field_b && b_valid) {
+                    px = B[0];
+                    py = B[1];
+                } else if (c_valid) {
+                    px = C[0];
+                    py = C[1];
+                } else
+                    px = py = 0;
+            }
+        } else if (total_valid == 1) {
+            px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]);
+            py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]);
+        } else
+            px = py = 0;
+    }
+
+    /* store MV using signed modulus of MV range defined in 4.11 */
+    s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy][0] = ((px + 
dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
+    s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy][1] = ((py + 
dmv_y + r_y) & ((r_y << 1) - 1)) - r_y;
+    if (mvn == 1) { /* duplicate motion data for 1-MV block */
+        s->current_picture.motion_val[dir][xy +    1    ][0] = 
s->current_picture.motion_val[dir][xy][0];
+        s->current_picture.motion_val[dir][xy +    1    ][1] = 
s->current_picture.motion_val[dir][xy][1];
+        s->current_picture.motion_val[dir][xy + wrap    ][0] = 
s->current_picture.motion_val[dir][xy][0];
+        s->current_picture.motion_val[dir][xy + wrap    ][1] = 
s->current_picture.motion_val[dir][xy][1];
+        s->current_picture.motion_val[dir][xy + wrap + 1][0] = 
s->current_picture.motion_val[dir][xy][0];
+        s->current_picture.motion_val[dir][xy + wrap + 1][1] = 
s->current_picture.motion_val[dir][xy][1];
+    } else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */
+        s->current_picture.motion_val[dir][xy + 1][0] = 
s->current_picture.motion_val[dir][xy][0];
+        s->current_picture.motion_val[dir][xy + 1][1] = 
s->current_picture.motion_val[dir][xy][1];
+        s->mv[dir][n + 1][0] = s->mv[dir][n][0];
+        s->mv[dir][n + 1][1] = s->mv[dir][n][1];
+    }
+}
+
+void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2],
+                      int direct, int mvtype)
+{
+    MpegEncContext *s = &v->s;
+    int xy, wrap, off = 0;
+    int16_t *A, *B, *C;
+    int px, py;
+    int sum;
+    int r_x, r_y;
+    const uint8_t *is_intra = v->mb_type[0];
+
+    r_x = v->range_x;
+    r_y = v->range_y;
+    /* scale MV difference to be quad-pel */
+    dmv_x[0] <<= 1 - s->quarter_sample;
+    dmv_y[0] <<= 1 - s->quarter_sample;
+    dmv_x[1] <<= 1 - s->quarter_sample;
+    dmv_y[1] <<= 1 - s->quarter_sample;
+
+    wrap = s->b8_stride;
+    xy = s->block_index[0];
+
+    if (s->mb_intra) {
+        s->current_picture.motion_val[0][xy + v->blocks_off][0] =
+        s->current_picture.motion_val[0][xy + v->blocks_off][1] =
+        s->current_picture.motion_val[1][xy + v->blocks_off][0] =
+        s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0;
+        return;
+    }
+    if (!v->field_mode) {
+        s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], 
v->bfraction, 0, s->quarter_sample);
+        s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], 
v->bfraction, 0, s->quarter_sample);
+        s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], 
v->bfraction, 1, s->quarter_sample);
+        s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], 
v->bfraction, 1, s->quarter_sample);
+
+        /* Pullback predicted motion vectors as specified in 8.4.5.4 */
+        s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), 
(s->mb_width  << 6) - 4 - (s->mb_x << 6));
+        s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), 
(s->mb_height << 6) - 4 - (s->mb_y << 6));
+        s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), 
(s->mb_width  << 6) - 4 - (s->mb_x << 6));
+        s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), 
(s->mb_height << 6) - 4 - (s->mb_y << 6));
+    }
+    if (direct) {
+        s->current_picture.motion_val[0][xy + v->blocks_off][0] = 
s->mv[0][0][0];
+        s->current_picture.motion_val[0][xy + v->blocks_off][1] = 
s->mv[0][0][1];
+        s->current_picture.motion_val[1][xy + v->blocks_off][0] = 
s->mv[1][0][0];
+        s->current_picture.motion_val[1][xy + v->blocks_off][1] = 
s->mv[1][0][1];
+        return;
+    }
+
+    if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
+        C   = s->current_picture.motion_val[0][xy - 2];
+        A   = s->current_picture.motion_val[0][xy - wrap * 2];
+        off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
+        B   = s->current_picture.motion_val[0][xy - wrap * 2 + off];
+
+        if (!s->mb_x) C[0] = C[1] = 0;
+        if (!s->first_slice_line) { // predictor A is not out of bounds
+            if (s->mb_width == 1) {
+                px = A[0];
+                py = A[1];
+            } else {
+                px = mid_pred(A[0], B[0], C[0]);
+                py = mid_pred(A[1], B[1], C[1]);
+            }
+        } else if (s->mb_x) { // predictor C is not out of bounds
+            px = C[0];
+            py = C[1];
+        } else {
+            px = py = 0;
+        }
+        /* Pullback MV as specified in 8.3.5.3.4 */
+        {
+            int qx, qy, X, Y;
+            if (v->profile < PROFILE_ADVANCED) {
+                qx = (s->mb_x << 5);
+                qy = (s->mb_y << 5);
+                X  = (s->mb_width  << 5) - 4;
+                Y  = (s->mb_height << 5) - 4;
+                if (qx + px < -28) px = -28 - qx;
+                if (qy + py < -28) py = -28 - qy;
+                if (qx + px > X) px = X - qx;
+                if (qy + py > Y) py = Y - qy;
+            } else {
+                qx = (s->mb_x << 6);
+                qy = (s->mb_y << 6);
+                X  = (s->mb_width  << 6) - 4;
+                Y  = (s->mb_height << 6) - 4;
+                if (qx + px < -60) px = -60 - qx;
+                if (qy + py < -60) py = -60 - qy;
+                if (qx + px > X) px = X - qx;
+                if (qy + py > Y) py = Y - qy;
+            }
+        }
+        /* Calculate hybrid prediction as specified in 8.3.5.3.5 */
+        if (0 && !s->first_slice_line && s->mb_x) {
+            if (is_intra[xy - wrap])
+                sum = FFABS(px) + FFABS(py);
+            else
+                sum = FFABS(px - A[0]) + FFABS(py - A[1]);
+            if (sum > 32) {
+                if (get_bits1(&s->gb)) {
+                    px = A[0];
+                    py = A[1];
+                } else {
+                    px = C[0];
+                    py = C[1];
+                }
+            } else {
+                if (is_intra[xy - 2])
+                    sum = FFABS(px) + FFABS(py);
+                else
+                    sum = FFABS(px - C[0]) + FFABS(py - C[1]);
+                if (sum > 32) {
+                    if (get_bits1(&s->gb)) {
+                        px = A[0];
+                        py = A[1];
+                    } else {
+                        px = C[0];
+                        py = C[1];
+                    }
+                }
+            }
+        }
+        /* store MV using signed modulus of MV range defined in 4.11 */
+        s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x;
+        s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y;
+    }
+    if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
+        C   = s->current_picture.motion_val[1][xy - 2];
+        A   = s->current_picture.motion_val[1][xy - wrap * 2];
+        off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
+        B   = s->current_picture.motion_val[1][xy - wrap * 2 + off];
+
+        if (!s->mb_x)
+            C[0] = C[1] = 0;
+        if (!s->first_slice_line) { // predictor A is not out of bounds
+            if (s->mb_width == 1) {
+                px = A[0];
+                py = A[1];
+            } else {
+                px = mid_pred(A[0], B[0], C[0]);
+                py = mid_pred(A[1], B[1], C[1]);
+            }
+        } else if (s->mb_x) { // predictor C is not out of bounds
+            px = C[0];
+            py = C[1];
+        } else {
+            px = py = 0;
+        }
+        /* Pullback MV as specified in 8.3.5.3.4 */
+        {
+            int qx, qy, X, Y;
+            if (v->profile < PROFILE_ADVANCED) {
+                qx = (s->mb_x << 5);
+                qy = (s->mb_y << 5);
+                X  = (s->mb_width  << 5) - 4;
+                Y  = (s->mb_height << 5) - 4;
+                if (qx + px < -28) px = -28 - qx;
+                if (qy + py < -28) py = -28 - qy;
+                if (qx + px > X) px = X - qx;
+                if (qy + py > Y) py = Y - qy;
+            } else {
+                qx = (s->mb_x << 6);
+                qy = (s->mb_y << 6);
+                X  = (s->mb_width  << 6) - 4;
+                Y  = (s->mb_height << 6) - 4;
+                if (qx + px < -60) px = -60 - qx;
+                if (qy + py < -60) py = -60 - qy;
+                if (qx + px > X) px = X - qx;
+                if (qy + py > Y) py = Y - qy;
+            }
+        }
+        /* Calculate hybrid prediction as specified in 8.3.5.3.5 */
+        if (0 && !s->first_slice_line && s->mb_x) {
+            if (is_intra[xy - wrap])
+                sum = FFABS(px) + FFABS(py);
+            else
+                sum = FFABS(px - A[0]) + FFABS(py - A[1]);
+            if (sum > 32) {
+                if (get_bits1(&s->gb)) {
+                    px = A[0];
+                    py = A[1];
+                } else {
+                    px = C[0];
+                    py = C[1];
+                }
+            } else {
+                if (is_intra[xy - 2])
+                    sum = FFABS(px) + FFABS(py);
+                else
+                    sum = FFABS(px - C[0]) + FFABS(py - C[1]);
+                if (sum > 32) {
+                    if (get_bits1(&s->gb)) {
+                        px = A[0];
+                        py = A[1];
+                    } else {
+                        px = C[0];
+                        py = C[1];
+                    }
+                }
+            }
+        }
+        /* store MV using signed modulus of MV range defined in 4.11 */
+
+        s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x;
+        s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y;
+    }
+    s->current_picture.motion_val[0][xy][0] = s->mv[0][0][0];
+    s->current_picture.motion_val[0][xy][1] = s->mv[0][0][1];
+    s->current_picture.motion_val[1][xy][0] = s->mv[1][0][0];
+    s->current_picture.motion_val[1][xy][1] = s->mv[1][0][1];
+}
+
+void ff_vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y,
+                            int mv1, int *pred_flag)
+{
+    int dir = (v->bmvtype == BMV_TYPE_BACKWARD) ? 1 : 0;
+    MpegEncContext *s = &v->s;
+    int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+
+    if (v->bmvtype == BMV_TYPE_DIRECT) {
+        int total_opp, k, f;
+        if (s->next_picture.mb_type[mb_pos + v->mb_off] != MB_TYPE_INTRA) {
+            s->mv[0][0][0] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0],
+                                      v->bfraction, 0, s->quarter_sample);
+            s->mv[0][0][1] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1],
+                                      v->bfraction, 0, s->quarter_sample);
+            s->mv[1][0][0] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0],
+                                      v->bfraction, 1, s->quarter_sample);
+            s->mv[1][0][1] = 
scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1],
+                                      v->bfraction, 1, s->quarter_sample);
+
+            total_opp = v->mv_f_next[0][s->block_index[0] + v->blocks_off]
+                      + v->mv_f_next[0][s->block_index[1] + v->blocks_off]
+                      + v->mv_f_next[0][s->block_index[2] + v->blocks_off]
+                      + v->mv_f_next[0][s->block_index[3] + v->blocks_off];
+            f = (total_opp > 2) ? 1 : 0;
+        } else {
+            s->mv[0][0][0] = s->mv[0][0][1] = 0;
+            s->mv[1][0][0] = s->mv[1][0][1] = 0;
+            f = 0;
+        }
+        v->ref_field_type[0] = v->ref_field_type[1] = v->cur_field_type ^ f;
+        for (k = 0; k < 4; k++) {
+            s->current_picture.motion_val[0][s->block_index[k] + 
v->blocks_off][0] = s->mv[0][0][0];
+            s->current_picture.motion_val[0][s->block_index[k] + 
v->blocks_off][1] = s->mv[0][0][1];
+            s->current_picture.motion_val[1][s->block_index[k] + 
v->blocks_off][0] = s->mv[1][0][0];
+            s->current_picture.motion_val[1][s->block_index[k] + 
v->blocks_off][1] = s->mv[1][0][1];
+            v->mv_f[0][s->block_index[k] + v->blocks_off] = f;
+            v->mv_f[1][s->block_index[k] + v->blocks_off] = f;
+        }
+        return;
+    }
+    if (v->bmvtype == BMV_TYPE_INTERPOLATED) {
+        ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0],   1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[0], 0);
+        ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1],   1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[1], 1);
+        return;
+    }
+    if (dir) { // backward
+        ff_vc1_pred_mv(v, n, dmv_x[1], dmv_y[1], mv1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[1], 1);
+        if (n == 3 || mv1) {
+            ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0],   1, v->range_x, 
v->range_y, v->mb_type[0], 0, 0);
+        }
+    } else { // forward
+        ff_vc1_pred_mv(v, n, dmv_x[0], dmv_y[0], mv1, v->range_x, v->range_y, 
v->mb_type[0], pred_flag[0], 0);
+        if (n == 3 || mv1) {
+            ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1],   1, v->range_x, 
v->range_y, v->mb_type[0], 0, 1);
+        }
+    }
+}
diff --git a/libavcodec/vc1_pred.h b/libavcodec/vc1_pred.h
new file mode 100644
index 0000000..34c9c1a
--- /dev/null
+++ b/libavcodec/vc1_pred.h
@@ -0,0 +1,59 @@
+/*
+ * VC-1 and WMV3 decoder
+ * 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
+ */
+
+#ifndef AVCODEC_VC1_PRED_H
+#define AVCODEC_VC1_PRED_H
+
+#include "vc1.h"
+#include "vc1data.h"
+
+void ff_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,
+                    int pred_flag, int dir);
+void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,
+                          int mvn, int r_x, int r_y, uint8_t* is_intra,
+                          int dir);
+void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2],
+                      int direct, int mvtype);
+void ff_vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y,
+                            int mv1, int *pred_flag);
+
+static av_always_inline int scale_mv(int value, int bfrac, int inv, int qs)
+{
+    int n = bfrac;
+
+#if B_FRACTION_DEN==256
+    if (inv)
+        n -= 256;
+    if (!qs)
+        return 2 * ((value * n + 255) >> 9);
+    return (value * n + 128) >> 8;
+#else
+    if (inv)
+        n -= B_FRACTION_DEN;
+    if (!qs)
+        return 2 * ((value * n + B_FRACTION_DEN - 1) / (2 * B_FRACTION_DEN));
+    return (value * n + B_FRACTION_DEN/2) / B_FRACTION_DEN;
+#endif
+}
+
+#endif /* AVCODEC_VC1_PRED_H */
diff --git a/libavcodec/vc1data.h b/libavcodec/vc1data.h
index 84e8188..66c569b 100644
--- a/libavcodec/vc1data.h
+++ b/libavcodec/vc1data.h
@@ -94,8 +94,6 @@ extern VLC ff_vc1_ac_coeff_table[8];
 #define VC1_IF_MBMODE_VLC_BITS 5
 //@}
 
-
-/* Denominator used for ff_vc1_bfraction_lut */
 #define B_FRACTION_DEN  256
 
 /* pre-computed scales for all bfractions and base=256 */
-- 
2.1.0

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

Reply via email to