从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);
}
}
}
对应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);
}
}
}
相关文章推荐
- 分类问题
- 转 java类的装载(Loading)、链接(Linking)和初始化(Initialization)
- Eclipse快捷键大全
- 我所认知的git
- iOS项目开发实战——使用CALayer实现图片的淡入淡出效果
- ORA-00257: archiver error. Connect internal only, until freed 归档日志满处理方法
- MySql 之 join 相关(1)
- 【A了两道题的沈阳赛】2015 ACM/ICPC Asia Regional Shenyang Online
- 如何保证黑盒测试的覆盖率(转)
- eclipse的环境变量的配置
- java__反射、批处理、对象拷贝
- C++ primer 5 笔记3 chapter 3 字符串, 向量和数组
- memcache知识梳理
- 线程池中使用条件变量和信号量的性能比较
- 人际关系
- Android应用——用LayoutTransition在View动态显示和隐藏时候加上动画
- Centos下安装jdk8、tomcat8
- Linux 基础入门(新版)”实验报告一~十二
- DOM 操作方法的简单归纳
- 转 一次完整地http请求