From patchwork Mon Apr 23 18:59:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Borsboom X-Patchwork-Id: 8615 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:155:0:0:0:0:0 with SMTP id c82-v6csp1020178jad; Mon, 23 Apr 2018 11:59:50 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/TM3Mn+NFs9iyEIOhWB4YrCWh42YsyNle+x0WP7yOg0VWwQiQSY7TW19L7JZvm7ZEVXy34 X-Received: by 2002:adf:87ab:: with SMTP id b40-v6mr18644070wrb.156.1524509990670; Mon, 23 Apr 2018 11:59:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524509990; cv=none; d=google.com; s=arc-20160816; b=jzlM9Gevj6borCaUb6oYLw1qF/PEUUiQkmCOKcbntK0YHb04SGDbIZHFzoN5lLZONc Nl85y3UeYblgFdbruL8YX/Qjid9kxxnOneAvcD13c2nlp43JobVBM4tf8dm57AW2mt00 716jRYhzWTnEZt4KMsv6u+m2+lTf08NwIXZlHbPVM5/a4Y4uCJsXYOADF7SHYR4cirVf NKsbhBx4s8XiDU2YLZQ0X3fogFyfpG9oGJspDZjSXXS8FBIjlitF4bD0iIlnm8OlhlWm VfxTemHukqgM+cgyUAegIz0LFLMLhC63SGbYURbQ9iGblVYbLa9OZYyKK8/eYxeGofeM 5YLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:content-language:mime-version:user-agent:date :message-id:from:to:dkim-signature:delivered-to :arc-authentication-results; bh=cOmkvGZTwac0MBrED4/BBRkxjtJY+d6cYkf8vGI/UBc=; b=r5HKiLgm+m2Dq3U3FV7GvYNa32fONKmrEb3kj4idXz2TcU121N0StjV7KWhAlJ69x5 kV9QPN/PpadPWwyI1voGZSpCsPba+V8jsunbo6cGEaNxkwGnHpm8GIrbaubLxW8pQfsy d0kLmz8Kbel61mobD9I597/rNB7HpEpitmPWQgmT/prWzKJcRiAoUkAmvFltdLip3wp6 JxvGkBKQUHU1GPwE4XNTgC7CptSgYSiNbgjxxDO7NTqvIq6tDJ5pNzQoQtRt51vjwU0N WoNHSDPZG/LY6dmfPaMmvhsjRjLTSabIuqTi9+by2dGhQCZiz0wC/LPHQAT1YRuoM/hV Aacg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@carpalis.nl header.s=default header.b=or12yQgh; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o12si5948885wme.114.2018.04.23.11.59.50; Mon, 23 Apr 2018 11:59:50 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@carpalis.nl header.s=default header.b=or12yQgh; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D502568A184; Mon, 23 Apr 2018 21:59:18 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from kyoto.xs4all.nl (kyoto.xs4all.nl [83.161.153.34]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3EFCA68A129 for ; Mon, 23 Apr 2018 21:59:13 +0300 (EEST) Received: from [IPv6:2001:980:9507:0:8e70:5aff:fec6:83fc] ([IPv6:2001:980:9507:0:8e70:5aff:fec6:83fc]) (authenticated bits=0) by kyoto.xs4all.nl (8.14.7/8.14.7) with ESMTP id w3NIxfhL003305 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 23 Apr 2018 20:59:41 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=carpalis.nl; s=default; t=1524509981; bh=aoo6hIWI9j0sKt+srZMWhJiD4qGEtik39ihJNYhqZ0A=; h=To:From:Subject:Date; b=or12yQghTsBmBI1eC2AvCj5QnzJMAmdDIA2r3fPUxUIQ5t2IvP7fEm5FfylohSFcx xn+cDOh1SlzSuNEem8y/oxsijJZtU/WRfPZB/WCvDrYm1mUc27PLaY+l252bqekkal kmOnfpbmljrSHl/ox1Wf3eTGFl1/Dn5T9DgqylDDpTIbSPPlgmDJvnu+RoLVYV1Wl8 6vSpeaWtKcOb0BUqO1jD+LU/QF+khv0NMjFVSL+9jdoVerCJPyvBJFB3eEYk1eVi96 4xOpqOFnhfK7c0hqNlTEyG+/g3Rd3wcs/HQc/6anVOggas1E71eZZGtO98tfvUaxcX l+9h4Br8xBdVw== To: ffmpeg-devel@ffmpeg.org From: Jerome Borsboom Message-ID: <45d5ec36-d64f-03c0-2c96-05e88a7d4b2f@carpalis.nl> Date: Mon, 23 Apr 2018 20:59:41 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 MIME-Version: 1.0 Content-Language: nl Subject: [FFmpeg-devel] [PATCH 08/14] avcodec/vc1: implement interlaced out-of-bounds reference pixel replication X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" The existing implementation did out-of-bounds reference pixel replication for progressive reference frames. In interlaced reference frames both the even and odd line on the horizontal edges need to be replicated. Signed-off-by: Jerome Borsboom --- libavcodec/vc1_mc.c | 376 +++++++++++++++++++++++++++++++++------- tests/ref/fate/vc1_ilaced_twomv | 18 +- 2 files changed, 318 insertions(+), 76 deletions(-) diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c index 5eacaaa8ee..04b359204c 100644 --- a/libavcodec/vc1_mc.c +++ b/libavcodec/vc1_mc.c @@ -254,9 +254,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; @@ -284,22 +289,113 @@ 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 (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, + k, + k >> 1, + src_x - s->mspel, + src_y - s->mspel + 1 >> 1, + s->h_edge_pos, + v_edge_pos + 1 >> 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); 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 (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); + } + } 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); + } srcU = ubuf; srcV = vbuf; /* if we deal with range reduction we need to scale source blocks */ @@ -443,26 +539,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]; - 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 @@ -471,11 +557,36 @@ 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 (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); + } + } 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); srcY = s->sc.edge_emu_buffer; /* if we deal with range reduction we need to scale source blocks */ if (v->rangeredfrm) { @@ -683,7 +794,10 @@ 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]; @@ -702,24 +816,56 @@ 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 (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); + } + } 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); + } srcU = s->sc.edge_emu_buffer; srcV = s->sc.edge_emu_buffer + 16; @@ -793,9 +939,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; @@ -822,22 +973,113 @@ 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 (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, + k, + k >> 1, + src_x - s->mspel, + src_y - s->mspel + 1 >> 1, + s->h_edge_pos, + v_edge_pos + 1 >> 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); 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 (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); + } + } 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); + } srcU = ubuf; srcV = vbuf; /* if we deal with range reduction we need to scale source blocks */ diff --git a/tests/ref/fate/vc1_ilaced_twomv b/tests/ref/fate/vc1_ilaced_twomv index fa56b29495..4dd5a40d74 100644 --- a/tests/ref/fate/vc1_ilaced_twomv +++ b/tests/ref/fate/vc1_ilaced_twomv @@ -7,12 +7,12 @@ 0, 2, 2, 1, 3110400, 0x3b615b79 0, 3, 3, 1, 3110400, 0x4fbb6f84 0, 4, 4, 1, 3110400, 0xc1ca8532 -0, 5, 5, 1, 3110400, 0xb6e7d363 -0, 6, 6, 1, 3110400, 0x1beb5c34 -0, 7, 7, 1, 3110400, 0xcb8cb061 -0, 8, 8, 1, 3110400, 0x13ddbd61 -0, 9, 9, 1, 3110400, 0xde8f052f -0, 10, 10, 1, 3110400, 0x4d4072db -0, 11, 11, 1, 3110400, 0x4e5d29e3 -0, 12, 12, 1, 3110400, 0x75300531 -0, 13, 13, 1, 3110400, 0x1114285a +0, 5, 5, 1, 3110400, 0xbdabd2a8 +0, 6, 6, 1, 3110400, 0x66e60c5a +0, 7, 7, 1, 3110400, 0x8044891c +0, 8, 8, 1, 3110400, 0x3a4e8992 +0, 9, 9, 1, 3110400, 0xe49fcb23 +0, 10, 10, 1, 3110400, 0xe8e165b6 +0, 11, 11, 1, 3110400, 0x046321b5 +0, 12, 12, 1, 3110400, 0x3cbe5125 +0, 13, 13, 1, 3110400, 0xcb4328e7