⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vc1.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * VC-1 and WMV3 decoder * Copyright (c) 2006-2007 Konstantin Shishkov * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer * * This file is part of FFmpeg. * * 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. * * 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file vc1.c * VC-1 and WMV3 decoder * */#include "dsputil.h"#include "avcodec.h"#include "mpegvideo.h"#include "vc1.h"#include "vc1data.h"#include "vc1acdata.h"#include "msmpeg4data.h"#include "unary.h"#include "simple_idct.h"#undef NDEBUG#include <assert.h>#define MB_INTRA_VLC_BITS 9#define DC_VLC_BITS 9#define AC_VLC_BITS 9static const uint16_t table_mb_intra[64][2];/** * 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(&ff_vc1_bfraction_vlc, VC1_BFRACTION_VLC_BITS, 23,                 ff_vc1_bfraction_bits, 1, 1,                 ff_vc1_bfraction_codes, 1, 1, 1);        init_vlc(&ff_vc1_norm2_vlc, VC1_NORM2_VLC_BITS, 4,                 ff_vc1_norm2_bits, 1, 1,                 ff_vc1_norm2_codes, 1, 1, 1);        init_vlc(&ff_vc1_norm6_vlc, VC1_NORM6_VLC_BITS, 64,                 ff_vc1_norm6_bits, 1, 1,                 ff_vc1_norm6_codes, 2, 2, 1);        init_vlc(&ff_vc1_imode_vlc, VC1_IMODE_VLC_BITS, 7,                 ff_vc1_imode_bits, 1, 1,                 ff_vc1_imode_codes, 1, 1, 1);        for (i=0; i<3; i++)        {            init_vlc(&ff_vc1_ttmb_vlc[i], VC1_TTMB_VLC_BITS, 16,                     ff_vc1_ttmb_bits[i], 1, 1,                     ff_vc1_ttmb_codes[i], 2, 2, 1);            init_vlc(&ff_vc1_ttblk_vlc[i], VC1_TTBLK_VLC_BITS, 8,                     ff_vc1_ttblk_bits[i], 1, 1,                     ff_vc1_ttblk_codes[i], 1, 1, 1);            init_vlc(&ff_vc1_subblkpat_vlc[i], VC1_SUBBLKPAT_VLC_BITS, 15,                     ff_vc1_subblkpat_bits[i], 1, 1,                     ff_vc1_subblkpat_codes[i], 1, 1, 1);        }        for(i=0; i<4; i++)        {            init_vlc(&ff_vc1_4mv_block_pattern_vlc[i], VC1_4MV_BLOCK_PATTERN_VLC_BITS, 16,                     ff_vc1_4mv_block_pattern_bits[i], 1, 1,                     ff_vc1_4mv_block_pattern_codes[i], 1, 1, 1);            init_vlc(&ff_vc1_cbpcy_p_vlc[i], VC1_CBPCY_P_VLC_BITS, 64,                     ff_vc1_cbpcy_p_bits[i], 1, 1,                     ff_vc1_cbpcy_p_codes[i], 2, 2, 1);            init_vlc(&ff_vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73,                     ff_vc1_mv_diff_bits[i], 1, 1,                     ff_vc1_mv_diff_codes[i], 2, 2, 1);        }        for(i=0; i<8; i++)            init_vlc(&ff_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_bits1(gb)) //rowskip            memset(plane, 0, width);        else            for (x=0; x<width; x++)                plane[x] = get_bits1(gb);        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 * @todo 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_bits1(gb)) //colskip            for (y=0; y<height; y++)                plane[y*stride] = 0;        else            for (y=0; y<height; y++)                plane[y*stride] = get_bits1(gb);        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 * @todo 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_bits1(gb);    imode = get_vlc2(gb, ff_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_bits1(gb);            offset = 1;        }        else offset = 0;        // decode bitplane as one long line        for (y = offset; y < height * width; y += 2) {            code = get_vlc2(gb, ff_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, ff_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, ff_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_bits1(gb);        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_bits1(gb);                if(!v->dqbilevel)                    v->halfpq = 0;            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;

⌨️ 快捷键说明

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