FLV 封裝格式解析

FLV 簡(jiǎn)介

FLV(Flash Video) 是 Adobe 公司推出的一種流媒體格式,由于其封裝后的音視頻文件體積小、封裝簡(jiǎn)單等特點(diǎn),非常適合于互聯(lián)網(wǎng)上使用。目前主流的視頻網(wǎng)站基本都支持FLV。采用 FLV 格式封裝的文件后綴為.flv。直播場(chǎng)景下拉流比較常見(jiàn)的是 http-flv 直播流,具有延時(shí)低,易傳輸?shù)忍攸c(diǎn)。

FLV 格式

總體上看,F(xiàn)LV 由文件頭(file header)和(file body)組成,其中 FLV body 由一對(duì)對(duì)的 Tag 和 Previous Tag Size(占用4個(gè)字節(jié),記錄前一個(gè) Tag 的大小,用于逆向讀取處理,F(xiàn)LV header 后的第一個(gè) Previous Tag Size 為 0)組成。而 Tag 一般分為三種類型:腳本數(shù)據(jù)、視頻數(shù)據(jù)、音頻數(shù)據(jù),有 Tag header 和 Tag Data 組成。FLV 數(shù)據(jù)以大端序進(jìn)行存儲(chǔ),在解析時(shí)需要注意。一個(gè)標(biāo)準(zhǔn) FLV 文件結(jié)構(gòu)如下圖:

FLV 文件的詳細(xì)內(nèi)容結(jié)構(gòu)如下:

FLV header(文件頭)

從上圖中可以看到,F(xiàn)LV 頭占用 9 個(gè)字節(jié),用來(lái)標(biāo)識(shí)文件類型為 FLV 類型,以及后續(xù)的音視頻標(biāo)識(shí)。一個(gè) FLV 文件,每種類型的 tag 都屬于一個(gè)流,也就是一個(gè) flv 文件最多只有一個(gè)音頻流,一個(gè)視頻流,不存在多個(gè)獨(dú)立的音視頻流在一個(gè)文件的情況。FLV 頭的結(jié)構(gòu)如下:

上面的 UI 表示無(wú)符號(hào)整型,后面跟著的數(shù)字代表其長(zhǎng)度是多少位;UB 表示位域,表示一個(gè)字節(jié)的多少位??梢詤⒖糃語(yǔ)言中的結(jié)構(gòu)體位域。

FLV Body(文件體)

FLV Header之后,就是 FLV File Body。FLV File Body 是由一連串的 back-pointers + tags 構(gòu)成。

back-pointer

back-pointer 表示 Previous Tag Size(前一個(gè) tag 的字節(jié)數(shù)據(jù)長(zhǎng)度),占4個(gè)字節(jié),第一個(gè) back-pointer 數(shù)據(jù)為0。

Tag

音視頻數(shù)據(jù),每一個(gè) tag 由兩部分組成:tag header 和 tag data。

FLV Tag 詳解

Tag 數(shù)據(jù)結(jié)構(gòu)

flv_tag_header + flv_tag_data,其中 flv_tag_header 占 11 個(gè)字節(jié)。

FLV_tag_header

存放當(dāng)前 tag 的類型、數(shù)據(jù)區(qū)長(zhǎng)度、時(shí)間戳等信息。tag header 一般占 11 個(gè)字節(jié)的內(nèi)粗空間。

FLV_Tag_Data

FLV Tag 的類型可以是視頻、音頻和 Script(腳本類型)

Script Tag Data(腳本類型、幀類型)

腳本 Tag 一般只有一個(gè),是 flv 的第一個(gè) Tag,跟在 flv header 后,用于存放 flv 視頻和音頻的元信息,比如 duration、audiodatarate、creator、width 等。一般來(lái)說(shuō),Script Tag Data結(jié)構(gòu)包含兩個(gè) AMF 包(AMF(Action Message Format)是 Adobe 設(shè)計(jì)的一種通用數(shù)據(jù)封裝格式,在 Adobe 的很多產(chǎn)品中應(yīng)用,簡(jiǎn)單來(lái)說(shuō),AMF 將不同類型的數(shù)據(jù)用統(tǒng)一的格式來(lái)描述),結(jié)構(gòu)如下:

第一個(gè) AMF 包(封裝字符串類型數(shù)據(jù)):

