FLV結構與相關信息------以1078終端推送的音視頻爲使用場景

序言

        關於1078實時監控的另一種做法,就是自己編碼處理音視頻裸流.這種形式需要了解更多的音視頻基礎知識,因爲之前的處理過程是JavaCV幫我們做了很多東西.本文只是做個準備工作,先了解一些基礎知識在,然後才能知道該方案的可行性

參考資料:

  1. https://blog.csdn.net/u013008311/article/details/80249586
  2. https://blog.csdn.net/u013008311/article/details/80251479
  3. https://blog.csdn.net/jefry_xdz/article/details/8461343
  4. https://www.cnblogs.com/wainiwann/p/7477794.html
  5. https://blog.csdn.net/bsplover/article/details/7426511
  6. https://blog.csdn.net/byxdaz/article/details/53993791

H264/AVC

視頻編解碼技術有兩套標準:

  1. 國際電聯(ITU-T)的標準H.263、H.263+等;
  2. ISO 的MPEG標準Mpeg1、Mpeg2、Mpeg4等等。

        H.264/AVC是兩大組織集合H.263+和Mpeg4的優點聯合推出的最新標準,最具價值的部分無疑是更高的數據壓縮比。在同等的圖像質量條件下,H.264的數據壓縮比能比H.263高2倍,比MPEG-4高1.5倍。 所以說H264和AVC 其實是指同一個東西.
 

       H.264/AVC標準是由ITU-T和ISO/IEC聯合開發的,定位於覆蓋整個視頻應用領域,包括:低碼率的無線應用、標準清晰度和高清晰度的電視廣播應用、Internet上的視頻流應用,傳輸高清晰度的DVD視頻以及應用於數碼相機的高質量視頻應用等等。
       ITU-T給這個標準命名爲H.264(以前叫做H.26L)而ISO/IEC稱它爲MPEG-4 高級視頻編碼(Advanced Video Coding,AVC),並且它將成爲MPEG-4標準的第10部分。既然AVC是當前MPEG-4標準的拓展,那麼它必然將受益於MPEG-4開發良好的基礎結構(比如系統分層和音頻等)。很明顯,作爲MPEG-4高級簡潔框架(Advanced Simple Profile,ASP)的MPEG-4 AVC將會優於當前的MPEG-4視頻壓縮標準,它將主要應用在具有高壓縮率和分層次質量需求的方向。

       H264原始碼流是一個接一個的NALU(網絡抽象層單元)租成的,每個單元之間是由 0x00 0x00 0x00 0x01 或者 0x00 0x00 0x01分割而成的,緊接着就是NALU的單元頭和數據體.(注意這裏的NALU是很重要的,因爲後面我會一定要現貨區NALU才能進行編碼操作與封裝操作[email protected],注意這裏的分隔符~~很重要,我們在收到終端的推流數據的時候就會遇到)

 

NAL

       在H.264/AVC視頻編碼標準中,整個系統框架被分爲了兩個層面:

  • 視頻編碼層面(VCL):負責有效表示視頻數據的內容
  • 網絡抽象層面(NAL):負責格式化數據並提供頭信息,保證數據適合各種信道和存儲介質上的傳輸(這個是我們要關注的重點)

       因此我們平時的每幀數據就是一個NAL單元(SPS與PPS除外)。在實際的H264數據幀中,往往幀前面帶有00 00 00 01 或 00 00 01分隔符,一般來說編碼器編出的首幀數據爲PPS與SPS,接着爲I幀…… 注意這裏的分隔符[email protected]

SPS(參數集合)

       SPS即Sequence Paramater Set,又稱作序列參數集。SPS中保存了一組編碼視頻序列(Coded video sequence)的全局參數。所謂的編碼視頻序列即原始視頻的一幀一幀的像素數據經過編碼之後的結構組成的序列。而每一幀的編碼後數據所依賴的參數保存於圖像參數集中。一般情況SPS和PPS的NAL Unit通常位於整個碼流的起始位置。但在某些特殊情況下,在碼流中間也可能出現這兩種結構,主要原因可能爲:(這個特殊情況不考慮)

  • 解碼器需要在碼流中間開始解碼;
  • 編碼器在編碼的過程中改變了碼流的參數(如圖像分辨率等)

