flv文件解析

21 篇文章 0 订阅
FLV是一个二进制文件,由文件头(FLV header)和很多tag组成。
tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流。
FLV Header
  文件类型3bytes 总是FLV(0x46 0x4C 0x56)
  版本1byte
  流信息1byte
  header长度4bytes (一般是9)
FLV Body
  FLV body就是由很多tag组成的,
一个tag包括下列信息:
  previoustagsize 4bytes 前一个tag的长度,第一个tag就是0
  tag类型1byte
  三类:
  * 8 -- 音频tag
  * 9 -- 视频tag
  * 18 -- 脚本tag
  数据区长度3bytes 时间戳3bytes 单位毫秒
  扩展时间戳1byte 作为时间戳的高位
  streamsID 3bytes 一般是0
  数据区 大小为之前获取的数据区大小

音频(视频)数据区的第一个字节包含音频(视频)的编码格式信息

audio信息1byte
前四位bits表示音频格式:
  * 0 -- 未压缩
  * 1 -- ADPCM
  * 2 -- MP3
  * 5 -- Nellymoser 8kHz momo
  * 6 -- Nellymoser
*10 -- HE-AAC
  下面两位bits表示samplerate:
  * 0 -- 5.5kHz
  * 1 -- 11kHz
  * 2 -- 22kHz
  * 3 -- 44kHz
  下面一位bit表示每个采样的长度:
  * 0 -- snd8Bit
  * 1 -- snd16Bit
  下面一位bit表示类型:
  * 0 -- sndMomo
  * 1 -- sndStereo

video信息1byte
  前四位bits表示类型:
  * 1 -- keyframe
  * 2 -- inner frame
  * 3 -- disposable inner frame (H.263 only)
  后四位bits表示编码器:
  * 2 -- Seronson H.263
  * 3 -- Screen video
  * 4 -- On2 VP6
  * 5 -- On2 VP6 without channel
  * 6 -- Screen video version 2
* 7 -- H.264
  video数据区
  

格式还是挺简单的,知道后可以自己进行剪切,合并操作


代码:
#include <CSTDIO>
#include <CSTDLIB>
#include <CSTRING>
#include <STRING>
#include <IOSTREAM>
using namespace std;

#define HTON16(x) ((x>>8&0xff)|(x<<8&0xff00))
#define HTON24(x) ((x>>16&0xff)|(x<<16&0xff0000)|x&0xff00)
#define HTON32(x) ((x>>24&0xff)|(x>>8&0xff00)|\
(x<<8&0xff0000)|(x<<24&0xff000000))

#define STR(x) (x.c_str())
#define FCUR(x) (ftell(x))
#define FSEEK(x,f) (fseek(f,x,SEEK_CUR))
#define FSET(x,f) (fseek(f,x,SEEK_SET))
#define LOG(x,f) (fprintf(f,STR(x)))
FILE *ffile=NULL;
FILE *flog=NULL;

int audionum=0;
int videonum=0;
int lasttime=0;
unsigned int size;
bool Init();
void Clear();

bool Read8(int &i8,FILE*f);
bool Read16(int &i16,FILE*f);
bool Read24(int &i24,FILE*f);
bool Read32(int &i32,FILE*f);
bool ReadTime(int &itime,FILE*f);

bool Peek8(int &i8,FILE*f);

bool ReadHead();
void ReadBody();

string GetAudioInfo(int info);
string GetVideoInfo(int info);


char filename[256]={0};
char logfilename[256]={0};
bool hasname=false;
int main(int argc,char**argv)
{
if (argc>1)
{
sprintf(filename,"%s",argv[1]);
sprintf(logfilename,"%sinfo.txt",argv[1]);
hasname=true;
}
if(!Init())
{
cout<<"Init Err"<<endl;
return -1;
}
if(!ReadHead())
{
cout<<"ReadHead Err"<<endl;
return -1;
}
ReadBody();
printf("time:%.4f s Audio num:%d Video num:%d\n",lasttime*1.0/1000,audionum,videonum);
fprintf(flog,"time:%.4f s Audio num:%d Video num:%d\n",lasttime*1.0/1000,audionum,videonum);
cout<<"read over"<<endl;
void Clear();
return 0;
}
bool Init()
{
if (!hasname)
{
printf("Please input filename:\n");
scanf(" %s",filename);
sprintf(logfilename,"%slog.txt",filename);
}
ffile=fopen(filename,"rb");
flog=fopen(logfilename,"wb");
if(ffile==NULL||flog==NULL)
{
return false;
}
fseek(ffile,0,SEEK_END);
size=FCUR(ffile);
fseek(ffile,0,SEEK_SET);
return true;
}
void Clear()
{
fclose(ffile);
fclose(flog);
}


