FLV学习(四)FlvParser源码阅读(2)相关的数据结构

FLV相关的数据结构



图1.文件结构(简图)



图2.FLV文件结构(详图)



CFlvParser表示FLV解析器

    FLV由FLV头部和FLV体构成,其中FLV体是由一系列的FLV tag构成的

class CFlvParser
{
public:
	CFlvParser();
	virtual ~CFlvParser();

	int Parse(unsigned char *pBuf, int nBufSize, int &nUsedLen);
	int PrintInfo();
	int DumpH264(const std::string &path);
	int DumpAAC(const std::string &path);
	int DumpFlv(const std::string &path);

private:

	// flv的头
	typedef struct FlvHeader_s FlvHeader;

	// Tag头部
	struct TagHeader;

	// flv的tag(普通的script Tag)
	class Tag;

	// 视频类型Tag
	class CVideoTag : public Tag;

	// 音频类型Tag
	class CAudioTag : public Tag;

	// FLV的状态信息
	struct FlvStat;

	static unsigned int ShowU32(unsigned char *pBuf) { return (pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]; }
	static unsigned int ShowU24(unsigned char *pBuf) { return (pBuf[0] << 16) | (pBuf[1] << 8) | (pBuf[2]); }
	static unsigned int ShowU16(unsigned char *pBuf) { return (pBuf[0] << 8) | (pBuf[1]); }
	static unsigned int ShowU8(unsigned char *pBuf) { return (pBuf[0]); }
	static void WriteU64(uint64_t & x, int length, int value);
    static unsigned int WriteU32(unsigned int n);

	friend class Tag;
	
private:

	FlvHeader *CreateFlvHeader(unsigned char *pBuf);
	int DestroyFlvHeader(FlvHeader *pHeader);
	Tag *CreateTag(unsigned char *pBuf, int nLeftLen);
	int DestroyTag(Tag *pTag);
	int Stat();
	int StatVideo(Tag *pTag);
	int IsUserDataTag(Tag *pTag);

private:

	FlvHeader* _pFlvHeader;
	vector<Tag *> _vpTag;
	FlvStat _sStat;
	CVideojj *_vjj;

	// H.264
	int _nNalUnitLength;
};



FlvHeader表示FLV的头部



	// flv的头
	typedef struct FlvHeader_s
	{
		int nVersion; // 版本
		int bHaveVideo, bHaveAudio; // 是否包含音视频
		int nHeadSize; // FLV头部长度

		/*
		** 指向存放FLV头部的buffer
		** 上面的三个成员指明了FLV头部的信息,是从FLV的头部中“翻译”得到的,
		** 真实的FLV头部是一个二进制比特串,放在一个buffer中,由pFlvHeader成员指明
		*/
		unsigned char *pFlvHeader; 
	} FlvHeader;




标签

    标签包括标签头部和标签体,根据类型的不同,标签体可以分成三种:script类型的标签,音频标签、视频标签


标签头部



	// Tag头部
	struct TagHeader
	{
		int nType; // 类型
		int nDataSize; // 标签body的大小
		int nTimeStamp; // 时间戳
		int nTSEx; // 时间戳的扩展字节
		int nStreamID; // 流的ID,总是0

		unsigned int nTotalTS;

		TagHeader() : nType(0), nDataSize(0), nTimeStamp(0), nTSEx(0), nStreamID(0), nTotalTS(0) {}
		~TagHeader() {}
	};





标签数据


script类型的标签


	// flv的tag
	class Tag
	{
	public:
	    Tag() : _pTagHeader(NULL), _pTagData(NULL), _pMedia(NULL), _nMediaLen(0) {}
		void Init(TagHeader *pHeader, unsigned char *pBuf, int nLeftLen);

		TagHeader _header;
		unsigned char *_pTagHeader; // 指向标签头部
		unsigned char *_pTagData; // 指向标签body
		unsigned char *_pMedia; // 指向标签的元数据
		int _nMediaLen;
	};





音频标签


	class CAudioTag : public Tag
	{
	public:
		CAudioTag(TagHeader *pHeader, unsigned char *pBuf, int nLeftLen, CFlvParser *pParser);

		int _nSoundFormat; // 音频编码类型
		int _nSoundRate; // 采样率
		int _nSoundSize; // 精度
		int _nSoundType; // 类型

		// aac
		static int _aacProfile;
		static int _sampleRateIndex;
		static int _channelConfig;

		int ParseAACTag(CFlvParser *pParser);
		int ParseAudioSpecificConfig(CFlvParser *pParser, unsigned char *pTagData);
		int ParseRawAAC(CFlvParser *pParser, unsigned char *pTagData);
	};