PPS(參數集合)

       除了序列參數集SPS之外,H.264中另一重要的參數集合爲圖像參數集Picture Paramater Set(PPS)。通常情況下,PPS類似於SPS,在H.264的裸碼流中單獨保存在一個NAL Unit中,只是PPS NAL Unit的nal_unit_type值爲8;而在封裝格式中,PPS通常與SPS一起,保存在視頻文件的文件頭中。(這個是我們的1078的環境,不考慮真實環境)

解析H264數據

       最上面圖的碼流對應的數據來層層分析,以00 00 00 01分割之後的下一個字節就是NALU類型,將其轉爲二進制數據後,解讀順序爲從左往右算,如下:

  1. 第1位禁止位,值爲1表示語法出錯
  2. 第2~3位爲參考級別
  3. 第4~8爲是nal單元類型(單元類型如下圖所示)

例如上面00000001後有67,68以及65

其中0x67的二進制碼爲:
0110 0111
4-8爲00111,轉爲十進制7,參考第二幅圖:7對應序列參數集SPS

其中0x68的二進制碼爲:
0110 1000
4-8爲01000,轉爲十進制8,參考第二幅圖:8對應圖像參數集PPS

其中0x65的二進制碼爲:
0110 0101
4-8爲00101,轉爲十進制5,參考第二幅圖:5對應IDR圖像中的片(I幀)

所以判斷是否爲I幀的算法爲: (NALU類型  & 0001  1111) = 5   即   NALU類型  & 31 = 5

 

FLV封裝格式

      FLV文件是由 FLV文件頭(FLV header)和 FLV文件體(FLV body)組成的。

      FLV body又是由 (previous tag size 和  flv tag)* N 組成的。

 

Flv Header

       FLV header 中包含的信息有: 文件類型、 FLV版本 、stream信息、 FLV header 長度。這個Header長度一般都是固定的9個字節:(注意這個頭信息需要搞明白,因爲後面我們的推流會要自己寫入頭信息,根據你的數據情況[email protected])

 

Flv Body(這個數據的生成過程其實不復雜,但是需要先搞清楚它原始的數據結構,比較耗費時間--心累)

       FLV body中包含很多個FLV tag,tag的分類有三種:0x8音頻0x9視頻0x12腳本。(後面會對着3中類型的數據分別講解,每個類型的tag的作用不一樣音頻和視頻很容易區分,主要是腳本的作用)

       每個tag中包含tag頭和tag體.

       每個tag前面還有一個previous size包. 記錄着上一個tag的數據的長度(這個長度就是header 和 body 的長度總和)

Tag Header

 

Tag Body---0x12腳本

         腳本tag 0x12(script tag),腳本tag描述了媒體信息,比如視頻的width 和 height ,幀率等等信息. (看到這感覺崩潰,不知道後面是否需要自己寫入腳本信息, 非常希望終端推送的數據已經包含了腳本[email protected])

        圖中爲一個腳本tag的數據截圖,腳本tag在tag頭後面的tag數據中一般會包含兩個AMF包AMF是Adobe設計的一種通用數據封裝格式。在第一個AMF包中有一個字符串類型的值,該值爲onMetaDate。第二個AMF包封裝一個“數據組”,每一組數據都有自己的元素名、元素類型、元素值、這裏不詳細描述(現在又引出了AMF的封裝格式---------痛哭流涕,這個後面空了在研究)

Tag Body---0x9視頻

       視頻tag 0x9 視頻tag頭都是一樣的,1byte Tag類型,3bytes數據長度記錄,3bytes時間戳,一個擴展時間戳bype,3bytes StreamID。(後面跟了一個字節用於區分視頻的數據類型)

       視頻tag頭後面的第一byte 的4bit表示視頻數據的類型,後4bit表示視頻的編碼器ID( 跟在這後面的纔是視頻幀的數據,如:I幀, P幀,B幀 等等---等等很牽強)

       數據類型:1<->keyframe、2<->innerframe、3<->disposable inner frame(h.263)、4<->generated keyframe

       編碼器ID:2<->h.263、3<->screen video、4<->On2 VP6、5<->On2 VP6 with alpha channel、6<->Screen video version、7<->AVC/h264  (注意這裏的 avc h264 其實是一個編碼器的不同稱呼-----希望終端推送的流數據中包含了~~~   =.=)

