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; 
	} 
}