扬州网站建设外包,网页链接 提取码:qqcd,中方元建设工程 网站,怎么做网站的自然排名分析一下GitHub上一份FLV文件分析和解析器的开源代码 GitHub源码地址#xff1a;功能强大的 FLV 文件分析和解析器
#xff1a;可以将flv文件的视频tag中的h264类型数据和音频tag中的aac类型数据导出 #xff08;只限h264和aac#xff09; (这个代码不太适合用于大文件的分…分析一下GitHub上一份FLV文件分析和解析器的开源代码 GitHub源码地址功能强大的 FLV 文件分析和解析器
可以将flv文件的视频tag中的h264类型数据和音频tag中的aac类型数据导出 只限h264和aac (这个代码不太适合用于大文件的分析因为所有数据都会一直存在内存中)
main.cpp
#include iostream
#include fstream
#include FlvParser.husing namespace std;void Pro(fstream fin);int main()
{cout Hello World! endl;string infilename(test.flv);if(!infilename.length()){cout!infilename.length() endl;}fstream fin;fin.open(infilename, ios_base::in | ios_base::binary);if(!fin){coutfin.open failed!endl;return 0;}Pro(fin);fin.close();return 0;}void Pro(fstream fin)
{FlvParser parser;int nBufSize 2 * 1024 * 1024;int nFlvPos 0;uint8_t *pBuf, *pBak;pBuf new uint8_t[nBufSize];pBak new uint8_t[nBufSize];while (1){int nReadNum 0;int nUsedLen 0;fin.read((char*)pBuf nFlvPos, nBufSize - nFlvPos);//获取上次读取的字符数nReadNum fin.gcount();//结束读取if(nReadNum 0)break;nFlvPos nReadNum;parser.Parse(pBuf, nFlvPos, nUsedLen);//判断没有处理nFlvPos长度就前移剩下的数据到前面if(nFlvPos ! nUsedLen){memcpy(pBak, pBuf nUsedLen, nFlvPos - nUsedLen);memcpy(pBuf, pBak, nFlvPos - nUsedLen);}nFlvPos - nUsedLen;}//输出文件信息parser.PrintInfo();//输出h264数据parser.DumpH264(parser.h264);//输出aac数据parser.DumpAAC(parser.aac);delete[] pBak;delete[] pBuf;}
FlvParser.h
#ifndef FLVPARSER_H
#define FLVPARSER_H#include vector
#include stdint.h
#include stringusing namespace std;class FlvParser
{
public:FlvParser();virtual ~FlvParser();int Parse(uint8_t *pBuf, int nBufSize,int nUsedLen);int PrintInfo();int DumpH264(const std::string path);int DumpAAC(const std::string path);private://flv头部信息typedef struct _FlvHeader{int nVersion; //版本int bHaveVideo;//是否有音频int bHaveAudio;//是否有视频int nHeadSize;//FLV头部长度//头部数据uint8_t *pFlvHeader;}FlvHeader;//Tag头部struct TagHeader{int nType;//类型int nDataSize;//body的大小int nTimeStamp;//时间戳int nTSEx; //时间戳的扩展字节int nStreamID;//流的ID,总是0//完整的时间戳nTimeStamp和nTSEx拼装uint32_t nTotalTS;TagHeader():nType(0), nDataSize(0), nTimeStamp(0), nTSEx(0), nStreamID(0), nTotalTS(0){}~TagHeader(){}};class Tag{public:TagHeader _header;uint8_t* _pTagHeader;//tag头部uint8_t* _pTagData;//tag bodyuint8_t* _pMedia;//tag 元数据改造后的数据int _nMediaLen;//数据长度public:Tag():_pTagHeader(0), _pTagData(0), _pMedia(0), _nMediaLen(0){}void Init(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen);};class VideoTag: public Tag{public:int _nFrameType;//帧类型int _nCodecID;//视频编解码类型public:VideoTag(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen, FlvParser* pParser);int ParseH264Tag(FlvParser *pParser);int ParseH264Configuration(FlvParser* pParser, uint8_t* pTagData);int ParseNalu(FlvParser* pParser, uint8_t* pTagData);};class AudioTag:public Tag{public:int _nSoundFormat; //编码类型int _nSoundRate;//采样率int _nSoundSize;//精度int _nSoundType;//类型static int _aacProfile;//AAC profilestatic int _sampleRateIndex;//采样率索引static int _channelConfig;//通道设置public:AudioTag(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen, FlvParser* pParser);int ParseAACTag(FlvParser *pParser);int ParseAudioSpecificConfig(FlvParser* pParser, uint8_t *pTagData);int ParserRawAAC(FlvParser* pParser, uint8_t* pTagData);};class MetaDataTag: public Tag{public:uint8_t m_amf1_type;uint32_t m_amf1_size;uint8_t m_amf2_type;unsigned char* m_meta;unsigned int m_length;double m_duration;double m_width;double m_height;double m_videodatarate;double m_framerate;double m_videocodecid;double m_audiodatarate;double m_audiosamplerate;double m_audiosamplesize;bool m_stereo;double m_audiocodecid;string m_major_brand;string m_minor_version;string m_compatible_brands;string m_encoder;double m_filesize;public:MetaDataTag(TagHeader *pHeader, uint8_t *pBuf, int nLeftLen, FlvParser *pParser);double hexStr2double(const unsigned char* hex, const unsigned int length);int parseMeta(FlvParser* pParser);void printMeta();};struct FlvStat{int nMetaNum, nVideoNum, nAudioNum;int nMaxTimeStamp;int nLengthSize;FlvStat(): nMetaNum(0), nVideoNum(0), nAudioNum(0), nMaxTimeStamp(0), nLengthSize(0){}~FlvStat(){}};//取4字节数值static uint32_t ShowU32(uint8_t* pBuf){return (pBuf[0] 24) | (pBuf[1] 16) | (pBuf[2] 8) | pBuf[3];}//取3字节数值static uint32_t ShowU24(uint8_t* pBuf){return (pBuf[0] 16) | (pBuf[1] 8) | pBuf[2];}//取2字节数值static uint32_t ShowU16(uint8_t* pBuf){return (pBuf[0] 8) | pBuf[1];}//取1字节数值static uint32_t ShowU8(uint8_t* pBuf){return pBuf[0];}//按位的数据写入到64位中x 本来的值会往左移高位移//length : 多少位数据//value : 实际的值static void WriteU64(uint64_t x, int length, int value){uint64_t mask 0xFFFFFFFFFFFFFFFF (64 - length);x (x length) | ((uint64_t)value mask);}//字节序替换static uint32_t WriteU32(uint32_t n){uint32_t nn 0;uint8_t *p (uint8_t*)n;uint8_t *pp (uint8_t*)nn;pp[0] p[3];pp[1] p[2];pp[2] p[1];pp[3] p[0];return nn;}friend class Tag;private:FlvHeader* CreateFlvHeader(uint8_t* pBuf);int DestroyFlvHeader(FlvHeader* pHeader);Tag* CreateTag(uint8_t* pBuf, int nLeftLen);int DestroyTag(Tag* pTag);int Stat();int StatVideo(Tag* pTag);int IsUserDataTag(Tag* pTag);private:FlvHeader* _pFlvHeader;vectorTag* _vpTag;FlvStat _sStat;//Videojj* _vjj;//h264int _nNaluUintLength;};#endif // FLVPARSER_H
FlvParser.cpp
#include FlvParser.h
#include iostream
#include fstream
#include string.husing namespace std;#define CheckBuffer(x) { if((nBufSize - nOffset) (x)){ nUsedLen nOffset; return 0;} }int FlvParser::AudioTag::_aacProfile;
int FlvParser::AudioTag::_sampleRateIndex;
int FlvParser::AudioTag::_channelConfig;static const uint32_t nH264StartCode 0x01000000;FlvParser::FlvParser()
{_pFlvHeader NULL;}FlvParser::~FlvParser()
{for(int i 0; i _vpTag.size(); i){DestroyTag(_vpTag[i]);delete _vpTag[i];}}int FlvParser::Parse(uint8_t *pBuf, int nBufSize,int nUsedLen)
{int nOffset 0;//初始化flv解析器if(_pFlvHeader 0){//CheckBuffer(9);//如果不够flv header长度就返回if((nBufSize - nOffset) 9){nUsedLen nOffset;return 0;}_pFlvHeader CreateFlvHeader(pBuf nOffset);nOffset _pFlvHeader-nHeadSize;}while (1){//CheckBuffer(15);if((nBufSize - nOffset) 15){nUsedLen nOffset;return 0;}int nPrevSize ShowU32(pBuf nOffset);nOffset 4;//移过4个字节的PreviousTagSizeTag* pTag CreateTag(pBuf nOffset, nBufSize - nOffset);if(pTag NULL){nOffset - 4;break;}nOffset (11 pTag-_header.nDataSize);_vpTag.push_back(pTag);}nUsedLen nOffset;return 0;
}int FlvParser::PrintInfo()
{Stat();cout vnum: _sStat.nVideoNum , anum: _sStat.nAudioNum , mnum: _sStat.nMetaNum endl;cout maxTimeStamp: _sStat.nMaxTimeStamp ,nLengthSize: _sStat.nLengthSize endl;return 0;
}//输出h264文件
int FlvParser::DumpH264(const std::string path)
{fstream f;f.open(path.c_str(), ios_base::out | ios_base::binary);vectorTag*::iterator it_tag;for(it_tag _vpTag.begin(); it_tag ! _vpTag.end(); it_tag){if((*it_tag)-_header.nType ! 0x09)continue;f.write((char*)(*it_tag)-_pMedia, (*it_tag)-_nMediaLen);}f.close();return 1;
}//输出AAC文件
int FlvParser::DumpAAC(const std::string path)
{fstream f;f.open(path.c_str(), ios_base::out | ios_base::binary);vectorTag*::iterator it_tag;for(it_tag _vpTag.begin(); it_tag ! _vpTag.end(); it_tag ){if((*it_tag)-_header.nType ! 0x08){continue;}AudioTag* pAudioTag (AudioTag*)(*it_tag);if(pAudioTag-_nSoundFormat ! 10)//不是AACcontinue;if(pAudioTag-_nMediaLen ! 0){f.write((char*)(*it_tag)-_pMedia, (*it_tag)-_nMediaLen);}}f.close();return 1;
}//创建保存Flv Header信息
FlvParser::FlvHeader* FlvParser::CreateFlvHeader(uint8_t *pBuf)
{FlvHeader* pHeader new FlvHeader;pHeader-nVersion pBuf[3]; //版本号pHeader-bHaveAudio (pBuf[4] 2) 0x01;//是否有音频pHeader-bHaveVideo (pBuf[4] 0) 0x01;//是否有视频pHeader-nHeadSize ShowU32(pBuf 5);// 头部长度//将原来的flv header 数据保存一份pHeader-pFlvHeader new uint8_t[pHeader-nHeadSize];memcpy(pHeader-pFlvHeader, pBuf, pHeader-nHeadSize);return pHeader;
}//释放Flv Header信息相关内存
int FlvParser::DestroyFlvHeader(FlvHeader *pHeader)
{if(pHeader NULL)return 0;delete pHeader-pFlvHeader;delete pHeader;pHeader NULL;return 1;
}int FlvParser::Stat()
{for(int i 0; i _vpTag.size(); i){switch (_vpTag[i]-_header.nType){case 0x08:_sStat.nAudioNum;break;case 0x09:StatVideo(_vpTag[i]);break;case 0x12:_sStat.nMetaNum;break;default:break;}}return 1;
}int FlvParser::StatVideo(Tag *pTag)
{_sStat.nVideoNum;_sStat.nMaxTimeStamp pTag-_header.nTimeStamp;//0x17 帧类型为 1 (h264的IDR 关键帧标识)// 7 (avc)//0x00 AVC 包类型为 0 AVC sequence headerif(pTag-_pTagData[0] 0x17 pTag-_pTagData[1] 0x00){//获取nalu 长度使用多少个字节表示//注意根据上面知道AVC sequence header包包含SPS 、PPS时//帧类型是 1 是使用h264的IDR 关键帧相同标识的_sStat.nLengthSize (pTag-_pTagData[9] 0x03) 1;}return 1;
}//创建Tag
FlvParser::Tag* FlvParser::CreateTag(uint8_t *pBuf, int nLeftLen)
{//开始解析tag头部TagHeader header;header.nType ShowU8(pBuf 0);//类型header.nDataSize ShowU24(pBuf 1);//tag body的长度header.nTimeStamp ShowU24(pBuf 4);//时间戳低24位header.nTSEx ShowU8(pBuf 7);//时间戳扩展字段高8位header.nStreamID ShowU24(pBuf 8);//流的idheader.nTotalTS (uint32_t)((header.nTSEx 24)) header.nTimeStamp;//合成完整的时间戳//如果这次数据不够整个tag长度包括tag header 和 tag body就不处理if((header.nDataSize 11) nLeftLen){return NULL;}Tag* pTag;switch (header.nType) {case 0x09://视频类型pTag new VideoTag(header, pBuf, nLeftLen, this);break;case 0x08://音频类型pTag new AudioTag(header, pBuf, nLeftLen, this);break;case 0x12://script 类型pTag new MetaDataTag(header, pBuf, nLeftLen, this);break;default:pTag new Tag();pTag-Init(header, pBuf, nLeftLen);break;}return pTag;}//释放Tag相应的内存
int FlvParser::DestroyTag(Tag* pTag)
{if(pTag-_pMedia ! NULL)delete[] pTag-_pMedia;if(pTag-_pTagData ! NULL)delete[] pTag-_pTagData;if(pTag-_pTagHeader ! NULL)delete[] pTag-_pTagHeader;return 1;
}//tag 初始化
void FlvParser::Tag::Init(TagHeader *pHeader, uint8_t *pBuf, int nLeftLen)
{//复制tag头部信息(解析好的)memcpy(_header, pHeader, sizeof(TagHeader));//复制tag头部信息原数据_pTagHeader new uint8_t[11];memcpy(_pTagHeader, pBuf, 11);//复制tag body_pTagData new uint8_t[_header.nDataSize];memcpy(_pTagData, pBuf 11, _header.nDataSize);
}FlvParser::MetaDataTag::MetaDataTag(TagHeader *pHeader, uint8_t *pBuf, int nLeftLen, FlvParser *pParser)
{Init(pHeader, pBuf, nLeftLen);uint8_t* pd _pTagData;m_amf1_type ShowU8(pd);//第一个AMF 包类型一般为2字符串m_amf1_size ShowU16(pd 1);//字符串数据的长度//不是字符串就返回不处理if(m_amf1_type ! 2){printf(no metadata\n);return;}//判断字符串是否等于onMetaData就进行处理if(strncmp((const char*)onMetaData, (const char*)(pd 3), 10) 0){parseMeta(pParser);}}//使用字符串的方式提取double类型值直接将原来的double8个字节字节序调转一下也一样的
double FlvParser::MetaDataTag::hexStr2double(const unsigned char* hex, const unsigned int length)
{double ret 0;
#if 0char hexstr[length * 2];memset(hexstr, 0, sizeof(hexstr));for(uint32_t i 0; i length; i){sprintf(hexstr i * 2, %02x, hex[i]);}sscanf(hexstr, %llx, (unsigned long long*)ret);
#elseret *(double*)hex;uint8_t* ret_begin (uint8_t*)ret;uint8_t* ret_end ret_begin 7;for(int i 0; i4; i){uint8_t temp *ret_begin;*ret_begin *ret_end;*ret_end temp;ret_begin;ret_end--;}#endifreturn ret;
}int FlvParser::MetaDataTag::parseMeta(FlvParser* pParser)
{uint8_t* pd _pTagData;int dataSize _header.nDataSize;uint32_t arrayLen 0;//跨过第一个AMF结构到第二个AFM结构uint32_t offset 13;uint32_t nameLen 0;double doubleValue 0;string strValue ;bool boolValue false;uint32_t valueLen 0;uint8_t u8Value 0;//判断类型是否等于8数组if(pd[offset] 0x08){//数组元素长度arrayLen ShowU32(pd offset);offset 4;//跨过数组长度占用的4个字节coutMetaData ArrayLen arrayLen endl;}else{coutMetaData format error! endl;return -1;}for(uint32_t i 0; i arrayLen; i){doubleValue 0;boolValue false;strValue ;//读取字段名称的长度nameLen ShowU16(pd offset);offset 2;char name[nameLen 1];//字段存储memset(name, 0, sizeof(name));//复制字段名称memcpy(name, pd[offset], nameLen);offset nameLen;//获取AFM类型uint8_t amfType pd[offset];switch (amfType) {case 0x0://double 8字节doubleValue hexStr2double(pd[offset], 8);offset 8;break;case 0x1: //bool 1个字节u8Value ShowU8(pd offset);offset 1;if(u8Value ! 0)boolValue true;elseboolValue false;break;case 0x2://字符串valueLen ShowU16(pd offset);offset 2;strValue.append(pd offset, pd offset valueLen);strValue.append();offset valueLen;break;default:printf(un handle amfType:%d\n, amfType);break;}//保存相应的参数值if(strncmp(name, duration, 8) 0){m_duration doubleValue;}else if(strncmp(name, width, 5) 0){m_width doubleValue;}else if(strncmp(name, height, 6) 0){m_height doubleValue;}else if(strncmp(name, videodatarate, 13) 0){m_videodatarate doubleValue;}else if(strncmp(name, framerate, 9) 0){m_framerate doubleValue;}else if(strncmp(name, videocodecid, 12) 0){m_videocodecid doubleValue;}else if(strncmp(name, audiodatarate, 13) 0){m_audiodatarate doubleValue;}else if(strncmp(name, audiosamplerate, 15) 0){m_audiosamplerate doubleValue;}else if(strncmp(name, audiosamplesize, 15) 0){m_audiosamplesize doubleValue;}else if(strncmp(name, stereo, 6) 0){m_stereo boolValue;}else if(strncmp(name, audiocodecid, 12) 0){m_audiocodecid doubleValue;}else if(strncmp(name, major_brand, 11) 0){m_major_brand strValue;}else if(strncmp(name, minor_version, 13) 0){m_minor_version strValue;}else if(strncmp(name, compatible_brands, 17) 0){m_compatible_brands strValue;}else if(strncmp(name, encoder, 7) 0){m_encoder strValue;}else if(strncmp(name, filesize, 8) 0){m_filesize doubleValue;}}printMeta();return 1;
}void FlvParser::MetaDataTag::printMeta()
{printf(\nduration: %0.2lfs, filesize: %.0lfbytes\n, m_duration, m_filesize);printf(width: %0.0lf, height: %0.0lf\n, m_width, m_height);printf(videodatarate: %0.2lfkbps, framerate: %0.0lffps\n, m_videodatarate, m_framerate);printf(videocodecid: %0.0lf\n, m_videocodecid);printf(audiodatarate: %0.2lfkbps, audiosamplerate: %0.0lfKhz\n,m_audiodatarate, m_audiosamplerate);printf(audiosamplesize: %0.0lfbit, stereo: %d\n, m_audiosamplesize, m_stereo);printf(audiocodecid: %0.0lf\n, m_audiocodecid);printf(major_brand: %s, minor_version: %s\n, m_major_brand.c_str(), m_minor_version.c_str());printf(compatible_brands: %s, encoder: %s\n\n, m_compatible_brands.c_str(), m_encoder.c_str());
}FlvParser::AudioTag::AudioTag(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen, FlvParser* pParser)
{Init(pHeader, pBuf, nLeftLen);uint8_t *pd _pTagData;_nSoundFormat (pd[0] 0xf0) 4;//音频格式 如AAC_nSoundRate (pd[0] 0x0c) 2;//采样率_nSoundSize (pd[0] 0x02) 1;//采样精度_nSoundType (pd[0] 0x01);//是否立体声if(_nSoundFormat 10)//AAC{ParseAACTag(pParser);}}int FlvParser::AudioTag::ParseAACTag(FlvParser *pParser)
{uint8_t* pd _pTagData;//数据包的类型音频配置信息音频数据int nAACPacketType pd[1];//AAC sequence headerif(nAACPacketType 0){ParseAudioSpecificConfig(pParser, pd);}//AAC 数据AAC RAWelse if(nAACPacketType 1){ParserRawAAC(pParser, pd);}else{coutParseAACTag nAACPacketType nAACPacketType endl;}return 1;
}int FlvParser::AudioTag::ParseAudioSpecificConfig(FlvParser* pParser, uint8_t *pTagData)
{uint8_t* pd _pTagData;_aacProfile ((pd[2] 0xf8) 3);//5位 AAC 编码级别_sampleRateIndex ((pd[2] 0x07) 1) | (pd[3] 7);//4bit 真正采样率索引_channelConfig (pd[3] 3) 0x0f; //4bit 通道数量printf(----- AAC info------\n);printf(profile:%d\n, _aacProfile);printf(sample rate index:%d\n, _sampleRateIndex);printf(channel config:%d\n, _channelConfig);_pMedia NULL;_nMediaLen 0;return 0;
}int FlvParser::AudioTag::ParserRawAAC(FlvParser* pParser, uint8_t* pTagData)
{uint64_t bits 0;//数据长度跳过tag data的第一个第二个字节int dataSize _header.nDataSize - 2;//制作 AAC ADTSWriteU64(bits, 12, 0xFFF);WriteU64(bits, 1, 0);WriteU64(bits, 2, 0);WriteU64(bits, 1, 1);WriteU64(bits, 2, _aacProfile - 1);WriteU64(bits, 4, _sampleRateIndex);WriteU64(bits, 1, 0);WriteU64(bits, 3, _channelConfig);WriteU64(bits, 1, 0);WriteU64(bits, 1, 0);WriteU64(bits, 1, 0);WriteU64(bits, 1, 0);WriteU64(bits, 13, 7 dataSize);WriteU64(bits, 11, 0x7FF);WriteU64(bits, 2, 0);//_nMediaLen 7 dataSize;_pMedia new uint8_t[_nMediaLen];uint8_t p64[8];//调转字节序p64[0] (uint8_t)(bits 56);//0,没用数据p64[1] (uint8_t)(bits 48);//ADTS 头的0xfff开始位置p64[2] (uint8_t)(bits 40);p64[3] (uint8_t)(bits 32);p64[4] (uint8_t)(bits 24);p64[5] (uint8_t)(bits 16);p64[6] (uint8_t)(bits 8);p64[7] (uint8_t)(bits);//ADTS header从p64 1 开始的memcpy(_pMedia, p64 1, 7);//AAC RAW 从 audio tag data的第3个字节开始的memcpy(_pMedia 7, pTagData 2, dataSize);return 1;
}//VideoTag构造
FlvParser::VideoTag::VideoTag(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen, FlvParser* pParser)
{//初始化Init(pHeader, pBuf, nLeftLen);uint8_t *pd _pTagData;_nFrameType (pd[0] 0xf0) 4;//帧类型 (HDR / 普通帧)_nCodecID pd[0] 0x0f;//视频编码类型(avc)//开始解析 (视频类型 的tag 、 avc 编码类型)if(_header.nType 0x09 _nCodecID 7){ParseH264Tag(pParser);}
}//解析h264
FlvParser::VideoTag::ParseH264Tag(FlvParser *pParser)
{uint8_t* pd _pTagData;int nAVCPacketType pd[1];int nCompositionTime FlvParser::ShowU24(pd 2);//视频配置信息sps、ppsif(nAVCPacketType 0){ParseH264Configuration(pParser, pd);}//视频数据else if(nAVCPacketType 1){ParseNalu(pParser, pd);}else{coutUnknow ParseH264Tag nAVCPacketType nAVCPacketType endl;}return 1;}FlvParser::VideoTag::ParseH264Configuration(FlvParser *pParser, uint8_t *pTagData)
{uint8_t* pd pTagData;//获取nalu长度使用多少个字节进行存储pParser-_nNaluUintLength (pd[9] 0x03) 1;int sps_size, pps_size;//sps(序列参数集)的长度sps_size FlvParser::ShowU16(pd 11);//pps(图像参数集)的长度pps_size FlvParser::ShowU16(pd 11 (2 sps_size) 1);//制作元数据(4表示start code)_nMediaLen 4 sps_size 4 pps_size;_pMedia new uint8_t[_nMediaLen];memcpy(_pMedia, nH264StartCode, 4);memcpy(_pMedia 4, pd 11 2, sps_size);memcpy(_pMedia 4 sps_size, nH264StartCode, 4);memcpy(_pMedia 4 sps_size 4, pd 11 2 sps_size 2 1, pps_size);return 1;
}FlvParser::VideoTag::ParseNalu(FlvParser *pParser, uint8_t *pTagData)
{uint8_t* pd pTagData;int nOffset 0;_pMedia new uint8_t[_header.nDataSize 10];_nMediaLen 0;nOffset 5;while (1){//如果解析完了一个TAG就跳出循环if(nOffset _header.nDataSize)break;//计算nalu的长度//一个tag可能包含多个nalu,每个nalu前面都有NalUnitLength字节表示每个nalu的长度int nNaluLen;switch (pParser-_nNaluUintLength){case 4:nNaluLen FlvParser::ShowU32(pd nOffset);break;case 3:nNaluLen FlvParser::ShowU24(pd nOffset);break;case 2:nNaluLen FlvParser::ShowU16(pd nOffset);break;default:nNaluLen FlvParser::ShowU8(pd nOffset);break;}//添加nalu start codememcpy(_pMedia _nMediaLen, nH264StartCode, 4);//复制nalu数据memcpy(_pMedia _nMediaLen 4, pd nOffset pParser-_nNaluUintLength, nNaluLen);_nMediaLen (4 nNaluLen);nOffset (pParser-_nNaluUintLength nNaluLen);}
}