FLV(Flash Video)是如今很是流行的流媒体格式,因为其视频文件体积轻巧、封装播放简单等特色,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式。另外因为当前浏览器与Flash Player紧密的结合,使得网页播放FLV视频垂手可得,也是FLV流行的缘由之一。html
FLV是流媒体封装格式,咱们能够将其数据看为二进制字节流。整体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。 git
用到资源文件:github
先来一张图,这是《科比退役演讲》下载)的一个FLV视频。我使用的是UltraEdit的二进制查看工具。 数组
头部分由一下几部分组成 Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)浏览器
FLV的body部分是一系列的back-pointers+tag构成的bash
tag type+tag data size+Timestamp+TimestampExtended+stream id+ tag data 复制代码
图上第一个tag:markdown
图中红色部分是我标出"("与")"先后的的两个back-pointers,都是4个字节。而括号中间就是第一个TAG。那是怎么计算的呢?咱们就以这个作个示例。网络
前面已经提到tag分3种。咱们一个个看ide
脚本Tag通常只有一个,是flv的第一个Tag,用于存放flv的信息,好比duration、audiodatarate、creator、width等。 首先介绍下脚本的数据类型。全部数据都是以数据类型+(数据长度)+数据的格式出现的,数据类型占1byte,数据长度看数据类型是否存在,后面才是数据。工具
通常来讲,该Tag Data结构包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的不少产品中应用,简单来讲,AMF将不一样类型的数据用统一的格式来描述。第一个AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有,在此不细述。第二个AMF包封装一个数组类型(srs返回为object类型),这个数组中包含了音视频信息项的名称和值。具体说明以下
值 | 类型 | 说明 |
---|---|---|
0 | Number type | 8 Bypte Double |
1 | Boolean type | 1 Bypte bool |
2 | String type | 后面2个字节为长度 |
3 | Object type | |
4 | MovieClip type | |
5 | Null type | |
6 | Undefined type | |
7 | Reference type | |
8 | ECMA array type | 数组,相似Map |
10 | Strict array type | |
11 | Date type | |
12 | Long string type | 后面4个字节为长度 |
表示数组,相似Map。后面4个字节为数组的个数。而后是键值对,第一个为键,2个字节为长度。后面跟具体的内容。接着3个字节表示值的类型,而后根据类型判断长度。 上图咱们能够判断,总共有13个键值对。 第一个长度为8个字节是duration。值类型是0x004073,第一个字节是00,因此是double,8个字节。 第二个长度5个字节是width。值也是double类型,8个字节。 依次解析下去...
stream-id以后:
值 | 类型 |
---|---|
0 | Linear PCM, platform endian |
1 | ADPCM |
2 | MP3 |
3 | Linear PCM, little endian |
4 | Nellymoser 16-kHz mono |
5 | Nellymoser 8-kHz mono |
6 | Nellymoser |
7 | G.711 A-law logarithmic PCM |
8 | G.711 mu-law logarithmic PCM |
9 | reserved |
10 | AAC |
11 | Speex |
14 | MP3 8-Khz |
15 | Device-specific sound |
值 | 类型 |
---|---|
0 | 5.5-kHz |
1 | 11-kHz |
2 | 22-kHz |
3 | 44-kHz |
值 | 类型 |
---|---|
0 | snd8Bit |
1 | snd16Bit |
值 | 类型 |
---|---|
0 | sndMono |
1 | sndStereo |
因为kobe视频音频编码是pcm,查找视频tag太难,使用<<东风破>> mv视频
咱们看到数据部分: 视频信息+数据 视频信息,1个字节。
StreamId以后的数据就表示是VideoTagHeader,若是是avc,VideoTagHeader会多出4个字节的信息就是AVCPacketType和CompositionTime
值 | 类型 |
---|---|
1 | keyframe (for AVC, a seekable frame) 关键帧 |
2 | inter frame (for AVC, a non-seekable frame) |
3 | disposable inter frame (H.263 only) |
4 | generated keyframe (reserved for server use only) |
5 | video info/command frame |
值 | 类型 |
---|---|
1 | JPEG (currently unused) |
2 | Sorenson H.263 |
3 | Screen video |
4 | On2 VP6 |
5 | On2 VP6 with alpha channel |
6 | Screen video version 2 |
7 | AVC |
特殊状况 视频的格式(CodecID)是AVC(H.264)的话,VideoTagHeader会多出4个字节的信息,AVCPacketType 和CompositionTime。
值 | 类型 |
---|---|
0 | AVCDecoderConfigurationRecord(AVC sequence header) |
1 | AVC NALU |
2 | AVC end of sequence (lower level NALU sequence ender is not required or supported) |
AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据流以前必定要把sps和pps信息送出,不然的话解码器不能正常解码。并且在解码器stop以后再次start以前,如seek、快进快退状态切换等,都须要从新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中通常状况也是出现1次,也就是第一个video tag.
条件 | 值 |
---|---|
AVCPacketType ==1 | Composition time offset |
AVCPacketType !=1 | 0 |
再看到第二个video tag
sps pps 前面咱们提到第一个video 通常存放的是sps和pps。这里咱们具体解析下sps和pps内容。先看下存储的格):
0x01+sps[1]+sps[2]+sps[3]+0xFF+0xE1+sps size+sps+01+pps size+pps
复制代码
sps[1]=0x64 sps[2]=00 sps[3]=0D sps size=0x001B=27(占两个字节) 跳过27个字节后,是0x01 pps size=0x0005=118(占两个字节) 跳过5个字节,就到了back-pointers。
视频帧数据 解析出sps和pps tag后,后面的video tag就是真正的视频数据内容了
引用:
(原)从mp4,flv文件中解析出h264和aac,送解码器解码失败:,avc1与H264区别在这里其实有人遇到了和我同样的问题:stackoverflow.com/questions/1…