Skip to content
Snippets Groups Projects
vc1.c 143 KiB
Newer Older
  • Learn to ignore specific revisions
  • /** Decode one P-frame MB (in Simple/Main profile)
     */
    
    static int vc1_decode_p_mb(VC1Context *v)
    
    {
        MpegEncContext *s = &v->s;
        GetBitContext *gb = &s->gb;
    
        int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
    
        int cbp; /* cbp decoding stuff */
        int mqdiff, mquant; /* MB quantization */
    
        int ttmb = v->ttfrm; /* MB Transform type */
    
        int status;
    
        static const int size_table[6] = { 0, 2, 3, 4, 5, 8 },
          offset_table[6] = { 0, 1, 3, 7, 15, 31 };
        int mb_has_coeffs = 1; /* last_flag */
        int dmv_x, dmv_y; /* Differential MV components */
        int index, index1; /* LUT indices */
        int val, sign; /* temp values */
    
        int first_block = 1;
        int dst_idx, off;
    
        mquant = v->pq; /* Loosy initialization */
    
    
        if (v->mv_type_is_raw)
            fourmv = get_bits1(gb);
        else
            fourmv = v->mv_type_mb_plane[mb_pos];
        if (v->skip_is_raw)
            skipped = get_bits1(gb);
        else
    
            skipped = v->s.mbskip_table[mb_pos];
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
        s->dsp.clear_blocks(s->block[0]);
    
    
                if (s->mb_intra) {
                    s->current_picture.motion_val[1][s->block_index[0]][0] = 0;
                    s->current_picture.motion_val[1][s->block_index[0]][1] = 0;
                }
    
                s->current_picture.mb_type[mb_pos] = s->mb_intra ? MB_TYPE_INTRA : MB_TYPE_16x16;
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                vc1_pred_mv(s, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0]);
    
                /* FIXME Set DC val for inter block ? */
    
                if (s->mb_intra && !mb_has_coeffs)
                {
                    GET_MQUANT();
    
                    s->ac_pred = get_bits1(gb);
    
                    if (s->mb_intra) s->ac_pred = get_bits1(gb);
    
                    cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2);
    
                s->current_picture.qscale_table[mb_pos] = mquant;
    
                if (!v->ttmbf && !s->mb_intra && mb_has_coeffs)
    
                    ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table,
    
                    s->dc_val[0][s->block_index[i]] = 0;
                    dst_idx += i >> 2;
    
                    off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize);
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                    v->mb_type[0][s->block_index[i]] = s->mb_intra;
    
                        /* check if prediction blocks A and C are available */
                        v->a_avail = v->c_avail = 0;
    
                        if(i == 2 || i == 3 || !s->first_slice_line)
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                            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;
    
                        s->dsp.vc1_inv_trans_8x8(s->block[i]);
    
                        if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
    
                        s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
    
                        if(v->pq >= 9 && v->overlap) {
                            if(v->c_avail)
    
                                s->dsp.vc1_h_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
    
                                s->dsp.vc1_v_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
    
                        vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY));
    
                        if(!v->ttmbf && ttmb < 8) ttmb = -1;
                        first_block = 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;
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                s->current_picture.qscale_table[mb_pos] = 0;
                vc1_pred_mv(s, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0]);
    
            if (!skipped /* unskipped MB */)
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                int intra_count = 0, coded_inter = 0;
                int is_intra[6], is_coded[6];
    
                cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2);
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                for (i=0; i<6; i++)
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                    s->dc_val[0][s->block_index[i]] = 0;
                    s->mb_intra = 0;
                    if(i < 4) {
                        dmv_x = dmv_y = 0;
                        s->mb_intra = 0;
                        mb_has_coeffs = 0;
                        if(val) {
                            GET_MVDATA(dmv_x, dmv_y);
                        }
                        vc1_pred_mv(s, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0]);
                        if(!s->mb_intra) vc1_mc_4mv_luma(v, i);
                        intra_count += s->mb_intra;
                        is_intra[i] = s->mb_intra;
                        is_coded[i] = mb_has_coeffs;
                    }
                    if(i&4){
                        is_intra[i] = (intra_count >= 3);
                        is_coded[i] = val;
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                    if(i == 4) vc1_mc_4mv_chroma(v);
                    v->mb_type[0][s->block_index[i]] = is_intra[i];
                    if(!coded_inter) coded_inter = !is_intra[i] & is_coded[i];
    
                // if there are no coded blocks then don't do anything more
    
                if(!intra_count && !coded_inter) return 0;
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                dst_idx = 0;
                GET_MQUANT();
                s->current_picture.qscale_table[mb_pos] = mquant;
                /* test if block is intra and has pred */
                {
                    int intrapred = 0;
                    for(i=0; i<6; i++)
                        if(is_intra[i]) {
    
                            if(((!s->first_slice_line || (i==2 || i==3)) && v->mb_type[0][s->block_index[i] - s->block_wrap[i]])
                                || ((s->mb_x || (i==1 || i==3)) && v->mb_type[0][s->block_index[i] - 1])) {
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                                intrapred = 1;
                                break;
                            }
                        }
    
                    if(intrapred)s->ac_pred = get_bits1(gb);
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                    else s->ac_pred = 0;
                }
                if (!v->ttmbf && coded_inter)
    
                    ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2);
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                for (i=0; i<6; i++)
                {
                    dst_idx += i >> 2;
                    off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize);
                    s->mb_intra = is_intra[i];
                    if (is_intra[i]) {
                        /* check if prediction blocks A and C are available */
                        v->a_avail = v->c_avail = 0;
    
                        if(i == 2 || i == 3 || !s->first_slice_line)
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                            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];
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                        vc1_decode_intra_block(v, s->block[i], i, is_coded[i], mquant, (i&4)?v->codingset2:v->codingset);
    
                        if((i>3) && (s->flags & CODEC_FLAG_GRAY)) continue;
    
                        s->dsp.vc1_inv_trans_8x8(s->block[i]);
    
                        if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
    
                        s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize);
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                        if(v->pq >= 9 && v->overlap) {
                            if(v->c_avail)
    
                                s->dsp.vc1_h_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
    
                                s->dsp.vc1_v_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                    } else if(is_coded[i]) {
    
                        status = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY));
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                        if(!v->ttmbf && ttmb < 8) ttmb = -1;
                        first_block = 0;
    
                s->current_picture.qscale_table[mb_pos] = 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;
                }
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                    vc1_pred_mv(s, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0]);
                    vc1_mc_4mv_luma(v, i);
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
                vc1_mc_4mv_chroma(v);
                s->current_picture.qscale_table[mb_pos] = 0;
    
    /** Decode one B-frame MB (in Main profile)
     */
    static void vc1_decode_b_mb(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 */
    
        static const int size_table[6] = { 0, 2, 3, 4, 5, 8 },
          offset_table[6] = { 0, 1, 3, 7, 15, 31 };
        int mb_has_coeffs = 0; /* last_flag */
        int index, index1; /* LUT indices */
        int val, sign; /* temp values */
        int first_block = 1;
        int dst_idx, off;
        int skipped, direct;
        int dmv_x[2], dmv_y[2];
    
        int bmvtype = BMV_TYPE_BACKWARD;
    
    
        mquant = v->pq; /* Loosy initialization */
        s->mb_intra = 0;
    
        if (v->dmb_is_raw)
            direct = get_bits1(gb);
        else
            direct = v->direct_mb_plane[mb_pos];
        if (v->skip_is_raw)
            skipped = get_bits1(gb);
        else
            skipped = v->s.mbskip_table[mb_pos];
    
        s->dsp.clear_blocks(s->block[0]);
        dmv_x[0] = dmv_x[1] = dmv_y[0] = dmv_y[1] = 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.qscale_table[mb_pos] = 0;
    
        if (!direct) {
            if (!skipped) {
                GET_MVDATA(dmv_x[0], dmv_y[0]);
    
            }
            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;
    
        for(i = 0; i < 6; i++)
            v->mb_type[0][s->block_index[i]] = s->mb_intra;
    
    
            if(direct) bmvtype = BMV_TYPE_INTERPOLATED;
            vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
    
            vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
            return;
        }
        if (direct) {
            cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2);
            GET_MQUANT();
    
            s->current_picture.qscale_table[mb_pos] = mquant;
    
                ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2);
    
            dmv_x[0] = dmv_y[0] = dmv_x[1] = dmv_y[1] = 0;
            vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
    
            vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
        } else {
            if(!mb_has_coeffs && !s->mb_intra) {
                /* no coded blocks - effectively skipped */
    
                vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
    
                vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
                return;
            }
            if(s->mb_intra && !mb_has_coeffs) {
                GET_MQUANT();
                s->current_picture.qscale_table[mb_pos] = mquant;
                s->ac_pred = get_bits1(gb);
                cbp = 0;
    
                vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
    
            } else {
                if(bmvtype == BMV_TYPE_INTERPOLATED) {
    
                    if(!mb_has_coeffs) {
                        /* interpolated skipped block */
    
                        vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
    
                vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype);
                if(!s->mb_intra) {
    
                    vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype);
    
                if(s->mb_intra)
                    s->ac_pred = get_bits1(gb);
                cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2);
                GET_MQUANT();
                s->current_picture.qscale_table[mb_pos] = mquant;
                if(!v->ttmbf && !s->mb_intra && mb_has_coeffs)
    
                    ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2);
    
            }
        }
        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);
            off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize);
            v->mb_type[0][s->block_index[i]] = s->mb_intra;
            if(s->mb_intra) {
                /* check if prediction blocks A and C are available */
                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;
    
                s->dsp.vc1_inv_trans_8x8(s->block[i]);
    
                if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
    
                s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
    
                vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize, (i&4) && (s->flags & CODEC_FLAG_GRAY));
    
    static void vc1_decode_i_blocks(VC1Context *v)
    
        int cbp, val;
        uint8_t *coded_val;
        int mb_pos;
    
        /* select codingmode used for VLC tables selection */
        switch(v->y_ac_table_index){
        case 0:
            v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
            break;
        case 1:
            v->codingset = CS_HIGH_MOT_INTRA;
            break;
        case 2:
            v->codingset = CS_MID_RATE_INTRA;
            break;
        }
    
        switch(v->c_ac_table_index){
        case 0:
            v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER;
            break;
        case 1:
            v->codingset2 = CS_HIGH_MOT_INTER;
            break;
        case 2:
            v->codingset2 = CS_MID_RATE_INTER;
            break;
        }
    
        /* Set DC scale - y and c use the same */
        s->y_dc_scale = s->y_dc_scale_table[v->pq];
        s->c_dc_scale = s->c_dc_scale_table[v->pq];
    
        //do frame decode
        s->mb_x = s->mb_y = 0;
        s->mb_intra = 1;
    
        s->first_slice_line = 1;
    
        for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
            for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
                ff_init_block_index(s);
                ff_update_block_index(s);
                s->dsp.clear_blocks(s->block[0]);
                mb_pos = s->mb_x + s->mb_y * s->mb_width;
                s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA;
                s->current_picture.qscale_table[mb_pos] = v->pq;
    
                s->current_picture.motion_val[1][s->block_index[0]][0] = 0;
                s->current_picture.motion_val[1][s->block_index[0]][1] = 0;
    
    
                // do actual MB decoding and displaying
                cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2);
    
                v->s.ac_pred = get_bits1(&v->s.gb);
    
    
                for(k = 0; k < 6; k++) {
                    val = ((cbp >> (5 - k)) & 1);
    
                    if (k < 4) {
                        int pred = vc1_coded_block_pred(&v->s, k, &coded_val);
                        val = val ^ pred;
                        *coded_val = val;
                    }
                    cbp |= val << (5 - k);
    
                    vc1_decode_i_block(v, s->block[k], k, val, (k<4)? v->codingset : v->codingset2);
    
    
                    s->dsp.vc1_inv_trans_8x8(s->block[k]);
    
                        for(j = 0; j < 64; j++) s->block[k][j] += 128;
    
                if(v->pq >= 9 && v->overlap) {
    
                        s->dsp.vc1_h_overlap(s->dest[0], s->linesize);
                        s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
    
                        if(!(s->flags & CODEC_FLAG_GRAY)) {
    
                            s->dsp.vc1_h_overlap(s->dest[1], s->uvlinesize);
                            s->dsp.vc1_h_overlap(s->dest[2], s->uvlinesize);
    
                    s->dsp.vc1_h_overlap(s->dest[0] + 8, s->linesize);
                    s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
    
                    if(!s->first_slice_line) {
    
                        s->dsp.vc1_v_overlap(s->dest[0], s->linesize);
                        s->dsp.vc1_v_overlap(s->dest[0] + 8, s->linesize);
    
                        if(!(s->flags & CODEC_FLAG_GRAY)) {
    
                            s->dsp.vc1_v_overlap(s->dest[1], s->uvlinesize);
                            s->dsp.vc1_v_overlap(s->dest[2], s->uvlinesize);
    
                    s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
                    s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
    
                if(get_bits_count(&s->gb) > v->bits) {
    
                    ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END));
    
                    av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", get_bits_count(&s->gb), v->bits);
                    return;
                }
            }
            ff_draw_horiz_band(s, s->mb_y * 16, 16);
    
            s->first_slice_line = 0;
    
        ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
    
    /** Decode blocks of I-frame for advanced profile
     */
    static void vc1_decode_i_blocks_adv(VC1Context *v)
    {
        int k, j;
        MpegEncContext *s = &v->s;
        int cbp, val;
        uint8_t *coded_val;
        int mb_pos;
        int mquant = v->pq;
        int mqdiff;
        int overlap;
        GetBitContext *gb = &s->gb;
    
        /* select codingmode used for VLC tables selection */
        switch(v->y_ac_table_index){
        case 0:
            v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
            break;
        case 1:
            v->codingset = CS_HIGH_MOT_INTRA;
            break;
        case 2:
            v->codingset = CS_MID_RATE_INTRA;
            break;
        }
    
        switch(v->c_ac_table_index){
        case 0:
            v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER;
            break;
        case 1:
            v->codingset2 = CS_HIGH_MOT_INTER;
            break;
        case 2:
            v->codingset2 = CS_MID_RATE_INTER;
            break;
        }
    
        //do frame decode
        s->mb_x = s->mb_y = 0;
        s->mb_intra = 1;
        s->first_slice_line = 1;
        for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
            for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
                ff_init_block_index(s);
                ff_update_block_index(s);
                s->dsp.clear_blocks(s->block[0]);
                mb_pos = s->mb_x + s->mb_y * s->mb_stride;
                s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA;
    
                s->current_picture.motion_val[1][s->block_index[0]][0] = 0;
                s->current_picture.motion_val[1][s->block_index[0]][1] = 0;
    
    
                // do actual MB decoding and displaying
                cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2);
                if(v->acpred_is_raw)
    
                    v->s.ac_pred = get_bits1(&v->s.gb);
    
                else
                    v->s.ac_pred = v->acpred_plane[mb_pos];
    
                if(v->condover == CONDOVER_SELECT) {
                    if(v->overflg_is_raw)
    
                        overlap = get_bits1(&v->s.gb);
    
                    else
                        overlap = v->over_flags_plane[mb_pos];
                } else
                    overlap = (v->condover == CONDOVER_ALL);
    
                GET_MQUANT();
    
                s->current_picture.qscale_table[mb_pos] = mquant;
    
                /* Set DC scale - y and c use the same */
                s->y_dc_scale = s->y_dc_scale_table[mquant];
                s->c_dc_scale = s->c_dc_scale_table[mquant];
    
    
                for(k = 0; k < 6; k++) {
                    val = ((cbp >> (5 - k)) & 1);
    
                    if (k < 4) {
                        int pred = vc1_coded_block_pred(&v->s, k, &coded_val);
                        val = val ^ pred;
                        *coded_val = val;
                    }
                    cbp |= val << (5 - k);
    
                    v->a_avail = !s->first_slice_line || (k==2 || k==3);
                    v->c_avail = !!s->mb_x || (k==1 || k==3);
    
                    vc1_decode_i_block_adv(v, s->block[k], k, val, (k<4)? v->codingset : v->codingset2, mquant);
    
                    s->dsp.vc1_inv_trans_8x8(s->block[k]);
                    for(j = 0; j < 64; j++) s->block[k][j] += 128;
                }
    
                vc1_put_block(v, s->block);
                if(overlap) {
                    if(s->mb_x) {
    
                        s->dsp.vc1_h_overlap(s->dest[0], s->linesize);
                        s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
    
                            s->dsp.vc1_h_overlap(s->dest[1], s->uvlinesize);
                            s->dsp.vc1_h_overlap(s->dest[2], s->uvlinesize);
    
                    s->dsp.vc1_h_overlap(s->dest[0] + 8, s->linesize);
                    s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
    
                    if(!s->first_slice_line) {
    
                        s->dsp.vc1_v_overlap(s->dest[0], s->linesize);
                        s->dsp.vc1_v_overlap(s->dest[0] + 8, s->linesize);
    
                        if(!(s->flags & CODEC_FLAG_GRAY)) {
    
                            s->dsp.vc1_v_overlap(s->dest[1], s->uvlinesize);
                            s->dsp.vc1_v_overlap(s->dest[2], s->uvlinesize);
    
                    s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
                    s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
    
                    ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END));
    
                    av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", get_bits_count(&s->gb), v->bits);
                    return;
                }
            }
            ff_draw_horiz_band(s, s->mb_y * 16, 16);
            s->first_slice_line = 0;
        }
    
        ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
    
    static void vc1_decode_p_blocks(VC1Context *v)
    
        /* select codingmode used for VLC tables selection */
        switch(v->c_ac_table_index){
        case 0:
            v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
            break;
        case 1:
            v->codingset = CS_HIGH_MOT_INTRA;
            break;
        case 2:
            v->codingset = CS_MID_RATE_INTRA;
            break;
    
        switch(v->c_ac_table_index){
        case 0:
            v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER;
            break;
        case 1:
            v->codingset2 = CS_HIGH_MOT_INTER;
            break;
        case 2:
            v->codingset2 = CS_MID_RATE_INTER;
            break;
    
        s->first_slice_line = 1;
        for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
            for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
                ff_init_block_index(s);
                ff_update_block_index(s);
                s->dsp.clear_blocks(s->block[0]);
    
    
                if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
    
                    ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END));
    
                    av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y);
                    return;
    
            ff_draw_horiz_band(s, s->mb_y * 16, 16);
            s->first_slice_line = 0;
    
        ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
    
    static void vc1_decode_b_blocks(VC1Context *v)
    {
        MpegEncContext *s = &v->s;
    
        /* select codingmode used for VLC tables selection */
        switch(v->c_ac_table_index){
        case 0:
            v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
            break;
        case 1:
            v->codingset = CS_HIGH_MOT_INTRA;
            break;
        case 2:
            v->codingset = CS_MID_RATE_INTRA;
            break;
        }
    
        switch(v->c_ac_table_index){
        case 0:
            v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER;
            break;
        case 1:
            v->codingset2 = CS_HIGH_MOT_INTER;
            break;
        case 2:
            v->codingset2 = CS_MID_RATE_INTER;
            break;
        }
    
        s->first_slice_line = 1;
        for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
            for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
                ff_init_block_index(s);
                ff_update_block_index(s);
                s->dsp.clear_blocks(s->block[0]);
    
                vc1_decode_b_mb(v);
                if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
    
                    ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END));
    
                    av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y);
                    return;
                }
            }
            ff_draw_horiz_band(s, s->mb_y * 16, 16);
            s->first_slice_line = 0;
        }
    
        ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
    
    static void vc1_decode_skip_blocks(VC1Context *v)
    {
        MpegEncContext *s = &v->s;
    
        ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
        s->first_slice_line = 1;
        for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
            s->mb_x = 0;
            ff_init_block_index(s);
            ff_update_block_index(s);
            memcpy(s->dest[0], s->last_picture.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16);
            memcpy(s->dest[1], s->last_picture.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
            memcpy(s->dest[2], s->last_picture.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
            ff_draw_horiz_band(s, s->mb_y * 16, 16);
            s->first_slice_line = 0;
        }
        s->pict_type = P_TYPE;
    }
    
    
    static void vc1_decode_blocks(VC1Context *v)
    
        if(v->x8_type){
            ff_intrax8_decode_picture(&v->x8, 2*v->pq+v->halfpq, v->pq*(!v->pquantizer) );
    
    anonymous's avatar
    anonymous committed
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            switch(v->s.pict_type) {
            case I_TYPE:
    
                if(v->profile == PROFILE_ADVANCED)
                    vc1_decode_i_blocks_adv(v);
                else
                    vc1_decode_i_blocks(v);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                break;
            case P_TYPE:
                if(v->p_frame_skipped)
                    vc1_decode_skip_blocks(v);
                else
                    vc1_decode_p_blocks(v);
                break;
            case B_TYPE:
                if(v->bi_type){
                    if(v->profile == PROFILE_ADVANCED)
                        vc1_decode_i_blocks_adv(v);
                    else
                        vc1_decode_i_blocks(v);
                }else
                    vc1_decode_b_blocks(v);
                break;
            }
    
    /** Find VC-1 marker in buffer
     * @return position where next marker starts or end of buffer if no marker found
     */
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
    static av_always_inline const uint8_t* find_next_marker(const uint8_t *src, const uint8_t *end)
    
    {
        uint32_t mrk = 0xFFFFFFFF;
    
        if(end-src < 4) return end;
        while(src < end){
            mrk = (mrk << 8) | *src++;
            if(IS_MARKER(mrk))
                return src-4;
        }
        return end;
    }
    
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
    static av_always_inline int vc1_unescape_buffer(const uint8_t *src, int size, uint8_t *dst)
    
    {
        int dsize = 0, i;
    
        if(size < 4){
            for(dsize = 0; dsize < size; dsize++) *dst++ = *src++;
            return size;
        }
        for(i = 0; i < size; i++, src++) {
            if(src[0] == 3 && i >= 2 && !src[-1] && !src[-2] && i < size-1 && src[1] < 4) {
                dst[dsize++] = src[1];
                src++;
                i++;
            } else
                dst[dsize++] = *src;
        }
        return dsize;
    }
    
    /** Initialize a VC1/WMV3 decoder
     * @todo TODO: Handle VC-1 IDUs (Transport level?)
    
     * @todo TODO: Decypher remaining bits in extra_data
     */
    
    static int vc1_decode_init(AVCodecContext *avctx)
    
        VC1Context *v = avctx->priv_data;
    
    anonymous's avatar
    anonymous committed
        MpegEncContext *s = &v->s;
    
        GetBitContext gb;
    
        if (!avctx->extradata_size || !avctx->extradata) return -1;
    
        if (!(avctx->flags & CODEC_FLAG_GRAY))
            avctx->pix_fmt = PIX_FMT_YUV420P;
        else
            avctx->pix_fmt = PIX_FMT_GRAY8;
    
    anonymous's avatar
    anonymous committed
        v->s.avctx = avctx;
    
        avctx->flags |= CODEC_FLAG_EMU_EDGE;
        v->s.flags |= CODEC_FLAG_EMU_EDGE;
    
        if(avctx->idct_algo==FF_IDCT_AUTO){
            avctx->idct_algo=FF_IDCT_WMV2;
        }
    
    
    anonymous's avatar
    anonymous committed
        if(ff_h263_decode_init(avctx) < 0)
            return -1;
    
        if (vc1_init_common(v) < 0) return -1;
    
    anonymous's avatar
    anonymous committed
        avctx->coded_width = avctx->width;
        avctx->coded_height = avctx->height;
    
    anonymous's avatar
    anonymous committed
            // looks like WMV3 has a sequence header stored in the extradata
            // advanced sequence header may be before the first frame
            // the last byte of the extradata is a version number, 1 for the
            // samples we can decode
    
            init_get_bits(&gb, avctx->extradata, avctx->extradata_size*8);
    
            if (decode_sequence_header(avctx, &gb) < 0)
              return -1;
    
    anonymous's avatar
    anonymous committed
            count = avctx->extradata_size*8 - get_bits_count(&gb);
            if (count>0)
            {
                av_log(avctx, AV_LOG_INFO, "Extra data: %i bits left, value: %X\n",
                       count, get_bits(&gb, count));
            }
    
    anonymous's avatar
    anonymous committed
            {
                av_log(avctx, AV_LOG_INFO, "Read %i bits in overflow\n", -count);
            }
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
            const uint8_t *start = avctx->extradata;
            uint8_t *end = avctx->extradata + avctx->extradata_size;
            const uint8_t *next;
            int size, buf2_size;
    
            uint8_t *buf2 = NULL;
    
            int seq_initialized = 0, ep_initialized = 0;
    
                av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", avctx->extradata_size);
    
            buf2 = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
            if(start[0]) start++; // in WVC1 extradata first byte is its size
            next = start;
            for(; next < end; start = next){
                next = find_next_marker(start + 4, end);
                size = next - start - 4;
                if(size <= 0) continue;
                buf2_size = vc1_unescape_buffer(start + 4, size, buf2);
                init_get_bits(&gb, buf2, buf2_size * 8);
                switch(AV_RB32(start)){
                case VC1_CODE_SEQHDR:
                    if(decode_sequence_header(avctx, &gb) < 0){
                        av_free(buf2);
                        return -1;
                    }
    
                    seq_initialized = 1;
    
                    break;
                case VC1_CODE_ENTRYPOINT:
                    if(decode_entry_point(avctx, &gb) < 0){
                        av_free(buf2);
                        return -1;
                    }
    
                    ep_initialized = 1;
    
            if(!seq_initialized || !ep_initialized){
    
                av_log(avctx, AV_LOG_ERROR, "Incomplete extradata\n");
                return -1;
            }
    
    anonymous's avatar
    anonymous committed
        avctx->has_b_frames= !!(avctx->max_b_frames);
    
        s->low_delay = !avctx->has_b_frames;
    
    anonymous's avatar
    anonymous committed
        s->mb_width = (avctx->coded_width+15)>>4;
        s->mb_height = (avctx->coded_height+15)>>4;
    
        v->mv_type_mb_plane = av_malloc(s->mb_stride * s->mb_height);
    
        v->direct_mb_plane = av_malloc(s->mb_stride * s->mb_height);
    
        v->acpred_plane = av_malloc(s->mb_stride * s->mb_height);
        v->over_flags_plane = av_malloc(s->mb_stride * s->mb_height);
    
    anonymous's avatar
    anonymous committed
    
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
        /* allocate block type info in that way so it could be used with s->block_index[] */
        v->mb_type_base = av_malloc(s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2);
        v->mb_type[0] = v->mb_type_base + s->b8_stride + 1;
        v->mb_type[1] = v->mb_type_base + s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride + 1;
        v->mb_type[2] = v->mb_type[1] + s->mb_stride * (s->mb_height + 1);
    
    
        if (v->profile == PROFILE_ADVANCED)
    
    //        if (alloc_bitplane(&v->over_flags_plane, s->mb_width, s->mb_height) < 0)
    //            return -1;
    //        if (alloc_bitplane(&v->ac_pred_plane, s->mb_width, s->mb_height) < 0)
    //            return -1;
    
        ff_intrax8_common_init(&v->x8,s);
    
    /** Decode a VC1/WMV3 frame
     * @todo TODO: Handle VC-1 IDUs (Transport level?)
    
    static int vc1_decode_frame(AVCodecContext *avctx,
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                                const uint8_t *buf, int buf_size)
    
        VC1Context *v = avctx->priv_data;
    
    anonymous's avatar
    anonymous committed
        MpegEncContext *s = &v->s;
    
    anonymous's avatar
    anonymous committed
    
        /* no supplementary picture */
        if (buf_size == 0) {
            /* special case for last picture */
            if (s->low_delay==0 && s->next_picture_ptr) {
                *pict= *(AVFrame*)s->next_picture_ptr;
                s->next_picture_ptr= NULL;
    
                *data_size = sizeof(AVFrame);
            }
    
            return 0;
        }
    
    
    Diego Biurrun's avatar
    Diego Biurrun committed
        /* We need to set current_picture_ptr before reading the header,
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
         * otherwise we cannot store anything in there. */
    
    anonymous's avatar
    anonymous committed
        if(s->current_picture_ptr==NULL || s->current_picture_ptr->data[0]){
    
            int i= ff_find_unused_picture(s, 0);
            s->current_picture_ptr= &s->picture[i];
    
    anonymous's avatar
    anonymous committed
        }
    
    
        //for advanced profile we may need to parse and unescape data
    
        if (avctx->codec_id == CODEC_ID_VC1) {
    
            int buf_size2 = 0;
            buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
    
            if(IS_MARKER(AV_RB32(buf))){ /* frame starts with marker and needs to be parsed */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                const uint8_t *start, *end, *next;
    
                int size;
    
                next = buf;
                for(start = buf, end = buf + buf_size; next < end; start = next){
                    next = find_next_marker(start + 4, end);
                    size = next - start - 4;
                    if(size <= 0) continue;
                    switch(AV_RB32(start)){
                    case VC1_CODE_FRAME:
                        buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
                        break;
                    case VC1_CODE_ENTRYPOINT: /* it should be before frame data */
                        buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
                        init_get_bits(&s->gb, buf2, buf_size2*8);
                        decode_entry_point(avctx, &s->gb);
                        break;
                    case VC1_CODE_SLICE:
                        av_log(avctx, AV_LOG_ERROR, "Sliced decoding is not implemented (yet)\n");
                        av_free(buf2);
                        return -1;
                    }