天天看點

h264封裝為flv檔案

轉載:http://blog.chinaunix.net/uid-24567872-id-3471547.html

前面寫了flv檔案的解析,有h264裸流的話就開始封裝吧。網上大多數都是用ffmeg庫來做這個工作的,哎,學習資料少學不會,還是自己動手吧。

封裝前要先了解下h.264格式,隻需要知道一點點就可以了,我看了h.264官方文檔,我靠,3百多頁,還全是中文,什麼,是中文?既然是中文的我就勉強看下吧,我靠,看起來還很複雜的,果斷不看了,不需要,也沒時間,我又不做解碼,這東西具體步驟資料又少,基本都是那一兩篇轉來轉去,這還要感謝我上一篇提到的那個連接配接的兄弟,記錄下過程,不然以後就忘幹淨了。   h264是一個個NALU單元組成的,每個單元以00 00 01 或者 00 00 00 01分隔開來,每2個00 00 00 01之間就是一個NALU單元。我們實際上就是将一個個NALU單元封裝進FLV檔案。

h264封裝為flv檔案

  每個NALU單元開頭第一個byte的低5bits表示着該單元的類型,即 NAL nal_unit_type: #define NALU_TYPE_SLICE 1

#define NALU_TYPE_DPA 2

#define NALU_TYPE_DPB 3

#define NALU_TYPE_DPC 4

#define NALU_TYPE_IDR 5

#define NALU_TYPE_SEI 6          

#define NALU_TYPE_SPS 7

#define NALU_TYPE_PPS 8

#define NALU_TYPE_AUD 9 #define NALU_TYPE_EOSEQ 10

#define NALU_TYPE_EOSTREAM 11

#define NALU_TYPE_FILL 12 每個NALU第一個byte & 0x1f 就可以得出它的類型,比如上圖第一個NALU:67 & 0x1f = 7,則此單元是SPS,第三個:68 & 0x1f = 8,則此單元是PPS。   前一章說到如果資料是AAC或者AVC的話,則有一個音頻和視訊的配置資訊需要寫入前兩個tag(metadata之後),AAC音頻就不說了,在ISO-14496-3 Audio 中有描述,給一張圖。

h264封裝為flv檔案

  說下AVC視訊流的configuretion,ISO-14496-15 AVC file format 有較長的描述,先給兩張圖,一張是說明,一張是實際截圖。

h264封裝為flv檔案
h264封裝為flv檔案

這個例子是對應我第一個截圖來的,一般h264資料最開始的兩個NALU就是PSP和PPS,但是我現在還沒有明白為什麼我的那個h264裸流在開始的時候會有兩個SPS、PPS,而且之後資料還會不時的出現,但是我沒有管這個,依然隻各弄了一個進去,其他的忽略掉了,反正多餘的我都忽略了,也沒發現有什麼錯。反正首先把音視訊的配置資訊封進metadata之後的tag,然後就可以封資料了。再說下中繼資料,flv header之後就是它了,再之後就是音視訊配置資訊,再後面就是音視訊資料,中繼資料前一章說了是amf格式的,安格式封就行了,測試其實沒有中繼資料視訊也可以正常播放,等會再簡單說下amf吧。     現在開始封裝h264資料吧,前一章提到了flv關于AVC的格式,除開中繼資料,其他資料是:一個byte的video資訊+一個byte的AVCPacket type+3個bytes的無用資料(composition time,當AVC時無用,全是0)+ 4個bytes的NALU單元長度 + N個bytes的NALU資料,是以標頭資料長度資訊是剛才提到的資訊的總和長度。要強調下,當音視訊配置資訊tag的時候,是沒有4個bytes的NALU單元長度的。 AVC的配置資訊時,先上一個圖,

h264封裝為flv檔案

17 -- 高4bits:1,keyframe。 低4bits:7,代表AVC。 後面一個byte 0x00,AVCPacket type,代表AVC sequence header。後3個bytes無意義,之後就是decoder configuration record的内容了。 圖中綠色後面 00 00 00 28就是前面tag的總長度。   當NALU第一個byte xx & 0x1f == 5的時候,說明該單元是一個I frame,關鍵幀

h264封裝為flv檔案

17 -- 和上面的一樣。 01 -- AVC NALU。藍色框内的4個bytes記錄後面NALU資料的長度。65 & 0x1f == 5.   如果NALU第一個byte xx & 0x1f != 5的時候,就不是一個I frame

h264封裝為flv檔案

27 -- 高4bits:2,inter frame ,P frame。 低4bits:7,AVC NALU。其他都一樣。圖中綠色後面 00 00 00 28就是前面tag的總長度。     整個的flv檔案其實是:FLV header + previous tag size0 + tag1 + previous tag size1 + tag2 + previous tag size2 + ... +tagN + previous tag sizeN。 tag1是metadata,記錄視訊的一些資訊;tag2是視訊配置資訊(AVC decoder configuration record),tag3是音頻配置資訊(如果沒有音頻則去掉此項),tag4以及之後的tag就是音視訊資料了。 每一個結構怎麼封都說清楚了,安上面的步驟一個一個NALU封就行了。         封包的時候要特别注意一下標頭裡面的時間戳,因為這個控制着播放的速度,如果不填,全是0的話,播放會相當快,一般按視訊幀率來設定。我這個h264流是8幀的,是以我每個tag的時間間隔是125ms左右。 注意了,flv裡面的資料都是大端模式,放資料進去要轉換一下,如果你是通常的小端的機器的話。        

  至于rtmp協定發送flv,之後再寫吧。