第 1 個(gè)字節(jié)表示 AMF 包類型,一般總是 0x02,表示字符串;
第 2-3 個(gè)字節(jié)為 UI16 類型值,表示字符串的長(zhǎng)度,一般總是 0x000A(“onMetaData”長(zhǎng)度);
后面字節(jié)為字符串?dāng)?shù)據(jù),一般總為 “onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。

第二個(gè) AMF 包(封裝一個(gè)數(shù)組類型,這個(gè)數(shù)組中包含了音視頻信息項(xiàng)的名稱和值):

第 1 個(gè)字節(jié)表示 AMF 包類型,一般總是 0x08,表示數(shù)組。
第 2-5 個(gè)字節(jié)為 UI32 類型值,表示數(shù)組元素的個(gè)數(shù)。
后面即為各數(shù)組元素的封裝,數(shù)組元素為元素名稱和值組成的對(duì)。表示方法如下:
第 1-2 個(gè)字節(jié)表示元素名稱的長(zhǎng)度,假設(shè)為 L。后面跟著為長(zhǎng)度為 L 的字符串。第 L+3 個(gè)字節(jié)表示元素值的類型。后面跟著為對(duì)應(yīng)值,占用字節(jié)數(shù)取決于值的類型。

常見(jiàn)的數(shù)組元素表示如下表:

Video Tag Data(視頻類型)

視頻 Tag Data 開(kāi)始的第一個(gè)字節(jié)包含視頻數(shù)據(jù)的參數(shù)信息,從第二個(gè)字節(jié)開(kāi)始為視頻流數(shù)據(jù)。結(jié)構(gòu)如下:

第一個(gè)字節(jié)包含視頻信息:前4位表示幀類型;后4位表示編碼類型。

第二個(gè)字節(jié)開(kāi)始為視頻數(shù)據(jù)

AVC VIDEO PACKET

視頻的格式(CodecID)是 AVC(H.264)的話,VideoTagHeader 會(huì)多出 4 個(gè)字節(jié)的信息,AVCPacketType 和 CompositionTime,所以是 H264 編碼的情況下 VideoHeader 長(zhǎng)度是 5 個(gè)字節(jié)。 AVC VIDEO PACKET 結(jié)構(gòu)如下:

AVCDecoderConfigurationRecord

包含著 H.264 解碼相關(guān)比較重要的 sps 和 pps 信息,再給 AVC 解碼器送數(shù)據(jù)流之前一定要把 sps 和 pps 信息送出,否則的話解碼器不能正常解碼。
而且在解碼器 stop 之后再次 start 之前,如 seek、快進(jìn)快退狀態(tài)切換等,都需要重新送一遍 sps 和 pps 的信息。
AVCDecoderConfigurationRecord 在 FLV 文件中一般情況也是出現(xiàn) 1 次,也就是第一個(gè) video tag。

sps pps

第一個(gè) video tag 一般存放的是 sps 和 pps。存儲(chǔ)的格式:
0x01 + sps[1] + sps[2] + sps[3] + 0xFF + 0xE1 + sps size + sps + 01 + pps size + pps
其中 sps size 和 pps siz e各占兩個(gè)字節(jié)。
data 數(shù)據(jù)結(jié)構(gòu):

關(guān)于 CTS:需要和 pts,dts 配合一起理解。
pts:presentation time stamps 顯示時(shí)間,也就是接收方在顯示器顯示這幀的時(shí)間。單位為1/90000 秒;
dts:decoder timestamps 解碼時(shí)間,也就是rtp包中傳輸?shù)臅r(shí)間戳,表明解碼的順序。單位為1/90000 秒?!鶕?jù)后面的理解,pts 就是標(biāo)準(zhǔn)中的 CompositionTime;
cts偏移:cts = (pts - dts) / 90。cts 的單位是毫秒;
pts 和 dts 的時(shí)間不一樣,應(yīng)該只出現(xiàn)在含有 B 幀的情況下,也就是 profile main 以上。baseline 是沒(méi)有這個(gè)問(wèn)題的,baseline 的 pts 和 dts 一直相同,所以 cts 一直為 0 。

Audio Tag Data(音頻類型)

音頻 Tag Data 區(qū)域開(kāi)始的第一個(gè)字節(jié)包含了音頻數(shù)據(jù)的參數(shù)信息,從第二個(gè)字節(jié)開(kāi)始為音頻流數(shù)據(jù)。結(jié)構(gòu)如下:

第一個(gè)字節(jié)包含音頻信息:前 4bit 表示音頻格式;第 5、6bit 表示采樣率;第 7bit 表示采樣精度;第 8bit 表示音頻聲道。

