1. 程式人生 > >[email protected] 專欄

[email protected] 專欄

 flv檔案主要由兩部分組成:header和body。

1.header

header部分記錄了flv的型別、版本等資訊,是flv的開頭,一般都差不多,佔9bytes。具體格式如下:
檔案型別 3 bytes “FLV”
版本 1 byte 一般為0x01
流資訊 1 byte 倒數第一位是1表示有視訊,倒數第三位是1表示有音訊,倒數第二、四位必須為0
header長度 4 bytes 整個header的長度,一般為9;大於9表示下面還有擴充套件資訊

2.body

body部分由一個個Tag組成,每個Tag的下面有一塊4bytes的空間,用來記錄這個tag的長度,這個後置用於逆向讀取處理,他們的關係如下圖:


2.1.Tag

每個Tag由也是由兩部分組成的:Tag Header和Tag Data。Tag Header裡存放的是當前Tag的型別、資料區(Tag Data)長度等資訊,具體如下:
名稱 長度 介紹
Tag型別 1 bytes 8:音訊
9:視訊
18:指令碼
其他:保留
資料區長度 3 bytes 在資料區的長度
時間戳 3 bytes 整數,單位是毫秒。對於指令碼型的tag總是0
時間戳擴充套件 1 bytes 將時間戳擴充套件為4bytes,代表高8位。很少用到
StreamsID 3 bytes 總是0
資料區(data) 由資料區長度決定 資料實體

2.2.Tag Data

資料區根據Tag型別的不同可分為三種,音訊資料、視訊資料和指令碼資料。

2.2.1.音訊資料

第一個byte是音訊的資訊,格式如下。
名稱 長度 介紹
音訊格式 4 bits 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
取樣率 2 bits 0 = 5.5-kHz
1 = 11-kHz
2 = 22-kHz
3 = 44-kHz
對於AAC總是3
取樣的長度 1 bit 0 = snd8Bit
1 = snd16Bit
壓縮過的音訊都是16bit
音訊型別 1 bit 0 = sndMono
1 = sndStereo
對於AAC總是1
第2byte開始就是音訊流資料了。

2.2.2.視訊資料

Field

type

Comment

幀型別

UB4

1: keyframe (for AVC, a seekable frame)——h264的IDR,關鍵幀,可重入幀。

2: inter frame (for AVC, a non- seekable frame)——h264的普通幀

3: disposable inter frame (H.263 only)
4: generated keyframe (reserved for server use only)

5: video info/command frame

編碼ID

UB4

使用哪種編碼型別:

1: JPEG (currently unused) 2: Sorenson H.263
3: Screen video

4: On2 VP6

5: On2 VP6 with alpha channel 6: Screen video version 2

7: AVC

視訊資料

UI[N]

如果是avc,則參考下面的介紹:

AVCVIDEOPACKET

AVCVIDEOPACKET

Field

type

Comment

AVC packet型別

UI8

0:AVC序列頭

1:AVC NALU單元

2:AVC序列結束。低級別avc不需要。

CTS

SI24

如果AVC packet型別是1,則為cts偏移(見下面的解釋),為0則為0

資料

UI8[n]

如果AVC packet型別是0,則是解碼器配置,sps,pps。

如果是1,則是nalu單元,可以是多個,具體格式:將下面

關於CTS:這是一個比較難以理解的概念,需要和pts,dts配合一起理解。

首先,pts(presentation time stamps),dts(decoder timestamps),cts(CompositionTime)的概念:

pts:顯示時間,也就是接收方在顯示器顯示這幀的時間。單位為1/90000 秒。

dts:解碼時間,也就是rtp包中傳輸的時間戳,表明解碼的順序。單位單位為1/90000 秒。——根據後面的理解,pts就是標準中的CompositionTime

cts偏移:cts = (pts - dts) / 90 。cts的單位是毫秒。

pts和dts的時間不一樣,應該只出現在含有B幀的情況下,也就是profile main以上。baseline是沒有這個問題的,baseline的pts和dts一直想吐,所以cts一直為0。

在flv tag中的時戳就是DTS。

研究 一下文件,  ISO/IEC 14496-12:2005(E)      8.15   Time to Sample Boxes,發現CompositionTime就是presentation time stamps,只是叫法不同。——需要再進一步確認。

