X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fvc1_mc.c;h=1b8d8799b3cbf5fc0c9e1be568993e4fef8f5289;hb=419d2524a8239a8f00b4c1702c91065b259615a2;hp=75c74cad8df706ba1fe27b90e345fd64dbc35698;hpb=b14761d1f8372dfe558193b8b754b9f1a858077d;p=ffmpeg diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c index 75c74cad8df..1b8d8799b3c 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) { @@ -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 */