iOS8系統(tǒng)H264視頻硬件編解碼說明

公司項(xiàng)目原因菇怀,接觸了一下視頻流H264的編解碼知識(shí),之前項(xiàng)目使用的是FFMpeg多媒體庫咽筋,利用CPU做視頻的編碼和解碼溶推,俗稱為軟編軟解。該方法比較通用奸攻,但是占用CPU資源悼潭,編解碼效率不高。一般系統(tǒng)都會(huì)提供GPU或者專用處理器來對(duì)視頻流進(jìn)行編解碼舞箍,也就是硬件編碼和解碼舰褪,簡(jiǎn)稱為硬編解碼。蘋果在iOS 8.0系統(tǒng)之前疏橄,沒有開放系統(tǒng)的硬件編碼解碼功能占拍,不過Mac OS系統(tǒng)一直有,被稱為Video ToolBox的框架來處理硬件的編碼和解碼捎迫,終于在iOS 8.0后晃酒,蘋果將該框架引入iOS系統(tǒng)。

由此窄绒,開發(fā)者便可以在iOS里面贝次,調(diào)用Video Toolbox框架提供的接口,來對(duì)視頻進(jìn)行硬件編解碼的工作彰导,為VOIP視頻通話蛔翅,視頻流播放等應(yīng)用的視頻編解碼提供了便利。

(PS:按照蘋果WWDC2014 513《direct access to media encoding and decoding》的描述位谋,蘋果之前提供的AVFoundation框架也使用硬件對(duì)視頻進(jìn)行硬編碼和解碼山析,但是編碼后直接寫入文件,解碼后直接顯示掏父。Video Toolbox框架可以得到編碼后的幀結(jié)構(gòu)笋轨,也可以得到解碼后的原始圖像,因此具有更大的靈活性做一些視頻圖像處理赊淑。)

一爵政,VideoToolbox基本數(shù)據(jù)結(jié)構(gòu)。

Video Toolbox視頻編解碼前后需要應(yīng)用的數(shù)據(jù)結(jié)構(gòu)進(jìn)行說明陶缺。

(1)CVPixelBuffer:編碼前和解碼后的圖像數(shù)據(jù)結(jié)構(gòu)钾挟。

(2)CMTime、CMClock和CMTimebase:時(shí)間戳相關(guān)组哩。時(shí)間以64-bit/32-bit的形式出現(xiàn)等龙。

(3)CMBlockBuffer:編碼后处渣,結(jié)果圖像的數(shù)據(jù)結(jié)構(gòu)。

(4)CMVideoFormatDescription:圖像存儲(chǔ)方式蛛砰,編解碼器等格式描述罐栈。

(5)CMSampleBuffer:存放編解碼前后的視頻圖像的容器數(shù)據(jù)結(jié)構(gòu)。

1.1視頻H264編解碼前后數(shù)據(jù)結(jié)構(gòu)示意圖

如圖1.1所示泥畅,編解碼前后的視頻圖像均封裝在CMSampleBuffer中荠诬,如果是編碼后的圖像,以CMBlockBuffe方式存儲(chǔ)位仁;解碼后的圖像柑贞,以CVPixelBuffer存儲(chǔ)。CMSampleBuffer里面還有另外的時(shí)間信息CMTime和視頻描述信息CMVideoFormatDesc聂抢。

二钧嘶,硬解碼使用方法。

通過如圖2.1所示的一個(gè)典型應(yīng)用琳疏,來說明如何使用硬件解碼接口有决。該應(yīng)用場(chǎng)景是從網(wǎng)絡(luò)處傳來H264編碼后的視頻碼流,最后顯示在手機(jī)屏幕上空盼。

2.1 H264典型應(yīng)用場(chǎng)景

1书幕,將H264碼流轉(zhuǎn)換成解碼前的CMSampleBuffer。

由圖1.1所示揽趾,解碼前的CMSampleBuffer = CMTime + FormatDesc + CMBlockBuffer台汇。需要從H264的碼流里面提取出以上的三個(gè)信息。最后組合成CMSampleBuffer篱瞎,提供給硬解碼接口來進(jìn)行解碼工作苟呐。

H264的碼流由NALU單元組成,NALU單元包含視頻圖像數(shù)據(jù)和H264的參數(shù)信息奔缠。其中視頻圖像數(shù)據(jù)就是CMBlockBuffer掠抬,而H264的參數(shù)信息則可以組合成FormatDesc吼野。具體來說參數(shù)信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set)校哎。圖2.2顯示一個(gè)H264碼流的結(jié)構(gòu)。

2.2 H264碼流結(jié)構(gòu)

