写点什么

音视频八股文(9)-- flv 的 h264 六层结构和 aac 六层结构

  • 2023-04-29
    北京
  • 本文字数:4550 字

    阅读完需:约 15 分钟

flv 介绍

FLV(Flash Video)是 Adobe 公司推出的⼀种流媒体格式,由于其封装后的⾳视频⽂件体积⼩、封装简单等特点,⾮常适合于互联⽹上使⽤。⽬前主流的视频⽹站基本都⽀持 FLV。采⽤FLV 格式封装的⽂件后缀为.flv。


FLV 封装格式是由⼀个⽂件头(file header)和 ⽂件体(file Body)组成。其中,FLV body 由⼀对对的(Previous Tag Size 字段 + tag)组成。Previous Tag Size 字段 排列在 Tag 之前,占⽤4 个字节。Previous Tag Size 记录了前⾯⼀个 Tag 的⼤⼩,⽤于逆向读取处理。FLV header 后的第⼀个 Pervious Tag Size 的值为 0。


Tag⼀般可以分为 3 种类型:脚本(帧)数据类型、⾳频数据类型、视频数据。FLV 数据以⼤端序进⾏存储,在解析时需要注意。⼀个标准 FLV⽂件结构如下图:



FLV⽂件的详细内容结构如下图:


⼤体的解析框架

FLV header

注:在下⾯的数据 type 中,UI 表示⽆符号整形,后⾯跟的数字表示其⻓度是多少位。⽐如 UI8,表示⽆符号整形,⻓度⼀个字节。UI24 是三个字节,UI[8*n]表示多个字节。UB 表示位域,UB5 表示⼀个字节的 5 位。可以参考 c 中的位域结构体。


FLV 头占 9 个字节,⽤来标识⽂件为 FLV 类型,以及后续存储的⾳视频流。⼀个 FLV⽂件,每种类型的 tag 都属于⼀个流,也就是⼀个 flv⽂件最多只有⼀个⾳频流,⼀个视频流,不存在多个独⽴的⾳视频流在⼀个⽂件的情况。


00000 1 0 1


FLV 头的结构如下:


FLV Body


FLV Tag


每⼀个 Tag 也是由两部分组成:tag header 和 tag data。Tag Header⾥存放的是当前 tag 的类型、数据区(tag data)的⻓度等信息。


tag header⼀般占 11 个字节的内存空间。FLV tag 结构如下:



注意:


1.flv⽂件中 Timestamp 和 TimestampExtended 拼出来的是 dts。也就是解码时间。Timestamp 和 TimestampExtended 拼出来 dts 单位为 ms。(如果不存在 B 帧,当然 dts 等于 pts)


2.CompositionTime 表示 PTS 相对于 DTS 的偏移值, 在每个视频 tag 的第 14~16 字节, 。显示时间(pts) = 解码时间(tag 的第 5~8 字节) + CompositionTime CompositionTime 的单位也是 ms


Script data 脚本数据就是描述视频或⾳频的信息的数据,如宽度、⾼度、时间等等,⼀个⽂件中通常只有⼀个元数据,⾳频 tag 和视频 tag 就是⾳视频信息了,采样、声道、频率,编码等信息。


Script Tag Data 结构(脚本类型、帧类型)


该类型 Tag⼜被称为 MetaDataTag,存放⼀些关于 FLV 视频和⾳频的元信息,⽐如:duration、width、height 等。通常该类型 Tag 会作为 FLV⽂件的第⼀个 tag,并且只有⼀个,跟在 File Header 后。该类型 TagDaTa 的结构如下所示(source.200kbps.768x320.flv⽂件为例):



第⼀个 AMF 包:第 1 个字节表示 AMF 包类型,⼀般总是 0x02,表示字符串。第 2-3 个字节为 UI16 类型值,标识字符串的⻓度,⼀般总是 0x000A(“onMetaData”⻓度)。后⾯字节为具体的字符串,⼀般总为“onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。


第⼆个 AMF 包:第 1 个字节表示 AMF 包类型,⼀般总是 0x08,表示数组。第 2-5 个字节为 UI32 类型值,表示数组元素的个数。后⾯即为各数组元素的封装,数组元素为元素名称和值组成的对。常⻅的数组元素如下表所示。



注:Lavf54.63.104 即是 Libavformat version 54.63.104. 即是 ffmpeg 对于库的版本



Audio Tag Data 结构(⾳频类型)


⾳频 Tag Data 区域开始的:


第⼀个字节包含了⾳频数据的参数信息,


第⼆个字节开始为⾳频流数据。


(这两个字节属于 tag 的 data 部分,不是 header 部分)


第⼀个字节为⾳频的信息(仔细看 spec 发现对于 AAC⽽⾔,⽐较有⽤的字段是 SoundFormat),格式如下:



If the SoundFormat indicates AAC, the SoundType should be set to 1 (stereo) and theSoundRate should be set to 3 (44 kHz). However, this does not mean that AAC audio in FLVis always stereo, 44 kHz data. Instead, the Flash Player ignores these values and extracts thechannel and sample rate data is encoded in the AAC bitstream.



第⼆个字节开始为⾳频数据(需要判断该数据是真正的⾳频数据,还是⾳频 config 信息)。



AAC AUDIO DATA



The AudioSpecificConfig is explained in ISO 14496-3. AAC sequence header 存放的是 AudioSpecificConfig 结构,该结构则在“ISO-14496-3 Audio”中描述。


《完整版 ISO-14496-3(2009-09).pdf 》


如果是 AAC 数据,如果他是 AAC RAW, tag data[3] 开始才是真正的 AAC frame data。



Video Tag Data 结构(视频类型)


视频 Tag Data 开始的:


第⼀个字节包含视频数据的参数信息,


第⼆个字节开始为视频流数据。


第⼀个字节包含视频信息,格式如下:



第⼆个字节开始为视频数据



AVCVIDEOPACKET



(1)CompositionTime 单位毫秒


CompositionTime 每个视频 tag(整个 tag)的第 14 ~ 16 字节(如果是 tag data 偏移[2] ~ [4])(表示 PTS 相对于 DTS 的偏移值 )。


CompositionTime 单位为 ms : 显示时间 = 解码时间(tag 的第 5 ~ 8 字节,位置索引[4] ~ [7])+ CompositionTime


(2)AVCDecoderConfigurationRecord


AVC sequence header 就是 AVCDecoderConfigurationRecord 结构


FLV 时间戳计算

题记:时间戳将每⼀秒分成 90000 份,即将每⼀毫秒分成 90 份 在 flv 中直接存储的都是毫秒级 在 TS 存储的是时间戳级其中 TS、flv⼀般按照编码顺序排列⼀个视频 tag⼀般只包含⼀帧视频的码流其中视频 tag 的时间戳对应的是解码时间戳(DTS/90)当前序列:编码顺序 I P P B B B......对应帧号 0 1 5 3 2 4.......flv 对每⼀个 tag 都规定了它将要播放的时间戳每个时间戳都可以对应转换特性的时间其中 script(脚本)、video(视频)、audio(⾳频)的第⼀个 tag 的时间戳值都为 0 时间戳占 4 个字节 其中第四个字节是⾼位 前三个字节是低位(每个 tag 的 5~8 字节)如 6E 8D A8 01 = 0x 01 6E 8D A8 = 24022440CompositionTime 每个视频 tag 的第 14~16 字节(表示 PTS 相对于 DTS 的偏移值 )CompositionTime 单位为 ms 显示时间 = 解码时间(tag 的第 5~8 字节) + CompositionTime 例如(注意显示时间最后⼀个字节是⾼位)tag0 (脚本) :时间戳为 0tag1 (视频) :第⼀个视频时间戳 值为 0 ⽆CompositionTime (头信息)tag2 (⾳频) :第⼀个⾳频时间戳 值为 0tag3 (视频) :00 00 00 00 值:0 00:00:00:00 (解码时间) CompositionTime:0x 00 00 50 值:8000:00:00:80 I 帧 显示时间: 00:00:00: 80 poc=0tag4 (视频) :00 00 28 00 值:40 00:00:00:40 (解码时间) CompositionTime:0x 00 00 50 值:80 00:00:00:80 P 帧 显示时间: 00:00:00: 120 poc=1tag5 (视频) :00 00 50 00 值:80 00:00:00:80 (显示时间) CompositionTime:0x 00 00 C8 值:200 00:00:00:200 P 帧 显示时间: 00:00:00: 280 poc=5tag6 (⾳频) :00 00 50 00 值:80 00:00:00:80(显示时间)tag7 (⾳频) :00 00 67 00 值:103 00:00:00:103(显示时间)tag8 (视频) :00 00 78 00 值:120 00:00:00:120 (解码时间) CompositionTime:0x 00 00 50 值:80 00:00:00:80 B 帧 显示时间: 00:00:00: 200 poc=3tag9 (⾳频) :00 00 7E 00 值:126 00:00:00:126(显示时间)tag10 (⾳频) :00 00 96 00 值:150 00:00:00:150(显示时间)tag11 (视频) :00 00 A0 00 值:160 00:00:00:160(解码时间) CompositionTime:0x 00 00 00 值:00 00:00:00:00 b 帧 显示时间: 00:00:00: 160 poc=2tag12 (⾳频) :00 00 AD 00 值:173 00:00:00:173(显示时间)tag13 (⾳频) :00 00 C4 00 值:196 00:00:00:196(显示时间)tag14(视频) :00 00 C8 00 值:200 00:00:00:200(解码时间) CompositionTime:0x 00 00 28 值:40 00:00:00:40 b 帧 显示时间: 00:00:00: 240 poc=4 我们可以看到 每个视频 tag 相差约 40ms 刚好是 25fps 视频 每帧视频的播放时⻓在上例中,我们会看到按照解码时间排列编码顺序 I P P B B B......对应帧号 0 1 5 3 2 4.......

