FLV視頻封裝格式詳細(xì)解析

FLV的定義:

Flash Video(簡稱FLV),是一種流行的網(wǎng)絡(luò)格式怕品,是Adobe推出的妇垢。目前大部分視頻網(wǎng)站都支持這種格式。

FLV的文件結(jié)構(gòu)

FLV文件由FLV Header 和 FLV Body構(gòu)成肉康。

FLV Header 頭部信息

Header 部分記錄了FLV的類型闯估、版本、流信息吼和、Header 長度等涨薪。一般整個(gè)Header占用9個(gè)字節(jié),大于9個(gè)字節(jié)則表示頭部信息在這基礎(chǔ)之上還存在擴(kuò)展數(shù)據(jù)炫乓。Header 的頭部信息排布如下所示:


FLV頭部信息排布

FLV Body 文件內(nèi)容部分

Body 是由一個(gè)個(gè)Tag組成的刚夺,每個(gè)Tag下面有一塊4個(gè)字節(jié)的空間,用來記錄這個(gè)Tag 的長度末捣。這個(gè)后置的PreviousTagSize用于逆向讀取處理侠姑,表示的是前面的Tag的大小,對(duì)于FLV版本0x01來說箩做,數(shù)值等于 11 + Tag的DataSize莽红。其結(jié)構(gòu)排布如下:


FLV Body結(jié)構(gòu)排布

FLV Tag

每個(gè)Tag 也是由兩部分組成的:Tag Header 和 Tag Data。Tag Header 存放了當(dāng)前Tag的類型卒茬,數(shù)據(jù)長度船老、時(shí)間戳咖熟、時(shí)間戳擴(kuò)展、StreamsID等信息柳畔,然后再接著數(shù)據(jù)區(qū)Tag Data馍管。Tag的排布如下:


Tag構(gòu)成排布

Tag Data

Tag Data分成 Audio,Video薪韩,Script 三種确沸。

Audio Tag Data

音頻的Tag Data又分為 AudioTagHeader 和 Data 數(shù)據(jù)區(qū),其排布結(jié)構(gòu)如下圖所示:


音頻Tag Data排布

AudioTagHeader通常占用1個(gè)字節(jié)俘陷,AAC編碼則會(huì)多出一個(gè)AACPacketType的字節(jié)罗捎,用于表示AAC的序列頭還是裸數(shù)據(jù)。
其中拉盾,前4bits表示SoundFormat桨菜,其數(shù)值對(duì)應(yīng)聲音格式,如下:
0 - Linear PCM, platform endian
1 - ADPCM
2 - MP3
3 - LinearPCM捉偏,little endian
4 - Nellymoser 16-kHz mono
5 - Nellymoser 8-kHZ mono
6 - Nellymoser
7 - G.711 A-law logarithmic PCM
8 - G.711 U-law logarithmic PCM
9 - reserved
10 - AAC
11 - Speex
14 - MP3 8-kHz
15 - Device-specific sound

第5倒得、6bit 表示SoundRate,數(shù)值對(duì)應(yīng)采樣率夭禽,對(duì)于AAC來說霞掺,總是3:
0 - 5.5kHz
1 - 11kHz
2 - 22kHz
3 - 44kHz

第7bit 表示采樣大小:
0 - snd 8 bit
1 - snd 16 bit

第8bit 表示音頻聲道數(shù)讹躯,對(duì)于AAC來說菩彬,總是1:
0 - sndMono
1 - sndStereo

audio Data數(shù)據(jù)區(qū),根據(jù)SoundFormat的數(shù)值來確定潮梯,如果SoundFormat = 10骗灶,則Data數(shù)據(jù)區(qū)是AAC編碼部分,其他聲音類型酷麦,則根據(jù)具體格式進(jìn)行解析矿卑。

AAC編碼

針對(duì)AAC編碼喉恋,音頻Data數(shù)據(jù)區(qū)的定義如下:
AACPacketType = 0 時(shí)沃饶,表示AAC序列頭,也就是AudioSpecificConfig轻黑, AACPacketType = 1 時(shí)糊肤,表示AAC的裸流,也就是AAC Raw frame data氓鄙。

AudioSpecificConfig

AudioSpecificConfig 只出現(xiàn)在第一個(gè)Audio Tag中馆揉,結(jié)構(gòu)如下,