bool Read8(int &i8,FILE*f)
{
if(fread(&i8,1,1,f)!=1)
return false;
return true;
}
bool Read16(int &i16,FILE*f)
{
if(fread(&i16,2,1,f)!=1)
return false;
i16=HTON16(i16);
return true;
}
bool Read24(int &i24,FILE*f)
{
if(fread(&i24,3,1,f)!=1)
return false;
i24=HTON24(i24);
return true;
}
bool Read32(int &i32,FILE*f)
{
if(fread(&i32,4,1,f)!=1)
return false;
i32=HTON32(i32);
return true;
}
bool Peek8(int &i8,FILE*f)
{
if(fread(&i8,1,1,f)!=1)
return false;
fseek(f,-1,SEEK_CUR);
return true;
}

bool ReadTime(int &itime,FILE*f)
{
int temp=0;
if(fread(&temp,4,1,f)!=1)
return false;
itime=HTON24(temp);
itime|=(temp&0xff000000);
return true;
}

bool ReadHead()
{
int headlength=0;
int filetype=0;
if(!Read24(filetype,ffile))
return false;
int typel='flv';
int typeh='FLV';
if (filetype!=typeh&&filetype!=typel)
{
printf("not flv file\n");
return false;
}
FSEEK(2,ffile);
if (!Read32(headlength,ffile))
return false;
printf("headlength:%d\n",headlength);
/跳过头部长度/
fseek(ffile,0,SEEK_SET);
FSEEK(headlength,ffile);
return true;
}
void ReadBody()
{

while(true)
{
string temp="";
char m_tt[200]={0};
sprintf(m_tt,"fseek:%d ",FCUR(,ffile));
temp+=m_tt;

FSEEK(4,ffile);
int type=0;
int time=0;
int htime=0;
int datelength=0;
int info=0;
char buff[256]={0};
if (!Read8(type,ffile))
break;
if (!Read24(datelength,ffile))
break;
if(!ReadTime(time,ffile))
break;
/* if (!Read24(time))
break;
//时间高位///
if (!Read8(htime))
break;
*/
跳过StreamID/
FSEEK(3,ffile);
if(!Peek8(info,ffile))
break;
lasttime=time;
switch(type)
{
case 8:
audionum++;
sprintf(buff,"Type:Audio time:%d length:%d ",time,datelength);
temp+=buff;
temp+=GetAudioInfo(info);
break;
case 9:
videonum++;
sprintf(buff,"Type:Video time:%d length:%d ",time,datelength);
temp+=buff;
temp+=GetVideoInfo(info);
break;
case 18:
sprintf(buff,"Type:script length:%d ",datelength);
temp+=buff;
break;
default:
sprintf(buff,"UnKnowType:%hd length:%d ",type,datelength);
temp+=buff;
}
temp+="\n";
LOG(temp,flog);
FSEEK(datelength,ffile);
}
}

string GetAudioInfo(int info)
{
string temp="";
char buff[100]={0};
int temptype=0;
temptype=info>>4&0xf;
switch (temptype)
{
case 0:
temp="0-未压缩 ";
break;
case 1:
temp="1-ADPCM ";
break;
case 2:
temp="2-MP3 ";
break;
case 5:
temp="5-Nellymoser 8kHz momo ";
break;
case 6:
temp="6-Nellymoser ";
break;
case 10:
temp="10-HE-AAC ";
break;
default:
sprintf(buff,"UnKnow:%hd ",temptype);
temp=buff;
}
temptype=0;
temptype=info>>2&0x3;
switch (temptype)
{
case 0:
temp+="0-5.5kHz ";
break;
case 1:
temp+="1-11kHz ";
break;
case 2:
temp+="2-22kHz ";
break;
case 3:
temp+="3-44kHz ";
break;
}
temptype=0;
temptype=info>>1&0x1;
switch (temptype)
{
case 0:
temp+="0-8Bit ";
break;
case 1:
temp+="1-16Bit ";
break;
}
temptype=0;
temptype=info&0x1;
switch (temptype)
{
case 0:
temp+="0-Momo ";
break;
case 1:
temp+="1-Stereo ";
break;
}
return temp;
}
string GetVideoInfo(int info)
{
string temp="";
char buff[100]={0};
int temptype=0;
temptype=info>>4&0xf;
switch (temptype)
{
case 1:
temp="1-keyframe ";
break;
case 2:
temp="2-inner frame ";
break;
case 3:
temp="3-disposable inner frame (H.263 only) ";
break;
default:
sprintf(buff,"UnKnow:%hd ",temptype);
temp=buff;
}
memset(buff,0,100);
temptype=0;
temptype=info&0xf;
switch (temptype)
{
case 2:
temp+="2-Seronson H.263 ";
break;
case 3:
temp+="3-Screen video ";
break;
case 4:
temp+="4-On2 VP6 ";
break;
case 5:
temp+="5-On2 VP6 without channel ";
break;
case 6:
temp+="6-Screen video version 2 ";
break;
case 7:
temp+="7-H.264 ";
break;
default:
sprintf(buff,"UnKnow:%hd ",temptype);
temp+=buff;
}
return temp;
}
效果:
flv文件解析 - 幻想少佳 - 我的博客
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值