您的位置:首页 > 其它

从flv文件提取H264数据

2015-09-20 20:49 225 查看
要求flv视频编码是H264方式

对应flv内h264保存方式,对应提取即可,生成的h264可用flv,kmp播放器打开

1bit 17 keyfram avc 27 innerkey

1bit avc type 0x00或0x01

3bit 无意义

头为0x00 sequence header

8bit ver

8bit avcprofi sps[1]

8bit pro sps[2]

8bit avc sps[3]

6bit reserved 111111

2bit lengthsicemi 3

3bit reser 111

5bit num numsps

16bit size

spsdata

8bit ppsnum

16bit ppssize

ppsdata

头为0x01 avcnalu

4bit avcbaluda长度

data

代码:

#include "FlvInfo.h"
#include "StdAfx.h"

#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 *flvfile=NULL;
FILE *h264file=NULL;

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

char flvfilename[256]={0};
char h264filename[256]={0};
bool hasname=false;
int main(int argc,char**argv)
{
if (argc>1)
{
sprintf(flvfilename,"%s",argv[1]);
sprintf(h264filename,"%s.h264",argv[1]);
hasname=true;
}
if(!Init())
{
cout<<"Init Err"<<endl;
return -1;
}
if(!ReadHead())
{
cout<<"ReadHead Err"<<endl;
return -1;
}
ReadBody();
cout<<"read over"<<endl;
Clear();
return 0;
}
bool Init()
{
if (!hasname)
{

printf("Please input filename:\n");

scanf(" %s",flvfilename);
sprintf(h264filename,"%s.h264",flvfilename);
}
flvfile=fopen(flvfilename,"rb");
h264file=fopen(h264filename,"wb");
if(flvfile==NULL||h264file==NULL)
{
return false;
}
fseek(flvfile,0,SEEK_END);
size=FCUR(flvfile);
fseek(flvfile,0,SEEK_SET);
return true;
}
void Clear()
{
fclose(flvfile);
fclose(h264file);
}

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,flvfile))
return false;
int typel='flv';
int typeh='FLV';
if (filetype!=typeh&&filetype!=typel)
{
printf("not flv file\n");
return false;
}
FSEEK(2,flvfile);
if (!Read32(headlength,flvfile))
return false;
printf("headlength:%d\n",headlength);
/////////跳过头部长度/////
fseek(flvfile,0,SEEK_SET);
FSEEK(headlength,flvfile);
return true;
}

void H264JIEXI(int datelength);
void ReadBody()
{

while(true)
{

FSEEK(4,flvfile);
int type=0;
int time=0;
int htime=0;
int datelength=0;
int info=0;

char buff[256]={0};
if (!Read8(type,flvfile))
break;
if (!Read24(datelength,flvfile))
break;
if(!ReadTime(time,flvfile))
break;
////////跳过StreamID/////
FSEEK(3,flvfile);
if(!Peek8(info,flvfile))
break;

int pos=FCUR(flvfile);
if(type==9)
H264JIEXI(datelength);
FSET(pos+datelength,flvfile);
}
}

int h264space=0x01000000;//H264内容间隔标识00000001

void H264JIEXI(int datelength)//关键
{
int info=0;
Read8(info,flvfile);
int avctype=0;
Read8(avctype,flvfile);
FSEEK(3,flvfile);
int templength=0;
char*tempbuff=NULL;
if (avctype==0)
{
FSEEK(6,flvfile);

Read16(templength,flvfile);
printf("sssize:%d\n",templength);

tempbuff=(char*)malloc(templength);
fread(tempbuff,1,templength,flvfile);
fwrite(&h264space,1,4,h264file);
fwrite(tempbuff,1,templength,h264file);
free(tempbuff);

Read8(templength,flvfile);//ppsnum

Read16(templength,flvfile);//ppssize
printf("ppsize:%d\n",templength);

tempbuff=(char*)malloc(templength);
fread(tempbuff,1,templength,flvfile);
fwrite(&h264space,1,4,h264file);
fwrite(tempbuff,1,templength,h264file);
free(tempbuff);
}else
{
// Read32(templength,flvfile);
// tempbuff=(char*)malloc(templength);
// fread(tempbuff,1,templength,flvfile);
// fwrite(&h264space,1,4,h264file);
// fwrite(tempbuff,1,templength,h264file);
// free(tempbuff);
//可能存在多个nal,需全部读取

int countsize=2+3;
while(countsize<datelength)
{
Read32(templength,flvfile);
tempbuff=(char*)malloc(templength);
fread(tempbuff,1,templength,flvfile);
fwrite(&h264space,1,4,h264file);
fwrite(tempbuff,1,templength,h264file);
free(tempbuff);
countsize+=(templength+4);
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: