]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/vc1_mc.c
avutil/frame: Remove deprecated AVFrame.pkt_pts field
[ffmpeg] / libavcodec / vc1_mc.c
index 75c74cad8df706ba1fe27b90e345fd64dbc35698..1b8d8799b3cbf5fc0c9e1be568993e4fef8f5289 100644 (file)
@@ -179,12 +179,17 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
     int i;
     uint8_t (*luty)[256], (*lutuv)[256];
     int use_ic;
+    int interlace;
+    int linesize, uvlinesize;
 
     if ((!v->field_mode ||
          (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) &&
         !v->s.last_picture.f->data[0])
         return;
 
+    linesize = s->current_picture_ptr->f->linesize[0];
+    uvlinesize = s->current_picture_ptr->f->linesize[1];
+
     mx = s->mv[dir][0][0];
     my = s->mv[dir][0][1];
 
@@ -220,6 +225,7 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
             luty  = v->curr_luty;
             lutuv = v->curr_lutuv;
             use_ic = *v->curr_use_ic;
+            interlace = 1;
         } else {
             srcY = s->last_picture.f->data[0];
             srcU = s->last_picture.f->data[1];
@@ -227,6 +233,7 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
             luty  = v->last_luty;
             lutuv = v->last_lutuv;
             use_ic = v->last_use_ic;
+            interlace = s->last_picture.f->interlaced_frame;
         }
     } else {
         srcY = s->next_picture.f->data[0];
@@ -235,6 +242,7 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
         luty  = v->next_luty;
         lutuv = v->next_lutuv;
         use_ic = v->next_use_ic;
+        interlace = s->next_picture.f->interlaced_frame;
     }
 
     if (!srcY || !srcU) {
@@ -254,9 +262,14 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
         uvsrc_y = av_clip(uvsrc_y,  -8, s->mb_height *  8);
     } else {
         src_x   = av_clip(  src_x, -17, s->avctx->coded_width);
-        src_y   = av_clip(  src_y, -18, s->avctx->coded_height + 1);
         uvsrc_x = av_clip(uvsrc_x,  -8, s->avctx->coded_width  >> 1);
-        uvsrc_y = av_clip(uvsrc_y,  -8, s->avctx->coded_height >> 1);
+        if (v->fcm == ILACE_FRAME) {
+            src_y = av_clip(src_y, -18 + (src_y & 1), s->avctx->coded_height + (src_y & 1));
+            uvsrc_y = av_clip(uvsrc_y, -8 + (uvsrc_y & 1), (s->avctx->coded_height >> 1) + (uvsrc_y & 1));
+        } else {
+            src_y = av_clip(src_y, -18, s->avctx->coded_height + 1);
+            uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
+        }
     }
 
     srcY += src_y   * s->linesize   + src_x;
@@ -264,9 +277,9 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
     srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
 
     if (v->field_mode && v->ref_field_type[dir]) {
-        srcY += s->current_picture_ptr->f->linesize[0];
-        srcU += s->current_picture_ptr->f->linesize[1];
-        srcV += s->current_picture_ptr->f->linesize[2];
+        srcY += linesize;
+        srcU += uvlinesize;
+        srcV += uvlinesize;
     }
 
     /* for grayscale we should not try to read from unknown area */
@@ -284,22 +297,106 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
         const int k = 17 + s->mspel * 2;
 
         srcY -= s->mspel * (1 + s->linesize);
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY,
-                                 s->linesize, s->linesize,
-                                 k, k,
-                                 src_x - s->mspel, src_y - s->mspel,
-                                 s->h_edge_pos, v_edge_pos);
+        if (interlace) {
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcY,
+                                     linesize << 1,
+                                     linesize << 1,
+                                     k,
+                                     v->field_mode ? k : k + 1 >> 1,
+                                     src_x - s->mspel,
+                                     src_y - s->mspel >> !v->field_mode,
+                                     s->h_edge_pos,
+                                     s->v_edge_pos >> 1);
+            if (!v->field_mode)
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + linesize,
+                                         srcY + linesize,
+                                         linesize << 1,
+                                         linesize << 1,
+                                         k,
+                                         k >> 1,
+                                         src_x - s->mspel,
+                                         src_y - s->mspel + 1 >> 1,
+                                         s->h_edge_pos,
+                                         s->v_edge_pos >> 1);
+        } else
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcY,
+                                     linesize,
+                                     linesize,
+                                     k,
+                                     v->field_mode ? (k << 1) - 1 : k,
+                                     src_x - s->mspel,
+                                     v->field_mode ? 2 * (src_y - s->mspel) + v->ref_field_type[dir] :
+                                                     src_y - s->mspel,
+                                     s->h_edge_pos,
+                                     s->v_edge_pos);
         srcY = s->sc.edge_emu_buffer;