Tag Body---0x8音頻(這裏的音頻格式我們用的是G711A)

        音頻tag0x8 和 視頻相比tagtype爲0x8 tag header 都是一樣的後面跟着的 tag數據類型,後續就是音頻的數據了。

        音頻tag佔1byte 前4bit表示音頻格式(比如MP3),接着2bit表示採樣率,接着1bit表示採樣長度接着1bit表示音頻類型

        音頻格式:0<->未壓縮、1<->ADPCM、2<->MP3、4<->Nellymoser 16-Hz mono、5<->Nellymoser 8-kHz mono、10<->AAC (竟然缺少了我們的G711A的編碼格式,但是字典表中肯定有的)

       採樣率: 0<->5.5kHz、1<->11kHz、2<->22kHz、3<->44kHz (缺少了8kHz,字典表中肯定有的)

       採樣位數:0<->snd8bit、1<->16bit(這個使我們要的)

       音配類型:0<->sndMono(單聲道) 1<->sndStereo(立體聲)

 

稍微詳細一點的FLV文件格式說明

FLV-Header(這裏的UI標識bit,後面的數字標識幾個bit, ub就是ui數組)

  1. Signature: FLV 文件的前3個字節爲固定的‘F’‘L’‘V’,用來標識這個文件是flv格式的.在做格式探測的時候,
  2. 如果發現前3個字節爲“FLV”,就認爲它是flv文件.
  3. Version: 第4個字節表示flv版本號.
  4. Flags: 第5個字節中的第0位和第2位,分別表示 video 與 audio 存在的情況.(1表示存在,0表示不存在)
  5. DataOffset : 最後4個字節表示FLV header 長度.
Field Type Comment
Signature UI8 Signature byte always 'F' (0x46)
Signature UI8 Signature byte always 'L' (0x4C)
Signature UI8 Signature byte always 'V' (0x56)
Version UI8 File version (for example, 0x01 for FLV version 1)
TypeFlagsReserved UB [5] Shall be 0
TypeFlagsAudio UB [1] 1 = Audio tags are present
TypeFlagsReserved UB [1] Shall be 0
TypeFlagsVideo UB [1] 1 = Video tags are present
DataOffset UI32 The length of this header in bytes

The FLV File Body

FLV header之後,就是 FLV File Body.

FLV File Body是由一連串的back-pointers + tags構成.back-pointers就是4個字節數據,表示前一個tag的size.

所以第一個PreviousTagSize0 是 Flv Header的長度.

Field Type Comment
PreviousTagSize0 UI32 Always 0
Tag1 FLVTAG First tag
PreviousTagSize1 UI32

Size of previous tag, including its header, in bytes. For FLV version1,

this value is 11 plus the DataSize of the previous tag.

Tag2 FLVTAG Second tag
... ... ...
PreviousTagSizeN-1 UI32 Size of second-to-last tag, including its header, in bytes.
TagN FLVTAG Last tag
PreviousTagSizeN UI32 Size of last tag, including its header, in bytes

 

FLVTAG

  • TagType: TAG中第1個字節中的前5位表示這個TAG中包含數據的類型,8 = audio,9 = video,18 = script data.
  • DataSize:StreamID之後的數據長度.
  • TimestampTimestampExtended組成了這個TAG包數據的PTS信息,記得剛開始做FVL demux的時候,並沒有考慮TimestampExtended的值,直接就把Timestamp默認爲是PTS,後來發生的現 象就是畫面有跳幀的現象,後來才仔細看了一下文檔發現真正數據的PTS是PTS= Timestamp | TimestampExtended<<24.
  • StreamID之後的數據就是每種格式的情況不一樣了,接下格式進行詳細的介紹.
