FLV(一)-解复用器
FLV的基本结构信息可以参考
http://www.cnblogs.com/chef/archive/2012/07/18/2597279.html
http://www.cnblogs.com/qingquan/archive/2011/08/11/2135531.html
http://blog.youkuaiyun.com/bsplover/article/details/7426511
http://help.adobe.com/en_US/FlashMediaLiveEncoder/3.0/Using/WS5b3ccc516d4fbf351e63e3d11c104ba878-7ff5.html
http://blog.youkuaiyun.com/zengraoli/article/details/7742278
以及
http://download.youkuaiyun.com/detail/zhuweigangzwg/5472729,中的文章,里面包括了官方文档
video_file_format_spec_v10 :这个是对 FLV/F4V的解析,很清楚。
ISOIEC 14496-15
:这个是对于sps,pps的解析
感谢各位网友的辛勤劳动,这里基本信息就先不讲解了,下面主要讲解在操作中遇到的几个问题
1:
//•0: 96000 Hz
//•1: 88200 Hz
//•2: 64000 Hz
//•3: 48000 Hz
//•4: 44100 Hz
//•5: 32000 Hz
//•6: 24000 Hz
//•7: 22050 Hz
//•8: 16000 Hz
//•9: 12000 Hz
//•10: 11025 Hz
//•11: 8000 Hz
//•12: 7350 Hz
//•13: Reserved
//•14: Reserved
//•15: frequency is written explictly
samplerate_t = 0x10;
//这里有的地方是 0x1c,但和采样率表对比有问题,对比AAC采样率44100HZ应该是0x10但有的flv中填写的是0x1c,这个需要研究下。
2:
typedef struct Tag_Video_AvcC
{
unsigned char configurationVersion;
unsigned char AVCProfileIndication;
unsigned char profile_compatibility;
unsigned char AVCLevelIndication;
unsigned char reserved_1;
unsigned char lengthSizeMinusOne;
unsigned char reserved_2;
unsigned char numOfSequenceParameterSets; //一般都是一个
unsigned int sequenceParameterSetLength;
unsigned char * sequenceParameterSetNALUnit;
unsigned char numOfPictureParameterSets; //一般都是一个
unsigned int pictureParameterSetLength;
unsigned char * pictureParameterSetNALUnit;
unsigned char reserved_3;
unsigned char chroma_format;
unsigned char reserved_4;
unsigned char bit_depth_luma_minus8;
unsigned char reserved_5;
unsigned char bit_depth_chroma_minus8;
unsigned char numOfSequenceParameterSetExt;
unsigned int sequenceParameterSetExtLength;
unsigned char * sequenceParameterSetExtNALUnit;
}Video_AvcC;
这个是装 sps,pps的结构体//AVCDecoderConfigurationRecord官方文档有详细介绍,里面的信息名称有解析。
3:
从flv的audio,tag中读取出来的aac音频同样既不是latm,也不是adts,和MP4一样,需要添加7个字节的adts头才能正常播放
video的关键帧(I帧)前面需要添加sps,pps从 AVCDecoderConfigurationRecord可以获取的到,但从video,tag中读取的第一个关键帧(I帧)大部分是有一个SEI和一个I帧,有些不常见的是有多个SEI和一个I帧,这里未作处理,需要注意,
I帧的获取在:Video_Tag中有个参数:
//1: keyframe (for AVC, a seekable frame)
//2: inter frame (for AVC, a nonseekable frame)
//3: disposable inter frame (H.263 only)
//4: generated keyframe (reserved for server use only)
//5: video info/command frame
unsigned char FrameType; //帧类型
4:
Script_Tag中是存放了音视频的信息的地方,例如宽高,采样率,样本,是否为立体声等等。
unsigned char Type_1;
unsigned int StringLength; //第2-3个字节为UI16类型值,表示字符串的长度,一般总是0x000A(“onMetaData”长度)
unsigned int ECMAArrayLength; //一共有多少组数据,即有多少个类似:宽,高,采样率这样的信息
double duration; //文件持续时间
double width; //文件 宽度
double height; //文件 高度
double videodatarate; //视频数据速率
double framerate; //帧速率
double videocodecid; //视频编解码器id
double audiosamplerate; //音频采样率
double audiodatarate; //音频数据速率
double audiosamplesize; //音频样本大小
int stereo; //是否是立体声
double audiocodecid; //音频编解码器id
double filesize; //文件大小
double lasttimetamp; //文件最后时间
double lastkeyframetimetamp; //文件最后关键帧时间点
unsigned char * Data; //信息剩下的数据,暂时没有解析
double char2double(unsigned char * buf,unsigned int size)
{
double scr = 0.0;
unsigned char buf_1[8];
unsigned char buf_2[8];
memcpy(buf_1,buf,size);
//大小端问题
buf_2[0] = buf_1[7];
buf_2[1] = buf_1[6];
buf_2[2] = buf_1[5];
buf_2[3] = buf_1[4];
buf_2[4] = buf_1[3];
buf_2[5] = buf_1[2];
buf_2[6] = buf_1[1];
buf_2[7] = buf_1[0];
scr = *(double *)buf_2;
return scr;
}
void double2char(unsigned char * buf,double val)
{
*(double *)buf = val;
}
从char * 中获取的buf,放到 double类型中,需要做一些转换,
“不是直接操作double的内存
,
而是就得一个临时的int变量后赋值”。这句话要理解下。
同样补习一下:浮点数表示,http://blog.youkuaiyun.com/juanjuan888/article/details/6672517
再有 for (int i = 0 ; i< tag->ECMAArrayLength ; i++) //一共有多少组数据,即有多少个类似:宽,高,采样率这样的信息
这个循环之后 else if (Arry_InFomation == 0x03) //数组信息的结束
{
break;
}
但Script_Tag的数据还未全完,这个还不知道剩下的数据是什么,下面在网上找下,进行解析,也希望高手指导。
注:本程序的demo地址:http://download.youkuaiyun.com/detail/zhuweigangzwg/5472767
交流请加QQ:379969650