-        s->vdsp.emulated_edge_mc(ubuf, srcU,
-                                 s->uvlinesize, s->uvlinesize,
-                                 8 + 1, 8 + 1,
-                                 uvsrc_x, uvsrc_y,
-                                 s->h_edge_pos >> 1, v_edge_pos >> 1);
-        s->vdsp.emulated_edge_mc(vbuf, srcV,
-                                 s->uvlinesize, s->uvlinesize,
-                                 8 + 1, 8 + 1,
-                                 uvsrc_x, uvsrc_y,
-                                 s->h_edge_pos >> 1, v_edge_pos >> 1);
+        if (interlace) {
+            s->vdsp.emulated_edge_mc(ubuf,
+                                     srcU,
+                                     uvlinesize << 1,
+                                     uvlinesize << 1,
+                                     9,
+                                     v->field_mode ? 9 : 5,
+                                     uvsrc_x,
+                                     uvsrc_y >> !v->field_mode,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 2);
+            s->vdsp.emulated_edge_mc(vbuf,
+                                     srcV,
+                                     uvlinesize << 1,
+                                     uvlinesize << 1,
+                                     9,
+                                     v->field_mode ? 9 : 5,
+                                     uvsrc_x,
+                                     uvsrc_y >> !v->field_mode,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 2);
+            if (!v->field_mode) {
+                s->vdsp.emulated_edge_mc(ubuf + uvlinesize,
+                                         srcU + uvlinesize,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         9,
+                                         4,
+                                         uvsrc_x,
+                                         uvsrc_y + 1 >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+                s->vdsp.emulated_edge_mc(vbuf + uvlinesize,
+                                         srcV + uvlinesize,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         9,
+                                         4,
+                                         uvsrc_x,
+                                         uvsrc_y + 1 >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+            }
+        } else {
+            s->vdsp.emulated_edge_mc(ubuf,
+                                     srcU,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[dir] : uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1);
+            s->vdsp.emulated_edge_mc(vbuf,
+                                     srcV,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[dir] : uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1);
+        }
         srcU = ubuf;
         srcV = vbuf;
         /* if we deal with range reduction we need to scale source blocks */
@@ -344,6 +441,10 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
         v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
         v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
     }
+    if (v->field_mode) {
+        v->mv_f[dir][s->block_index[4] + v->mb_off] = v->cur_field_type != v->ref_field_type[dir];
+        v->mv_f[dir][s->block_index[5] + v->mb_off] = v->cur_field_type != v->ref_field_type[dir];
+    }
 }
 
 /** Do motion compensation for 4-MV macroblock - luminance block
@@ -358,12 +459,16 @@ void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
     int v_edge_pos = s->v_edge_pos >> v->field_mode;
     uint8_t (*luty)[256];
     int use_ic;
+    int interlace;
+    int linesize;
 
     if ((!v->field_mode ||
          (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) &&
         !v->s.last_picture.f->data[0])
         return;
 
+    linesize = s->current_picture_ptr->f->linesize[0];
+
     mx = s->mv[dir][n][0];
     my = s->mv[dir][n][1];
 
@@ -372,15 +477,18 @@ void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
             srcY = s->current_picture.f->data[0];
             luty = v->curr_luty;
             use_ic = *v->curr_use_ic;
+            interlace = 1;
         } else {
             srcY = s->last_picture.f->data[0];
             luty = v->last_luty;
             use_ic = v->last_use_ic;
+            interlace = s->last_picture.f->interlaced_frame;
         }
     } else {
         srcY = s->next_picture.f->data[0];
         luty = v->next_luty;
         use_ic = v->next_use_ic;
+        interlace = s->next_picture.f->interlaced_frame;
     }
 
     if (!srcY) {
@@ -439,26 +547,16 @@ void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
         src_y = av_clip(src_y, -16, s->mb_height * 16);
     } else {
         src_x = av_clip(src_x, -17, s->avctx->coded_width);
-        if (v->fcm == ILACE_FRAME) {
-            if (src_y & 1)
-                src_y = av_clip(src_y, -17, s->avctx->coded_height + 1);
-            else
-                src_y = av_clip(src_y, -18, s->avctx->coded_height);
-        } else {
+        if (v->fcm == ILACE_FRAME)
+            src_y = av_clip(src_y, -18 + (src_y & 1), s->avctx->coded_height + (src_y & 1));
+        else
             src_y = av_clip(src_y, -18, s->avctx->coded_height + 1);
-        }
     }
 
     srcY += src_y * s->linesize + src_x;
     if (v->field_mode && v->ref_field_type[dir])
-        srcY += s->current_picture_ptr->f->linesize[0];
+        srcY += linesize;
 
-    if (fieldmv) {
-        if (!(src_y & 1))
-            v_edge_pos--;
-        else
-            src_y -= (src_y < 4);
-    }
     if (v->rangeredfrm || use_ic
         || s->h_edge_pos < 13 || v_edge_pos < 23
         || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2
@@ -467,11 +565,40 @@ void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
 
         srcY -= s->mspel * (1 + (s->linesize << fieldmv));
         /* check emulate edge stride and offset */
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY,
-                                 s->linesize, s->linesize,
-                                 k, k << fieldmv,
-                                 src_x - s->mspel, src_y - (s->mspel << fieldmv),
-                                 s->h_edge_pos, v_edge_pos);
+        if (interlace) {
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcY,
+                                     linesize << 1,
+                                     linesize << 1,
+                                     k,
+                                     v->field_mode ? k : (k << fieldmv) + 1 >> 1,
+                                     src_x - s->mspel,
+                                     src_y - (s->mspel << fieldmv) >> !v->field_mode,
+                                     s->h_edge_pos,
+                                     s->v_edge_pos >> 1);
+            if (!v->field_mode && !fieldmv)
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + linesize,
+                                         srcY + linesize,
+                                         linesize << 1,
+                                         linesize << 1,
+                                         k,
+                                         k >> 1,
+                                         src_x - s->mspel,
+                                         src_y - s->mspel + 1 >> 1,
+                                         s->h_edge_pos,
+                                         s->v_edge_pos >> 1);
+        } else
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcY,
+                                     linesize,
+                                     linesize,
+                                     k,
+                                     v->field_mode ? (k << 1) - 1 : k << fieldmv,
+                                     src_x - s->mspel,
+                                     v->field_mode ? 2 * (src_y - s->mspel) + v->ref_field_type[dir] :
+                                                     src_y - (s->mspel << fieldmv),
+                                     s->h_edge_pos,
+                                     s->v_edge_pos);
         srcY = s->sc.edge_emu_buffer;
         /* if we deal with range reduction we need to scale source blocks */
         if (v->rangeredfrm) {
@@ -515,6 +642,8 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
     int v_edge_pos = s->v_edge_pos >> v->field_mode;
     uint8_t (*lutuv)[256];
     int use_ic;
+    int interlace;
+    int uvlinesize;
 
     if (!v->field_mode && !v->s.last_picture.f->data[0])
         return;
@@ -539,6 +668,9 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
         return;
     s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx;
     s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty;
+
+    uvlinesize = s->current_picture_ptr->f->linesize[1];
+
     uvmx = (tx + ((tx & 3) == 3)) >> 1;
     uvmy = (ty + ((ty & 3) == 3)) >> 1;
 
@@ -570,17 +702,20 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
             srcV = s->current_picture.f->data[2];
             lutuv = v->curr_lutuv;
             use_ic = *v->curr_use_ic;
+            interlace = 1;
         } else {
             srcU = s->last_picture.f->data[1];
             srcV = s->last_picture.f->data[2];
             lutuv = v->last_lutuv;
             use_ic = v->last_use_ic;
+            interlace = s->last_picture.f->interlaced_frame;
         }
     } else {
         srcU = s->next_picture.f->data[1];
         srcV = s->next_picture.f->data[2];
         lutuv = v->next_lutuv;
         use_ic = v->next_use_ic;
+        interlace = s->next_picture.f->interlaced_frame;
     }
 
     if (!srcU) {
@@ -593,8 +728,8 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
 
     if (v->field_mode) {
         if (chroma_ref_type) {
-            srcU += s->current_picture_ptr->f->linesize[1];
-            srcV += s->current_picture_ptr->f->linesize[2];
+            srcU += uvlinesize;
+            srcV += uvlinesize;
         }
     }
 
@@ -602,14 +737,71 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
         || s->h_edge_pos < 18 || v_edge_pos < 18
         || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9
         || (unsigned)uvsrc_y > (v_edge_pos    >> 1) - 9) {
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcU,
-                                 s->uvlinesize, s->uvlinesize,
-                                 8 + 1, 8 + 1, uvsrc_x, uvsrc_y,
-                                 s->h_edge_pos >> 1, v_edge_pos >> 1);
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16, srcV,
-                                 s->uvlinesize, s->uvlinesize,
-                                 8 + 1, 8 + 1, uvsrc_x, uvsrc_y,
-                                 s->h_edge_pos >> 1, v_edge_pos >> 1);
+        if (interlace) {
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcU,
+                                     uvlinesize << 1,
+                                     uvlinesize << 1,
+                                     9,
+                                     v->field_mode ? 9 : 5,
+                                     uvsrc_x,
+                                     uvsrc_y >> !v->field_mode,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 2);
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
+                                     srcV,
+                                     uvlinesize << 1,
+                                     uvlinesize << 1,
+                                     9,
+                                     v->field_mode ? 9 : 5,
+                                     uvsrc_x,
+                                     uvsrc_y >> !v->field_mode,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 2);
+            if (!v->field_mode) {
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + uvlinesize,
+                                         srcU + uvlinesize,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         9,
+                                         4,
+                                         uvsrc_x,
+                                         uvsrc_y + 1 >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16 + uvlinesize,
+                                         srcV + uvlinesize,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         9,
+                                         4,
+                                         uvsrc_x,
+                                         uvsrc_y + 1 >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+            }
+        } else {
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcU,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     v->field_mode ? 2 * uvsrc_y + chroma_ref_type : uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1);
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
+                                     srcV,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     v->field_mode ? 2 * uvsrc_y + chroma_ref_type : uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1);
+        }
         srcU = s->sc.edge_emu_buffer;
         srcV = s->sc.edge_emu_buffer + 16;
 
