vc1.c

来自「linux下的MPEG1」· C语言 代码 · 共 1,909 行 · 第 1/5 页

C
1,909
字号
 * @param[in] len Maximum length * @return Unary length/index */static int get_prefix(GetBitContext *gb, int stop, int len){#if 1    int i;    for(i = 0; i < len && get_bits1(gb) != stop; i++);    return i;/*  int i = 0, tmp = !stop;  while (i != len && tmp != stop)  {    tmp = get_bits(gb, 1);    i++;  }  if (i == len && tmp != stop) return len+1;  return i;*/#else  unsigned int buf;  int log;  OPEN_READER(re, gb);  UPDATE_CACHE(re, gb);  buf=GET_CACHE(re, gb); //Still not sure  if (stop) buf = ~buf;  log= av_log2(-buf); //FIXME: -?  if (log < limit){    LAST_SKIP_BITS(re, gb, log+1);    CLOSE_READER(re, gb);    return log;  }  LAST_SKIP_BITS(re, gb, limit);  CLOSE_READER(re, gb);  return limit;#endif}static inline int decode210(GetBitContext *gb){    int n;    n = get_bits1(gb);    if (n == 1)        return 0;    else        return 2 - get_bits1(gb);}/** * Init VC-1 specific tables and VC1Context members * @param v The VC1Context to initialize * @return Status */static int vc1_init_common(VC1Context *v){    static int done = 0;    int i = 0;    v->hrd_rate = v->hrd_buffer = NULL;    /* VLC tables */    if(!done)    {        done = 1;        init_vlc(&vc1_bfraction_vlc, VC1_BFRACTION_VLC_BITS, 23,                 vc1_bfraction_bits, 1, 1,                 vc1_bfraction_codes, 1, 1, 1);        init_vlc(&vc1_norm2_vlc, VC1_NORM2_VLC_BITS, 4,                 vc1_norm2_bits, 1, 1,                 vc1_norm2_codes, 1, 1, 1);        init_vlc(&vc1_norm6_vlc, VC1_NORM6_VLC_BITS, 64,                 vc1_norm6_bits, 1, 1,                 vc1_norm6_codes, 2, 2, 1);        init_vlc(&vc1_imode_vlc, VC1_IMODE_VLC_BITS, 7,                 vc1_imode_bits, 1, 1,                 vc1_imode_codes, 1, 1, 1);        for (i=0; i<3; i++)        {            init_vlc(&vc1_ttmb_vlc[i], VC1_TTMB_VLC_BITS, 16,                     vc1_ttmb_bits[i], 1, 1,                     vc1_ttmb_codes[i], 2, 2, 1);            init_vlc(&vc1_ttblk_vlc[i], VC1_TTBLK_VLC_BITS, 8,                     vc1_ttblk_bits[i], 1, 1,                     vc1_ttblk_codes[i], 1, 1, 1);            init_vlc(&vc1_subblkpat_vlc[i], VC1_SUBBLKPAT_VLC_BITS, 15,                     vc1_subblkpat_bits[i], 1, 1,                     vc1_subblkpat_codes[i], 1, 1, 1);        }        for(i=0; i<4; i++)        {            init_vlc(&vc1_4mv_block_pattern_vlc[i], VC1_4MV_BLOCK_PATTERN_VLC_BITS, 16,                     vc1_4mv_block_pattern_bits[i], 1, 1,                     vc1_4mv_block_pattern_codes[i], 1, 1, 1);            init_vlc(&vc1_cbpcy_p_vlc[i], VC1_CBPCY_P_VLC_BITS, 64,                     vc1_cbpcy_p_bits[i], 1, 1,                     vc1_cbpcy_p_codes[i], 2, 2, 1);            init_vlc(&vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73,                     vc1_mv_diff_bits[i], 1, 1,                     vc1_mv_diff_codes[i], 2, 2, 1);        }        for(i=0; i<8; i++)            init_vlc(&vc1_ac_coeff_table[i], AC_VLC_BITS, vc1_ac_sizes[i],                     &vc1_ac_tables[i][0][1], 8, 4,                     &vc1_ac_tables[i][0][0], 8, 4, 1);        init_vlc(&ff_msmp4_mb_i_vlc, MB_INTRA_VLC_BITS, 64,                 &ff_msmp4_mb_i_table[0][1], 4, 2,                 &ff_msmp4_mb_i_table[0][0], 4, 2, 1);    }    /* Other defaults */    v->pq = -1;    v->mvrange = 0; /* 7.1.1.18, p80 */    return 0;}/***********************************************************************//** * @defgroup bitplane VC9 Bitplane decoding * @see 8.7, p56 * @{ *//** @addtogroup bitplane * Imode types * @{ */enum Imode {    IMODE_RAW,    IMODE_NORM2,    IMODE_DIFF2,    IMODE_NORM6,    IMODE_DIFF6,    IMODE_ROWSKIP,    IMODE_COLSKIP};/** @} */ //imode defines/** Decode rows by checking if they are skipped * @param plane Buffer to store decoded bits * @param[in] width Width of this buffer * @param[in] height Height of this buffer * @param[in] stride of this buffer */static void decode_rowskip(uint8_t* plane, int width, int height, int stride, GetBitContext *gb){    int x, y;    for (y=0; y<height; y++){        if (!get_bits(gb, 1)) //rowskip            memset(plane, 0, width);        else            for (x=0; x<width; x++)                plane[x] = get_bits(gb, 1);        plane += stride;    }}/** Decode columns by checking if they are skipped * @param plane Buffer to store decoded bits * @param[in] width Width of this buffer * @param[in] height Height of this buffer * @param[in] stride of this buffer * @fixme FIXME: Optimize */static void decode_colskip(uint8_t* plane, int width, int height, int stride, GetBitContext *gb){    int x, y;    for (x=0; x<width; x++){        if (!get_bits(gb, 1)) //colskip            for (y=0; y<height; y++)                plane[y*stride] = 0;        else            for (y=0; y<height; y++)                plane[y*stride] = get_bits(gb, 1);        plane ++;    }}/** Decode a bitplane's bits * @param bp Bitplane where to store the decode bits * @param v VC-1 context for bit reading and logging * @return Status * @fixme FIXME: Optimize */static int bitplane_decoding(uint8_t* data, int *raw_flag, VC1Context *v){    GetBitContext *gb = &v->s.gb;    int imode, x, y, code, offset;    uint8_t invert, *planep = data;    int width, height, stride;    width = v->s.mb_width;    height = v->s.mb_height;    stride = v->s.mb_stride;    invert = get_bits(gb, 1);    imode = get_vlc2(gb, vc1_imode_vlc.table, VC1_IMODE_VLC_BITS, 1);    *raw_flag = 0;    switch (imode)    {    case IMODE_RAW:        //Data is actually read in the MB layer (same for all tests == "raw")        *raw_flag = 1; //invert ignored        return invert;    case IMODE_DIFF2:    case IMODE_NORM2:        if ((height * width) & 1)        {            *planep++ = get_bits(gb, 1);            offset = 1;        }        else offset = 0;        // decode bitplane as one long line        for (y = offset; y < height * width; y += 2) {            code = get_vlc2(gb, vc1_norm2_vlc.table, VC1_NORM2_VLC_BITS, 1);            *planep++ = code & 1;            offset++;            if(offset == width) {                offset = 0;                planep += stride - width;            }            *planep++ = code >> 1;            offset++;            if(offset == width) {                offset = 0;                planep += stride - width;            }        }        break;    case IMODE_DIFF6:    case IMODE_NORM6:        if(!(height % 3) && (width % 3)) { // use 2x3 decoding            for(y = 0; y < height; y+= 3) {                for(x = width & 1; x < width; x += 2) {                    code = get_vlc2(gb, vc1_norm6_vlc.table, VC1_NORM6_VLC_BITS, 2);                    if(code < 0){                        av_log(v->s.avctx, AV_LOG_DEBUG, "invalid NORM-6 VLC\n");                        return -1;                    }                    planep[x + 0] = (code >> 0) & 1;                    planep[x + 1] = (code >> 1) & 1;                    planep[x + 0 + stride] = (code >> 2) & 1;                    planep[x + 1 + stride] = (code >> 3) & 1;                    planep[x + 0 + stride * 2] = (code >> 4) & 1;                    planep[x + 1 + stride * 2] = (code >> 5) & 1;                }                planep += stride * 3;            }            if(width & 1) decode_colskip(data, 1, height, stride, &v->s.gb);        } else { // 3x2            planep += (height & 1) * stride;            for(y = height & 1; y < height; y += 2) {                for(x = width % 3; x < width; x += 3) {                    code = get_vlc2(gb, vc1_norm6_vlc.table, VC1_NORM6_VLC_BITS, 2);                    if(code < 0){                        av_log(v->s.avctx, AV_LOG_DEBUG, "invalid NORM-6 VLC\n");                        return -1;                    }                    planep[x + 0] = (code >> 0) & 1;                    planep[x + 1] = (code >> 1) & 1;                    planep[x + 2] = (code >> 2) & 1;                    planep[x + 0 + stride] = (code >> 3) & 1;                    planep[x + 1 + stride] = (code >> 4) & 1;                    planep[x + 2 + stride] = (code >> 5) & 1;                }                planep += stride * 2;            }            x = width % 3;            if(x) decode_colskip(data  ,             x, height    , stride, &v->s.gb);            if(height & 1) decode_rowskip(data+x, width - x, 1, stride, &v->s.gb);        }        break;    case IMODE_ROWSKIP:        decode_rowskip(data, width, height, stride, &v->s.gb);        break;    case IMODE_COLSKIP:        decode_colskip(data, width, height, stride, &v->s.gb);        break;    default: break;    }    /* Applying diff operator */    if (imode == IMODE_DIFF2 || imode == IMODE_DIFF6)    {        planep = data;        planep[0] ^= invert;        for (x=1; x<width; x++)            planep[x] ^= planep[x-1];        for (y=1; y<height; y++)        {            planep += stride;            planep[0] ^= planep[-stride];            for (x=1; x<width; x++)            {                if (planep[x-1] != planep[x-stride]) planep[x] ^= invert;                else                                 planep[x] ^= planep[x-1];            }        }    }    else if (invert)    {        planep = data;        for (x=0; x<stride*height; x++) planep[x] = !planep[x]; //FIXME stride    }    return (imode<<1) + invert;}/** @} */ //Bitplane group/***********************************************************************//** VOP Dquant decoding * @param v VC-1 Context */static int vop_dquant_decoding(VC1Context *v){    GetBitContext *gb = &v->s.gb;    int pqdiff;    //variable size    if (v->dquant == 2)    {        pqdiff = get_bits(gb, 3);        if (pqdiff == 7) v->altpq = get_bits(gb, 5);        else v->altpq = v->pq + pqdiff + 1;    }    else    {        v->dquantfrm = get_bits(gb, 1);        if ( v->dquantfrm )        {            v->dqprofile = get_bits(gb, 2);            switch (v->dqprofile)            {            case DQPROFILE_SINGLE_EDGE:            case DQPROFILE_DOUBLE_EDGES:                v->dqsbedge = get_bits(gb, 2);                break;            case DQPROFILE_ALL_MBS:                v->dqbilevel = get_bits(gb, 1);            default: break; //Forbidden ?            }            if (v->dqbilevel || v->dqprofile != DQPROFILE_ALL_MBS)            {                pqdiff = get_bits(gb, 3);                if (pqdiff == 7) v->altpq = get_bits(gb, 5);                else v->altpq = v->pq + pqdiff + 1;            }        }    }    return 0;}/** Put block onto picture */static void vc1_put_block(VC1Context *v, DCTELEM block[6][64]){    uint8_t *Y;    int ys, us, vs;    DSPContext *dsp = &v->s.dsp;    if(v->rangeredfrm) {        int i, j, k;        for(k = 0; k < 6; k++)            for(j = 0; j < 8; j++)                for(i = 0; i < 8; i++)                    block[k][i + j*8] = ((block[k][i + j*8] - 128) << 1) + 128;    }    ys = v->s.current_picture.linesize[0];    us = v->s.current_picture.linesize[1];    vs = v->s.current_picture.linesize[2];    Y = v->s.dest[0];    dsp->put_pixels_clamped(block[0], Y, ys);    dsp->put_pixels_clamped(block[1], Y + 8, ys);    Y += ys * 8;    dsp->put_pixels_clamped(block[2], Y, ys);    dsp->put_pixels_clamped(block[3], Y + 8, ys);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?