【流媒体FLV封装协议】
?
FLV封裝格式介紹及解析
FLV封裝格式
FLV(Flash Video)是Adobe公司推出的一種流媒體格式,由于其封裝后的音視頻文件體積小、封裝簡(jiǎn)單等特點(diǎn),非常適合于互聯(lián)網(wǎng)上使用。目前主流的視頻網(wǎng)站基本都支持FLV。采用FLV格式封裝的文件后綴為.flv。
FLV封裝格式是由一個(gè)文件頭(flie header)和 文件體(file Body)組成。其中,FLV body由一對(duì)對(duì)的(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ù)字表示其長(zhǎng)度是多少位。比如UI8,表示無法整形,長(zhǎng)度一個(gè)字節(jié)。UI24是三個(gè)字節(jié),UI[8*n]表示多個(gè)字節(jié)。UB表示位域,UB5表示一個(gè)字節(jié)的5位。可以參考c中的位域結(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ù)長(zhǎng)度),占4個(gè)字節(jié)。
?
FLV Tag
每一個(gè)Tag也是由兩部分組成:tag header 和 tag data。Tag Header里存放的是當(dāng)前tag的類型、數(shù)據(jù)區(qū)(tag data)的長(zhǎng)度等信息。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í)字符串的長(zhǎng)度,一般總是0x000A(“onMetaData”長(zhǎng)度)。后面字節(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ù)組元素為元素名稱和值組成的對(duì)。常見的數(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í),Flash?播放器會(huì)忽略采樣率和聲音類型兩個(gè)字段。對(duì)于其他采樣率的?Nellymoser?格式,?即格式?6,則正常使用采樣率和聲音類型兩個(gè)字段。
格式?10,AAC,聲音類型應(yīng)為?1 (立體聲)?且采樣率應(yīng)為?3 (44 kHz)。這并不表示?FLV?中的?AAC?音頻總是立體聲、44 kHz的數(shù)據(jù)。實(shí)際上,Flash?播放器會(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):
參考
https://www.jianshu.com/p/419f99be3989
https://www.cnblogs.com/leisure_chn/p/10662941.html
https://blog.csdn.net/leixiaohua1020/article/details/17934487
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的【流媒体FLV封装协议】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux的驱动在哪个文件里(linux
- 下一篇: FFmpeg NDK跨平台交叉编译