@@ -636,6 +828,10 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
         v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
         v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
     }
+    if (v->field_mode) {
+        v->mv_f[dir][s->block_index[4] + v->mb_off] = v->cur_field_type != chroma_ref_type;
+        v->mv_f[dir][s->block_index[5] + v->mb_off] = v->cur_field_type != chroma_ref_type;
+    }
 }
 
 /** Do motion compensation for 4-MV interlaced frame chroma macroblock (both U and V)
@@ -653,11 +849,15 @@ void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
     int v_dist = fieldmv ? 1 : 4; // vertical offset for lower sub-blocks
     int v_edge_pos = s->v_edge_pos >> 1;
     int use_ic;
+    int interlace;
+    int uvlinesize;
     uint8_t (*lutuv)[256];
 
     if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
         return;
 
+    uvlinesize = s->current_picture_ptr->f->linesize[1];
+
     for (i = 0; i < 4; i++) {
         int d = i < 2 ? dir: dir2;
         tx = s->mv[d][i][0];
@@ -675,17 +875,22 @@ void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
         uvsrc_y = s->mb_y * 8 + ((i & 2) ? v_dist : 0) + (uvmy_field[i] >> 2);
         // FIXME: implement proper pull-back (see vc1cropmv.c, vc1CROPMV_ChromaPullBack())
         uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width  >> 1);
-        uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
+        if (v->fcm == ILACE_FRAME)
+            uvsrc_y = av_clip(uvsrc_y, -8 + (uvsrc_y & 1), (s->avctx->coded_height >> 1) + (uvsrc_y & 1));
+        else
+            uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
         if (i < 2 ? dir : dir2) {
             srcU = s->next_picture.f->data[1];
             srcV = s->next_picture.f->data[2];
             lutuv  = v->next_lutuv;
             use_ic = v->next_use_ic;
+            interlace = s->next_picture.f->interlaced_frame;
         } else {
             srcU = s->last_picture.f->data[1];
             srcV = s->last_picture.f->data[2];
             lutuv  = v->last_lutuv;
             use_ic = v->last_use_ic;
+            interlace = s->last_picture.f->interlaced_frame;
         }
         if (!srcU)
             return;
@@ -694,24 +899,75 @@ void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
         uvmx_field[i] = (uvmx_field[i] & 3) << 1;
         uvmy_field[i] = (uvmy_field[i] & 3) << 1;
 
-        if (fieldmv) {
-            if (!(uvsrc_y & 1))
-                v_edge_pos = (s->v_edge_pos >> 1) - 1;
-            else
-                uvsrc_y -= (uvsrc_y < 2);
-        }
         if (use_ic
             || s->h_edge_pos < 10 || v_edge_pos < (5 << fieldmv)
             || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5
             || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) {
-            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcU,
-                                     s->uvlinesize, s->uvlinesize,
-                                     5, (5 << fieldmv), uvsrc_x, uvsrc_y,
-                                     s->h_edge_pos >> 1, v_edge_pos);
-            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16, srcV,
-                                     s->uvlinesize, s->uvlinesize,
-                                     5, (5 << fieldmv), uvsrc_x, uvsrc_y,
-                                     s->h_edge_pos >> 1, v_edge_pos);
+            if (interlace) {
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                         srcU,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         5,
+                                         (5 << fieldmv) + 1 >> 1,
+                                         uvsrc_x,
+                                         uvsrc_y >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
+                                         srcV,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         5,
+                                         (5 << fieldmv) + 1 >> 1,
+                                         uvsrc_x,
+                                         uvsrc_y >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+                if (!fieldmv) {
+                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + uvlinesize,
+                                             srcU + uvlinesize,
+                                             uvlinesize << 1,
+                                             uvlinesize << 1,
+                                             5,
+                                             2,
+                                             uvsrc_x,
+                                             uvsrc_y + 1 >> 1,
+                                             s->h_edge_pos >> 1,
+                                             s->v_edge_pos >> 2);
+                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16 + uvlinesize,
+                                             srcV + uvlinesize,
+                                             uvlinesize << 1,
+                                             uvlinesize << 1,
+                                             5,
+                                             2,
+                                             uvsrc_x,
+                                             uvsrc_y + 1 >> 1,
+                                             s->h_edge_pos >> 1,
+                                             s->v_edge_pos >> 2);
+                }
+            } else {
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                         srcU,
+                                         uvlinesize,
+                                         uvlinesize,
+                                         5,
+                                         5 << fieldmv,
+                                         uvsrc_x,
+                                         uvsrc_y,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 1);
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
+                                         srcV,
+                                         uvlinesize,
+                                         uvlinesize,
+                                         5,
+                                         5 << fieldmv,
+                                         uvsrc_x,
+                                         uvsrc_y,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 1);
+            }
             srcU = s->sc.edge_emu_buffer;
             srcV = s->sc.edge_emu_buffer + 16;
 
@@ -753,10 +1009,15 @@ void ff_vc1_interp_mc(VC1Context *v)
     int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;
     int v_edge_pos = s->v_edge_pos >> v->field_mode;
     int use_ic = v->next_use_ic;
+    int interlace;
+    int linesize, uvlinesize;
 
     if (!v->field_mode && !v->s.next_picture.f->data[0])
         return;
 
+    linesize = s->current_picture_ptr->f->linesize[0];
+    uvlinesize = s->current_picture_ptr->f->linesize[1];
+
     mx   = s->mv[1][0][0];
     my   = s->mv[1][0][1];
     uvmx = (mx + ((mx & 3) == 3)) >> 1;
@@ -773,6 +1034,8 @@ void ff_vc1_interp_mc(VC1Context *v)
     srcU = s->next_picture.f->data[1];
     srcV = s->next_picture.f->data[2];
 
+    interlace = s->next_picture.f->interlaced_frame;
+
     src_x   = s->mb_x * 16 + (mx   >> 2);
     src_y   = s->mb_y * 16 + (my   >> 2);
     uvsrc_x = s->mb_x *  8 + (uvmx >> 2);
@@ -785,9 +1048,14 @@ void ff_vc1_interp_mc(VC1Context *v)
         uvsrc_y = av_clip(uvsrc_y,  -8, s->mb_height *  8);
     } else {
         src_x   = av_clip(  src_x, -17, s->avctx->coded_width);
-        src_y   = av_clip(  src_y, -18, s->avctx->coded_height + 1);
         uvsrc_x = av_clip(uvsrc_x,  -8, s->avctx->coded_width  >> 1);
-        uvsrc_y = av_clip(uvsrc_y,  -8, s->avctx->coded_height >> 1);
+        if (v->fcm == ILACE_FRAME) {
+            src_y = av_clip(src_y, -18 + (src_y & 1), s->avctx->coded_height + (src_y & 1));
+            uvsrc_y = av_clip(uvsrc_y, -8 + (uvsrc_y & 1), (s->avctx->coded_height >> 1) + (uvsrc_y & 1));
+        } else {
+            src_y = av_clip(src_y, -18, s->avctx->coded_height + 1);
+            uvsrc_y = av_clip(uvsrc_y,  -8, s->avctx->coded_height >> 1);
+        }
     }
 
     srcY += src_y   * s->linesize   + src_x;
@@ -795,9 +1063,9 @@ void ff_vc1_interp_mc(VC1Context *v)
     srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
 
     if (v->field_mode && v->ref_field_type[1]) {
-        srcY += s->current_picture_ptr->f->linesize[0];
-        srcU += s->current_picture_ptr->f->linesize[1];
-        srcV += s->current_picture_ptr->f->linesize[2];
+        srcY += linesize;
+        srcU += uvlinesize;
+        srcV += uvlinesize;
     }
 
     /* for grayscale we should not try to read from unknown area */