(1)提取sps和pps生成format description瞳步。

a闷哆,每個(gè)NALU的開始碼是0x00 00 01,按照開始碼定位NALU单起。

b抱怔,通過類型信息找到sps和pps并提取,開始碼后第一個(gè)byte的后5位嘀倒,7代表sps屈留,8代表pps局冰。

c,CMVideoFormatDescriptionCreateFromH264ParameterSets函數(shù)來構(gòu)建CMVideoFormatDescriptionRef灌危。具體代碼可以見demo康二。

(2)提取視頻圖像數(shù)據(jù)生成CMBlockBuffer。

a勇蝙,通過開始碼沫勿,定位到NALU。

b味混,確定類型為數(shù)據(jù)后产雹,將開始碼替換成NALU的長(zhǎng)度信息(4 Bytes)。

c翁锡,CMBlockBufferCreateWithMemoryBlock接口構(gòu)造CMBlockBufferRef蔓挖。具體代碼可以見demo。

(3)根據(jù)需要馆衔,生成CMTime信息时甚。(實(shí)際測(cè)試時(shí),加入time信息后哈踱,有不穩(wěn)定的圖像荒适,不加入time信息反而沒有,需要進(jìn)一步研究开镣,這里建議不加入time信息)

根據(jù)上述得到CMVideoFormatDescriptionRef刀诬、CMBlockBufferRef和可選的時(shí)間信息,使用CMSampleBufferCreate接口得到CMSampleBuffer數(shù)據(jù)這個(gè)待解碼的原始的數(shù)據(jù)邪财。見圖2.3的H264數(shù)據(jù)轉(zhuǎn)換示意圖陕壹。

2.3 H264碼流轉(zhuǎn)換CMSampleBuffer示意圖

2,硬件解碼圖像顯示树埠。

硬件解碼顯示的方式有兩種:

(1)通過系統(tǒng)提供的AVSampleBufferDisplayLayer來解碼并顯示糠馆。

AVSampleBufferDisplayLayer是蘋果提供的一個(gè)專門顯示編碼后的H264數(shù)據(jù)的顯示層,它是CALayer的子類怎憋,因此使用方式和其它CALayer類似又碌。該層內(nèi)置了硬件解碼功能,將原始的CMSampleBuffer解碼后的圖像直接顯示在屏幕上面绊袋,非常的簡(jiǎn)單方便毕匀。圖2.4顯示了這一解碼過程。

2.4 AVSampleBufferDisplayLayer硬解壓后顯示圖像

顯示的接口為[_avslayer enqueueSampleBuffer:sampleBuffer];

(2)通過VTDecompression接口來癌别,將CMSampleBuffer解碼成圖像皂岔,將圖像通過UIImageView或者OpenGL上顯示。

a展姐,初始化VTDecompressionSession躁垛,設(shè)置解碼器的相關(guān)信息剖毯。初始化信息需要CMSampleBuffer里面的FormatDescription,以及設(shè)置解碼后圖像的存儲(chǔ)方式教馆。demo里面設(shè)置的CGBitmap模式速兔,使用RGB方式存放。編碼后的圖像經(jīng)過解碼后活玲,會(huì)調(diào)用一個(gè)回調(diào)函數(shù)涣狗,將解碼后的圖像交個(gè)這個(gè)回調(diào)函數(shù)來進(jìn)一步處理。我們就在這個(gè)回調(diào)里面舒憾,將解碼后的圖像發(fā)給control來顯示镀钓,初始化的時(shí)候要將回調(diào)指針作為參數(shù)傳給create接口函數(shù)。最后使用create接口對(duì)session來進(jìn)行初始化镀迂。

b丁溅,a中所述的回調(diào)函數(shù)可以完成CGBitmap圖像轉(zhuǎn)換成UIImage圖像的處理,將圖像通過隊(duì)列發(fā)送到Control來進(jìn)行顯示處理探遵。

c窟赏,調(diào)用VTDecompresSessionDecodeFrame接口進(jìn)行解碼操作。解碼后的圖像會(huì)交由a箱季,b步驟設(shè)置的回調(diào)函數(shù)涯穷,來進(jìn)一步的處理。

圖2.5顯示來硬解碼的過程步驟藏雏。

2.5 VTDecompression硬解碼過程示意圖

三拷况,硬編碼使用方法。

硬編碼的使用也通過一個(gè)典型的應(yīng)用場(chǎng)景來描述掘殴。首先赚瘦,通過攝像頭來采集圖像,然后將采集到的圖像奏寨,通過硬編碼的方式進(jìn)行編碼起意,最后編碼后的數(shù)據(jù)將其組合成H264的碼流通過網(wǎng)絡(luò)傳播。

