diff mbox

[FFmpeg-devel] avcodec/vc1: fix out-of-bounds reference pixel replication

Message ID 85bd0478-73c1-100f-2376-ef24b12992b5@carpalis.nl
State Superseded
Headers show

Commit Message

Jerome Borsboom May 27, 2018, 8:27 p.m. UTC
Out-of-bounds reference pixel replication should take into account the frame
coding mode of the reference frame(s), not the frame coding mode of the
current frame.

Signed-off-by: Jerome Borsboom <jerome.borsboom@carpalis.nl>
---
This should fix the remaining issue with the SA10180.vc1 test file.

 libavcodec/vc1_mc.c | 659 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 379 insertions(+), 280 deletions(-)

Comments

Carl Eugen Hoyos May 27, 2018, 8:39 p.m. UTC | #1
2018-05-27 22:27 GMT+02:00, Jerome Borsboom <jerome.borsboom@carpalis.nl>:
> Out-of-bounds reference pixel replication should take into account
> the frame coding mode of the reference frame(s), not the frame
> coding mode of the current frame.
>
> Signed-off-by: Jerome Borsboom <jerome.borsboom@carpalis.nl>
> ---
> This should fix the remaining issue with the SA10180.vc1 test file.

With this patch, the first 601 frames are decoded bit-exact, the
following frame is not decoded correctly.

Carl Eugen
Jerome Borsboom May 28, 2018, 8:26 a.m. UTC | #2
>> Out-of-bounds reference pixel replication should take into account
>> the frame coding mode of the reference frame(s), not the frame
>> coding mode of the current frame.
>>
>> Signed-off-by: Jerome Borsboom <jerome.borsboom at carpalis.nl>
>> ---
>> This should fix the remaining issue with the SA10180.vc1 test file.
> 
> With this patch, the first 601 frames are decoded bit-exact, the
> following frame is not decoded correctly.
> 
> Carl Eugen

Are you sure you have applied all five patches of my previous patch set?
The set has only been partially applied to the master branch. My output
is fully equal to the output of the reference decoder. You could also
specify -bitexact on the command line when decoding as I have previously
run into issues with non-bitexact decoding.


Regards,
Jerome
Carl Eugen Hoyos May 28, 2018, 9:55 p.m. UTC | #3
2018-05-28 10:26 GMT+02:00, Jerome Borsboom <jerome.borsboom@carpalis.nl>:
>>> Out-of-bounds reference pixel replication should take into account
>>> the frame coding mode of the reference frame(s), not the frame
>>> coding mode of the current frame.
>>>
>>> Signed-off-by: Jerome Borsboom <jerome.borsboom at carpalis.nl>
>>> ---
>>> This should fix the remaining issue with the SA10180.vc1 test file.
>>
>> With this patch, the first 601 frames are decoded bit-exact, the
>> following frame is not decoded correctly.
>>
>> Carl Eugen
>
> Are you sure you have applied all five patches of my previous patch set?

No, sorry, I hadn't realized there were still patches missing, I pushed the
remaining patches of the last set.

I will push this one in a few days if nobody beats me or comments.

I still get incorrect frames for SA10100.vc1, ticket #7173.

Thank you Carl Eugen
Michael Niedermayer May 29, 2018, 1:08 a.m. UTC | #4
On Sun, May 27, 2018 at 10:27:39PM +0200, Jerome Borsboom wrote:
> Out-of-bounds reference pixel replication should take into account the frame
> coding mode of the reference frame(s), not the frame coding mode of the
> current frame.
> 
> Signed-off-by: Jerome Borsboom <jerome.borsboom@carpalis.nl>
> ---
> This should fix the remaining issue with the SA10180.vc1 test file.
> 
>  libavcodec/vc1_mc.c | 659 ++++++++++++++++++++++++++++++----------------------
>  1 file changed, 379 insertions(+), 280 deletions(-)

This causes segfaults

Program received signal SIGSEGV, Segmentation fault.
0x0000000000c36920 in ff_emu_edge_vfix18_sse ()
(gdb) bt
Python Exception <type 'exceptions.ImportError'> No module named gdb.frames: 
#0  0x0000000000c36920 in ff_emu_edge_vfix18_sse ()
#1  0x00000000009e6426 in emulated_edge_mc (dst=<optimized out>, src=<optimized out>, dst_stride=<optimized out>, src_stride=<optimized out>, block_w=<optimized out>, block_h=<optimized out>, src_x=<optimized out>, src_y=<optimized out>, w=<optimized out>, h=<optimized out>, vfix_tbl=<optimized out>, 
    v_extend_var=<optimized out>, hfix_tbl=<optimized out>, h_extend_var=<optimized out>) at libavcodec/x86/videodsp_init.c:195
