www.pudn.com > rm52c.rar > bitstream.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2003, Advanced Audio Video Coding Standard, Part II 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
/* 
************************************************************************************* 
* File name: bitstream.c 
* Function: decode bitstream 
* 
************************************************************************************* 
*/ 
 
#include  
#include  
#include  
 
#include "global.h" 
#include "annexb.h" 
#include "memalloc.h" 
 
 
FILE *bitsfile = NULL;		//!< the bit stream file 
 
#define SVA_STREAM_BUF_SIZE 1024 
 
unsigned char bit[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; 
 
 
typedef struct { 
	FILE *f; 
	unsigned char	buf[SVA_STREAM_BUF_SIZE];  //流缓冲区,size must be large than 3 bytes 
	unsigned int	uClearBits;//不含填充位的位缓冲,32位,初始值是0xFFFFFFFF 
	unsigned int	uPre3Bytes;//  含填充位的位缓冲,32位,初始值是0x00000000 
	int	iBytePosition;		//当前字节位置 
	int	iBufBytesNum;		//最近一次读入缓冲区的字节数 
	int	iClearBitsNum;		//不含填充位的位的个数 
	int	iStuffBitsNum;		//已剔除的填充位的个数,遇到开始码时置0 
	int iBitsCount;			//码流总位数 
} InputStream; 
 
InputStream IRABS; 
InputStream *pIRABS = &IRABS; 
 
void OpenIRABS(InputStream *p, char *fname) 
{ 
	p->f = fopen(fname,"rb"); 
	if(p->f==NULL){printf ("\nCan't open file %s",fname);exit(-1);} 
	 
	p->uClearBits			= 0xffffffff; 
	p->iBytePosition		= 0; 
	p->iBufBytesNum			= 0; 
	p->iClearBitsNum		= 0; 
	p->iStuffBitsNum		= 0; 
	p->iBitsCount			= 0; 
	p->uPre3Bytes			= 0; 
} 
void CloseIRABS(InputStream *p) 
{ 
	fclose(p->f); 
} 
//------------------------------------------------------------------------ 
// move iBytePosition to the next byte of start code prefix 
//return 
//    0 : OK 
//   -1 : arrive at stream end and start code is not found 
//   -2 : p->iBytePosition error 
int NextStartCode(InputStream *p) 
{ 
	int i, m; 
	unsigned char a,b;	// a b 0 1 2 3 4 ... M-3 M-2 M-1 
	while(1) 
	{ 
		if(p->iBytePosition >= p->iBufBytesNum - 2)	//if all bytes in buffer has been searched 
		{ 
			m = p->iBufBytesNum - p->iBytePosition; 
			if(m <0)  return -2;	// p->iBytePosition error 
			if(m==1)  b=p->buf[p->iBytePosition+1]; 
			if(m==2){ b=p->buf[p->iBytePosition+1]; a=p->buf[p->iBytePosition];} 
			p->iBufBytesNum = fread(p->buf,1,SVA_STREAM_BUF_SIZE,p->f); 
			p->iBytePosition = 0; 
		} 
		if(p->iBufBytesNum + m < 3)  return -1;  //arrive at stream end and start code is not found 
		if(m==1 && b==0 && p->buf[0]==0 && p->buf[1]==1) 
		{ 
			p->iBytePosition	= 2; 
			p->iClearBitsNum	= 0; 
			p->iStuffBitsNum	= 0; 
			p->iBitsCount		+= 24; 
			p->uPre3Bytes		= 1; 
			return 0; 
		} 
		if(m==2 && b==0 && a==0 && p->buf[0]==1) 
		{ 
			p->iBytePosition	= 1; 
			p->iClearBitsNum	= 0; 
			p->iStuffBitsNum	= 0; 
			p->iBitsCount		+= 24; 
			p->uPre3Bytes		= 1; 
			return 0; 
		} 
		if(m==2 && b==0 && p->buf[0]==0 && p->buf[1]==1) 
		{ 
			p->iBytePosition	= 2; 
			p->iClearBitsNum	= 0; 
			p->iStuffBitsNum	= 0; 
			p->iBitsCount		+= 24; 
			p->uPre3Bytes		= 1; 
			return 0; 
		} 
		for(i = p->iBytePosition; i < p->iBufBytesNum - 2; i++) 
		{ 
			if(p->buf[i]==0 && p->buf[i+1]==0 && p->buf[i+2]==1) 
			{ 
				p->iBytePosition	= i+3; 
				p->iClearBitsNum	= 0; 
				p->iStuffBitsNum	= 0; 
				p->iBitsCount		+= 24; 
				p->uPre3Bytes		= 1; 
				return 0; 
			} 
			p->iBitsCount += 8; 
		} 
		p->iBytePosition = i; 
	} 
} 
//---------------------------------------------------------------------- 
//return 
//    0 : OK 
//   -1 : arrive at stream end 
//   -2 : meet another start code 
int ClearNextByte(InputStream *p) 
{ 
	int i,k,j; 
	unsigned char temp[3]; 
	i = p->iBytePosition; 
	k = p->iBufBytesNum - i; 
	if(k < 3) 
	{ 
		for(j=0;jbuf[i+j]; 
		p->iBufBytesNum = fread(p->buf+k,1,SVA_STREAM_BUF_SIZE-k,p->f); 
		if(p->iBufBytesNum == 0) 
		{ 
			if(k>0) 
			{ 
				p->uPre3Bytes = ((p->uPre3Bytes<<8) | p->buf[i]) & 0x00ffffff; 
				if(p->uPre3Bytes < 4) 
				{ 
					p->uClearBits = (p->uClearBits << 6) | (p->buf[i] >> 2); 
					p->iClearBitsNum += 6; 
				} 
				else 
				{ 
					p->uClearBits = (p->uClearBits << 8) | p->buf[i]; 
					p->iClearBitsNum += 8; 
				} 
				p->iBytePosition++; 
				return 0; 
			} 
			else 
			{ 
				return -1;//arrive at stream end 
			} 
		} 
		else 
		{ 
			for(j=0;jbuf[j] = temp[j]; 
			p->iBufBytesNum += k; 
			i = p->iBytePosition = 0; 
		} 
	} 
	if(p->buf[i]==0 && p->buf[i+1]==0 && p->buf[i+2]==1)	return -2;// meet another start code 
	p->uPre3Bytes = ((p->uPre3Bytes<<8) | p->buf[i]) & 0x00ffffff; 
	if(p->uPre3Bytes < 4) 
	{ 
		p->uClearBits = (p->uClearBits << 6) | (p->buf[i] >> 2); 
		p->iClearBitsNum += 6; 
	} 
	else 
	{ 
		p->uClearBits = (p->uClearBits << 8) | p->buf[i]; 
		p->iClearBitsNum += 8; 
	} 
	p->iBytePosition++; 
	return 0; 
} 
//---------------------------------------------------------- 
//return 
//    0 : OK 
//   -1 : arrive at stream end 
//   -2 : meet another start code 
int read_n_bit(InputStream *p,int n,int *v) 
{ 
	int r; 
	unsigned int t; 
	while(n > p->iClearBitsNum) 
	{ 
		r = ClearNextByte( p ); 
		if(r) 
		{ 
			if(r==-1) 
			{ 
				if(p->iBufBytesNum - p->iBytePosition > 0) 
					break; 
			} 
			return r; 
		} 
	} 
	t = p->uClearBits; 
	r = 32 - p->iClearBitsNum; 
	*v = (t << r) >> (32 - n); 
	p->iClearBitsNum -= n; 
	return 0; 
} 
//================================================================================== 
void OpenBitstreamFile (char *fn) 
{ 
	OpenIRABS(pIRABS, fn); 
} 
void CloseBitstreamFile() 
{ 
	CloseIRABS(pIRABS); 
} 
static int FindStartCode (unsigned char *Buf, int i) 
{ 
	if(Buf[i]==0 && Buf[i+1]==0 && Buf[i+2]==1) 
		return 1; 
	else 
		return 0; 
} 
 
 
//////////////////////////////////////////////////////////////////////////// 
//check slice start code    jlzheng  6.30 
//////////////////////////////////////////////////////////////////////////// 
int checkstartcode()   //check slice start code    jlzheng  6.30 
{ 
  	if (currStream->bitstream_length*8 - currStream->frame_bitoffset == 0) 
		return 1; 
 
	if(img->current_mb_nr == 0)  
	{ 
	    
	   //--- added by Yulj 2004.07.15 
			if (  currStream->bitstream_length*8 - currStream->frame_bitoffset <=8  
				  && currStream->bitstream_length*8 - currStream->frame_bitoffset > 0  ) 						 
			{ 
				int temp_i, temp_val; 
				temp_i = currStream->bitstream_length*8 - currStream->frame_bitoffset;  
				assert( temp_i > 0 ); 
				temp_val = get_uv(temp_i, "filling data") ;			 
			} 
	 
	 } 
 
	if(img->current_mb_nr == 0) 
	{ 
 
		if(StartCodePosition>6 && StartCodePosition<20) 
		   return 1; 
		else 
		{ 
           currStream->frame_bitoffset = currentbitoffset; 
		   return 0; 
		} 
	} 
	if(img->current_mb_nr != 0)  
	{ 
	    
	   //--- added by Yulj 2004.07.15 
			if (  currStream->bitstream_length*8 - currStream->frame_bitoffset <= 8  
				  && currStream->bitstream_length*8 - currStream->frame_bitoffset > 0  ) 						 
			{ 
				int temp_i, temp_val; 
				temp_i = currStream->bitstream_length*8 - currStream->frame_bitoffset;  
				assert( temp_i > 0 ); 
				temp_val = get_uv(temp_i, "filling data") ; 
				if ( temp_val == (1 << (temp_i -1))  && img->cod_counter <= 0   ) 
				 	return 1; // last MB in current slice  
				 
			} 
	          
			return 0;        // not last MB in current slice  
		//---end	 
	 } 
} 
 
 
 
//------------------------------------------------------------ 
// buf          : buffer 
// startcodepos :  
// length       :  
int GetOneUnit (char *buf,int *startcodepos,int *length) 
{ 
	int i,j,k; 
	i = NextStartCode(pIRABS); 
	if(i!=0) 
	{ 
		if(i==-1) printf("\narrive at stream end and start code is not found!"); 
		if(i==-2) printf("\np->iBytePosition error!"); 
		exit(i); 
	} 
	buf[0] = 0; 
	buf[1] = 0; 
	buf[2] = 1; 
	*startcodepos = 3; 
	i = read_n_bit(pIRABS,8,&j); 
	buf[3] = (char)j; 
	if(buf[3]==SEQUENCE_END_CODE) 
	{ 
		*length = 4; 
		return -1; 
	} 
	k = 4; 
	while(1) 
	{ 
		i = read_n_bit(pIRABS,8,&j); 
		if(i<0) break; 
		buf[k++] = (char)j; 
	} 
	if(pIRABS->iClearBitsNum>0) 
	{ 
		int shift; 
		shift = 8 - pIRABS->iClearBitsNum; 
		i = read_n_bit(pIRABS,pIRABS->iClearBitsNum,&j); 
		buf[k++] = (char)(j<