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);
};