前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >音视频封装:FLV格式详解和打包H264、AAC方案(下)

音视频封装:FLV格式详解和打包H264、AAC方案(下)

作者头像
潇湘落木
发布2020-11-12 11:59:50
发布2020-11-12 11:59:50
3.3K0
举报
文章被收录于专栏:智媒黑板报智媒黑板报

接着上一篇继续分析Video Tag和Audio Tag相关内容。


Video Tag 视频Tag:

该Tag类型封装真实的视频裸数据,虽然支持H263、H264等编码类型的视频,但是现在主流还是H264,所以下面会重点分析如何将H264视频帧打进Flv方法。

Flv Parse 解析的结果如下:

previous tag1:

十六机制:0x00 00 01 37

十进制:311

因表示了前一个Metadata Tag的长度是311字节,这跟上篇分析结果是一致的;


Video tag header:

十六进制:0x09 00 00 2C 00 00 00 00 00 00 00

Tagtype:

十六进制:0x09

二进制:0000 1001

通过前1-2bit即知道非加密,后面4-8bit10010即十进制为9则为Video Tag类型;

DataSize:

十六进制:0x 00 00 2C

十进制:44

说明这个Video Tag的data字段长度为44字节;

Timestamp:

十六进制:0x 00 00 00

由于是第一个Video Tag该字段一般就是默认为0;

TimeStampExtended:

十六进制:0x 00 00 00

时间戳扩展字段也是默认为0;

Stream ID:

十六进制:0x 00 00 00

无论那种类型的Tag,一般默认为0;


Video Tag Data:

视频头:

在Video tag的Header后面按道理就是视频裸数据了,但是这里我们需要分析下第一个字节,判断视频数据的编码格式等信息,然后才知道视频裸数据是怎么打包进Video Tag的Data字段的,第一个Video Tag的Data部分如图所示:

视频头字段格式:

字段

占位

含义

Frame type帧类型

第一字节1-4bit位

十进制1: keyframe (for AVC, a seekable frame)——h264的IDR,关键帧,可重入。该关键帧时进行视频拖动 seek的关键;2: inter frame (for AVC, a non- seekable frame)——h264的普通幀 ,比如P帧,B帧等3: disposable inter frame (H.263 only)4: generated keyframe (reserved for server use only)5: video info/command frame

Code ID编码ID

第一字节4-8bit位

视频的编码类型:1: JPEG (currently unused) 2: Sorenson H.2633: Screen video4: On2 VP65: On2 VP6 with alpha channel 6: Screen video version 27: AVC也就是说的H264


待分析数据第一字节:

十六进制:0x17 我们先分析Video Tag数据部分的第一个字节即视频头

Frame type:

十六进制:0x17

二进制:0001 0111

十进制:1

通过前面1-4bit位发现十进制为1,即认为是key frame;

CodeID:

十六进制:0x17

二进制:0001 0111

十进制:7

说明这个Video的编码格式AVC也就是常说的H264;

特别注意:

分析到这里,我们发现这个Video Tag的承载数据是AVC即H264编码格式的数据,一般情况下Flv承载的数据格式都是这种。那么就需要继续向下面分析后面的Packet Type字段。


Packet Typ数据格式:

字段

type

Comment

AVC packet Type 类型

1字节

0:AVC序列头1:AVC NALU单元2:AVC序列结束。低级别AVC不需要。

CTS CompositionTime 字段

3字节

如果AVC packet类型是1,則为cts偏移;如果AVC packet为0則为0;

数据

后面部分

如果AVC packet类型是0,則是编码器配置,sps,pps;如果AVC packet类型是1,則是nalu单元,可以是多个,具体格式见下面分析;

对各个字段解释:

CTS:这个字段需要结合PTS和DTS一块来理解,至于还不知道PTS和DTS参考以前的文章,我这里的理解就是编码延时,有更深理解的可以留言交流。

CTS的大小:cts = pts - dts/90,CTS的单位是毫秒,除以90是因为H264的采样率是90KHz,这里是为了将时间戳单位转化为毫秒;

同时H264编码时有编码级别和规范的说法,一般而言profile级别是没有B帧的,这就意味着pts等于dts,那cts直接为0即可;如果是profile main级别,说明有B帧则需要根据公式计算,B帧时双向预测帧,则有编码延时大部分情况不启用这边级别编码方式;


待分析数据第2-5字节:

十六进制:0x00 00 00 00

Avc packet:

十六进制:0x00

十进制:0

通过说明后面承载的数据是H264的序列头也就是编码器配置SPS PPS而不是裸数据Nalu;

CTS:

十六进制:0x00 00 00