AudioSpecificConfig() {     
    audioObjectType;                              5bits
    samplingFrequencyIndex;                 4bits
    if  ( samplingFrequencyIndex == 0xf ) {
        samplingFrequency;                         24bits
    }
    channelConfiguration;                           4bits
    sbrPresentFlag = -1;
    if  ( audioObjectType == 5 ) {
        extensionAudioObjectType = audioObjectType;
        sbrPresentFlag = 1;
        extensionSamplingFrequencyIndex;            4bits
        if ( extensionSamplingFrequencyIndex == 0xf )  {
            extensionSamplingFrequency;             24bits
        }
        audioObjectType;                            5bits
    } else {
         extensionAudioObjectType = 0;
    }
    
    if ( audioObjectType == 1 || audioObjectType == 2 ||
         audioObjectType == 3 || audioObjectType == 4 ||
         audioObjectType == 6 || audioObjectType == 7 ) {
        GASpecificConfig();
    }
    if ( audioObjectType == 8 )  {
        CelpSpecificConfig();
    }
    if ( audioObjectType == 9 ) {
        HvxcSpecificConfig();
    }
    if ( audioObjectType == 12 ) {
        TTSSpecificConfig();
    }
    if ( audioObjectType == 13 || audioObjectType == 14 ||
        audioObjectType == 15 || audioObjectType == 16 ) {
        StructureAudioSpecificConfig();
    }
    if ( audioObjectType == 17 || audioObjectType == 19 ||
        audioObjectType == 20 || audioObjectType == 21 ||
        audioObjectType == 22 || audioObjectType == 23 ) {
        GASpecificConfig();
    }
    if ( audioObjectType == 24 ) {
        ErrorResilientCelpSpecificConfig();
    }
    if ( audioObjectType == 25 ) {
        ErrorResilientHvxcSpecificConfig();
    }
    if ( audioObjectType == 26 || audioObjectType == 27 ) {
        ParametricSpecificConfig();
    }
    if ( audioObjectType == 17 || audioObjectType == 19 ||
        audioObjectType == 20 || audioObjectType == 21 ||
        audioObjectType == 22 || audioObjectType == 23 ||
        audioObjectType == 24 || audioObjectType == 25 ||
        audioObjectType == 26 || audioObjectType == 27 )  {
        epConfig;                                      2bits
        if ( epConfig == 2 || epConfig == 3 ) {
            ErrorProtectionSpecificConfig();
        }
        if ( epConfig == 3 ) {
            directMapping;                               1bit
            if ( ! directMapping ) {
              /* tbd */
            }
        }
    }
    if ( audioObjectType == 28 ) {
        SSCSpecificConfig();
    }
    if ( extensionAudioObjectType != 5 && bits_to_decode() >= 16 ) { 
        syncExtensionType;                                          11bits
        if ( syncExtensionType == 0x2b7 ) {
            extensionAudioObjectType;                                 5bits
            if ( extensionAudioObjectType == 5 ) {
                sbrPresentFlag;                                        1bit
                if ( sbrPresentFlag == 1 ) {
                    extensionSamplingFrequencyIndex;                     4bits
                    if ( extensionSamplingFrequencyIndex == 0xf ) {
                        extensionSamplingFrequency;                      24bits
                    }
                }
            }
        }
    }
}

AudioSpecificConfig 簡化格式如下:

audioObjectType               5bits    編碼結(jié)構(gòu)類型抖拦,AAC-LC為2
samplingFreguencyIndex        4bits    音頻采樣率索引值
channelConfiguration          4bits    音頻聲道數(shù)
GASpecificConfig
    frameLengthFlag           1bits    標(biāo)志位升酣,用于表明IMDCT窗口長度舷暮,為0
    dependsOnCoreCoder        1bits    標(biāo)志位,用于表明是否依賴corecoder噩茄,為0
    extensionFlag             1bits    擴(kuò)展標(biāo)志位下面,選擇了AAC-LC,這里必須為0

其中绩聘,samplingFreguencyIndex 對(duì)應(yīng)關(guān)系如下:

0 - 96000
1 - 88200
2 - 64000
3 - 48000
4 - 44100
5 - 32000
6 - 24000
7 - 22050
8 - 16000
9 - 12000
10 - 11025
11 - 8000
12 - 7350
13 - Reserved
14 - Reserved
15 - frequency is written explictly

AAC Raw frame data

AAC裸流AAC Raw frame data沥割,即AAC音頻原始數(shù)據(jù),不包括AAC頭數(shù)據(jù)ADTS凿菩。

AAC頭部數(shù)據(jù) ADTS

ADTS包括采樣頻率机杜、幀長度等信息,共7個(gè)字節(jié)衅谷,分為兩部分:
adts_fixed_header 椒拗、adts_variable_header

adts_fixed_header 排布如下:

adts_fixed_header() {
    syncword                  12bits    always 0xFFF
    ID                        1bit      0--MPEG-4   1--MPEG-2
    layer                     2bits     always '00'
    protection_absent         1bit
    profile                   2bits     0--Main profile     1--Low Complexity profile(LC) 
                                        2--Scalable Sampling Rate profile(SSR) 3--reserved
    sampling_frequency_index  4bits     音頻采樣率索引值
    private_bit               1bit
    channel_configuration     3bits     音頻聲道數(shù)
    original_copy             1bit
    home                      1bit
}