tag data

Tag Data : Audio Data

1-1:音频头【AudioTagHeader】


--1-4bit,音频格式【SoundFormat】


----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 , reserved


----8 = G.711 mu-law logarithmic PCM , reserved


----9 = reserved


----10 = AAC (supported in Flash Player 9,0,115,0 and higher)


----11 = Speex (supported in Flash Player 10 and higher)


----14 = MP3 8 kHz , reserved


----15 = Device-specific sound , reserved


--5-6bit,采样率【SoundRate】


----0 = 5.5kHz


----1 = 11kHz


----2 = 22kHz


----3 = 44kHz


--7-7bit,位宽,0 = 8bit samples, 1= 16bit samples【SoundSize】


----8-8bit,通道,0 = Mono, 1 = Stereo【SoundType】


[2-2]:AAC 音频类型,注,只有在 SoundFormat=AAC 时,才有此数据


--0 = AAC sequence header


--1 = AAC raw


x-x:音频数据


注:SoundFormat


如果 SoundFormat=10 即 AAC 格式,官方建议使用 44.1kHz 采样率和双声道,即 SoundType=1,SoundRate=3;Flash Player 会忽略这两个参数,并从音频比特流中解析获得。


如果 SoundFormat=11 即 Speex 格式,音频使用压缩的 16kHz 采样率的单声道,各参数取值为 SoundRate=0,SoundSize=1,SoundType=0。

Tag Data : Video Data

1-1:视频头【VideoTagHeader】


--1-4bit,帧类型【FrameType】


----1 = key frame (for AVC, a seekable frame)


----2 = inter frame (for AVC, a non-seekable frame)


----3 = disposable inter frame (H.263 only)


----4 = generated key frame (reserved for server use only)


----5 = video info/command frame


--5-8bit,编码类型【CodecID】


----2 = Sorenson H.263


----3 = Screen video


----4 = On2 VP6


----5 = On2 VP6 with alpha channel


----6 = Screen video version 2


----7 = AVC(H.264)


[2-5]:H.264 视频类型,注,只有在 CodecID=AVC 时,才有此数据 AVCPacketType


CompositionTime (ISO 14496-12, 8.15.3)


x-x:视频数据

Tag Data : Script Data

1-1:格式类型【Type】


--0 = Number【DOUBLE】


--1 = Boolean【UI8】


--2 = String【SCRIPTDATASTRING】


--3 = Object【SCRIPTDATAOBJECT】


--4 = MovieClip (reserved, not supported)


--5 = Null


--6 = Undefined


--7 = Reference【UI16】


--8 = ECMA array【SCRIPTDATAECMAARRAY】


--9 = Object end marker


--10 = Strict array【SCRIPTDATASTRICTARRAY】


--11 = Date【SCRIPTDATADATE】


--12 = Long string【SCRIPTDATALONGSTRING】


x-x:

flv 视频层次结构,h264 视频数据作为参考。

第一层:flv:⼀个⽂件头(file header)和 ⽂件体(file Body)。


第二层:flv body:多个(Previous Tag Size 字段 + tag)。


第三层:tag(video):tag header+tag data。


第四层:tag data:1 字节的参数信息+AVC VIDEO PACKET。—— 注,只有在 CodecID=AVC 时,才有第五层,否则没有第五层。


第五层:AVC VIDEO PACKET:4 字节的视频类型+视频数据。


第六层:视频数据。

flv 音频层次结构,aac 数据作为参考。

第一层:flv:⼀个⽂件头(file header)和 ⽂件体(file Body)。


第二层:flv body:多个(Previous Tag Size 字段 + tag)。


第三层:tag(audio):tag header+tag data。


第四层:tag data:1 字节的参数信息+AAC AUDIO PACKET。—— 注,只有在 SoundFormat=AAC 时,才有第五层,否则没有第五层。


第五层:AAC AUDIO PACKET:1 字节的音频类型+音频数据。


第六层:音频数据。

发布于: 刚刚阅读数: 6
用户头像

公众号:福大大架构师每日一题 2021-02-15 加入

公众号:福大大架构师每日一题

评论

发布
暂无评论
音视频八股文(9)-- flv的h264六层结构和aac六层结构_音视频_福大大架构师每日一题_InfoQ写作社区