@@ -814,22 +1082,106 @@ void ff_vc1_interp_mc(VC1Context *v)
         const int k = 17 + s->mspel * 2;
 
         srcY -= s->mspel * (1 + s->linesize);
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY,
-                                 s->linesize, s->linesize,
-                                 k, k,
-                                 src_x - s->mspel, src_y - s->mspel,
-                                 s->h_edge_pos, v_edge_pos);
+        if (interlace) {
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcY,
+                                     linesize << 1,
+                                     linesize << 1,
+                                     k,
+                                     v->field_mode ? k : (k + 1 >> 1),
+                                     src_x - s->mspel,
+                                     src_y - s->mspel >> !v->field_mode,
+                                     s->h_edge_pos,
+                                     s->v_edge_pos >> 1);
+            if (!v->field_mode)
+                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + linesize,
+                                         srcY + linesize,
+                                         linesize << 1,
+                                         linesize << 1,
+                                         k,
+                                         k >> 1,
+                                         src_x - s->mspel,
+                                         src_y - s->mspel + 1 >> 1,
+                                         s->h_edge_pos,
+                                         s->v_edge_pos >> 1);
+        } else
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
+                                     srcY,
+                                     linesize,
+                                     linesize,
+                                     k,
+                                     v->field_mode ? (k << 1) - 1 : k,
+                                     src_x - s->mspel,
+                                     v->field_mode ? 2 * (src_y - s->mspel) + v->ref_field_type[1] :
+                                                     src_y - s->mspel,
+                                     s->h_edge_pos,
+                                     s->v_edge_pos);
         srcY = s->sc.edge_emu_buffer;