channel_configuration 對(duì)應(yīng)關(guān)系如下:

0 bit : Defined in AOT Specific Config
1 bit : 1 channel:front-center
2 bit : 2 channels:front-left,front-right  
3 bit : 3 channels:front-center获黔,front-left陡叠,front-right  
4 bit : 4 channels:front-center,front-left肢执,front-right枉阵,back-center
5 bit : 5 channels:front-center,front-left预茄,front-right兴溜,back-left,back-right  
6 bit : 6 channels:front-center耻陕,front-left拙徽,front-right,back-left诗宣,back-right膘怕,LFE-channel 
7 bit : 8 channels:front-center,front-left召庞,front-right岛心,side-left,side-right篮灼,back-left忘古,back-right,LFE-channel 
8-15 bit:Reserved

adts_variable_header排布如下:

adts_variable_header() {
    copyright_identification_bit        1bit
    copyright_identification_start      1bit
    aac_frame_length                    13bits  ADTS頭 + AAC原始流     
    adts_buffer_fullness                11bits  0x7FF表示碼率可變的碼流
    number_of_raw_data_blocks_in_frame  2bits 
}

MP3編碼

如果是MP3 編碼部分诅诱,audio 數(shù)據(jù)區(qū)直接為 MP3 頭 + MP3 原始數(shù)據(jù)髓堪。

MP3 頭部格式如下:

MP3FrameHeader
{
    sync                11bits  同步信息always 0xFFF     
    version             2bits   版本 00--MPEG 2.5  01--未定義 10--MPEG 2  11--MPEG 1    
    layer               2bits   層 00--未定義 01--Layer 3  10--Layer 2  11--Layer 1    
    error_protection    1bit    CRC校驗(yàn)0--校驗(yàn)  1--不校驗(yàn)    
    bitrate_index       4bits   位率 
    sampling_frequency  2bits   采樣率索引值   
    padding             1bit    幀長調(diào)節(jié)    
    private             1bit    保留字    
    mode                2bits   聲道模式    
    mode_extension      2bits   擴(kuò)充模式    
    copyright           1bit    版權(quán)     
    original            1bit    原版標(biāo)志    
    emphasis            2bits   強(qiáng)調(diào)模式 
}

sampling_frequency對(duì)應(yīng)關(guān)系如下:

version   00--MPEG 2.5    01--未定義  10--MPEG 2    11--MPEG 1 
MPEG 1:   00--44.1kHz     01--48kHz   10--32kHz     11--未定義 
MPEG 2:   00--22.05kHz    01--24kHz   10--16kHz     11--未定義 
MPEG 2.5: 00--11.025kHz   01--12kHz   10--8kHz      11--未定義

mode對(duì)應(yīng)關(guān)系如下:

00--立體聲Stereo   01--Joint Stereo   10--雙聲道   11--單聲道

Video Tag Data

如果Tag 包中的TagType = 9時(shí),這個(gè)Tag就表示video數(shù)據(jù)。則StreamID之后緊跟著 VideoTagHeader 和 Video Data 數(shù)據(jù)區(qū)干旁。
Video Tag 有一個(gè)字節(jié)的VideoTagHeader 和 Video數(shù)據(jù)區(qū)部分組成

VideoTagHeader

VideoTagHeader 通常由一個(gè)字節(jié)構(gòu)成驶沼,前4bit表示類型,后4bit表示編碼器Id争群。


VideoTagHeader

Video數(shù)據(jù)區(qū)

Video數(shù)據(jù)區(qū)部分格式不確定商乎。對(duì)于H264/AVC編碼部分,Video數(shù)據(jù)區(qū)排布如下:


Video數(shù)據(jù)區(qū)排布

其中祭阀,AVCsequenceheader只有出現(xiàn)在第一個(gè)Video Tag鹉戚,只有一個(gè)。為了能夠從FLV中獲取NALU专控,必須知道前面的NALU長度所占的字節(jié)數(shù)抹凳,通常是1、2伦腐、4個(gè)字節(jié)赢底,這個(gè)內(nèi)容則必須從AVCDecoderConfigurationRecord中獲取,這個(gè)遵從標(biāo)準(zhǔn)ISO/IEC 14496-15的5.2.4小節(jié)柏蘑。AVCDecoderConfigurationRecord 的結(jié)構(gòu)如下:

aligned(8) class AVCDecoderConfigurationRecord {
    unsigned int(8) configurationVersion = 1;  //版本號(hào)
    unsigned int(8) AVCProfileIndication;     //sps[1]幸冻,即0x67后面那個(gè)字節(jié)
    unsigned int(8) profile_compatibility;     //sps[2]
    unsigned int(8) AVCLevelIndication;      //sps[3]
    bit(6) reserved = '111111'b;
    unsigned int(2) lengthSizeMinusOne;     //NALUnitLength的長度減1,一般為3  
    bit(3) reserved = '111'b;
    unsigned int(5) numOfSequenceParameterSets;    //sps個(gè)數(shù)咳焚,一般為1
    for ( i=0; i<numOfSequenceParameterSets; i++ ) {
        unsigned int(16) sequenceParameterSetLength;  //sps的長度      
        bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
    }
    unsigned int(8) numOfPictureParameterSets;      //pps個(gè)數(shù)洽损,一般為1
    for ( i=0; i<numOfPictureParameterSets; i++) {
        unsigned int(16) pictureParameterSetLength;   //pps長度   
        bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
   }
}

其中,lengthSizeMinusOne + 1 = NALU長度字段所占字節(jié)數(shù)

Script Tag

當(dāng)TagType = 0x12時(shí)革半, 這個(gè)Tag就是Script tag碑定。Script Tag一般只有一個(gè),是FLV文件的第一個(gè)Tag又官,用于存放FLV文件信息延刘,比如時(shí)長、分辨率六敬、音頻采樣率等碘赖。所有的數(shù)據(jù)都是以數(shù)據(jù)類型 + (數(shù)據(jù)長度) + 數(shù)據(jù)格式出現(xiàn),數(shù)據(jù)類型占1個(gè)字節(jié)外构,數(shù)據(jù)長度看數(shù)據(jù)類型是否存在普泡,后面才是數(shù)據(jù)。數(shù)據(jù)排布如下:


ScriptTag排布

其中SCRIPTDATAOBJECTEND和SCRIPTDATAVARIABLEEND為0x000009典勇,用于標(biāo)記結(jié)尾

SCRIPTDATASTRING結(jié)構(gòu)為:

StringLength    2bytes  
StringData      String 

SCRIPTDATALONGSTRING結(jié)構(gòu)為:

StringLength  4bytes  
StringData    String  

ECMA array type結(jié)構(gòu)為:

ECMAArrayLength   4bytes 
StringLength      2bytes 
StringData        String 
DataType          1byte 
Data              不定長 
SCRIPTDATAVARIABLEEND  

Object type結(jié)構(gòu)為:

StringLength  2bytes 
StringData    String 
DataType      1byte  
DataVale      不定長 
SCRIPTDATAOBJECTEND  

Strict array type結(jié)構(gòu)為:

ArrayNum    4bytes 
DataType    byte 
DataValue   不定長

類型在FLV的官方文檔中有詳細(xì)的介紹劫哼。

onMeteData

onMeteData 是FLV文件中的第一個(gè)Tag,是ScriptData中對(duì)我們來說十分重要的信息割笙,結(jié)構(gòu)如下:


onMeteData結(jié)構(gòu)

audiocodecid

音頻編碼類型id,跟AudioTagHeader中的SoundFormat是對(duì)應(yīng)的。

videocodecid

視頻編碼類型id伤溉,跟VideoTagHeader 的 CodecID是對(duì)應(yīng)的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末般码,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子乱顾,更是在濱河造成了極大的恐慌板祝,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件走净,死亡現(xiàn)場(chǎng)離奇詭異券时,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伏伯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門橘洞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人说搅,你說我怎么就攤上這事炸枣。” “怎么了弄唧?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵适肠,是天一觀的道長。 經(jīng)常有香客問我候引,道長侯养,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任澄干,我火速辦了婚禮沸毁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘傻寂。我一直安慰自己息尺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布疾掰。 她就那樣靜靜地躺著搂誉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪静檬。 梳的紋絲不亂的頭發(fā)上炭懊,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音拂檩,去河邊找鬼侮腹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛稻励,可吹牛的內(nèi)容都是我干的父阻。 我是一名探鬼主播愈涩,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼加矛!你這毒婦竟也來了履婉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤斟览,失蹤者是張志新(化名)和其女友劉穎毁腿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苛茂,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡已烤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妓羊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胯究。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖侍瑟,靈堂內(nèi)的尸體忽然破棺而出唐片,到底是詐尸還是另有隱情,我是刑警寧澤涨颜,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布费韭,位于F島的核電站,受9級(jí)特大地震影響庭瑰,放射性物質(zhì)發(fā)生泄漏星持。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一弹灭、第九天 我趴在偏房一處隱蔽的房頂上張望督暂。 院中可真熱鬧,春花似錦穷吮、人聲如沸逻翁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽八回。三九已至,卻和暖如春驾诈,著一層夾襖步出監(jiān)牢的瞬間缠诅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來泰國打工乍迄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留管引,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓闯两,卻偏偏與公主長得像褥伴,于是被迫代替她去往敵國和親谅将。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350