www.pudn.com > AVS.rar > vlc.cpp
/*************************************************************************
AVS1-P2视频解码器源码
版权所有:联合信源数字音视频技术(北京)有限公司, (c) 2005-2006
AVS1-P2 Video Decoder Source Code
(c) Copyright, NSCC All Rights Reserved, 2005-2006
*************************************************************************
Distributed under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*************************************************************************/
/*************************************************************************
文件名称: vlc.cpp
描 述: 变长解码过程相关的函数。
*************************************************************************/
/*************************************************************************
Revision History
data Modification Author
2005-2-8 Created jthou
*************************************************************************/
#include "vlc.h"
#include "define.h"
#include "global.h"
#include "assert.h"
#include "memory.h"
char AVS_2DVLC_INTRA_dec[7][64][2]={{{-1,-1}}};
char AVS_2DVLC_INTER_dec[7][64][2]={{{-1,-1}}};
char AVS_2DVLC_CHROMA_dec[5][64][2]={{{-1,-1}}};
/************************************************************************/
/* 函数功能:数码流中1前面有多少个零 */
/* - 用在解哥伦布码中 */
/************************************************************************/
AVS_INT PassLeadingZeroBits(const AVS_BYTE* buffer,AVS_DWORD* totbitoffset)
{
AVS_LONG byteoffset; // byte from start of buffer
AVS_INT bitLeft; // bit from start of byte
AVS_INT findtag;
AVS_INT oldbitoffset = *totbitoffset;
findtag=0;
byteoffset= (*totbitoffset)/8;
bitLeft= 31-((*totbitoffset)&7);
AVS_INT data = DWORD_SWAP(*(AVS_DWORD*)(buffer+byteoffset));
while(!findtag)
{
findtag = (data & (0x01<>3;
AVS_INT bitoffset = (*totbitoffset)&7;
AVS_INT bitleft = 31-bitoffset;
AVS_UINT data = DWORD_SWAP(*(AVS_DWORD*)(buffer+byteoffset));
*totbitoffset += numbits;
AVS_UINT tmp = data<>(32-numbits);
return inf;
}
AVS_INT se(const AVS_BYTE* buffer,AVS_DWORD* totbitoffset, AVS_INT bytecount)
{
AVS_INT info = 0;
AVS_INT value1=0;
AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset);
info = read_bits(buffer, totbitoffset, len);
linfo_se(len,info,&value1);
return value1;
}
AVS_INT ue(const AVS_BYTE* buffer,AVS_DWORD* totbitoffset, AVS_INT bytecount)
{
AVS_INT info = 0;
AVS_INT value1;
AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset);
info = read_bits(buffer, totbitoffset, len);
linfo_ue(len*2+1,info,&value1);
return value1;
}
void linfo_ue(AVS_INT len, AVS_INT info, AVS_INT *value1)
{
//*value1 = (AVS_INT)pow(2,(len/2))+info-1;
AVS_INT n = 1<<(len/2);
info --;
*value1 = n + info;
}
void linfo_se(AVS_INT len, AVS_INT info, AVS_INT *value1)
{
AVS_INT n;
n = 1<>1);
else
*value1 = (n>>1);
}
void linfo_cbp_intra(AVS_INT len,AVS_INT info,AVS_INT *cbp)
{
AVS_INT cbp_idx;
linfo_ue(len,info,&cbp_idx);
*cbp=NCBP[cbp_idx][0];
}
void linfo_cbp_inter(AVS_INT len,AVS_INT info,AVS_INT *cbp)
{
AVS_INT cbp_idx;
linfo_ue(len,info,&cbp_idx);
*cbp=NCBP[cbp_idx][1];
}
void linfo_cbp_intra422(AVS_INT len,AVS_INT info,AVS_INT *cbp)
{
AVS_INT cbp_idx;
linfo_ue(len,info,&cbp_idx);
*cbp=NCBP422[cbp_idx][0];
}
void linfo_cbp_inter422(AVS_INT len,AVS_INT info,AVS_INT *cbp)
{
AVS_INT cbp_idx;
linfo_ue(len,info,&cbp_idx);
*cbp=NCBP422[cbp_idx][1];
}
AVS_INT me(const AVS_BYTE* buffer,AVS_DWORD* totbitoffset, AVS_INT bytecount, AVS_DWORD dwMbType)
{
AVS_INT cbp = 0;
AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset);
AVS_INT info = read_bits(buffer, totbitoffset, len);
if(dwMbType == I_8x8)
linfo_cbp_intra(len*2+1, info, &cbp);
else
linfo_cbp_inter(len*2+1, info, &cbp);
return cbp;
}
AVS_INT me_chroma422(const AVS_BYTE* buffer,AVS_DWORD* totbitoffset, AVS_INT bytecount, AVS_DWORD dwMbType)
{
AVS_INT cbp = 0;
AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset);
AVS_INT info = read_bits(buffer, totbitoffset, len);
if(dwMbType == I_8x8)
linfo_cbp_intra422(len*2+1, info, &cbp);
else
linfo_cbp_inter422(len*2+1, info, &cbp);
return cbp;
}
/************************************************************************/
/* 函数功能:初始化VLC表 */
/************************************************************************/
void MakeVlcTable()
{
AVS_INT level, run, ipos;
AVS_INT i;
//make decoder table for 2DVLC_INTRA code
if(AVS_2DVLC_INTRA_dec[0][0][1]<0) // Don't need to set this every time. rewrite later.
{
memset(AVS_2DVLC_INTRA_dec,-1,sizeof(AVS_2DVLC_INTRA_dec));
for(i=0;i<7;i++)
{
for(run=0;run<26;run++)
for(level=0;level<27;level++)
{
ipos=AVS_2DVLC_INTRA[i][run][level];
assert(ipos<64);
if(ipos>=0)
{
if(i==0)
{
AVS_2DVLC_INTRA_dec[i][ipos][0]=level+1;
AVS_2DVLC_INTRA_dec[i][ipos][1]=run;
AVS_2DVLC_INTRA_dec[i][ipos+1][0]=-(level+1);
AVS_2DVLC_INTRA_dec[i][ipos+1][1]=run;
}
else
{
AVS_2DVLC_INTRA_dec[i][ipos][0]=level;
AVS_2DVLC_INTRA_dec[i][ipos][1]=run;
if(level)
{
AVS_2DVLC_INTRA_dec[i][ipos+1][0]=-(level);
AVS_2DVLC_INTRA_dec[i][ipos+1][1]=run;
}
}
}
}
}
assert(AVS_2DVLC_INTRA_dec[0][0][1]>=0); //otherwise, tables are bad.
}
//make decoder table for 2DVLC_INTER code
if(AVS_2DVLC_INTER_dec[0][0][1]<0) // Don't need to set this every time. rewrite later.
{
memset(AVS_2DVLC_INTER_dec,-1,sizeof(AVS_2DVLC_INTER_dec));
for(i=0;i<7;i++)
{
for(run=0;run<26;run++)
for(level=0;level<27;level++)
{
ipos=AVS_2DVLC_INTER[i][run][level];
assert(ipos<64);
if(ipos>=0)
{
if(i==0)
{
AVS_2DVLC_INTER_dec[i][ipos][0]=level+1;
AVS_2DVLC_INTER_dec[i][ipos][1]=run;
AVS_2DVLC_INTER_dec[i][ipos+1][0]=-(level+1);
AVS_2DVLC_INTER_dec[i][ipos+1][1]=run;
}
else
{
AVS_2DVLC_INTER_dec[i][ipos][0]=level;
AVS_2DVLC_INTER_dec[i][ipos][1]=run;
if(level)
{
AVS_2DVLC_INTER_dec[i][ipos+1][0]=-(level);
AVS_2DVLC_INTER_dec[i][ipos+1][1]=run;
}
}
}
}
}
assert(AVS_2DVLC_INTER_dec[0][0][1]>=0); //otherwise, tables are bad.
}
//make decoder table for 2DVLC_CHROMA code
if(AVS_2DVLC_CHROMA_dec[0][0][1]<0) // Don't need to set this every time. rewrite later.
{
memset(AVS_2DVLC_CHROMA_dec,-1,sizeof(AVS_2DVLC_CHROMA_dec));
for(i=0;i<5;i++)
{
for(run=0;run<26;run++)
for(level=0;level<27;level++)
{
ipos=AVS_2DVLC_CHROMA[i][run][level];
assert(ipos<64);
if(ipos>=0)
{
if(i==0)
{
AVS_2DVLC_CHROMA_dec[i][ipos][0]=level+1;
AVS_2DVLC_CHROMA_dec[i][ipos][1]=run;
AVS_2DVLC_CHROMA_dec[i][ipos+1][0]=-(level+1);
AVS_2DVLC_CHROMA_dec[i][ipos+1][1]=run;
}
else
{
AVS_2DVLC_CHROMA_dec[i][ipos][0]=level;
AVS_2DVLC_CHROMA_dec[i][ipos][1]=run;
if(level)
{
AVS_2DVLC_CHROMA_dec[i][ipos+1][0]=-(level);
AVS_2DVLC_CHROMA_dec[i][ipos+1][1]=run;
}
}
}
}
}
assert(AVS_2DVLC_CHROMA_dec[0][0][1]>=0); //otherwise, tables are bad.
}
}
void ReadLumaCoeff(const AVS_BYTE* pbCurrent,AVS_DWORD dwDataLen, AVS_DWORD* pdwBitOffset, MBINFO* pCurrMb, AVS_DWORD dwPictureStructure, AVS_SHORT* pResidual)
{
static const AVS_INT incVlc_intra[7] = { 0,1,2,4,7,10,3000};
static const AVS_INT incVlc_inter[7] = { 0,1,2,3,6, 9,3000};
AVS_INT i;
AVS_INT ii, jj;
AVS_DWORD tabNo = 0;
AVS_INT symbol2D;
AVS_INT vlc_numcoef = 0;
AVS_INT run = 0, level = 0;
AVS_INT buffer_level[65];
AVS_INT buffer_run[65];
AVS_INT* TABNO = TabNoBuf+512;
AVS_INT* TABNO2 = TabNoBuf2+512;
AVS_INT qp, shift;
qp = pCurrMb->dwMbQp;
AVS_INT QPI, sum;
AVS_INT ipos = -1;
AVS_INT Golomb_se_type=SE_LUM_AC_INTER;
AVS_INT leadingZeroBits;
AVS_INT grad;
AVS_INT val, val2;
memset(buffer_run, 0, 65*sizeof(AVS_INT));
memset(buffer_level, 0, 65*sizeof(AVS_INT));
if(pCurrMb->dwMbType == I_8x8)
{
for(i=0; i<65; i++)
{
leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset);
grad = VLC_Golomb_Order[0][tabNo][0];
val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad);
symbol2D = (1<<(leadingZeroBits+grad)) - (1<>1;
leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset);
grad = 1;
val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad);
val2 = (1<<(leadingZeroBits+grad)) - (1<MaxRun[0][tabNo])?1:RefAbsLevel[tabNo][run]);
if(symbol2D & 1)
level=-level;
}
buffer_level[i] = level;
buffer_run[i] = run;
if(abs(level) > incVlc_intra[tabNo])
{
tabNo = TABNO[level];
}
}
for(i=(vlc_numcoef-1); i>=0; i--)
{
ipos += (buffer_run[i]+1);
ii = SCAN[dwPictureStructure][ipos][0];
jj = SCAN[dwPictureStructure][ipos][1];
shift = IQ_SHIFT[qp];
QPI = IQ_TAB[qp];
val = buffer_level[i];
sum = (val*QPI+(1<<(shift-2)) )>>(shift-1);
*(pResidual+jj*8+ii) = sum;
}
}
else
{
tabNo = 0;
for(i=0; i<65; i++)
{
leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset);
grad = VLC_Golomb_Order[1][tabNo][0];
val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad);
symbol2D = (1<<(leadingZeroBits+grad)) - (1<>1;
leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset);
grad = 0;
val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad);
val2 = (1<<(leadingZeroBits+grad)) - (1<MaxRun[1][tabNo])?1:RefAbsLevel[tabNo+7][run]);
if(symbol2D & 1) //jlzheng 7.20
level=-level;
}
buffer_level[i] = level;
buffer_run[i] = run;
if(abs(level) > incVlc_inter[tabNo]) //qwang 11.29
{
tabNo = TABNO2[level];
}
}
//将解码的level,run写到LumaCoeff[][];
for(i=(vlc_numcoef-1); i>=0; i--)
{
ipos += (buffer_run[i]+1);
ii = SCAN[dwPictureStructure][ipos][0];
jj = SCAN[dwPictureStructure][ipos][1];
shift = IQ_SHIFT[qp];
QPI = IQ_TAB[qp];
val = buffer_level[i];
sum = (val*QPI+(1<<(shift-2)) )>>(shift-1);
*(pResidual+jj*8+ii) = sum;
}
}
}
void ReadChromaCoeff(const AVS_BYTE* pbCurrent,AVS_DWORD dwDataLen, AVS_DWORD* pdwBitOffset, MBINFO* pCurrMb, AVS_DWORD dwPictureStructure, AVS_SHORT* pResidual)
{
AVS_INT tabNo = 0;
AVS_INT symbol2D = 0;
AVS_INT vlc_numcoef = 0;
AVS_INT run, level;
AVS_INT buffer_level[65];
AVS_INT buffer_run[65];
static const AVS_INT EOB_Pos_chroma[2][5] = {
{-1, 4, 8, 6, 4},
{-1, 0, 2, 0, 0}
};
static const AVS_INT incVlc_chroma[5] = {0,1,2,4,3000};
AVS_INT leadingZeroBits;
AVS_INT grad;
AVS_INT val, val2;
AVS_INT qp_chroma = QP_SCALE_CR[pCurrMb->dwMbQp]; // using old style qp.
AVS_INT temp;
AVS_INT ii, jj;
AVS_INT shift, QPI;
AVS_INT ipos = -1;
for(AVS_INT i=0; i<65; i++)
{
leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset);
grad = VLC_Golomb_Order[2][tabNo][0];
val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad);
symbol2D = (1<<(leadingZeroBits+grad)) - (1<>1;
leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset);
grad = 0;
val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad);
val2 = (1<<(leadingZeroBits+grad)) - (1<MaxRun[2][tabNo])?1:RefAbsLevel[tabNo+14][run]);
if(symbol2D & 1)
level=-level;
}
buffer_level[i] = level;
buffer_run[i] = run;
if(abs(level) > incVlc_chroma[tabNo]) //qwang 11.29
{
if(abs(level) <= 2)
tabNo = abs(level);
else if(abs(level) <= 4)
tabNo = 3;
else
tabNo = 4;
}
}
for(i=(vlc_numcoef-1); i>=0; i--)
{
ipos += (buffer_run[i]+1);
ii = SCAN[dwPictureStructure][ipos][0];
jj = SCAN[dwPictureStructure][ipos][1];
shift = IQ_SHIFT[qp_chroma];
QPI = IQ_TAB[qp_chroma];
val = buffer_level[i];
temp = (val*QPI+(1<<(shift-2)) )>>(shift-1);
*(pResidual+jj*8+ii) = temp;
}
}