在上圖中,cp就是pts,顯示時間。DT是解碼時間,rtp的時戳。

I1是第一個幀,B2是第二個,後面的序號就是攝像頭輸出的順序。決定了顯示的順序。

DT,是編碼的順序,特別是在有B幀的情況,P4要在第二個解,因為B2和B3依賴於P4,但是P4的顯示要在B3之後,因為他的順序靠後。這樣就存在顯示時間CT(PTS)和解碼時間DT的差,就有了CT偏移。

P4解碼時間是10,但是顯示時間是40,

AVCVIDEOPACKET中data格式:

Field

type

Comment

長度

UI32

nalu單元的長度,不包括長度欄位。

nalu資料

UI8[N]

NALU資料,沒有四個位元組的nalu單元頭,直接從h264頭開始,比如:65 ** ** **,41 **  ** ** 

長度

UI32

nalu單元的長度,不包括長度欄位。

nalu資料

UI8[N]

NALU資料,沒有四個位元組的nalu單元頭,直接從h264頭開始,比如:65 ** ** **,41 **  ** ** 

...

...

...

Data tags

主要是onMeta資訊需要關注。

AVCDecoderConfigurationRecord

AVCVIDEOPACKET的資料格式,儲存控制資訊。

記錄sps,pps資訊。一般出現在第二個tag中,緊跟在onMeta之後。

一個典型的序列:

0000190: 0900 0033 0000 0000 0000 0017 0000 0000  ...3............
00001a0:0164 002a ffe1 001e 6764 002a acd9 4078  .d.*....gd.*[email protected]
00001b0:0227 e5ff c389 4388 0400 0003 0028 0000  .'....C......(..
00001c0:0978 3c60 c658 0100 0568 ebec b22c 0000  .x<`.X...h...,..
17:表示h264IDR data
00:表示是AVC序列頭
00 00 00 :cts為0
//從此往下就是AVCDecoderConfigurationRecord
01 :版本號
64 00 2a:profile level id,sps的三個位元組,64表示是h264 high profile,2a表示level。
FF:NALU長度,為3?不知道這個長度用在哪裡。
E1:表示下面緊跟SPS有一個。
//sps[N]:sps陣列。
00 1e:    前面是兩個位元組的sps長度,表示後面的sps的長度是1e大小。
6764 002a acd9 4078 0227 e5ff c389 4388 0400 0003 0028 0000 0978 3c60 c658:sps的資料。
//因為只有一個sps,跳過這些長度,然後就是pps的個數資訊:
01 :pps個數,1
//pps[n] pps 的個數
00 05:表示pps的大小是5個位元組。
68 eb ec b2 2c:pps的資料
00 00 …….這是下一個tag 的內容了

2.2.3指令碼資料 指令碼Tag一般只有一個,是flv的第一個Tag,用於存放flv的資訊,比如duration、audiodatarate、creator、width等。

首先介紹下指令碼的資料型別。所有資料都是以資料型別+(資料長度)+資料的格式出現的,資料型別佔1byte,資料長度看資料型別是否存在,後面才是資料。
其中資料型別的種類有:

  • 0 = Number type
  • 1 = Boolean type
  • 2 = String type
  • 3 = Object type
  • 4 = MovieClip type
  • 5 = Null type
  • 6 = Undefined type
  • 7 = Reference type
  • 8 = ECMA array type
  • 10 = Strict array type
  • 11 = Date type
  • 12 = Long string type

如果型別為String,後面的2bytes為字串的長度(Long String是4bytes),再後面才是字串資料;如果是Number型別,後面的8bytes為Double型別的資料;Boolean型別,後面1byte為Bool型別。

知道了這些後再來看看flv中的指令碼,一般開頭是0x02,表示String型別,後面的2bytes為字串長度,一般是0x000a(“onMetaData”的長度),再後面就是字串“onMetaData”。好像flv格式的檔案都有onMetaData標記,在執行ActionScript的時候會用到它。後面跟的是0x08,表示ECMA Array型別,這個和Map比較相似,一個鍵跟著一個值。鍵都是String型別的,所以開頭的0x02被省略了,直接跟著的是字串的長度,然後是字串,再是值的型別,也就是上面介紹的那些了。

參考連結

https://wuyuans.com/2012/08/flv-format/
http://blog.csdn.net/chgaowei/article/details/51243345