将h.264视频流封装成flv格式文件(二.开始动手)
生活随笔
收集整理的這篇文章主要介紹了
将h.264视频流封装成flv格式文件(二.开始动手)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
前面寫了flv文件的解析,有h264裸流的話就開始封裝吧。網(wǎng)上大多數(shù)都是用ffmeg庫來做這個工作的,哎,學(xué)習(xí)資料少學(xué)不會,還是自己動手吧。
封裝前要先了解下h.264格式,只需要知道一點點就可以了,我看了h.264官方文檔,我靠,3百多頁,還全是中文,什么,是中文?既然是中文的我就勉強看下吧,我靠,看起來還很復(fù)雜的,果斷不看了,不需要,也沒時間,我又不做解碼,這東西具體步驟資料又少,基本都是那一兩篇轉(zhuǎn)來轉(zhuǎn)去,這還要感謝我上一篇提到的那個連接的兄弟,記錄下過程,不然以后就忘干凈了。 ? h264是一個個NALU單元組成的,每個單元以00 00 01 或者 00 00 00 01分隔開來,每2個00 00 00 01之間就是一個NALU單元。我們實際上就是將一個個NALU單元封裝進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。 ? 前一章說到如果數(shù)據(jù)是AAC或者AVC的話,則有一個音頻和視頻的配置信息需要寫入前兩個tag(metadata之后),AAC音頻就不說了,在ISO-14496-3 Audio 中有描述,給一張圖。 ? 說下AVC視頻流的configuretion,ISO-14496-15 AVC file format 有詳細描述,先給兩張圖,一張是說明,一張是實際截圖。 ? 這個例子是對應(yīng)我第一個截圖來的,一般h264數(shù)據(jù)最開始的兩個NALU就是PSP和PPS,但是我現(xiàn)在還沒有明白為什么我的那個h264裸流在開始的時候會有兩個SPS、PPS,而且之后數(shù)據(jù)還會不時的出現(xiàn),但是我沒有管這個,依然只各弄了一個進去,其他的忽略掉了,反正多余的我都忽略了,也沒發(fā)現(xiàn)有什么錯。反正首先把音視頻的配置信息封進metadata之后的tag,然后就可以封數(shù)據(jù)了。再說下元數(shù)據(jù),flv header之后就是它了,再之后就是音視頻配置信息,再后面就是音視頻數(shù)據(jù),元數(shù)據(jù)前一章說了是amf格式的,安格式封就行了,測試其實沒有元數(shù)據(jù)視頻也可以正常播放,等會再簡單說下amf吧。 ? ? 現(xiàn)在開始封裝h264數(shù)據(jù)吧,前一章提到了flv關(guān)于AVC的格式,除開元數(shù)據(jù),其他數(shù)據(jù)是:一個byte的video信息+一個byte的AVCPacket type+3個bytes的無用數(shù)據(jù)(composition time,當(dāng)AVC時無用,全是0)+ 4個bytes的NALU單元長度 + N個bytes的NALU數(shù)據(jù),所以包頭數(shù)據(jù)長度信息是剛才提到的信息的總和長度。要強調(diào)下,當(dāng)音視頻配置信息tag的時候,是沒有4個bytes的NALU單元長度的。 AVC的配置信息時,先上一個圖, 17 -- 高4bits:1,keyframe。 低4bits:7,代表AVC。 后面一個byte 0x00,AVCPacket type,代表AVC sequence header。后3個bytes無意義,之后就是decoder configuration record的內(nèi)容了。 圖中綠色后面 00 00 00 28就是前面tag的總長度。 ? 當(dāng)NALU第一個byte xx & 0x1f == 5的時候,說明該單元是一個I frame,關(guān)鍵幀 17 -- 和上面的一樣。 01 -- AVC NALU。藍色框內(nèi)的4個bytes記錄后面NALU數(shù)據(jù)的長度。65 & 0x1f == 5. ? 如果NALU第一個byte xx & 0x1f != 5的時候,就不是一個I frame 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就是音視頻數(shù)據(jù)了。 每一個結(jié)構(gòu)怎么封都說清楚了,安上面的步驟一個一個NALU封就行了。 ? ? 封包的時候要特別注意一下包頭里面的時間戳,因為這個控制著播放的速度,如果不填,全是0的話,播放會相當(dāng)快,一般按視頻幀率來設(shè)置。我這個h264流是8幀的,所以我每個tag的時間間隔是125ms左右。 注意了,flv里面的數(shù)據(jù)都是大端模式,放數(shù)據(jù)進去要轉(zhuǎn)換一下,如果你是通常的小端的機器的話。 ? ? ? ? 到這里應(yīng)該差不多了吧,我是一個NALU單元封裝成一個tag,我也是剛接觸,不知道上述還有哪些地方不合理,不過測試沒有發(fā)現(xiàn)問題。我也才接觸這東西,如果有知情人,望解釋一下為什么有多個PPS SPS,謝謝。 ? 至于rtmp協(xié)議發(fā)送flv,之后再寫吧。
?
總結(jié)
以上是生活随笔為你收集整理的将h.264视频流封装成flv格式文件(二.开始动手)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: codevs 2977 二叉堆练习1x
- 下一篇: 几款制作帮助文档的工具汇总