Field Type Comment
Reserved UB [2] Reserved for FMS, should be 0
Filter UB [1] Indicates if packets are filtered.
0 = No pre-processing required.
1 = Pre-processing (such as decryption) of the packet is
required before it can be rendered.
Shall be 0 in unencrypted files, and 1 for encrypted tags.
See Annex F. FLV Encryption for the use of filters.
TagType UB [5]

Type of contents in this tag. The following types are
defined:
8 = audio
9 = video
18 = script data

DataSize UI24 Length of the message. Number of bytes after StreamID to
end of tag (Equal to length of the tag – 11)
Timestamp UI24 Time in milliseconds at which the data in this tag applies.
This value is relative to the first tag in the FLV file, which
always has a timestamp of 0.
TimestampExtended UI8 Extension of the Timestamp field to form a SI32 value. This
field represents the upper 8 bits, while the previous
Timestamp field represents the lower 24 bits of the time in
milliseconds.
StreamID UI24 Always 0.
AudioTagHeader IF TagType == 8
AudioTagHeader
 
VideoTagHeader IF TagType == 9
VideoTagHeader
 
EncryptionHeader IF Filter == 1
EncryptionTagHeader
 
FilterParams IF Filter == 1
FilterParams
 
Data IF TagType == 8
AUDIODATA
IF TagType == 9
VIDEODATA
IF TagType == 18
SCRIPTDATA
Data specific for each media type.

Audio Tags

 

Field Type Comment
SoundFormat UB [4] Format of SoundData. The following values are defined:
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
8 = G.711 mu-law logarithmic PCM
9 = reserved
10 = AAC
11 = Speex
14 = MP3 8 kHz
15 = Device-specific sound
Formats 7, 8, 14, and 15 are reserved.
AAC is supported in Flash Player 9,0,115,0 and higher.
Speex is supported in Flash Player 10 and higher.
SoundRate UB [2] Sampling rate. The following values are defined:
0 = 5.5 kHz
1 = 11 kHz
2 = 22 kHz
3 = 44 kHz
SoundSize UB [1]

Size of each audio sample. This parameter only pertains to
uncompressed formats. Compressed formats always decode
to 16 bits internally.
0 = 8-bit samples
1 = 16-bit samples

SoundType UB [1] Mono or stereo sound
0 = Mono sound
1 = Stereo sound
AACPacketType IF SoundFormat == 10
UI8
The following values are defined:
0 = AAC sequence header
1 = AAC raw

 

Video Tags

Field Type Comment
Frame Type UB [4] Type of video frame. The following values are defined:
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
CodecID UB [4] Codec Identifier. The following values are defined:
2 = Sorenson H.263
3 = Screen video
4 = On2 VP6
5 = On2 VP6 with alpha channel
6 = Screen video version 2
7 = AVC
AVCPacketType IF CodecID == 7
UI8

The following values are defined:
0 = AVC sequence header
1 = AVC NALU
2 = AVC end of sequence (lower level NALU sequence ender is not required or supported)

CompositionTime IF CodecID == 7
SI24
IF AVCPacketType == 1
Composition time offset
ELSE
0
See ISO 14496-12, 8.15.3 for an explanation of composition
times. The offset in an FLV file is always in milliseconds.

 

Script Tags

Field Type Comment
Type UI8 Type of the ScriptDataValue.
The following types are defined:
0 = Number
1 = Boolean
2 = String
3 = Object
4 = MovieClip (reserved, not supported)
5 = Null
6 = Undefined
7 = Reference
8 = ECMA array
9 = Object end marker
10 = Strict array
11 = Date
12 = Long string
ScriptDataValue IF Type == 0
DOUBLE
IF Type == 1
UI8
IF Type == 2
SCRIPTDATASTRING
IF Type == 3
SCRIPTDATAOBJECT
IF Type == 7
UI16
IF Type == 8
SCRIPTDATAECMAARRAY
IF Type == 10
SCRIPTDATASTRICTARRAY
IF Type == 11
SCRIPTDATADATE
IF Type == 12
SCRIPTDATALONGSTRING
Script data value.
The Boolean value is (ScriptDataValue ≠ 0).

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章