第二個(gè)字節(jié)開(kāi)始為音頻數(shù)據(jù)

其中如果音頻格式為 10,即是 AAC 格式的,AudioTagHeader 中會(huì)多出一個(gè)字節(jié) AACPacketType,這個(gè)字段來(lái)表示 AACAUDIODATA 的類型:0 = AAC sequence header,1 = AAC raw。

  • AAC sequence header 也就是包含了 AudioSpecificConfig,AudioSpecificConfig 包含著一些更加詳細(xì)音頻的信息。
  • AAC raw 這種包含的就是音頻 ES 流了,也就是 audio payload。

舉例子

根據(jù)真實(shí)數(shù)據(jù)來(lái)解析 FLV 格式。

FLV header

<464c5601 05000000 09000000 00120001 17000000 00000000 02000a6f 
6e4d6574 61446174 61030005 77696474 68004084 00000000 00000006 
68656967 68740040 7e000000 00000000 0c736f75 7263655f 77696474 
6800409e 00000000 0000000d 736f7572 63655f68 65696768 74004090 
e0000000 00000009 6672616d 65726174 6500402e 00000000 0000000c 
76696465 6f636f64 65636964 00401c00 00000000 00000f61 7564696f 
73616d70 6c657261 74650040 bf400000 00000000 0f617564 696f7361 
6d706c65 73697a65 00403000 00000000 00000673 74657265 6f010000 
0c617564 696f636f 64656369 64004024 00000000 0000000c 63726561 
74696f6e 64617465 02001732 3032312d 31312d30 33203037 3a32373a 
33302055 54430006 61757468 6f720200 034c4c4c 00000900 000122>

46 4C 56 01 05 00 00 00 09:表示 FLV header(9 字節(jié)),音視頻都有;
0x 00 00 00 00 表示第一個(gè) back-pointers(前一個(gè) tag 的 size)。因?yàn)榍懊鏇](méi)有 tag,所以為 0。

腳本 Tag

12 00 01 17 00 00 00 00 00 00 00 (tag header 11 字節(jié))
0x12 表示這是一個(gè) scripts tag, 00 01 17 三子節(jié)表示 tag data 長(zhǎng)度為 279 個(gè)字節(jié),Timestreamp、TimestampExtended、stream id 均為0。
下一個(gè) back-pointers,表示該 scripts tag 的 size,即 279 + 11 = 290 = 0x122,即 00 00 01 22,可以看到最后4字節(jié)剛好是的。
02 00 0a 6f 6e 4d 65 74 61 44 61 74 61 表示第一個(gè) AMF 包,02 表示類型為 string type,后面兩個(gè)字節(jié) 00 0A 表示長(zhǎng)度是 10,值 onMetaData;
03
表示 ObjectType,此處應(yīng)該一般是 08 才對(duì),表示數(shù)組類型;表示有8個(gè)鍵值對(duì)。
00 05 表示鍵長(zhǎng)度,77 69 64 74 68 表示 width,00 表示類型為 Number,后面 8 字節(jié)表示值;
00 06 表示鍵長(zhǎng)度, 68 65 69 67 68 74 表示 height,00 表示類型為 Number,后面 8 字節(jié)表示值。
以此類推解析到最后 end marker 00 00 09,表示解析完畢。

第一個(gè) video tag

一般包含 sps、pps

<09000022 00000000 00000017 00000000 014d401e ffe1000e 674d401e 
a680a03d a6e02020 20400100 0468ee3c 80000000 2d>

09 00 00 22 00 00 00 00 00(tag header 11 字節(jié))
09 表示視頻 tag;
00 00 22 表示長(zhǎng)度為 0x22 = 34,加上頭部長(zhǎng)度 11 字節(jié),為 45。下一個(gè) back-pointers 是 00 00 00 2D(上面數(shù)據(jù)的最后的四字節(jié)), Timestreamp、TimestampExtended、stream id 均為 0;
下面就是 tag data 數(shù)據(jù):
0x17 即 0001 0111,前 4 位表示幀類型,1 為關(guān)鍵幀;后 4 位表示編碼 ID,7 表示 AVC。
視頻格式是AVC(H.264)類型的話,后面 1 個(gè)字節(jié)表示 AVCPacketType,再后三個(gè)字節(jié)表示 CompositionTime:
00
AVCPacketType 為 0,表示是 AVCDecoderConfigurationRecord。就表示包含著 sps 和 pps 了。這個(gè)東西要第一個(gè)發(fā)給解碼器,要不然不能正常解碼。
00 00 00
CompositionTime 為 0。接下來(lái)就是 sps 和 pps 的信息了。
按照 0x01 + sps[1] + sps[2] + sps[3] + 0xFF + 0xE1 + sps size + sps + 01 + pps size + pps 的格式,參照二進(jìn)制數(shù)據(jù):
sps[1] = 4d;sps[2] = 40;sps[3] = 1e;sps size = 000e,表示 sps 的長(zhǎng)度為 14,14 字節(jié)的數(shù)據(jù)讀取完,讀到 01;pps size = 0004,表示 pps 的長(zhǎng)度為 4,讀取完后該 tag 結(jié)束。下一個(gè)back-pointers。