视频标签


	class CVideoTag : public Tag
	{
	public:
		CVideoTag(TagHeader *pHeader, unsigned char *pBuf, int nLeftLen, CFlvParser *pParser);

		int _nFrameType; // 帧类型
		int _nCodecID; // 视频编解码类型
		int ParseH264Tag(CFlvParser *pParser);
		int ParseH264Configuration(CFlvParser *pParser, unsigned char *pTagData);
		int ParseNalu(CFlvParser *pParser, unsigned char *pTagData);
	};



【该资源在win7——64位系统下验证通过。win10系统试试用win7兼容方式打开】 解析flv二进制数据的小工具,tag header tag data等都分析出来了的 这个工具的主要功能是查看FLV的文件结构,帮助我们理解FLV格式。另外,如果涉及到处理flv文件的开发,这个工具对于查看处理结果非常有帮助。因此我觉得有必要写一个使用说明,希望这个工具能够给大家提供帮助。 打开后的界面如下图所示。 先说一下界面布局:左上方是FLV文件的结构树,右边是FLV文件的字节流数据;左侧结构树下面依次是结构树的信息等级选择、高速模式选择、文件分析用时及进度条等;下方是分析文件的地址显示以及文件选择按钮。下面详细介绍一下相关部分。 结构树及信息等级 FLV结构树是这个工具最重要的显示信息,用户可以直观的查看当前FLV文件的结构。FLVParse默认FLV文件结构树的形式为:File Header + Metadata Tag(1个) + Video or Audio Tags(按顺序)。 结构树的信息详细程度是按等级划分的,之所以要分等级,是为了区分显示信息的详细程度,因为不同程度的分析对于分析所用的时间影响是比较大的(主要在UI界面上),越详细的信息等级占用分析时间越长。一共有6个等级,按从简单到详细介绍如下。 only section position info —— 只有每个section的位置信息,如下图所示。其中每个section后的方括号里是位置信息(十六进制表示),每个“Pre Tag Size”后面的数字表示size的大小(十进制表示),Video&Audio Tag按照在文件中的顺序依次排序标号; file header info, metadata info —— 只有File Header + Metadata Tag的详细信息,如下图所示。其中File Header的详细结构信息会在子树中列出,并在每项后面标示该项的值;Metadata Tag类似,包含Tag Header和Tag Data两个子树,并且对应子项的详细信息也都列出; file header info, metadata info, tag position info —— 包含File Header + Metadata Tag的详细信息,Video&Audio Tags的位置信息,以及Pre Tag Size信息,如下图所示; file header info, metadata info, tag section position info —— 比上个等级多出Video&Audio Tags的Tag Header和Tag Data的位置信息,如下图所示; file header info, metadata info, tag header info —— 比上个等级多出Tag Header的详细子项信息,如下图所示; file header info, metadata info, tag info —— 比上个等级多出Tag Data的详细子项信息,如下图所示。 FLV字节流数据显示 右侧显示了FLV文件的数据,可以让用户方便地查询对应位置上的字节。每一行都以一个十六进制的位置开始,该位置为相对于文件开头的位置。每一行有十六个字节,每个字节按高4位和第4位显示2个十六进制的字符,用户可以滑动滚动条查看任意位置的字节。 当用户选中左边结构树中的某项时,右边数据会自动选中对应的数据区域(绿色),根据不同项的类型,选中的区域大小也会自动对应。 高速模式 这个选项是为了解决分析比较大的FLV文件时,用户等待时间过长的问题。 普通模式时,分析过程为阻塞模式,即主线程分析完毕后刷新界面,用户才可以继续操作。 高速模式时,为非阻塞模式,主线程分析一小部分后立即返回刷新界面,响应用户操作;另外一个线程会继续分析剩余大部分文件,直到分析完毕自动结束线程。因此高速模式时,用户会看到结构树的滚动条一直在滑动,这是因为后台分析线程在不断向结构树里添加子项。需要注意的是,当后台分析线程还没有结束,如果用户打开新的文件进行分析,有可能出现错误的分析结果。这个目前没有进行测试,我想应该是这样的。 这里需要提一下,其实真正分析文件的时间并不会特别长,即使几百兆的文件,几十秒内应该没有问题,时间主要消耗在MFC的树型控件CTreeCtrl上。为了开发效率,FLVParse使用了MFC控件,但是CTreeCtrl在结构比较复杂,子项比较多的时候,效率会出现比较大的下降。当子项超过10000的时候,再进行添加的时间大大变长,几乎到了无法忍受的程度,好在还算稳定,没有出现崩溃等现象。粗略估计,每次分析文件,花在更新UI界面上的时间要占总耗时的90%以上,而且对于越大的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值