diff options
Diffstat (limited to 'libavcodec/vc1dec.c')
-rw-r--r-- | libavcodec/vc1dec.c | 967 |
1 files changed, 740 insertions, 227 deletions
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 04b7efbca3..bce0b452e1 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -4,20 +4,20 @@ * Copyright (c) 2006-2007 Konstantin Shishkov * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -39,6 +39,7 @@ #include "unary.h" #include "mathops.h" #include "vdpau_internal.h" +#include "libavutil/avassert.h" #undef NDEBUG #include <assert.h> @@ -73,6 +74,17 @@ enum Imode { }; /** @} */ //imode defines +static void init_block_index(VC1Context *v) +{ + MpegEncContext *s = &v->s; + ff_init_block_index(s); + if (v->field_mode && !(v->second_field ^ v->tff)) { + s->dest[0] += s->current_picture_ptr->f.linesize[0]; + s->dest[1] += s->current_picture_ptr->f.linesize[1]; + s->dest[2] += s->current_picture_ptr->f.linesize[2]; + } +} + /** @} */ //Bitplane group @@ -80,7 +92,7 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v) { MpegEncContext *s = &v->s; int topleft_mb_pos, top_mb_pos; - int stride_y, fieldtx; + int stride_y, fieldtx = 0; int v_dist; /* The put pixels loop is always one MB row behind the decoding loop, @@ -93,7 +105,8 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v) if (!s->first_slice_line) { if (s->mb_x) { topleft_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x - 1; - fieldtx = v->fieldtx_plane[topleft_mb_pos]; + if (v->fcm == ILACE_FRAME) + fieldtx = v->fieldtx_plane[topleft_mb_pos]; stride_y = s->linesize << fieldtx; v_dist = (16 - fieldtx) >> (fieldtx == 0); s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][0], @@ -117,7 +130,8 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v) } if (s->mb_x == s->mb_width - 1) { top_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x; - fieldtx = v->fieldtx_plane[top_mb_pos]; + if (v->fcm == ILACE_FRAME) + fieldtx = v->fieldtx_plane[top_mb_pos]; stride_y = s->linesize << fieldtx; v_dist = fieldtx ? 15 : 8; s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][0], @@ -336,6 +350,9 @@ static void vc1_mc_1mv(VC1Context *v, int dir) int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; int off, off_uv; int v_edge_pos = s->v_edge_pos >> v->field_mode; + int i; + uint8_t (*luty)[256], (*lutuv)[256]; + int use_ic; if ((!v->field_mode || (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && @@ -347,8 +364,10 @@ static void vc1_mc_1mv(VC1Context *v, int dir) // store motion vectors for further use in B frames if (s->pict_type == AV_PICTURE_TYPE_P) { - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = mx; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = my; + for (i = 0; i < 4; i++) { + s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][0] = mx; + s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][1] = my; + } } uvmx = (mx + ((mx & 3) == 3)) >> 1; @@ -367,34 +386,34 @@ static void vc1_mc_1mv(VC1Context *v, int dir) uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1)); uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1)); } - if (v->field_mode) { // interlaced field picture - if (!dir) { - if ((v->cur_field_type != v->ref_field_type[dir]) && v->cur_field_type) { - srcY = s->current_picture.f.data[0]; - srcU = s->current_picture.f.data[1]; - srcV = s->current_picture.f.data[2]; - } else { - srcY = s->last_picture.f.data[0]; - srcU = s->last_picture.f.data[1]; - srcV = s->last_picture.f.data[2]; - } + if (!dir) { + if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) { + srcY = s->current_picture.f.data[0]; + srcU = s->current_picture.f.data[1]; + srcV = s->current_picture.f.data[2]; + luty = v->curr_luty; + lutuv= v->curr_lutuv; + use_ic=v->curr_use_ic; } else { - srcY = s->next_picture.f.data[0]; - srcU = s->next_picture.f.data[1]; - srcV = s->next_picture.f.data[2]; - } - } else { - if (!dir) { srcY = s->last_picture.f.data[0]; srcU = s->last_picture.f.data[1]; srcV = s->last_picture.f.data[2]; - } else { - srcY = s->next_picture.f.data[0]; - srcU = s->next_picture.f.data[1]; - srcV = s->next_picture.f.data[2]; + luty = v->last_luty ; + lutuv= v->last_lutuv; + use_ic=v->last_use_ic; } + } else { + srcY = s->next_picture.f.data[0]; + srcU = s->next_picture.f.data[1]; + srcV = s->next_picture.f.data[2]; + luty = v->next_luty ; + lutuv= v->next_lutuv; + use_ic=v->next_use_ic; } + if(!srcY) + return; + src_x = s->mb_x * 16 + (mx >> 2); src_y = s->mb_y * 16 + (my >> 2); uvsrc_x = s->mb_x * 8 + (uvmx >> 2); @@ -428,7 +447,7 @@ static void vc1_mc_1mv(VC1Context *v, int dir) srcV = s->edge_emu_buffer + 18 * s->linesize; } - if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + if (v->rangeredfrm || use_ic || s->h_edge_pos < 22 || v_edge_pos < 22 || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3 || (unsigned)(src_y - 1) > v_edge_pos - (my&3) - 16 - 3) { @@ -469,22 +488,24 @@ static void vc1_mc_1mv(VC1Context *v, int dir) } } /* if we deal with intensity compensation we need to scale source blocks */ - if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + if (use_ic) { int i, j; uint8_t *src, *src2; src = srcY; for (j = 0; j < 17 + s->mspel * 2; j++) { + int f = v->field_mode ? v->ref_field_type[dir] : ((j + src_y - s->mspel)&1) ; for (i = 0; i < 17 + s->mspel * 2; i++) - src[i] = v->luty[src[i]]; + src[i] = luty[f][src[i]]; src += s->linesize; } src = srcU; src2 = srcV; for (j = 0; j < 9; j++) { + int f = v->field_mode ? v->ref_field_type[dir] : ((j + uvsrc_y)&1); for (i = 0; i < 9; i++) { - src[i] = v->lutuv[src[i]]; - src2[i] = v->lutuv[src2[i]]; + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; } src += s->uvlinesize; src2 += s->uvlinesize; @@ -493,13 +514,8 @@ static void vc1_mc_1mv(VC1Context *v, int dir) srcY += s->mspel * (1 + s->linesize); } - if (v->field_mode && v->cur_field_type) { - off = s->current_picture_ptr->f.linesize[0]; - off_uv = s->current_picture_ptr->f.linesize[1]; - } else { off = 0; off_uv = 0; - } if (s->mspel) { dxy = ((my & 3) << 2) | (mx & 3); v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off , srcY , s->linesize, v->rnd); @@ -541,7 +557,7 @@ static inline int median4(int a, int b, int c, int d) /** Do motion compensation for 4-MV macroblock - luminance block */ -static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) +static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) { MpegEncContext *s = &v->s; uint8_t *srcY; @@ -549,6 +565,8 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) int off; int fieldmv = (v->fcm == ILACE_FRAME) ? v->blk_mv_type[s->block_index[n]] : 0; int v_edge_pos = s->v_edge_pos >> v->field_mode; + uint8_t (*luty)[256]; + int use_ic; if ((!v->field_mode || (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && @@ -559,15 +577,23 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) my = s->mv[dir][n][1]; if (!dir) { - if (v->field_mode) { - if ((v->cur_field_type != v->ref_field_type[dir]) && v->cur_field_type) - srcY = s->current_picture.f.data[0]; - else - srcY = s->last_picture.f.data[0]; - } else + if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) { + srcY = s->current_picture.f.data[0]; + luty = v->curr_luty; + use_ic=v->curr_use_ic; + } else { srcY = s->last_picture.f.data[0]; - } else + luty = v->last_luty; + use_ic=v->last_use_ic; + } + } else { srcY = s->next_picture.f.data[0]; + luty = v->next_luty; + use_ic=v->next_use_ic; + } + + if(!srcY) + return; if (v->field_mode) { if (v->cur_field_type != v->ref_field_type[dir]) @@ -601,6 +627,8 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) tx = (chosen_mv[f][0][0] + chosen_mv[f][1][0]) / 2; ty = (chosen_mv[f][0][1] + chosen_mv[f][1][1]) / 2; break; + default: + av_assert2(0); } 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; @@ -612,6 +640,10 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) int qx, qy; int width = s->avctx->coded_width; int height = s->avctx->coded_height >> 1; + if (s->pict_type == AV_PICTURE_TYPE_P) { + s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][0] = mx; + s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][1] = my; + } qx = (s->mb_x * 16) + (mx >> 2); qy = (s->mb_y * 8) + (my >> 3); @@ -629,8 +661,6 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) off = ((n > 1) ? s->linesize : 0) + (n & 1) * 8; else off = s->linesize * 4 * (n & 2) + (n & 1) * 8; - if (v->field_mode && v->cur_field_type) - off += s->current_picture_ptr->f.linesize[0]; src_x = s->mb_x * 16 + (n & 1) * 8 + (mx >> 2); if (!fieldmv) @@ -661,7 +691,7 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) v_edge_pos--; if (fieldmv && (src_y & 1) && src_y < 4) src_y--; - if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + 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 || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) { @@ -685,14 +715,15 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) } } /* if we deal with intensity compensation we need to scale source blocks */ - if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + if (use_ic) { int i, j; uint8_t *src; src = srcY; for (j = 0; j < 9 + s->mspel * 2; j++) { + int f = v->field_mode ? v->ref_field_type[dir] : (((j<<fieldmv)+src_y - (s->mspel << fieldmv))&1); for (i = 0; i < 9 + s->mspel * 2; i++) - src[i] = v->luty[src[i]]; + src[i] = luty[f][src[i]]; src += s->linesize << fieldmv; } } @@ -701,7 +732,10 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) if (s->mspel) { dxy = ((my & 3) << 2) | (mx & 3); - v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); + if (avg) + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); + else + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); } else { // hpel mc - always used for luma dxy = (my & 2) | ((mx & 2) >> 1); if (!v->rnd) @@ -777,6 +811,8 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) int valid_count; int chroma_ref_type = v->cur_field_type, off = 0; int v_edge_pos = s->v_edge_pos >> v->field_mode; + uint8_t (*lutuv)[256]; + int use_ic; if (!v->field_mode && !v->s.last_picture.f.data[0]) return; @@ -839,32 +875,39 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) } if (!dir) { - if (v->field_mode) { - if ((v->cur_field_type != chroma_ref_type) && v->cur_field_type) { - srcU = s->current_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; - srcV = s->current_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; - } else { - srcU = s->last_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; - srcV = s->last_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; - } + if (v->field_mode && (v->cur_field_type != chroma_ref_type) && v->second_field) { + srcU = s->current_picture.f.data[1]; + srcV = s->current_picture.f.data[2]; + lutuv= v->curr_lutuv; + use_ic=v->curr_use_ic; } else { - srcU = s->last_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; - srcV = s->last_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + srcU = s->last_picture.f.data[1]; + srcV = s->last_picture.f.data[2]; + lutuv= v->last_lutuv; + use_ic=v->last_use_ic; } } else { - srcU = s->next_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; - srcV = s->next_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + srcU = s->next_picture.f.data[1]; + srcV = s->next_picture.f.data[2]; + lutuv= v->next_lutuv; + use_ic=v->next_use_ic; } + if(!srcU) + return; + + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + if (v->field_mode) { if (chroma_ref_type) { srcU += s->current_picture_ptr->f.linesize[1]; srcV += s->current_picture_ptr->f.linesize[2]; } - off = v->cur_field_type ? s->current_picture_ptr->f.linesize[1] : 0; + off = 0; } - if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + if (v->rangeredfrm || use_ic || 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) { @@ -894,16 +937,17 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) } } /* if we deal with intensity compensation we need to scale source blocks */ - if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + if (use_ic) { int i, j; uint8_t *src, *src2; src = srcU; src2 = srcV; for (j = 0; j < 9; j++) { + int f = v->field_mode ? chroma_ref_type : ((j + uvsrc_y)&1); for (i = 0; i < 9; i++) { - src[i] = v->lutuv[src[i]]; - src2[i] = v->lutuv[src2[i]]; + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; } src += s->uvlinesize; src2 += s->uvlinesize; @@ -923,9 +967,9 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) } } -/** Do motion compensation for 4-MV field chroma macroblock (both U and V) +/** Do motion compensation for 4-MV interlaced frame chroma macroblock (both U and V) */ -static void vc1_mc_4mv_chroma4(VC1Context *v) +static void vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg) { MpegEncContext *s = &v->s; H264ChromaContext *h264chroma = &v->h264chroma; @@ -937,16 +981,17 @@ static void vc1_mc_4mv_chroma4(VC1Context *v) static const int s_rndtblfield[16] = { 0, 0, 1, 2, 4, 4, 5, 6, 2, 2, 3, 8, 6, 6, 7, 12 }; int v_dist = fieldmv ? 1 : 4; // vertical offset for lower sub-blocks int v_edge_pos = s->v_edge_pos >> 1; + int use_ic; + uint8_t (*lutuv)[256]; - if (!v->s.last_picture.f.data[0]) - return; if (s->flags & CODEC_FLAG_GRAY) return; for (i = 0; i < 4; i++) { - tx = s->mv[0][i][0]; + int d = i<2 ? dir: dir2; + tx = s->mv[d][i][0]; uvmx_field[i] = (tx + ((tx & 3) == 3)) >> 1; - ty = s->mv[0][i][1]; + ty = s->mv[d][i][1]; if (fieldmv) uvmy_field[i] = (ty >> 4) * 8 + s_rndtblfield[ty & 0xF]; else @@ -960,16 +1005,26 @@ static void vc1_mc_4mv_chroma4(VC1Context *v) // 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); - srcU = s->last_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; - srcV = s->last_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + if (i < 2 ? dir : dir2) { + srcU = s->next_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; + srcV = s->next_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + lutuv = v->next_lutuv; + use_ic = v->next_use_ic; + } else { + srcU = s->last_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; + srcV = s->last_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + lutuv = v->last_lutuv; + use_ic = v->last_use_ic; + } uvmx_field[i] = (uvmx_field[i] & 3) << 1; uvmy_field[i] = (uvmy_field[i] & 3) << 1; if (fieldmv && !(uvsrc_y & 1)) - v_edge_pos--; + v_edge_pos = (s->v_edge_pos >> 1) - 1; + if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2) uvsrc_y--; - if ((v->mv_mode == MV_PMODE_INTENSITY_COMP) + 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)) { @@ -983,22 +1038,32 @@ static void vc1_mc_4mv_chroma4(VC1Context *v) srcV = s->edge_emu_buffer + 16; /* if we deal with intensity compensation we need to scale source blocks */ - if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + if (use_ic) { int i, j; uint8_t *src, *src2; src = srcU; src2 = srcV; for (j = 0; j < 5; j++) { + int f = (uvsrc_y + (j<<fieldmv))&1; for (i = 0; i < 5; i++) { - src[i] = v->lutuv[src[i]]; - src2[i] = v->lutuv[src2[i]]; + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; } - src += s->uvlinesize << 1; - src2 += s->uvlinesize << 1; + src += s->uvlinesize << fieldmv; + src2 += s->uvlinesize << fieldmv; } } } + if (avg) { + if (!v->rnd) { + h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } else { + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } + } else { if (!v->rnd) { h264chroma->put_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); h264chroma->put_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); @@ -1006,6 +1071,7 @@ static void vc1_mc_4mv_chroma4(VC1Context *v) v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); } + } } } @@ -1142,6 +1208,7 @@ static av_always_inline void get_mvdata_interlaced(VC1Context *v, int *dmv_x, } } else { + av_assert0(index < esc); if (extend_x) offs_tab = offset_table2; else @@ -1599,7 +1666,7 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, /** Predict and set motion vector for interlaced frame picture MBs */ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, - int mvn, int r_x, int r_y, uint8_t* is_intra) + int mvn, int r_x, int r_y, uint8_t* is_intra, int dir) { MpegEncContext *s = &v->s; int xy, wrap, off = 0; @@ -1641,14 +1708,14 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, if (s->mb_x || (n == 1) || (n == 3)) { if ((v->blk_mv_type[xy]) // current block (MB) has a field MV || (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both have frame MV - A[0] = s->current_picture.motion_val[0][xy - 1][0]; - A[1] = s->current_picture.motion_val[0][xy - 1][1]; + A[0] = s->current_picture.motion_val[dir][xy - 1][0]; + A[1] = s->current_picture.motion_val[dir][xy - 1][1]; a_valid = 1; } else { // current block has frame mv and cand. has field MV (so average) - A[0] = (s->current_picture.motion_val[0][xy - 1][0] - + s->current_picture.motion_val[0][xy - 1 + off * wrap][0] + 1) >> 1; - A[1] = (s->current_picture.motion_val[0][xy - 1][1] - + s->current_picture.motion_val[0][xy - 1 + off * wrap][1] + 1) >> 1; + A[0] = (s->current_picture.motion_val[dir][xy - 1][0] + + s->current_picture.motion_val[dir][xy - 1 + off * wrap][0] + 1) >> 1; + A[1] = (s->current_picture.motion_val[dir][xy - 1][1] + + s->current_picture.motion_val[dir][xy - 1 + off * wrap][1] + 1) >> 1; a_valid = 1; } if (!(n & 1) && v->is_intra[s->mb_x - 1]) { @@ -1668,11 +1735,11 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) { n_adj = (n & 2) | (n & 1); } - B[0] = s->current_picture.motion_val[0][s->block_index[n_adj] - 2 * wrap][0]; - B[1] = s->current_picture.motion_val[0][s->block_index[n_adj] - 2 * wrap][1]; + B[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0]; + B[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1]; if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) { - B[0] = (B[0] + s->current_picture.motion_val[0][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1; - B[1] = (B[1] + s->current_picture.motion_val[0][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1; + B[0] = (B[0] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1; + B[1] = (B[1] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1; } } if (s->mb_width > 1) { @@ -1683,11 +1750,11 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { n_adj = n & 2; } - C[0] = s->current_picture.motion_val[0][s->block_index[n_adj] - 2 * wrap + 2][0]; - C[1] = s->current_picture.motion_val[0][s->block_index[n_adj] - 2 * wrap + 2][1]; + C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0]; + C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1]; if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { - C[0] = (1 + C[0] + (s->current_picture.motion_val[0][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1; - C[1] = (1 + C[1] + (s->current_picture.motion_val[0][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1; + C[0] = (1 + C[0] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1; + C[1] = (1 + C[1] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1; } if (s->mb_x == s->mb_width - 1) { if (!v->is_intra[s->mb_x - s->mb_stride - 1]) { @@ -1697,11 +1764,11 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { n_adj = n | 1; } - C[0] = s->current_picture.motion_val[0][s->block_index[n_adj] - 2 * wrap - 2][0]; - C[1] = s->current_picture.motion_val[0][s->block_index[n_adj] - 2 * wrap - 2][1]; + C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0]; + C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1]; if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { - C[0] = (1 + C[0] + s->current_picture.motion_val[0][s->block_index[1] - 2 * wrap - 2][0]) >> 1; - C[1] = (1 + C[1] + s->current_picture.motion_val[0][s->block_index[1] - 2 * wrap - 2][1]) >> 1; + C[0] = (1 + C[0] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1; + C[1] = (1 + C[1] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1; } } else c_valid = 0; @@ -1712,12 +1779,12 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, } else { pos_b = s->block_index[1]; b_valid = 1; - B[0] = s->current_picture.motion_val[0][pos_b][0]; - B[1] = s->current_picture.motion_val[0][pos_b][1]; + B[0] = s->current_picture.motion_val[dir][pos_b][0]; + B[1] = s->current_picture.motion_val[dir][pos_b][1]; pos_c = s->block_index[0]; c_valid = 1; - C[0] = s->current_picture.motion_val[0][pos_c][0]; - C[1] = s->current_picture.motion_val[0][pos_c][1]; + C[0] = s->current_picture.motion_val[dir][pos_c][0]; + C[1] = s->current_picture.motion_val[dir][pos_c][1]; } total_valid = a_valid + b_valid + c_valid; @@ -1738,9 +1805,10 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, px = mid_pred(A[0], B[0], C[0]); py = mid_pred(A[1], B[1], C[1]); } else if (total_valid) { - if (a_valid) { px = A[0]; py = A[1]; } - if (b_valid) { px = B[0]; py = B[1]; } - if (c_valid) { px = C[0]; py = C[1]; } + if (a_valid) { px = A[0]; py = A[1]; } + else if (b_valid) { px = B[0]; py = B[1]; } + else if (c_valid) { px = C[0]; py = C[1]; } + else av_assert2(0); } else px = py = 0; } @@ -1795,7 +1863,7 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, } else if (c_valid) { px = C[0]; py = C[1]; - } + } else px = py = 0; } } else if (total_valid == 1) { px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]); @@ -1805,20 +1873,20 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, } /* store MV using signed modulus of MV range defined in 4.11 */ - s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; - s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y; + s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y; if (mvn == 1) { /* duplicate motion data for 1-MV block */ - s->current_picture.motion_val[0][xy + 1 ][0] = s->current_picture.motion_val[0][xy][0]; - s->current_picture.motion_val[0][xy + 1 ][1] = s->current_picture.motion_val[0][xy][1]; - s->current_picture.motion_val[0][xy + wrap ][0] = s->current_picture.motion_val[0][xy][0]; - s->current_picture.motion_val[0][xy + wrap ][1] = s->current_picture.motion_val[0][xy][1]; - s->current_picture.motion_val[0][xy + wrap + 1][0] = s->current_picture.motion_val[0][xy][0]; - s->current_picture.motion_val[0][xy + wrap + 1][1] = s->current_picture.motion_val[0][xy][1]; + s->current_picture.motion_val[dir][xy + 1 ][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + 1 ][1] = s->current_picture.motion_val[dir][xy][1]; + s->current_picture.motion_val[dir][xy + wrap ][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + wrap ][1] = s->current_picture.motion_val[dir][xy][1]; + s->current_picture.motion_val[dir][xy + wrap + 1][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + wrap + 1][1] = s->current_picture.motion_val[dir][xy][1]; } else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */ - s->current_picture.motion_val[0][xy + 1][0] = s->current_picture.motion_val[0][xy][0]; - s->current_picture.motion_val[0][xy + 1][1] = s->current_picture.motion_val[0][xy][1]; - s->mv[0][n + 1][0] = s->mv[0][n][0]; - s->mv[0][n + 1][1] = s->mv[0][n][1]; + s->current_picture.motion_val[dir][xy + 1][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + 1][1] = s->current_picture.motion_val[dir][xy][1]; + s->mv[dir][n + 1][0] = s->mv[dir][n][0]; + s->mv[dir][n + 1][1] = s->mv[dir][n][1]; } } @@ -1832,6 +1900,7 @@ static void vc1_interp_mc(VC1Context *v) int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; int off, off_uv; int v_edge_pos = s->v_edge_pos >> v->field_mode; + int use_ic = v->next_use_ic; if (!v->field_mode && !v->s.next_picture.f.data[0]) return; @@ -1886,7 +1955,7 @@ static void vc1_interp_mc(VC1Context *v) srcV = s->edge_emu_buffer + 18 * s->linesize; } - if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 + if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 || use_ic || (unsigned)(src_x - 1) > s->h_edge_pos - (mx & 3) - 16 - 3 || (unsigned)(src_y - 1) > v_edge_pos - (my & 3) - 16 - 3) { uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; @@ -1925,16 +1994,37 @@ static void vc1_interp_mc(VC1Context *v) src2 += s->uvlinesize; } } + + if (use_ic) { + uint8_t (*luty )[256] = v->next_luty; + uint8_t (*lutuv)[256] = v->next_lutuv; + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + int f = v->field_mode ? v->ref_field_type[1] : ((j+src_y - s->mspel)&1); + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = luty[f][src[i]]; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + int f = v->field_mode ? v->ref_field_type[1] : ((j+uvsrc_y)&1); + for (i = 0; i < 9; i++) { + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } srcY += s->mspel * (1 + s->linesize); } - if (v->field_mode && v->cur_field_type) { - off = s->current_picture_ptr->f.linesize[0]; - off_uv = s->current_picture_ptr->f.linesize[1]; - } else { off = 0; off_uv = 0; - } if (s->mspel) { dxy = ((my & 3) << 2) | (mx & 3); @@ -1989,30 +2079,18 @@ static av_always_inline int scale_mv(int value, int bfrac, int inv, int qs) static inline void vc1_b_mc(VC1Context *v, int dmv_x[2], int dmv_y[2], int direct, int mode) { - if (v->use_ic) { - v->mv_mode2 = v->mv_mode; - v->mv_mode = MV_PMODE_INTENSITY_COMP; - } if (direct) { vc1_mc_1mv(v, 0); vc1_interp_mc(v); - if (v->use_ic) - v->mv_mode = v->mv_mode2; return; } if (mode == BMV_TYPE_INTERPOLATED) { vc1_mc_1mv(v, 0); vc1_interp_mc(v); - if (v->use_ic) - v->mv_mode = v->mv_mode2; return; } - if (v->use_ic && (mode == BMV_TYPE_BACKWARD)) - v->mv_mode = v->mv_mode2; vc1_mc_1mv(v, (mode == BMV_TYPE_BACKWARD)); - if (v->use_ic) - v->mv_mode = v->mv_mode2; } static inline void vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], @@ -2708,7 +2786,7 @@ static int vc1_decode_i_block_adv(VC1Context *v, int16_t block[64], int n, MpegEncContext *s = &v->s; int dc_pred_dir = 0; /* Direction of the DC prediction used */ int i; - int16_t *dc_val; + int16_t *dc_val = NULL; int16_t *ac_val, *ac_val2; int dcdiff; int a_avail = v->a_avail, c_avail = v->c_avail; @@ -2920,7 +2998,7 @@ static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n, MpegEncContext *s = &v->s; int dc_pred_dir = 0; /* Direction of the DC prediction used */ int i; - int16_t *dc_val; + int16_t *dc_val = NULL; int16_t *ac_val, *ac_val2; int dcdiff; int mb_pos = s->mb_x + s->mb_y * s->mb_stride; @@ -3569,7 +3647,7 @@ static int vc1_decode_p_mb(VC1Context *v) } vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); if (!s->mb_intra) - vc1_mc_4mv_luma(v, i, 0); + vc1_mc_4mv_luma(v, i, 0, 0); intra_count += s->mb_intra; is_intra[i] = s->mb_intra; is_coded[i] = mb_has_coeffs; @@ -3659,7 +3737,7 @@ static int vc1_decode_p_mb(VC1Context *v) } for (i = 0; i < 4; i++) { vc1_pred_mv(v, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); - vc1_mc_4mv_luma(v, i, 0); + vc1_mc_4mv_luma(v, i, 0, 0); } vc1_mc_4mv_chroma(v, 0); s->current_picture.qscale_table[mb_pos] = 0; @@ -3695,7 +3773,7 @@ static int vc1_decode_p_mb_intfr(VC1Context *v) int idx_mbmode = 0, mvbp; int stride_y, fieldtx; - mquant = v->pq; /* Loosy initialization */ + mquant = v->pq; /* Lossy initialization */ if (v->skip_is_raw) skipped = get_bits1(gb); @@ -3737,8 +3815,10 @@ static int vc1_decode_p_mb_intfr(VC1Context *v) break; } if (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB - s->current_picture.motion_val[1][s->block_index[0]][0] = 0; - s->current_picture.motion_val[1][s->block_index[0]][1] = 0; + for (i = 0; i < 4; i++) { + s->current_picture.motion_val[1][s->block_index[i]][0] = 0; + s->current_picture.motion_val[1][s->block_index[i]][1] = 0; + } s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; s->mb_intra = v->is_intra[s->mb_x] = 1; for (i = 0; i < 6; i++) @@ -3807,10 +3887,10 @@ static int vc1_decode_p_mb_intfr(VC1Context *v) if (val) { get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); } - vc1_pred_mv_intfr(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0]); - vc1_mc_4mv_luma(v, i, 0); + vc1_pred_mv_intfr(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_4mv_luma(v, i, 0, 0); } else if (i == 4) { - vc1_mc_4mv_chroma4(v); + vc1_mc_4mv_chroma4(v, 0, 0, 0); } } } else if (twomv) { @@ -3819,24 +3899,24 @@ static int vc1_decode_p_mb_intfr(VC1Context *v) if (mvbp & 2) { get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); } - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0]); - vc1_mc_4mv_luma(v, 0, 0); - vc1_mc_4mv_luma(v, 1, 0); + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_4mv_luma(v, 0, 0, 0); + vc1_mc_4mv_luma(v, 1, 0, 0); dmv_x = dmv_y = 0; if (mvbp & 1) { get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); } - vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0]); - vc1_mc_4mv_luma(v, 2, 0); - vc1_mc_4mv_luma(v, 3, 0); - vc1_mc_4mv_chroma4(v); + vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_4mv_luma(v, 2, 0, 0); + vc1_mc_4mv_luma(v, 3, 0, 0); + vc1_mc_4mv_chroma4(v, 0, 0, 0); } else { mvbp = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][2]; dmv_x = dmv_y = 0; if (mvbp) { get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); } - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0]); + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); vc1_mc_1mv(v, 0); } if (cbp) @@ -3876,7 +3956,7 @@ static int vc1_decode_p_mb_intfr(VC1Context *v) v->blk_mv_type[s->block_index[1]] = 0; v->blk_mv_type[s->block_index[2]] = 0; v->blk_mv_type[s->block_index[3]] = 0; - vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0]); + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); vc1_mc_1mv(v, 0); } if (s->mb_x == s->mb_width - 1) @@ -3899,11 +3979,11 @@ static int vc1_decode_p_mb_intfi(VC1Context *v) int val; /* temp values */ int first_block = 1; int dst_idx, off; - int pred_flag; + int pred_flag = 0; int block_cbp = 0, pat, block_tt = 0; int idx_mbmode = 0; - mquant = v->pq; /* Loosy initialization */ + mquant = v->pq; /* Lossy initialization */ idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); if (idx_mbmode <= 1) { // intra MB @@ -3938,7 +4018,6 @@ static int vc1_decode_p_mb_intfi(VC1Context *v) continue; v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - off += v->cur_field_type ? ((i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]) : 0; s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize); // TODO: loop filter } @@ -3964,7 +4043,7 @@ static int vc1_decode_p_mb_intfi(VC1Context *v) get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag); } vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], pred_flag, 0); - vc1_mc_4mv_luma(v, i, 0); + vc1_mc_4mv_luma(v, i, 0, 0); } else if (i == 4) vc1_mc_4mv_chroma(v, 0); } @@ -3985,8 +4064,6 @@ static int vc1_decode_p_mb_intfi(VC1Context *v) dst_idx += i >> 2; val = ((cbp >> (5 - i)) & 1); off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; - if (v->cur_field_type) - off += (i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]; if (val) { pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, @@ -4176,7 +4253,7 @@ static void vc1_decode_b_mb_intfi(VC1Context *v) int bmvtype = BMV_TYPE_BACKWARD; int idx_mbmode, interpmvp; - mquant = v->pq; /* Loosy initialization */ + mquant = v->pq; /* Lossy initialization */ s->mb_intra = 0; idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); @@ -4215,7 +4292,6 @@ static void vc1_decode_b_mb_intfi(VC1Context *v) for (j = 0; j < 64; j++) s->block[i][j] <<= 1; off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - off += v->cur_field_type ? ((i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]) : 0; s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize); // TODO: yet to perform loop filter } @@ -4276,7 +4352,7 @@ static void vc1_decode_b_mb_intfi(VC1Context *v) &pred_flag[bmvtype == BMV_TYPE_BACKWARD]); } vc1_pred_b_mv_intfi(v, i, dmv_x, dmv_y, 0, pred_flag); - vc1_mc_4mv_luma(v, i, bmvtype == BMV_TYPE_BACKWARD); + vc1_mc_4mv_luma(v, i, bmvtype == BMV_TYPE_BACKWARD, 0); } else if (i == 4) vc1_mc_4mv_chroma(v, bmvtype == BMV_TYPE_BACKWARD); } @@ -4297,8 +4373,6 @@ static void vc1_decode_b_mb_intfi(VC1Context *v) dst_idx += i >> 2; val = ((cbp >> (5 - i)) & 1); off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; - if (v->cur_field_type) - off += (i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]; if (val) { vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, @@ -4312,6 +4386,357 @@ static void vc1_decode_b_mb_intfi(VC1Context *v) } } +/** Decode one B-frame MB (in interlaced frame B picture) + */ +static int vc1_decode_b_mb_intfr(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + int mvsw = 0; /* motion vector switch */ + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int val; /* temp value */ + int first_block = 1; + int dst_idx, off; + int skipped, direct, twomv = 0; + int block_cbp = 0, pat, block_tt = 0; + int idx_mbmode = 0, mvbp; + int stride_y, fieldtx; + int bmvtype = BMV_TYPE_BACKWARD; + int dir, dir2; + + mquant = v->pq; /* Lossy initialization */ + s->mb_intra = 0; + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + + if (!skipped) { + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 2); + if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_2MV_FIELD) + { + twomv = 1; + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + } else { + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + } + } + + if (v->dmb_is_raw) + direct = get_bits1(gb); + else + direct = v->direct_mb_plane[mb_pos]; + + if (direct) { + s->mv[0][0][0] = s->current_picture.motion_val[0][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][0][1] = s->current_picture.motion_val[0][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][0][0] = s->current_picture.motion_val[1][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][0][1] = s->current_picture.motion_val[1][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 1, s->quarter_sample); + + if (twomv) { + s->mv[0][2][0] = s->current_picture.motion_val[0][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][2][1] = s->current_picture.motion_val[0][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][2][0] = s->current_picture.motion_val[1][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][2][1] = s->current_picture.motion_val[1][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 1, s->quarter_sample); + + for (i = 1; i < 4; i+=2) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][i-1][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][i-1][1]; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][i-1][0]; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][i-1][1]; + } + } else { + for (i = 1; i < 4; i++) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][0][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][0][1]; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][0][0]; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][0][1]; + } + } + } + + if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB + for (i = 0; i < 4; i++) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = 0; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = 0; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = 0; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; + s->mb_intra = v->is_intra[s->mb_x] = 1; + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 1; + fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = get_bits1(gb); + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + v->mb_type[0][s->block_index[i]] = s->mb_intra; + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (i < 4) { + stride_y = s->linesize << fieldtx; + off = (fieldtx) ? ((i & 1) * 8) + ((i & 2) >> 1) * s->linesize : (i & 1) * 8 + 4 * (i & 2) * s->linesize; + } else { + stride_y = s->uvlinesize; + off = 0; + } + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, stride_y); + } + } else { + s->mb_intra = v->is_intra[s->mb_x] = 0; + if (!direct) { + if (skipped || !s->mb_intra) { + bmvtype = decode012(gb); + switch (bmvtype) { + case 0: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_BACKWARD : BMV_TYPE_FORWARD; + break; + case 1: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_FORWARD : BMV_TYPE_BACKWARD; + break; + case 2: + bmvtype = BMV_TYPE_INTERPOLATED; + } + } + + if (twomv && bmvtype != BMV_TYPE_INTERPOLATED) + mvsw = get_bits1(gb); + } + + if (!skipped) { // inter MB + mb_has_coeffs = ff_vc1_mbmode_intfrp[0][idx_mbmode][3]; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (!direct) { + if (bmvtype == BMV_TYPE_INTERPOLATED & twomv) { + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + } + else if (bmvtype == BMV_TYPE_INTERPOLATED | twomv) { + v->twomvbp = get_vlc2(gb, v->twomvbp_vlc->table, VC1_2MV_BLOCK_PATTERN_VLC_BITS, 1); + } + } + + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 0; + fieldtx = v->fieldtx_plane[mb_pos] = ff_vc1_mbmode_intfrp[0][idx_mbmode][1]; + /* for all motion vector read MVDATA and motion compensate each block */ + dst_idx = 0; + if (direct) { + if (twomv) { + for (i = 0; i < 4; i++) { + vc1_mc_4mv_luma(v, i, 0, 0); + vc1_mc_4mv_luma(v, i, 1, 1); + } + vc1_mc_4mv_chroma4(v, 0, 0, 0); + vc1_mc_4mv_chroma4(v, 1, 1, 1); + } else { + vc1_mc_1mv(v, 0); + vc1_interp_mc(v); + } + } else if (twomv && bmvtype == BMV_TYPE_INTERPOLATED) { + mvbp = v->fourmvbp; + for (i = 0; i < 4; i++) { + dir = i==1 || i==3; + dmv_x = dmv_y = 0; + val = ((mvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + j = i > 1 ? 2 : 0; + vc1_pred_mv_intfr(v, j, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); + vc1_mc_4mv_luma(v, j, dir, dir); + vc1_mc_4mv_luma(v, j+1, dir, dir); + } + + vc1_mc_4mv_chroma4(v, 0, 0, 0); + vc1_mc_4mv_chroma4(v, 1, 1, 1); + } else if (bmvtype == BMV_TYPE_INTERPOLATED) { + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_1mv(v, 0); + + dmv_x = dmv_y = 0; + if (mvbp & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 1); + vc1_interp_mc(v); + } else if (twomv) { + dir = bmvtype == BMV_TYPE_BACKWARD; + dir2 = dir; + if (mvsw) + dir2 = !dir; + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); + + dmv_x = dmv_y = 0; + if (mvbp & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir2); + + if (mvsw) { + for (i = 0; i<2; i++) { + s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; + s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; + s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; + s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; + } + } else { + vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); + vc1_pred_mv_intfr(v, 2, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); + } + + vc1_mc_4mv_luma(v, 0, dir, 0); + vc1_mc_4mv_luma(v, 1, dir, 0); + vc1_mc_4mv_luma(v, 2, dir2, 0); + vc1_mc_4mv_luma(v, 3, dir2, 0); + vc1_mc_4mv_chroma4(v, dir, dir2, 0); + } else { + dir = bmvtype == BMV_TYPE_BACKWARD; + + mvbp = ff_vc1_mbmode_intfrp[0][idx_mbmode][2]; + dmv_x = dmv_y = 0; + if (mvbp) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], dir); + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); + for (i = 0; i<2; i++) { + s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; + s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; + } + vc1_mc_1mv(v, dir); + } + + if (cbp) + GET_MQUANT(); // p. 227 + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + if (!fieldtx) + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + else + off = (i & 4) ? 0 : ((i & 1) * 8 + ((i > 1) * s->linesize)); + if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : (s->linesize << fieldtx), + (i & 4) && (s->flags & CODEC_FLAG_GRAY), &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + + } else { // skipped + dir = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; + s->current_picture.qscale_table[mb_pos] = 0; + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + + if (!direct) { + if (bmvtype == BMV_TYPE_INTERPOLATED) { + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 1); + } else { + dir = bmvtype == BMV_TYPE_BACKWARD; + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], dir); + if (mvsw) { + int dir2 = dir; + if (mvsw) + dir2 = !dir; + for (i = 0; i<2; i++) { + s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; + s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; + s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; + s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; + } + } else { + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); + for (i = 0; i<2; i++) { + s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; + s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; + } + } + } + } + + vc1_mc_1mv(v, dir); + if (direct || bmvtype == BMV_TYPE_INTERPOLATED) { + vc1_interp_mc(v); + } + } + } + if (s->mb_x == s->mb_width - 1) + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0])*s->mb_stride); + v->cbp[s->mb_x] = block_cbp; + v->ttblk[s->mb_x] = block_tt; + return 0; +} + /** Decode blocks of I-frame */ static void vc1_decode_i_blocks(VC1Context *v) @@ -4357,7 +4782,7 @@ static void vc1_decode_i_blocks(VC1Context *v) s->first_slice_line = 1; for (s->mb_y = 0; s->mb_y < s->end_mb_y; s->mb_y++) { s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); for (; s->mb_x < v->end_mb_x; s->mb_x++) { uint8_t *dst[6]; ff_update_block_index(s); @@ -4497,13 +4922,13 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) s->mb_y = s->start_mb_y; if (s->start_mb_y) { s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); memset(&s->coded_block[s->block_index[0] - s->b8_stride], 0, (1 + s->b8_stride) * sizeof(*s->coded_block)); } for (; s->mb_y < s->end_mb_y; s->mb_y++) { s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); for (;s->mb_x < s->mb_width; s->mb_x++) { int16_t (*block)[64] = v->block[v->cur_blk_idx]; ff_update_block_index(s); @@ -4574,7 +4999,8 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) /* raw bottom MB row */ s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); + for (;s->mb_x < s->mb_width; s->mb_x++) { ff_update_block_index(s); vc1_put_signed_blocks_clamped(v); @@ -4622,7 +5048,7 @@ static void vc1_decode_p_blocks(VC1Context *v) memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride); for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); for (; s->mb_x < s->mb_width; s->mb_x++) { ff_update_block_index(s); @@ -4648,9 +5074,9 @@ static void vc1_decode_p_blocks(VC1Context *v) if (s->mb_y != s->start_mb_y) ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); s->first_slice_line = 0; } - if (apply_loop_filter) { + if (apply_loop_filter && v->fcm == PROGRESSIVE) { s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); for (; s->mb_x < s->mb_width; s->mb_x++) { ff_update_block_index(s); vc1_apply_p_loop_filter(v); @@ -4694,12 +5120,14 @@ static void vc1_decode_b_blocks(VC1Context *v) s->first_slice_line = 1; for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); for (; s->mb_x < s->mb_width; s->mb_x++) { ff_update_block_index(s); if (v->fcm == ILACE_FIELD) vc1_decode_b_mb_intfi(v); + else if (v->fcm == ILACE_FRAME) + vc1_decode_b_mb_intfr(v); else vc1_decode_b_mb(v); if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { @@ -4731,11 +5159,13 @@ static void vc1_decode_skip_blocks(VC1Context *v) s->first_slice_line = 1; for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { s->mb_x = 0; - ff_init_block_index(s); + init_block_index(v); ff_update_block_index(s); - memcpy(s->dest[0], s->last_picture.f.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16); - memcpy(s->dest[1], s->last_picture.f.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); - memcpy(s->dest[2], s->last_picture.f.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); + if (s->last_picture.f.data[0]) { + memcpy(s->dest[0], s->last_picture.f.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16); + memcpy(s->dest[1], s->last_picture.f.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); + memcpy(s->dest[2], s->last_picture.f.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); + } ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); s->first_slice_line = 0; } @@ -5005,6 +5435,7 @@ static void vc1_draw_sprites(VC1Context *v, SpriteData* sd) static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb) { + int ret; MpegEncContext *s = &v->s; AVCodecContext *avctx = s->avctx; SpriteData sd; @@ -5022,10 +5453,8 @@ static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb) } av_frame_unref(&v->sprite_output_frame); - if (ff_get_buffer(avctx, &v->sprite_output_frame, 0) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return -1; - } + if ((ret = ff_get_buffer(avctx, &v->sprite_output_frame, 0)) < 0) + return ret; vc1_draw_sprites(v, &sd); @@ -5088,9 +5517,6 @@ av_cold int ff_vc1_decode_init_alloc_tables(VC1Context *v) v->mv_f_base = av_mallocz(2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); v->mv_f[0] = v->mv_f_base + s->b8_stride + 1; v->mv_f[1] = v->mv_f[0] + (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); - v->mv_f_last_base = av_mallocz(2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); - v->mv_f_last[0] = v->mv_f_last_base + s->b8_stride + 1; - v->mv_f_last[1] = v->mv_f_last[0] + (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); v->mv_f_next_base = av_mallocz(2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); v->mv_f_next[0] = v->mv_f_next_base + s->b8_stride + 1; v->mv_f_next[1] = v->mv_f_next[0] + (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); @@ -5160,6 +5586,16 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) if (ff_vc1_init_common(v) < 0) return -1; + // ensure static VLC tables are initialized + if (ff_msmpeg4_decode_init(avctx) < 0) + return -1; + if (ff_vc1_decode_init_alloc_tables(v) < 0) + return -1; + // Hack to ensure the above functions will be called + // again once we know all necessary settings. + // That this is necessary might indicate a bug. + ff_vc1_decode_end(avctx); + ff_h264chroma_init(&v->h264chroma, 8); ff_vc1dsp_init(&v->vc1dsp); @@ -5260,6 +5696,11 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) v->sprite_height > 1 << 14 || v->output_width > 1 << 14 || v->output_height > 1 << 14) return -1; + + if ((v->sprite_width&1) || (v->sprite_height&1)) { + avpriv_request_sample(avctx, "odd sprites support"); + return AVERROR_PATCHWELCOME; + } } return 0; } @@ -5288,7 +5729,6 @@ av_cold int ff_vc1_decode_end(AVCodecContext *avctx) av_freep(&v->mb_type_base); av_freep(&v->blk_mv_type_base); av_freep(&v->mv_f_base); - av_freep(&v->mv_f_last_base); av_freep(&v->mv_f_next_base); av_freep(&v->block); av_freep(&v->cbp_base); @@ -5312,14 +5752,19 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, MpegEncContext *s = &v->s; AVFrame *pict = data; uint8_t *buf2 = NULL; - const uint8_t *buf_start = buf; - int mb_height, n_slices1; + const uint8_t *buf_start = buf, *buf_start_second_field = NULL; + int mb_height, n_slices1=-1; struct { uint8_t *buf; GetBitContext gb; int mby_start; } *slices = NULL, *tmp; + v->second_field = 0; + + if(s->flags & CODEC_FLAG_LOW_DELAY) + s->low_delay = 1; + /* no supplementary picture */ if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) { /* special case for last picture */ @@ -5331,7 +5776,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, *got_frame = 1; } - return 0; + return buf_size; } if (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) { @@ -5364,6 +5809,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, break; case VC1_CODE_FIELD: { int buf_size3; + if (avctx->hwaccel || + s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) + buf_start_second_field = start; tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); if (!tmp) goto err; @@ -5415,6 +5863,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n"); goto err; } else { // found field marker, unescape second field + if (avctx->hwaccel || + s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) + buf_start_second_field = divider; tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); if (!tmp) goto err; @@ -5468,6 +5919,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, s->low_delay = !avctx->has_b_frames || v->res_sprite; if (v->profile == PROFILE_ADVANCED) { + if(avctx->coded_width<=1 || avctx->coded_height<=1) + goto err; s->h_edge_pos = avctx->coded_width; s->v_edge_pos = avctx->coded_height; } @@ -5484,15 +5937,20 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, // do parse frame header v->pic_header_flag = 0; + v->first_pic_header_flag = 1; if (v->profile < PROFILE_ADVANCED) { - if (ff_vc1_parse_frame_header(v, &s->gb) == -1) { + if (ff_vc1_parse_frame_header(v, &s->gb) < 0) { goto err; } } else { - if (ff_vc1_parse_frame_header_adv(v, &s->gb) == -1) { + if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) { goto err; } } + v->first_pic_header_flag = 0; + + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_log(v->s.avctx, AV_LOG_DEBUG, "pict_type: %c\n", av_get_picture_type_char(s->pict_type)); if ((avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) && s->pict_type != AV_PICTURE_TYPE_I) { @@ -5500,6 +5958,11 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, goto err; } + if ((s->mb_height >> v->field_mode) == 0) { + av_log(v->s.avctx, AV_LOG_ERROR, "image too short\n"); + goto err; + } + // process pulldown flags s->current_picture_ptr->f.repeat_pict = 0; // Pulldown flags are only valid when 'broadcast' has been set. @@ -5537,39 +6000,71 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, goto err; } + v->s.current_picture_ptr->f.interlaced_frame = (v->fcm != PROGRESSIVE); + v->s.current_picture_ptr->f.top_field_first = v->tff; + s->me.qpel_put = s->dsp.put_qpel_pixels_tab; s->me.qpel_avg = s->dsp.avg_qpel_pixels_tab; if ((CONFIG_VC1_VDPAU_DECODER) - &&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) - ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start); - else if (avctx->hwaccel) { - if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0) - goto err; - if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0) - goto err; - if (avctx->hwaccel->end_frame(avctx) < 0) - goto err; + &&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) { + if (v->field_mode && buf_start_second_field) { + ff_vdpau_vc1_decode_picture(s, buf_start, buf_start_second_field - buf_start); + ff_vdpau_vc1_decode_picture(s, buf_start_second_field, (buf + buf_size) - buf_start_second_field); + } else { + ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start); + } + } else if (avctx->hwaccel) { + if (v->field_mode && buf_start_second_field) { + // decode first field + s->picture_structure = PICT_BOTTOM_FIELD - v->tff; + if (avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start) < 0) + goto err; + if (avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start) < 0) + goto err; + if (avctx->hwaccel->end_frame(avctx) < 0) + goto err; + + // decode second field + s->gb = slices[n_slices1 + 1].gb; + s->picture_structure = PICT_TOP_FIELD + v->tff; + v->second_field = 1; + v->pic_header_flag = 0; + if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) { + av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed"); + goto err; + } + v->s.current_picture_ptr->f.pict_type = v->s.pict_type; + + if (avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0) + goto err; + if (avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0) + goto err; + if (avctx->hwaccel->end_frame(avctx) < 0) + goto err; + } else { + s->picture_structure = PICT_FRAME; + if (avctx->hwaccel->start_frame(avctx, buf_start, (buf + buf_size) - buf_start) < 0) + goto err; + if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0) + goto err; + if (avctx->hwaccel->end_frame(avctx) < 0) + goto err; + } } else { + int header_ret = 0; + + ff_mpeg_er_frame_start(s); v->bits = buf_size * 8; v->end_mb_x = s->mb_width; if (v->field_mode) { - uint8_t *tmp[2]; s->current_picture.f.linesize[0] <<= 1; s->current_picture.f.linesize[1] <<= 1; s->current_picture.f.linesize[2] <<= 1; s->linesize <<= 1; s->uvlinesize <<= 1; - tmp[0] = v->mv_f_last[0]; - tmp[1] = v->mv_f_last[1]; - v->mv_f_last[0] = v->mv_f_next[0]; - v->mv_f_last[1] = v->mv_f_next[1]; - v->mv_f_next[0] = v->mv_f[0]; - v->mv_f_next[1] = v->mv_f[1]; - v->mv_f[0] = tmp[0]; - v->mv_f[1] = tmp[1]; } mb_height = s->mb_height >> v->field_mode; for (i = 0; i <= n_slices; i++) { @@ -5581,7 +6076,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, continue; } v->second_field = 1; - v->blocks_off = s->mb_width * s->mb_height << 1; + v->blocks_off = s->b8_stride * (s->mb_height&~1); v->mb_off = s->mb_stride * s->mb_height >> 1; } else { v->second_field = 0; @@ -5591,44 +6086,62 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, if (i) { v->pic_header_flag = 0; if (v->field_mode && i == n_slices1 + 2) { - if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) { + if ((header_ret = ff_vc1_parse_frame_header_adv(v, &s->gb)) < 0) { av_log(v->s.avctx, AV_LOG_ERROR, "Field header damaged\n"); continue; } } else if (get_bits1(&s->gb)) { v->pic_header_flag = 1; - if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) { + if ((header_ret = ff_vc1_parse_frame_header_adv(v, &s->gb)) < 0) { av_log(v->s.avctx, AV_LOG_ERROR, "Slice header damaged\n"); continue; } } } + if (header_ret < 0) + continue; s->start_mb_y = (i == 0) ? 0 : FFMAX(0, slices[i-1].mby_start % mb_height); if (!v->field_mode || v->second_field) s->end_mb_y = (i == n_slices ) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height); - else + else { + if (i >= n_slices) { + av_log(v->s.avctx, AV_LOG_ERROR, "first field slice count too large\n"); + continue; + } s->end_mb_y = (i <= n_slices1 + 1) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height); + } + if (s->end_mb_y <= s->start_mb_y) { + av_log(v->s.avctx, AV_LOG_ERROR, "end mb y %d %d invalid\n", s->end_mb_y, s->start_mb_y); + continue; + } + if (!v->p_frame_skipped && s->pict_type != AV_PICTURE_TYPE_I && !v->cbpcy_vlc) { + av_log(v->s.avctx, AV_LOG_ERROR, "missing cbpcy_vlc\n"); + continue; + } ff_vc1_decode_blocks(v); if (i != n_slices) s->gb = slices[i].gb; } if (v->field_mode) { v->second_field = 0; - if (s->pict_type == AV_PICTURE_TYPE_B) { - memcpy(v->mv_f_base, v->mv_f_next_base, - 2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); - } s->current_picture.f.linesize[0] >>= 1; s->current_picture.f.linesize[1] >>= 1; s->current_picture.f.linesize[2] >>= 1; s->linesize >>= 1; s->uvlinesize >>= 1; + if (v->s.pict_type != AV_PICTURE_TYPE_BI && v->s.pict_type != AV_PICTURE_TYPE_B) { + FFSWAP(uint8_t *, v->mv_f_next[0], v->mv_f[0]); + FFSWAP(uint8_t *, v->mv_f_next[1], v->mv_f[1]); + } } av_dlog(s->avctx, "Consumed %i/%i bits\n", get_bits_count(&s->gb), s->gb.size_in_bits); // if (get_bits_count(&s->gb) > buf_size * 8) // return -1; - ff_er_frame_end(&s->er); + if(s->er.error_occurred && s->pict_type == AV_PICTURE_TYPE_B) + goto err; + if(!v->field_mode) + ff_er_frame_end(&s->er); } ff_MPV_frame_end(s); @@ -5650,11 +6163,11 @@ image: if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) goto err; - ff_print_debug_info(s, s->current_picture_ptr); + ff_print_debug_info(s, s->current_picture_ptr, pict); } else if (s->last_picture_ptr != NULL) { if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) goto err; - ff_print_debug_info(s, s->last_picture_ptr); + ff_print_debug_info(s, s->last_picture_ptr, pict); } if (s->last_picture_ptr || s->low_delay) { *got_frame = 1; |