#2  0x00000000009e6289 in emulated_edge_mc_sse2 (buf=0x1db3541 "", src=0x300 <error: Cannot access memory at address 0x300>, buf_stride=140737352976960, src_stride=768, block_w=<optimized out>, block_h=<optimized out>, src_x=-1, src_y=-2, w=720, h=240) at libavcodec/x86/videodsp_init.c:256
#3  0x0000000000913cee in ff_vc1_mc_1mv (v=0x1d01200, dir=<optimized out>) at libavcodec/vc1_mc.c:323
#4  0x00000000009086d4 in vc1_decode_p_mb_intfi (v=<optimized out>) at libavcodec/vc1_block.c:1758
#5  0x0000000000906516 in vc1_decode_p_blocks (v=<optimized out>) at libavcodec/vc1_block.c:2796
#6  0x000000000091b1c8 in vc1_decode_frame (avctx=0x1c46500, data=0x1c91ec0, got_frame=0x7fffffffd6c4, avpkt=<optimized out>) at libavcodec/vc1dec.c:1042
#7  0x00000000006ec6fb in decode_simple_internal (avctx=0x1c46500, frame=0x1c91ec0) at libavcodec/decode.c:398
#8  0x00000000006ec647 in decode_simple_receive_frame (avctx=0x1c46500, frame=0x1c91ec0) at libavcodec/decode.c:594
#9  0x00000000006ea0b2 in decode_receive_frame_internal (avctx=<optimized out>, frame=<optimized out>) at libavcodec/decode.c:612
#10 0x00000000006e9e7d in avcodec_send_packet (avctx=0x1c46500, avpkt=<optimized out>) at libavcodec/decode.c:674
#11 0x000000000042abda in decode (avctx=0x1c46500, frame=0x1c92600, got_frame=0x7fffffffd954, pkt=0x300) at fftools/ffmpeg.c:2234
#12 0x000000000042a0e1 in decode_video (ist=0x1c46c40, pkt=0x7fffffffd960, got_output=0x7fffffffd954, duration_pts=0x7fffffffd958, eof=0, decode_failed=0x7fffffffd950) at fftools/ffmpeg.c:2378
#13 0x00000000004234bd in process_input_packet (ist=0x1c46c40, pkt=0x7fffffffdcc0, no_eof=0) at fftools/ffmpeg.c:2619
#14 0x0000000000427574 in process_input (file_index=<optimized out>) at fftools/ffmpeg.c:4457
#15 0x000000000042263d in transcode_step () at fftools/ffmpeg.c:4577
#16 0x0000000000421081 in transcode () at fftools/ffmpeg.c:4631
#17 0x00000000004207b5 in main (argc=<optimized out>, argv=<optimized out>) at fftools/ffmpeg.c:4838