十进制:0

由于Av Packet是0,则这里的cts肯定是0,因为不是真正的视频帧所以没有cts的概念;

后面我们会分析Avc Packet是Nalu的数据部分,现在先分析Avc Packet是Avc序列头的数据部分。


AVCDecoderConfigurationRecord部分:

分析完视频数据前五个字节,后面就是Video Tag Data字段对SPS PPS的封装:


待分析数据:

十六机制:0x 01 64 00 28 FF E1

Configuration version:

十六进制:0x01

一般默认固定为0x01;

Avc Profile Indication:

十六进制:0x64

这是提取来自SPS的字段值,表示编码级别,表示的profile high这种级别。

Profile compatibility:

十六进制:0x00

Avc Level Indication:

十六进制:0x28

这是也是提取来自SPS的字段值,表示编码能力,跟分辨率、帧率、码率有关系;

Reserved:

十六进制:0xFF

二进制:0x1111 1111

Length size minus one:

十六进制:0xFF

二进制:0x1111 1111

十进制:3,暂时没用字段;

Reserved:

十六进制:0xE1

二进制:0x1110 0001

Num sequence parmeter sets:

十六进制:0xE1

二进制:0x1110 0001

紧接着的后面只有一个SPS;

接下来就很容易分析了:

0x00 18表示SPS的开始部分,长度为24;

0x67-0xA8 的24个字节就是SPS数据部分;

0x01 表示PPS的个数

0x00 0x04表示PPS的长度

0x68-0xB0 表示PPS的数据部分;

看到这里大家肯定想知道SPS PPS的具体字段,这里就不详细解释了,会在后面的文章详细讲解。作用就是初始化播放器,没有这个值播放器拿不到编码器编码H264数据的参数信息也就没办法进行解码和渲染播放。SPS PPS值很关键,跟首屏秒开、拖动随机播放等功能有密切功能,后面帮大家分析分析。同样为了交叉验证,我用程序将这个flv的音视频裸数据进行了分离,然后用Stream Eye工具分析了其中的SPS PPS,结果如下:

分析到这里,分析了Video Tag的视频编码格式为H264即AVC的AVCDecoderConfigurationRecord数据类型,下面再分析一个NALU类型的Video Tag数据部分:


刚才我们分析的Video Tag1,Data部分承载的SPS PPS 部分,现在我们分析的Video Tag3,中间是音频,先跳过,等下分析。对于Video Tag3也是直接跳过11字节的Tag Header前面已经分析,不再赘述,直接分析Tag Data部分:

待分析数据第一字节:

十六进制:0x17 我们先分析Video Tag数据部分的第一个字节即视频头

Frame type:

十六进制:0x17

二进制:0001 0111

十进制:1

通过前面1-4bit位发现十进制为1,即认为是key frame;

CodeID:

十六进制0x17

二进制:0001 0111

十进制:7

说明这个Video的编码格式AVC也就是常说的H264;


待分析数据第2-5字节:

十六进制:0x00 00 00 00

Avc packet:

十六进制0x00

十进制:0

通过说明后面承载的数据是H264即AVC的NALU单元;

CTS:

十六进制0x00 00 00

十进制:0

由于此AVC的编码级别显示没有B帧,则PTS=DTS,所以这里的CTS一直为0;

NALU Legth:

十六机制:0x00 00 01 EF

十进制:495

表示这个NALU的长度为495字节,同时我们分析这个Video Tag的头中显示长度为504,也就很快发现Data部分就是前面分析的这9个字节,剩余的495则为NALU的真实数据,这就是NALU的裸数据,非常关键。

接下来的0x65-0x29都是NALU的数据,NALU也是有不同的类型,后面文章会详细介绍。

这里0x65就是NALU的类型,二进制为0110 0101,其中红色显示的5bit就是NALU类型,这里是IDR帧类型。

至此我们分析完了Flv的Video Tag部分,基本也分析了H264的Nalu打包方法。

Audio Tag音频 Tag:

虽然Flv支持的音频编码格式不仅仅支持AAC,也支持一些MP3等。但是目前项目实际使用时,我们基本都会把音频编码格式转成AAC,然后打包进Flv,所以这里也重点分析下AAC裸数据如何打进Flv,先看下第一个Audio的Tag:


Audio Tag Header部分:

这里基本参考Script Tag的头部分析即可,这里简单说明下:

待分析数据:

十六进制:0x08 00 00 04 00 00 00 00 00 00 00

Tagtype:

十六进制:0x08

二进制:0000 1000

通过前1-2bit即知道非加密,后面4-8bit10010即十进制为8 则Tag类型Audio tag;

DataSize:

十六进制:0x 00 00 04

十进制:4

说明这个Audio Tag的data字段长度为4字节;

Timestamp:

十六进制:0x 00 00 00

第一个Audio Tag该字段一般就是默认为0;

TimeStampExtended:

十六进制:0x 00 00 00

时间戳扩展字段也是默认为0;

Stream ID:

十六进制:0x 00 00 00

默认为0,该字段暂时未启用;


Audio Tag Data部分:

音频头格式:

字段

占位

含义

SoundFormat音频格式

第一字节1-4bit位

音频编码:十进制0 = Linear PCM, platform endian1 = ADPCM2 = MP33 = Linear PCM, little endian4 = Nellymoser 16 kHz mono5 = Nellymoser 8 kHz mono6 = Nellymoser7 = G.711 A-law logarithmic PCM , reserved8 = G.711 mu-law logarithmic PCM , reserved 9 = reserved10 = AAC (supported in Flash Player 9,0,115,0 and higher)11 = Speex (supported in Flash Player 10 and higher)14 = MP3 8 kHz , reserved15 = Device-specific sound , reserved 说明:这里面一般就是10和14会用到,对于G711系列其实是不支持的,只是保留位而已;

SoundRate音频采样率

第一字节5-6bit位

采样率:0 = 5.5kHz1 = 11kHz2 = 22kHz3 = 44kHz注意:这里是不支持48HKz的,对于音频AAC而言,基本就是3即44KHz;

SoundSize采样位宽

第一字节第7bit位

采样位宽也就会说采样精度:0 = 8bit samples1= 16bit samples 对于AAC而言就是1即16位表示一个采样点的大小;

SoundType 音频通道

第一字节第8bit位

通道个数:0 = Mono,单通道1 = Stereo,双通道对于AAC一般就是双通道;

AAC Packet Type 音频数据

第二字节

0 则表示的是AAC sequence header1 则表示的AAC Raw码流可选字段,只有是AAC音频有该字段。


我们先分析数据部分第一字节弄清楚音频的编码格式等基本信息:

待分析数据:

十六进制:0xAF

二进制:1010 1111

SoundFormat:

十六进制:0xAF

二进制:1010 1111

通过前4个bit,则表示的A即12,所以音频编码为AAC;

SoundRate:

十六进制:0xAF

二进制:1010 1111

说明AAC采样频率用的44KHz

SoundSize:

十六进制:0xAF

二进制:1010 1111

说明AAC采样精度是16bit即2字节;

SoundType:

十六进制:0xAF

二进制:1010 1111

说明AAC的声道数是2;

其实对于AAC音频来说,一般Audio Tag的音频头字段都是0xAF,这里变化不大。由于是AAC,接

下来需要继续分析一个字节。


AAC Packet Type:

待分析数据:

十六机制数据:0x00

AAC Packet Type:

十六进制:0x00

十进制:0

这里为0则说明下面的真实数据是AAC Sequence Header,这个字段有点类似H264的编码配置SPS或者PPS,一般只在整个Flv文件出现一次。

那么下面分析AAC Sequence Header字段,这个值需要解析AAC的裸数据得到,同时它起到的作用和AAC的ADTS一样,但是这里并不是ADTS,可以认为是AAC裸数据的另外一种封装格式。


AAC Sequence Header:

这个字段也被称为是AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细的音频信息,它的定义在ISO14496-3中1.6.2.1。

格式如下:

字段

占位

含义

AAC Profile编码级别

第一字节1-5bit

编码级别:AAC Main 0x01AAC LC 0x02AAC SSR 0x03

AAC Sample Frequence采样率

第一字节6-8bit第二字节1-1bit

0x00 960000x01 882000x02 640000x03 480000x04 441000x05 320000x06 240000x07 220500x08 160000x09 120000x0A 110250x0B 80000x0C reserved0x0D reserved0x0E reserved0x0F escape value

AAC Channel config通道数

第二字节2-5bit

0x00 - defined in audioDecderSpecificConfig0x01 单声道(center front speaker)0x02 双声道(left, right front speakers)0x03 三声道(center, left, right front speakers)0x04 四声道(center, left, right front speakers, rear surround speakers)0x05 五声道(center, left, right front speakers, left surround, right surround rear speakers)0x06 5.1声道(center, left, right front speakers, left surround, right surround rear speakers, front low frequency effects speaker)0x07 7.1声道(center, left, right center front speakers, left, right outside front speakers, left surround, right surround rear speakers, front low frequency effects speaker)0x08-0x0F - reserved

AAC Reserve

第二字节6-8bit

保留位


待分析数据:

十六机制数据:0x12 10

