分类: 嵌入式
2010-06-10 09:48:40
H.264 NAL格式及分析器程序源代码
email:zsw_davy@hotmail.com
NAL分析器程序源代码
/*!
**************************************************************************************
* \file
* nalchek.c
* \brief
* NALU handling common to encoder and decoder
l
l Aug.18.2006 ***************************************************************************************
*/
#include "stdio.h"
#include "stdlib.h"
#include "nalucommon.h"
//#####################################
//#本程序检查一个缓冲区里面有几个NALU #
//#输出每个NALU的类型到输出文件 #
//#输入为一个带有标记/NALU+标记/的文件#
//#####################################
void main(void)
{
FILE *pSrc;
FILE *pRep;
if((pSrc=fopen("H264.rec","r+b"))==NULL)
exit(-1);
else printf("open src file succeed\n");
if((pRep=fopen("H264.rep","w+t"))==NULL)
exit(-1);
else printf("open report file succeed\n");
ReportNalu(pSrc,pRep);
fclose(pSrc);
fclose(pRep);
}
/*! **************************************************************************************
* \file
* nalucommon.h.h
* \brief
* NALU handling common to encoder and decoder
*
* Aug.18.2006 ***************************************************************************************
*/
#include
#ifndef _NALUCOMMON_H_
#define _NALUCOMMON_H_
typedef struct
{
int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else
(suggested)
unsigned len; //! Length of the NAL unit (Excluding the start code, which does not belong
to the NALU)
unsigned max_size; //! Nal Unit Buffer size
int nal_unit_type; //! NALU_TYPE_xxxx
int nal_reference_idc; //! NALU_PRIORITY_xxxx
int forbidden_bit; //! should be always FALSE
unsigned char *buf; //! conjtains the first byte followed by the EBSP
} NALU_t;
#define MAXRBSPSIZE 64000
#define NALU_TYPE_SLICE 1
#define NALU_TYPE_DPA 2
#define NALU_TYPE_DPB 3
#define NALU_TYPE_DPC 4
#define NALU_TYPE_IDR 5
#define NALU_TYPE_SEI 6
#define NALU_TYPE_SPS 7
#define NALU_TYPE_PPS 8
#define NALU_TYPE_AUD 9
#define NALU_TYPE_EOSEQ 10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL 12
#define NALU_PRIORITY_HIGHEST 3
#define NALU_PRIORITY_HIGH 2
#define NALU_PRIRITY_LOW 1
#define NALU_PRIORITY_DISPOSABLE 0
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef BOOL
#define BOOL unsigned int
#endif
void ReportNalu(FILE* src,FILE* rep);
void ParseRecBuf(unsigned char *p,int bufsize,FILE* pReport);
int ShowBits (unsigned char buffer[],int totbitoffset,int bytecount, int numbits);
BOOL next_bits(unsigned char *p,int bufpos,int bs,int id );
static int FindStartCode (unsigned char *Buf, int bufpos, int bufsize, int next_start_pos, BOOL fIRFD);
BOOL gETNALandPROC(unsigned char *p,int bufpos,int bufsize, BOOL fisrtfd,NALU_t *mNal,int inc_SIZE,FILE
*pReport);
#endif
//############################################################
//# src 文件格式如下
//# #-#-#-#-#-B-INT32LEN-T264DST - #-#-#-#-B-INT32LEN #
//# 1 1 1 1 1 1 4 INT32LEN #
//############################################################
void ReportNalu(FILE* src,FILE* rep)
{
unsigned char tempbuf[1];
unsigned char *pBuf;
int *dstlen;
int fpos=0;
int fstart=0;
int FileSize=0;
int BufSize;
int dstpacketid=0;
unsigned int SymState=0;
fseek(src,0,SEEK_END);
FileSize=ftell(src);
printf("the src file size is %d \n",FileSize);
fseek(src,0,SEEK_SET);
do {
while (fread(tempbuf,sizeof(unsigned char),1,src))
{
if(tempbuf=="#") SymState++;
else
{
fpos=fstart+1;
SymState=0;
fseek(src,fpos,SEEK_SET);
}
if(SymState==4)
{fpos+=4;break;}
}
fread(tempbuf,sizeof(unsigned char),1,src);
if(tempbuf=="B")
{
SymState++;
fpos+=1;
}
else
{
fpos=fstart+1;
fseek(src,fpos,SEEK_SET);
}
if(SymState==5)
{
dstpacketid++;
fprintf(rep,"the %d dstpacket\n",dstpacketid);
dstlen=(int*)malloc(sizeof(int));
fread(dstlen,sizeof(unsigned char),4,src);
BufSize=(int*)dstlen;
pBuf=(unsigned char*)malloc(sizeof(unsigned char)*BufSize);
fpos+=4;
fread(pBuf,sizeof(unsigned char),BufSize,src);
ParseRecBuf(pBuf,BufSize,rep);
fstart=fpos;
free(dstlen);
free(pBuf);
}
} while(fpos!=FileSize);//
}
//####################################################
//# unsigned char *p --T264 encode的一个dst长度为len#
//# int bufsize --buffer的大小 #
//##FILE* pReport --文件指针,存放NAL的分析结果 #
//####################################################
void ParseRecBuf(unsigned char *p,int bufsize,FILE* pReport)
{
int bufpos=0;
int bUFSTART=0;
struct NALU_t *mNal;
BOOL isfirst;
BOOL starcode_ex;
BOOL zero_ex;
BOOL trail_ex;
int nALSIZE=0;
int nal_id=0;
BOOL firstfd=FALSE;
while (bufpos
if( !next_bits(p,bufpos,bufsize, 24 ) &&
!next_bits(p,bufpos,bufsize,32 ) &&
next_bits( p,bufpos,bufsize,8 ))
{bufpos+=8;isfirst=TRUE;firstfd=TRUE;}// leading_zero_8bits /* equal to 0x00 */ //f(8)
else{ isfirst=FALSE; }
if(!next_bits( p,bufpos,bufsize,24 ) &&
next_bits( p,bufpos,bufsize,8 )
)
{
bufpos+=8;//zero_byte /* equal to 0x00 */ f(8)
zero_ex=TRUE;
if( bufpos
{
bufpos+=24; // start_code_prefix_one_3bytes /* equal to 0x000001 */ f(24)
starcode_ex=TRUE;
mNal=(struct NALU_t* )malloc(sizeof( NALU_t));
if(gETNALandPROC(p,bufpos,bufsize,firstfd,mNal,nALSIZE,pReport))
{
nal_id++;
fprintf(pReport," id of the nal packet above is %d\n",nal_id);
bufpos+=(nALSIZE>>3);
if(( bufpos
(!next_bits(p,bufpos,bufsize, 32 ) ) &&
(next_bits(p,bufpos, bufsize,8 )))
{
bufpos+=8; trail_ex=TRUE ;/* trailing_zero_8bitsequal to 0x00 */
}
else trail_ex=FALSE;
free(mNal);
}
else printf("cannot get any nal units\n");
}
else{starcode_ex=FALSE;}
}
else
{ zero_ex=FALSE; }
if (!zero_ex || !starcode_ex)
bufpos=bUFSTART+1;
else bUFSTART=bufpos;
}
}
//############################################
//#unsigned char *p =--buffer containing NALU#
//#int bufpos--current buffer position #
//#int bs---buffersize #
//#int id #
//# id=24 ----0x000001----FALSE #
//# id=32 ----0x00000001---FALSE #
//# id=8 ----0x00------TRUE #
//############################################
BOOL next_bits(unsigned char *p,int bufpos,int bs,int id )
{
BOOL rERULT;
switch(id) {
case 8:
if(ShowBits(p,bufpos,bs,8)==0x00) rERULT=TRUE ;
else rERULT=FALSE;
break;
case 24:
if(ShowBits(p,bufpos,bs,24)!=0x000001) rERULT=FALSE;
else rERULT=TRUE;
break;
case 32 :
if(ShowBits(p,bufpos,bs,32)!=0x00000001) rERULT=FALSE;
else rERULT=TRUE;
break;
default:
break;
}
return rERULT;
}
//##############################################
// # \brief #
// # Reads bits from the bitstream buffer #
// # \param buffer #
// # buffer containing VLC-coded data bits #
// # \param totbitoffset #
// # bit offset from start of partition #
// # \param bytecount #
// # total bytes in bitstream #
// # \param numbits #
// # number of bits to read #
// #############################################
int ShowBits (unsigned char buffer[],int totbitoffset,int bytecount, int numbits)
{
register int inf;
long byteoffset; // byte from start of buffer
int bitoffset; // bit from start of byte
byteoffset= totbitoffset/8;
bitoffset= 7-(totbitoffset%8);
inf=0;
while (numbits)
{
inf <<=1;
inf |= (buffer[byteoffset] & (0x01<
numbits--;
bitoffset--;
if (bitoffset < 0)
{
byteoffset++;
bitoffset += 8;
if (byteoffset > bytecount)
{
return -1;
}
}
}
return inf; // return absolute offset in bit from start of frame
}
//#########################################################################
// # \brief
#
// # returns if new start code is found at byte aligned position buf. #
// # new-startcode is of form N 0x00 bytes, followed by a 0x01 byte. #
// # \return
#
// # 1 if start-code is found or \n #
// # 0, indicating that there is no start code #
// # #
// # \param Buf #
// # pointer to byte-stream #
// # \param bufpos #
// # indicates current bufpos.
//# \bufsize
// # indicates total buffer size #
// # \param next_star_pos #
// # indicates the next_start_code pos #
// # \param fIRFD
// # is firs nal already found
// ########################################################################
static int FindStartCode (unsigned char *Buf, int bufpos, int bufsize, int next_start_pos, BOOL fIRFD)
{
int info;
int tPOS;
int tSTART=bufpos;
BOOL sTARFOUND=FALSE;
info = 1;
while (!sTARFOUND && tSTART
if(Buf[tSTART+tPOS] != 0)
info = 0;
if(Buf[tSTART+tPOS] != 1)
info = 0;
if (info==0) tSTART++;
else sTARFOUND=TRUE;
}
if (fIRFD && sTARFOUND)
{
if(Buf[tSTART-1]==0 &&
Buf[tSTART-2]==0)
{ info=2;//trailing zero found
next_start_pos=tSTART-2;}
else {info=1;
next_start_pos=tSTART;}
}
return info;
}
//#####################################
//# unsigned char *p #
//# int bufpos #
//# NALU_t *mNal #
//# int n_SIZE #
//# #
//# #
//#####################################
BOOL gETNALandPROC(unsigned char *p,
int bufpos,
int bufsize,
BOOL fisrtfd,
NALU_t *mNal,
int inc_SIZE,
FILE *pReport)
{
BOOL getNfailed=FALSE;
int nal_BUFSIZE=0;
int next_start_point=0;
int mNal_size=0;
int b_bufpos=bufpos/8;
unsigned int finresult;
BOOL info=TRUE;
finresult=FindStartCode (p,b_bufpos,bufsize,next_start_point,fisrtfd);
if (finresult==1 || finresult==2) {
nal_BUFSIZE=next_start_point-b_bufpos-1;
inc_SIZE=nal_BUFSIZE;
mNal->buf=(unsigned char *)malloc(sizeof(unsigned char)*nal_BUFSIZE);
mNal->len=nal_BUFSIZE;
memcpy (mNal->buf, &p[b_bufpos+1], mNal->len);
mNal->forbidden_bit = (mNal->buf[0]>>7) & 1;
mNal->nal_reference_idc = (mNal->buf[0]>>5) & 3;
mNal->nal_unit_type = (mNal->buf[0]) & 0x1f;
fprintf(pReport,"#########################################################################\n");
fprintf(pReport,"nal len is %d\n",mNal->len);
fprintf(pReport,"fobidden bit is % d\n",mNal->forbidden_bit);
fprintf(pReport,"nal_reference_idc is d%\n",mNal->nal_reference_idc);
switch(mNal->nal_unit_type) {
case NALU_TYPE_SLICE :
fprintf(pReport," nal type is * NALU_TYPE_SLICE\n");
break;
case NALU_TYPE_DPA:
fprintf(pReport,"nal type is * NALU_TYPE_DPA\n");
break;
case NALU_TYPE_DPB :
fprintf(pReport,"nal type is * NALU_TYPE_DPB\n");
break;
case NALU_TYPE_DPC:
fprintf(pReport,"nal type is * NALU_TYPE_DPC\n");
break;
case NALU_TYPE_IDR:
fprintf(pReport,"nal type is * NALU_TYPE_IDR\n");
break;
case NALU_TYPE_SEI:
fprintf(pReport,"nal type is * NALU_TYPE_SEI\n");
break;
case NALU_TYPE_SPS:
fprintf(pReport,"nal type is * NALU_TYPE_SPS\n");
break;
case NALU_TYPE_PPS:
fprintf(pReport,"nal type is * NALU_TYPE_PPS\n");
break;
case NALU_TYPE_AUD:
fprintf(pReport,"nal type is * NALU_TYPE_AUD\n");
break;
case NALU_TYPE_EOSEQ:
fprintf(pReport,"nal type is * NALU_TYPE_EOSEQ\n");
break;
case NALU_TYPE_EOSTREAM:
fprintf(pReport,"nal type is * NALU_TYPE_EOSTREAM\n");
break;
case NALU_TYPE_FILL :
fprintf(pReport,"nal type is * NALU_TYPE_FILL\n");
break;
default:
break;
}
fprintf(pReport,"nal start code len is %d\n",mNal->startcodeprefix_len);
fprintf(pReport,"#########################################################################\n");
free(mNal->buf);
mNal->buf=NULL;
}
else info=FALSE;
return info;
}