rax            0x0	0
rbx            0x1	1
rcx            0x300	768
rdx            0x7ffff7ee4a40	140737352976960
rsi            0x300	768
rdi            0x1db3541	31143233
rbp            0x7fffffffd390	0x7fffffffd390
rsp            0x7fffffffd338	0x7fffffffd338
r8             0x2	2
r9             0x23	35
r10            0x7ffff7ee4a40	140737352976960
r11            0x1db3540	31143232
r12            0x300	768
r13            0x13	19
r14            0x25	37
r15            0x13	19
rip            0xc36920	0xc36920 <ff_emu_edge_vfix18_sse+16>
eflags         0x10202	[ IF RF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0

   0x0000000000c36900 <ff_emu_edge_vfix17_sse+80>:	(bad)  
   0x0000000000c36901 <ff_emu_edge_vfix17_sse+81>:	movd   %mm0,0xd(%rdi)
   0x0000000000c36905 <ff_emu_edge_vfix17_sse+85>:	add    %rsi,%rdi
   0x0000000000c36908 <ff_emu_edge_vfix17_sse+88>:	dec    %rax
   0x0000000000c3690b <ff_emu_edge_vfix17_sse+91>:	jne    0xc368fe <ff_emu_edge_vfix17_sse+78>
   0x0000000000c3690d <ff_emu_edge_vfix17_sse+93>:	repz retq 
   0x0000000000c3690f <ff_emu_edge_vfix17_sse+95>:	nop
   0x0000000000c36910 <ff_emu_edge_vfix18_sse+0>:	mov    0x8(%rsp),%rax
   0x0000000000c36915 <ff_emu_edge_vfix18_sse+5>:	sub    %r9,%rax
   0x0000000000c36918 <ff_emu_edge_vfix18_sse+8>:	sub    %r8,%r9
   0x0000000000c3691b <ff_emu_edge_vfix18_sse+11>:	test   %r8,%r8
   0x0000000000c3691e <ff_emu_edge_vfix18_sse+14>:	je     0xc36936 <ff_emu_edge_vfix18_sse+38>
=> 0x0000000000c36920 <ff_emu_edge_vfix18_sse+16>:	movups (%rdx),%xmm0
   0x0000000000c36923 <ff_emu_edge_vfix18_sse+19>:	movd   0xe(%rdx),%mm0
   0x0000000000c36927 <ff_emu_edge_vfix18_sse+23>:	movups %xmm0,(%rdi)
   0x0000000000c3692a <ff_emu_edge_vfix18_sse+26>:	movd   %mm0,0xe(%rdi)
   0x0000000000c3692e <ff_emu_edge_vfix18_sse+30>:	add    %rsi,%rdi
   0x0000000000c36931 <ff_emu_edge_vfix18_sse+33>:	dec    %r8
   0x0000000000c36934 <ff_emu_edge_vfix18_sse+36>:	jne    0xc36927 <ff_emu_edge_vfix18_sse+23>
   0x0000000000c36936 <ff_emu_edge_vfix18_sse+38>:	movups (%rdx),%xmm0
   0x0000000000c36939 <ff_emu_edge_vfix18_sse+41>:	movd   0xe(%rdx),%mm0
   0x0000000000c3693d <ff_emu_edge_vfix18_sse+45>:	movups %xmm0,(%rdi)

[...]
diff mbox

Patch

diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c
index 04b359204c..b0f246eb4d 100644
--- a/libavcodec/vc1_mc.c
+++ b/libavcodec/vc1_mc.c
@@ -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) {
@@ -269,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 */
@@ -289,112 +297,104 @@  void ff_vc1_mc_1mv(VC1Context *v, int dir)
         const int k = 17 + s->mspel * 2;
 
         srcY -= s->mspel * (1 + s->linesize);
-        if (v->fcm == ILACE_FRAME) {
-            if (src_y - s->mspel & 1) {
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
-                                         srcY,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
-                                         k,
-                                         k + 1 >> 1,
-                                         src_x - s->mspel,
-                                         src_y - s->mspel >> 1,
-                                         s->h_edge_pos,
-                                         v_edge_pos + 1 >> 1);
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->linesize,
-                                         srcY + s->linesize,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
-                                         k,
-                                         k >> 1,
-                                         src_x - s->mspel,
-                                         src_y - s->mspel + 1 >> 1,
-                                         s->h_edge_pos,
-                                         v_edge_pos >> 1);
-            } else {
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
-                                         srcY,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
-                                         k,
-                                         k + 1 >> 1,
-                                         src_x - s->mspel,
-                                         src_y - s->mspel >> 1,
-                                         s->h_edge_pos,
-                                         v_edge_pos >> 1);
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->linesize,
-                                         srcY + s->linesize,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
+        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,
-                                         v_edge_pos + 1 >> 1);
-            }
+                                         s->v_edge_pos >> 1);
         } else
-            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);
+            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,
+                                     src_y - s->mspel,
+                                     s->h_edge_pos,
+                                     s->v_edge_pos >> v->field_mode);
         srcY = s->sc.edge_emu_buffer;
