本文转自http://blog.csdn.net/yuanzhenhai/archive/2010/05/28/5629853.aspx
/*! ************************************************************************************** * /file * nalchek.c * /brief * NALU handling common to encoder and decoder l [email protected] 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 * [email protected] * Aug.18.2006 *************************************************************************************** */ #include <memory.h> #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<bufsize) { 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<bufsize && next_bits(p,bufpos,bufsize, 24 ) ) { 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<bufsize) && (!next_bits(p,bufpos,bufsize, 24 )) && (!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<<bitoffset))>>bitoffset; 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<bufsize) { for (tPOS = 0; tPOS < 3; tPOS++) 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; }