1病瞳,攝像頭采集數(shù)據(jù)揽咕。

攝像頭采集,iOS系統(tǒng)提供了AVCaptureSession來采集攝像頭的圖像數(shù)據(jù)仍源。設(shè)定好session的采集解析度心褐。再設(shè)定好input和output即可。output設(shè)定的時(shí)候笼踩,需要設(shè)置delegate和輸出隊(duì)列。在delegate方法亡嫌,處理采集好的圖像嚎于。

注意掘而,需要說明的是,圖像輸出的格式于购,是未編碼的CMSampleBuffer形式袍睡。

2,使用VTCompressionSession進(jìn)行硬編碼肋僧。

(1)初始化VTCompressionSession斑胜。

VTCompressionSession初始化的時(shí)候,一般需要給出width寬嫌吠,height長(zhǎng)止潘,編碼器類型kCMVideoCodecType_H264等。然后通過調(diào)用VTSessionSetProperty接口設(shè)置幀率等屬性辫诅,demo里面提供了一些設(shè)置參考凭戴,測(cè)試的時(shí)候發(fā)現(xiàn)幾乎沒有什么影響,可能需要進(jìn)一步調(diào)試炕矮。最后需要設(shè)定一個(gè)回調(diào)函數(shù)么夫,這個(gè)回調(diào)是視頻圖像編碼成功后調(diào)用。全部準(zhǔn)備好后肤视,使用VTCompressionSessionCreate創(chuàng)建session档痪。

(2)提取攝像頭采集的原始圖像數(shù)據(jù)給VTCompressionSession來硬編碼。

攝像頭采集后的圖像是未編碼的CMSampleBuffer形式邢滑,利用給定的接口函數(shù)CMSampleBufferGetImageBuffer從中提取出CVPixelBufferRef钞它,使用硬編碼接口VTCompressionSessionEncodeFrame來對(duì)該幀進(jìn)行硬編碼,編碼成功后殊鞭,會(huì)自動(dòng)調(diào)用session初始化時(shí)設(shè)置的回調(diào)函數(shù)遭垛。

(3)利用回調(diào)函數(shù),將因編碼成功的CMSampleBuffer轉(zhuǎn)換成H264碼流操灿,通過網(wǎng)絡(luò)傳播锯仪。

基本上是硬解碼的一個(gè)逆過程。解析出參數(shù)集SPS和PPS趾盐,加上開始碼后組裝成NALU庶喜。提取出視頻數(shù)據(jù),將長(zhǎng)度碼轉(zhuǎn)換成開始碼救鲤,組長(zhǎng)成NALU久窟。將NALU發(fā)送出去。

圖2.6顯示了整個(gè)硬編碼的處理邏輯本缠。

2.6硬編碼處理流程示意圖

四斥扛,硬編解碼的一些編碼說明。

由于Video Toolbox是基礎(chǔ)的core Foundation庫函數(shù)丹锹,C語言寫成稀颁,和使用core Foundation所有的其它功能一樣需要適應(yīng)芬失,記得Github有個(gè)同志,將其改成了OC語言能方便調(diào)用的模式匾灶,但是地址忘了棱烂,以后有緣找到,就會(huì)提供下鏈接阶女。


Demo : https://github.com/manishganvir/iOS-h264Hw-Toolbox

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颊糜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子秃踩,更是在濱河造成了極大的恐慌衬鱼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吞瞪,死亡現(xiàn)場(chǎng)離奇詭異馁启,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)芍秆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門惯疙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人妖啥,你說我怎么就攤上這事霉颠。” “怎么了荆虱?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵蒿偎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我怀读,道長(zhǎng)诉位,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任菜枷,我火速辦了婚禮苍糠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘啤誊。我一直安慰自己岳瞭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布蚊锹。 她就那樣靜靜地躺著瞳筏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牡昆。 梳的紋絲不亂的頭發(fā)上姚炕,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼钻心。 笑死凄硼,一個(gè)胖子當(dāng)著我的面吹牛铅协,可吹牛的內(nèi)容都是我干的捷沸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼狐史,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼痒给!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起骏全,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤苍柏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后姜贡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體试吁,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年楼咳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熄捍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡母怜,死狀恐怖余耽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情苹熏,我是刑警寧澤碟贾,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站轨域,受9級(jí)特大地震影響袱耽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜干发,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一朱巨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铐然,春花似錦蔬崩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至自点,卻和暖如春桐罕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工功炮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溅潜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓薪伏,卻偏偏與公主長(zhǎng)得像滚澜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嫁怀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容