二进制数据:0001 0010 0001 0000

AAC Profile:

十六进制:0x12

二进制:0001 0010

十进制:2

这里为2,则说明编码方式是AAC LC

AAC Sample Frequence:

十六进制:0x12 0x10

二进制:0001 0010 0001 0000

十进制:4

这里为4,则说明采样频率是44KHz,对于AAC基本都是这个值;

AAC Channel Config:

十六进制:0x12 0x10

二进制:0001 0010 0001 0000

十进制:4

这里为2,则说明AAC的音频通道是2;

AAC Reserve:

十六进制:0x12 0x10

二进制:0001 0010 0001 0000

这里三个bit保留位都是0;

综上所述,对于音频编码格式是AAC的,则第一个Audio Tag基本是四字节的固定值:

0xAF 00 12 10,这可以作为判断音频为AAC的快速方法。当然有时会有点出入。

我们分析了Audio的第一个Tag值为AudioSpecificConfig类型的,再分析一个是裸数据的Tag Data字段如下图:

说明:

1. 第一部分红框11字节还是Audio Tag的Header字段,上面已经分析不再赘述;

2. 第二部分承载数据的蓝框1字节是音频编码类型等信息,前面分析AAC Sequence Header已经分析了,一般只有一路音频,所以该字段固定不再变化;

3. 绿框决定了该Audi Tag的数据部分是AAC Sequence Header还是 AAC Raw Data,这里值为0x01,则说明该Audio承载的AAC Raw裸数据;

4. 后面的粉框9字节即为AAC Raw Data,关于AAC的编码方式和裸数据含义以后再讲。


FLV总结:

这篇文章首先讲解了Flv的基本概念、目前现状以及在直播方案中的应用。后面在我本地通过Flv Parse专门分析了Flv文件的封装格式。其中Audio Tag和Video Tag已经分析到AAC和H264的数据帧如何封装到Tag的Data字段,基本按照分析的方法就能很简单的将Flv里面的音频和视频裸数据提取出来,当然也能将H264和AAC数据打包封装成Flv。

下面说解装的操作步骤:

1. 分析Flv的头字段,一般9字节作为开头,主要是根据头字段判断是不是FLV格式,其次判断是否有音视频。因为Flv只封装视频,没有音频是可以传输和播放的,这个我在本地做了实验,VLC是可以播放的,甚至没有Script Tag也是可以的;

2. 接着分析第一个Tag,一般是Script Tag。这个Tag前面是11字节的Tag Header头数据,后面AMF0和AMF1包,严格按照这两个包的定义分析即可,上文已经详细说明;

3. 分析视频的第一个Video Tag,还是11字节的Tag Header头,紧接着分析Data的第一字节,分析帧类型和编码方式。帧类型能找出关键帧,这是很多特殊操作的关键。

4. 如果3分析出来的编码方式不是AVC即H264,那么直接走5.如果是AVC,则继续分析下一个字节AVC packet类型,一般不是AVC的编码配置就是NALU字段。第一个是AVC的编码配置,则提取出SPS PPS等信息,如果是NALU则根据NALU的类型分析出裸码流;

5. 直接按照指定的编码方式分析裸数据即可;

6. 分析第一个音频Video Tag,同样分析Tag Data字段的第一字节分析音频编码方式和基本信息,如果不是AAC则直接走7;如果是再分析第二字节,判断AAC的Packet类型是AAC Sequence Header还是AAV Law裸数据。是AAC Sequence Header就进一步分析AAC相关信息,如果裸数据,则解析出AAC音频帧即可;

7. 分析AAC Sequence Header即可,参考上文;

8. 后面交替分析Video Tag和Audio Tag的裸数据即可,直到分析结束;

封装步骤跟解装步骤相反即可;


今天就说这么多,祝您心情愉快,工作顺利!

如果有疑问,你可以在公众号后台发消息咨询我。

参考文章:

flv.js相关:

https://mp.weixin.qq.com/s/M97Krog9VS2C2QqSld9o9w

分析工具下载:

https://github.com/ty6815/AvStackDocs

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 智媒黑板报 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 该Tag类型封装真实的视频裸数据,虽然支持H263、H264等编码类型的视频,但是现在主流还是H264,所以下面会重点分析如何将H264视频帧打进Flv方法。
  • Audio Tag音频 Tag:
  • 虽然Flv支持的音频编码格式不仅仅支持AAC,也支持一些MP3等。但是目前项目实际使用时,我们基本都会把音频编码格式转成AAC,然后打包进Flv,所以这里也重点分析下AAC裸数据如何打进Flv,先看下第一个Audio的Tag:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档