From patchwork Tue May 29 09:18:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Borsboom X-Patchwork-Id: 9150 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:11c:0:0:0:0:0 with SMTP id c28-v6csp2867340jad; Tue, 29 May 2018 02:18:23 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrKQGS25gk+GcWkN/oyCRtIMto5OqyxRJiAJMdXB5t9V/8RtT6rpMGuT2912n7tDXpf0qSq X-Received: by 2002:adf:b097:: with SMTP id i23-v6mr11861050wra.52.1527585503061; Tue, 29 May 2018 02:18:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527585503; cv=none; d=google.com; s=arc-20160816; b=CbAQNwEk2NgU5WyzuIixcwquK/2Op8jKoHH029G4gQGYJhPasbeYfIUN4vJ3JBlQYz IWBqr6WwIPmXJqoSkL7ph3drpooBGtDrCEtkYuenWYcJfpS29U8lCWcDHIvWDschCI9c 2usJGrSNBP0519ecl3MctfIn3Wy6RDfW4z8XY0G15o1Za4JF1ivWpYCpkBtvp9wcE0zk skPtltKEYPV10CHKAQzfCFWCMKfSYQIEJuKuPE1IY9dmFR3EzfPJTrIe5XvvT1r5t92Q bmwjUXk3mzPdPPN+Hil2CjOvkJpUtpvBEjyFtLW9uis+sFHh2zDLN3oD/JWqG9Dv8hth K59g== 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:in-reply-to:mime-version :user-agent:date:message-id:from:references:to:dkim-signature :delivered-to:arc-authentication-results; bh=zheICd821xzChh+jOPrZsDLHoZeRMI0kjoiT+ZR9Eh0=; b=jhakVYJutx5BvZ8XJ+Jdtn4em8RskgvzZViwkUmdn/828ZwtP6jb9cRqgq3QQvGNEf J81P2yEfdWaQwou1Eo2mN+DddFJmaMMvvHRdb+1tEx0tQ3srqXJewsMNSLkU41d9pn6r ZzpRBD7TbhsREdjvJBLHhqK50IqRkegOGgRn1laZ4FYLapvZvCMVHLWwgYtYEJaTdHmr 11QEI1FXSJZuQ3+vMZEiEfVxL7mP2AZxvbx7PDby61zDmfs5fXHL7RlVAABlL2eHSZ4a sGqN2pS3+L7fc2JvmKLLsMmqXTalTDJZoF6ytAWOA5GaOFyLWk9OpDEAId6DvvUM3Ha9 cgjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@carpalis.nl header.s=default header.b=lGgnS7kW; 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 k12-v6si29184075wrl.87.2018.05.29.02.18.22; Tue, 29 May 2018 02:18:23 -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=lGgnS7kW; 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 7D32268A042; Tue, 29 May 2018 12:17:36 +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 6D145689AEC for ; Tue, 29 May 2018 12:17:30 +0300 (EEST) Received: from [10.1.48.103] ([87.215.30.74]) (authenticated bits=0) by kyoto.xs4all.nl (8.14.7/8.14.7) with ESMTP id w4T9IBj7022875 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 29 May 2018 11:18:12 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=carpalis.nl; s=default; t=1527585493; bh=H4NssX4NBcrbN6CpO4ugP1xvzCNnDoTL3GIQjmnB5uw=; h=To:References:Subject:From:Date:In-Reply-To; b=lGgnS7kW8mquArSUwkVu5QkTFsp+YD2ZkYJJROmGPJzxGjLMTAZjrpRDfS6kAfKi5 eJH2o2M+EeNNIW5jCvsc0aSiJ1CGhhWdyfAqi3EgadmzRh7huFUr8xA++PrNvgfdzQ KxEebVJisenn0/4iBfWzv/vt8P6vAYXfUyfHZN+po/bdqPAd8sY0TTCtoqIZ9T+Day 8Gk2yWs6Gr7bkxXzAS/fZIbXfzOzrrqlkfUrj/9eYlNz5iCmAJDEe5cmWep0d+v/Fr 4Xax6R467PKODvVB8rDQ7NQYWnAJZewg8j8JaIrchLf8Kl/p76TNFlp3XqXUh/qYjh xTRV3n+YDxGfg== To: ffmpeg-devel@ffmpeg.org References: <85bd0478-73c1-100f-2376-ef24b12992b5@carpalis.nl> From: Jerome Borsboom Message-ID: <0e742d85-d081-87ed-18bf-68abc09ce302@carpalis.nl> Date: Tue, 29 May 2018 11:18:12 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <85bd0478-73c1-100f-2376-ef24b12992b5@carpalis.nl> Content-Language: nl Subject: Re: [FFmpeg-devel] [PATCH v2] avcodec/vc1: fix 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" 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 --- Does this resolve the SIGSEGV? I think I made a mistake in the calculation of the starting line for progressive reference pictures when the current picture is a field interlaced picture. Instead of adjusting the edge position, the starting line must be adjusted as the vertical stride for replication is half the stride of the field interlaced picture. libavcodec/vc1_mc.c | 659 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 379 insertions(+), 280 deletions(-) diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c index 04b359204c..16fc531712 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 << v->field_mode, + s->h_edge_pos, + s->v_edge_pos); 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 << v->field_mode, + 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, + uvsrc_y << v->field_mode, + s->h_edge_pos >> 1, + s->v_edge_pos >> 1); } 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) << v->field_mode, + 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) { @@ -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 << v->field_mode, + 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, + uvsrc_y << v->field_mode, + s->h_edge_pos >> 1, + s->v_edge_pos >> 1); + } 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 << v->field_mode, + s->h_edge_pos, + s->v_edge_pos); 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 << v->field_mode, + 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, + uvsrc_y << v->field_mode, + s->h_edge_pos >> 1, + s->v_edge_pos >> 1); } srcU = ubuf; srcV = vbuf;