-        if (v->fcm == ILACE_FRAME) {
-            if (uvsrc_y & 1) {
-                s->vdsp.emulated_edge_mc(ubuf, srcU,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 1);
-                s->vdsp.emulated_edge_mc(ubuf + s->uvlinesize, srcU + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-                s->vdsp.emulated_edge_mc(vbuf, srcV,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 1);
-                s->vdsp.emulated_edge_mc(vbuf + s->uvlinesize, srcV + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-            } else {
-                s->vdsp.emulated_edge_mc(ubuf, srcU,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-                s->vdsp.emulated_edge_mc(ubuf + s->uvlinesize, srcU + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 1);
-                s->vdsp.emulated_edge_mc(vbuf, srcV,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-                s->vdsp.emulated_edge_mc(vbuf + s->uvlinesize, srcV + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 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,
-                                     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);
+            s->vdsp.emulated_edge_mc(ubuf,
+                                     srcU,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1 + v->field_mode);
+            s->vdsp.emulated_edge_mc(vbuf,
+                                     srcV,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1 + v->field_mode);
         }
         srcU = ubuf;
         srcV = vbuf;
@@ -458,12 +458,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];
 
@@ -472,15 +476,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) {
@@ -547,7 +554,7 @@  void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
 
     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 (v->rangeredfrm || use_ic
         || s->h_edge_pos < 13 || v_edge_pos < 23
@@ -557,36 +564,39 @@  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 */
-        if (v->fcm == ILACE_FRAME) {
-            if (src_y - (s->mspel << fieldmv) & 1) {
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY,
-                                         2 * s->linesize, 2 * s->linesize,
-                                         k, (k << fieldmv) + 1 >> 1,
-                                         src_x - s->mspel, src_y - (s->mspel << fieldmv) >> 1,
-                                         s->h_edge_pos, v_edge_pos + 1 >> 1);
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->linesize, srcY + s->linesize,
-                                         2 * s->linesize, 2 * s->linesize,
-                                         k, (k << fieldmv) >> 1,
-                                         src_x - s->mspel, src_y - (s->mspel << fieldmv) + 1 >> 1,
-                                         s->h_edge_pos, v_edge_pos >> 1);
-            } else {
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY,
-                                         2 * s->linesize, 2 * s->linesize,
-                                         k, (k << fieldmv) + 1 >> 1,
-                                         src_x - s->mspel, src_y - (s->mspel << fieldmv) >> 1,
-                                         s->h_edge_pos, v_edge_pos >> 1);
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->linesize, srcY + s->linesize,
-                                         2 * s->linesize, 2 * s->linesize,
-                                         k, (k << fieldmv) >> 1,
-                                         src_x - s->mspel, src_y - (s->mspel << fieldmv) + 1 >> 1,
-                                         s->h_edge_pos, v_edge_pos + 1 >> 1);
-            }
+        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,
-                                     s->linesize, s->linesize,
-                                     k, k,
-                                     src_x - s->mspel, src_y - s->mspel,
-                                     s->h_edge_pos, v_edge_pos);
+            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,
+                                     src_y - (s->mspel << fieldmv),
+                                     s->h_edge_pos,
+                                     s->v_edge_pos >> v->field_mode);
         srcY = s->sc.edge_emu_buffer;
         /* if we deal with range reduction we need to scale source blocks */
         if (v->rangeredfrm) {
@@ -630,6 +640,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;
@@ -654,6 +666,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;
 
@@ -685,17 +700,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) {
@@ -708,8 +726,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;
         }
     }
 
@@ -717,14 +735,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,
+                                     uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1 + v->field_mode);
+            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
+                                     srcV,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1 + v->field_mode);
+        }
         srcU = s->sc.edge_emu_buffer;
         srcV = s->sc.edge_emu_buffer + 16;
 
@@ -772,11 +847,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];
@@ -803,11 +882,13 @@  void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
             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;