第二個(gè) video tag 以及后續(xù)的 video tag
<09002374 00000000 00000017 01000000 0000236b 65b82129 7f7ae073 
74574ffe 0fd1ebcc 6851014a d25aa986 6daee3a1 6f0d7b77 734e17a9 
0fe00e56 a92b864b 3d423839 c229a2ab 23208467 ... ...00 00237f>

下一個(gè) video 長(zhǎng)度為 9076 的視頻數(shù)據(jù),0x17 后一位 AVCPacketType 01,表示 NALU 數(shù)據(jù),三個(gè) CompositionTime 字節(jié)過(guò)后,就是 NALU 數(shù)據(jù)了。

第一個(gè) audio tag 以及后續(xù)的 audio tag

<08000004 00005d00 000000ae 00158800 00000f>

08 00 00 04 00 00 5d 00 00 00 00
0x08 表示音頻,00 00 04 表示長(zhǎng)度為 4,時(shí)間戳為 93;加上頭部長(zhǎng)度 11,為 15,下一個(gè) back-pointers 是
0x 00 00 00 0F(最后四子節(jié));接下來(lái)就是 tag data:
AE:
即 0b10101110,前 4 位為 10,表示音頻格式是 AAC;10 會(huì)多一個(gè)字節(jié) AACPacketType,表示該 AACAUDIODATA 的類型;第 5、6 位為 11,十進(jìn)制 3,表示采樣率為 44kHz;第 7 位為1,表示 16 位采樣精度;第 8 位為 0,表示 sndMono 單聲道。
00:
表示 AACPacketType,為 0 表示該 Tag 是 AAC sequence header。接下來(lái)兩個(gè)字節(jié)表示 AudioSpecificConfig,包含更加詳細(xì)音頻的信息。讀取完后該 tag 結(jié)束。下一個(gè) back-pointers。

第二個(gè) audio tag 以及后續(xù)的 audio tag
<080002fb 00005d00 000000ae 01010e34 14564a2d 92154484 d0602e72 
f7cab6d6 af82156c cae24cba a6f8d2b9 d2d512d3 db8b5632 ef76c8a9 
95225c3b 69e84d7d 03a6fa66 7b475759 0ead71f5 37c73379 fd124cd5 
1ba64d95 48d7aa3b c558863e 090fc9ae ... ...0000 0306>

下一個(gè)長(zhǎng)度為 752 的音頻數(shù)據(jù),時(shí)間戳為 93,0xae 后一位為 01,表示 ACC raw,即音頻 NALU 數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、簡(jiǎn)介 FLV(Flash Video)是現(xiàn)在非常流行的流媒體格式,由于其視頻文件體積輕巧、封裝播放簡(jiǎn)單等特點(diǎn),...
    Magic11閱讀 232評(píng)論 0 0
  • 簡(jiǎn)介 FLV(Flash Video)是現(xiàn)在非常流行的流媒體格式,由于其視頻文件體積輕巧、封裝播放簡(jiǎn)單等特點(diǎn),使其...
    輕口味閱讀 1,208評(píng)論 0 0
  • FLV封裝格式 FLV(Flash Video)是Adobe公司推出的一種流媒體格式,由于其封裝后的音視頻文件體積...
    _zzbb閱讀 8,570評(píng)論 3 11
  • 簡(jiǎn)介 FLV(Flash Video)是現(xiàn)在非常流行的流媒體格式,由于其視頻文件體積輕巧、封裝播放簡(jiǎn)單等特點(diǎn),使其...
    第八區(qū)閱讀 23,179評(píng)論 23 33
  • 了解FLV格式的基礎(chǔ)可以參照https://wuyuans.com/2012/08/flv-format/前兩篇文...
    心有琳鑫閱讀 1,097評(píng)論 0 3

友情鏈接更多精彩內(nèi)容