-        s->vdsp.emulated_edge_mc(ubuf, srcU,
-                                 s->uvlinesize, s->uvlinesize,
-                                 8 + 1, 8 + 1,
-                                 uvsrc_x, uvsrc_y,
-                                 s->h_edge_pos >> 1, v_edge_pos >> 1);
-        s->vdsp.emulated_edge_mc(vbuf, srcV,
-                                 s->uvlinesize, s->uvlinesize,
-                                 8 + 1, 8 + 1,
-                                 uvsrc_x, uvsrc_y,
-                                 s->h_edge_pos >> 1, v_edge_pos >> 1);
+        if (interlace) {
+            s->vdsp.emulated_edge_mc(ubuf,
+                                     srcU,
+                                     uvlinesize << 1,
+                                     uvlinesize << 1,
+                                     9,
+                                     v->field_mode ? 9 : 5,
+                                     uvsrc_x,
+                                     uvsrc_y >> !v->field_mode,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 2);
+            s->vdsp.emulated_edge_mc(vbuf,
+                                     srcV,
+                                     uvlinesize << 1,
+                                     uvlinesize << 1,
+                                     9,
+                                     v->field_mode ? 9 : 5,
+                                     uvsrc_x,
+                                     uvsrc_y >> !v->field_mode,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 2);
+            if (!v->field_mode) {
+                s->vdsp.emulated_edge_mc(ubuf + uvlinesize,
+                                         srcU + uvlinesize,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         9,
+                                         4,
+                                         uvsrc_x,
+                                         uvsrc_y + 1 >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+                s->vdsp.emulated_edge_mc(vbuf + uvlinesize,
+                                         srcV + uvlinesize,
+                                         uvlinesize << 1,
+                                         uvlinesize << 1,
+                                         9,
+                                         4,
+                                         uvsrc_x,
+                                         uvsrc_y + 1 >> 1,
+                                         s->h_edge_pos >> 1,
+                                         s->v_edge_pos >> 2);
+            }
+        } else {
+            s->vdsp.emulated_edge_mc(ubuf,
+                                     srcU,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[1] : uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1);
+            s->vdsp.emulated_edge_mc(vbuf,
+                                     srcV,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[1] : uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1);
+        }
         srcU = ubuf;
         srcV = vbuf;
         /* if we deal with range reduction we need to scale source blocks */