音視頻學(xué)習(xí)基礎(chǔ):FLV封裝格式介紹及解析
FLV封裝格式
FLV(Flash Video)是Adobe公司推出的一種流媒體格式,由于其封裝后的音視頻文件體積小、封裝簡單等特點(diǎn),非常適合于互聯(lián)網(wǎng)上使用。目前主流的視頻網(wǎng)站基本都支持FLV。采用FLV格式封裝的文件后綴為.flv。
FLV封裝格式是由一個(gè)文件頭(flie header)和 文件體(file Body)組成。其中,F(xiàn)LV body由一對對的(Previous Tag Size字段 + tag)組成。Previous Tag Size字段 排列在Tag之前,占用4個(gè)字節(jié)。Previous Tag Size記錄了前面一個(gè)Tag的大小,用于逆向讀取處理。FLV header后的第一個(gè)Pervious Tag Size的值為0。Tag一般可以分為3種類型:腳本(幀)數(shù)據(jù)類型、音頻數(shù)據(jù)類型、視頻數(shù)據(jù)。FLV數(shù)據(jù)以大端序進(jìn)行存儲(chǔ),在解析時(shí)需要注意。一個(gè)標(biāo)準(zhǔn)FLV文件結(jié)構(gòu)如下圖:

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

FLV文件詳細(xì)內(nèi)容結(jié)構(gòu)
FLV header
注:在下面的數(shù)據(jù)type中,UI表示無符號(hào)整形,后面跟的數(shù)字表示其長度是多少位。比如UI8,表示無法整形,長度一個(gè)字節(jié)。UI24是三個(gè)字節(jié),UI[8*n]表示多個(gè)字節(jié)。UB表示位域,UB5表示一個(gè)字節(jié)的5位??梢詤⒖糲中的位域結(jié)構(gòu)體。
FLV頭占9個(gè)字節(jié),用來標(biāo)識(shí)文件為FLV類型,以及后續(xù)存儲(chǔ)的音視頻流。一個(gè)FLV文件,每種類型的tag都屬于一個(gè)流,也就是一個(gè)flv文件最多只有一個(gè)音頻流,一個(gè)視頻流,不存在多個(gè)獨(dú)立的音視頻流在一個(gè)文件的情況。FLV頭的結(jié)構(gòu)如下:

FLV Body
FLV Header之后,就是FLV File Body.FLV File Body是由一連串的back-pointers + tags構(gòu)成。Back-pointer表示Previous Tag Size(前一個(gè)tag的字節(jié)數(shù)據(jù)長度),占4個(gè)字節(jié)。

FLV Tag
每一個(gè)Tag也是由兩部分組成:tag header 和 tag data。Tag Header里存放的是當(dāng)前tag的類型、數(shù)據(jù)區(qū)(tag data)的長度等信息。tag header一般占11個(gè)字節(jié)的內(nèi)存空間。FLV tag結(jié)構(gòu)如下:

FLV Tag的類型可以是視頻、音頻和Script(腳本類型),下面分別介紹這三種Tag類型
Script Tag Data結(jié)構(gòu)(腳本類型、幀類型)
該類型Tag又被稱為MetaData Tag,存放一些關(guān)于FLV視頻和音頻的元信息,比如:duration、width、height等。通常該類型Tag會(huì)作為FLV文件的第一個(gè)tag,并且只有一個(gè),跟在File Header后。該類型Tag DaTa的結(jié)構(gòu)如下所示:

第一個(gè)AMF包:
第1個(gè)字節(jié)表示AMF包類型,一般總是0x02,表示字符串。第2-3個(gè)字節(jié)為UI16類型值,標(biāo)識(shí)字符串的長度,一般總是0x000A(“onMetaData”長度)。后面字節(jié)為具體的字符串,一般總為“onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。
第二個(gè)AMF包:
第1個(gè)字節(jié)表示AMF包類型,一般總是0x08,表示數(shù)組。第2-5個(gè)字節(jié)為UI32類型值,表示數(shù)組元素的個(gè)數(shù)。后面即為各數(shù)組元素的封裝,數(shù)組元素為元素名稱和值組成的對。常見的數(shù)組元素如下表所示。

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

Audio Tag Data結(jié)構(gòu)
第一個(gè)字節(jié)為音頻的信息,格式如下:

格式3,linear PCM,存儲(chǔ)原始PCM采樣點(diǎn)。如果采樣位深為8,采樣點(diǎn)數(shù)據(jù)為無符號(hào)型。如果采樣位深為16,采樣點(diǎn)數(shù)據(jù)為小端存儲(chǔ)的帶符號(hào)型。如果是立體聲,左右聲道采樣點(diǎn)交織存放:左-右-左-右-...
格式0與格式3的不同之處只有一點(diǎn):格式0存儲(chǔ)16位采樣數(shù)據(jù),采用的大小端順序是創(chuàng)建FLV文件的平臺(tái)所使用的大小端順序。因此,不應(yīng)使用格式0,而應(yīng)使用格式3。
格式 4 (Nellymoser 16-kHz mono) 和格式 5 (Nellymoser 8 kHz mono),是兩種特殊情況, 因?yàn)椴蓸勇首侄螣o法表示 8 kHz 和 16 kHz。當(dāng)采樣格式是格式 4 或格式 5 時(shí),F(xiàn)lash 播放器會(huì)忽略采樣率和聲音類型兩個(gè)字段。對于其他采樣率的 Nellymoser 格式, 即格式 6,則正常使用采樣率和聲音類型兩個(gè)字段。
格式10,AAC,聲音類型應(yīng)為1 (立體聲)且采樣率應(yīng)為3 (44 kHz)。這并不表示FLV中的AAC音頻總是立體聲、44 kHz的數(shù)據(jù)。實(shí)際上,F(xiàn)lash播放器會(huì)忽略這兩個(gè)值,而從已編碼的AAC位流中提取出聲道數(shù)和采樣率信息。
格式11,Speex,音頻以16 kHz采樣率壓縮為單聲道,采樣率字段值應(yīng)為0,采樣位深字段值應(yīng)為1,聲音類型字段值應(yīng)為0。
格式 7,8,14 和 15 保留。
第二個(gè)字節(jié)開始為音頻數(shù)據(jù)。

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

video Tag Data結(jié)構(gòu)

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

AVC VIDEO PACKET
關(guān)于下面這塊內(nèi)容有興趣的話可以結(jié)合h264結(jié)構(gòu)來看,不感興趣的話可以直接跳過。
AVC VIDEO PACKET的結(jié)構(gòu):

關(guān)于CTS:這是一個(gè)比較難以理解的概念,需要和pts,dts配合一起理解。
首先,pts(presentation time stamps),dts(decoder timestamps),cts(CompositionTime)的概念:
pts:顯示時(shí)間,也就是接收方在顯示器顯示這幀的時(shí)間。單位為1/90000 秒。
dts:解碼時(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是沒有這個(gè)問題的,baseline的pts和dts一直相同,所以cts一直為0。
AVC VIDEO PACKET中Data的結(jié)構(gòu):

FFmpeg/WebRTC/RTMP/NDK/Android音視頻流媒體高級(jí)開發(fā) 系統(tǒng)性視頻學(xué)習(xí)
面試題、學(xué)習(xí)資料、教學(xué)視頻和學(xué)習(xí)路線圖,免費(fèi)分享有需要的可以自行添加學(xué)習(xí)交流群973961276