@@ -820,51 +901,70 @@  void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
             || 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)) {
-            if (v->fcm == ILACE_FRAME) {
-                if (uvsrc_y & 1) {
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcU,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) + 1 >> 1, uvsrc_x, uvsrc_y >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos + 1 >> 1);
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->uvlinesize, srcU + s->uvlinesize,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) >> 1, uvsrc_x, uvsrc_y + 1 >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos >> 1);
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16, srcV,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) + 1 >> 1, uvsrc_x, uvsrc_y >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos + 1 >> 1);
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16 + s->uvlinesize, srcV + s->uvlinesize,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) >> 1, uvsrc_x, uvsrc_y + 1 >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos >> 1);
-                } else {
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcU,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) + 1 >> 1, uvsrc_x, uvsrc_y >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos >> 1);
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->uvlinesize, srcU + s->uvlinesize,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) >> 1, uvsrc_x, uvsrc_y + 1 >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos + 1 >> 1);
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16, srcV,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) + 1 >> 1, uvsrc_x, uvsrc_y >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos >> 1);
-                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16 + s->uvlinesize, srcV + s->uvlinesize,
-                                             2 * s->uvlinesize, 2 * s->uvlinesize,
-                                             5, (5 << fieldmv) + 1, uvsrc_x, uvsrc_y + 1 >> 1,
-                                             s->h_edge_pos >> 1, v_edge_pos + 1 >> 1);
+            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,
-                                         s->uvlinesize, s->uvlinesize,
-                                         5, 5, 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, uvsrc_x, uvsrc_y,
-                                         s->h_edge_pos >> 1, v_edge_pos);
+                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;
@@ -907,10 +1007,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;
@@ -927,6 +1032,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);
@@ -973,112 +1080,104 @@  void ff_vc1_interp_mc(VC1Context *v)
         const int k = 17 + s->mspel * 2;
 
         srcY -= s->mspel * (1 + s->linesize);
-        if (v->fcm == ILACE_FRAME) {
-            if (src_y - s->mspel & 1) {
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
-                                         srcY,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
-                                         k,
-                                         k + 1 >> 1,
-                                         src_x - s->mspel,
-                                         src_y - s->mspel >> 1,
-                                         s->h_edge_pos,
-                                         v_edge_pos + 1 >> 1);
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->linesize,
-                                         srcY + s->linesize,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
-                                         k,
-                                         k >> 1,
-                                         src_x - s->mspel,
-                                         src_y - s->mspel + 1 >> 1,
-                                         s->h_edge_pos,
-                                         v_edge_pos >> 1);
-            } else {
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
-                                         srcY,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
-                                         k,
-                                         k + 1 >> 1,
-                                         src_x - s->mspel,
-                                         src_y - s->mspel >> 1,
-                                         s->h_edge_pos,
-                                         v_edge_pos >> 1);
-                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + s->linesize,
-                                         srcY + s->linesize,
-                                         2 * s->linesize,
-                                         2 * s->linesize,
+        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,
-                                         v_edge_pos + 1 >> 1);
-            }
+                                         s->v_edge_pos >> 1);
         } else
-            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);
+            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,
+                                     src_y - s->mspel,
+                                     s->h_edge_pos,
+                                     s->v_edge_pos >> v->field_mode);
         srcY = s->sc.edge_emu_buffer;
-        if (v->fcm == ILACE_FRAME) {
-            if (uvsrc_y & 1) {
-                s->vdsp.emulated_edge_mc(ubuf, srcU,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 1);
-                s->vdsp.emulated_edge_mc(ubuf + s->uvlinesize, srcU + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-                s->vdsp.emulated_edge_mc(vbuf, srcV,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 1);
-                s->vdsp.emulated_edge_mc(vbuf + s->uvlinesize, srcV + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-            } else {
-                s->vdsp.emulated_edge_mc(ubuf, srcU,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-                s->vdsp.emulated_edge_mc(ubuf + s->uvlinesize, srcU + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 1);
-                s->vdsp.emulated_edge_mc(vbuf, srcV,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 5,
-                                         uvsrc_x, uvsrc_y >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) >> 1);
-                s->vdsp.emulated_edge_mc(vbuf + s->uvlinesize, srcV + s->uvlinesize,
-                                         2 * s->uvlinesize, 2 * s->uvlinesize,
-                                         8 + 1, 4,
-                                         uvsrc_x, uvsrc_y + 1 >> 1,
-                                         s->h_edge_pos >> 1, (v_edge_pos >> 1) + 1 >> 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,
-                                     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);
+            s->vdsp.emulated_edge_mc(ubuf,
+                                     srcU,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1 + v->field_mode);
+            s->vdsp.emulated_edge_mc(vbuf,
+                                     srcV,
+                                     uvlinesize,
+                                     uvlinesize,
+                                     9,
+                                     v->field_mode ? 17 : 9,
+                                     uvsrc_x,
+                                     uvsrc_y,
+                                     s->h_edge_pos >> 1,
+                                     s->v_edge_pos >> 1 + v->field_mode);
         }
         srcU = ubuf;
         srcV = vbuf;