?上一篇文章講視頻編解碼的第一種情況了嚎,收到H.264格式的視頻數(shù)據(jù)并在應(yīng)用中播放挟冠。接下來進(jìn)一步講一下當(dāng)收到視頻數(shù)據(jù)播放同時(shí)可以得到每一幀圖像捶朵。
這里我們不從AVSampleBufferDisplayLayer中的解碼器中去獲取每一幀圖像,而是通過VTDecompressionSession這個(gè)類來獲取刁标,跟AVSampleBufferDisplayLayer一樣博助,它也需要CMSampleBuffers做為輸入。這個(gè)類會(huì)將CMSampleBuffers轉(zhuǎn)化成CVPixelBuffers并且在代碼塊回調(diào)中提供猪瞬。
在創(chuàng)建VTDecompressionSession前憎瘸,需要CMVideoFormatDescription對(duì)象。如果是從Elementary Stream中解碼的話陈瘦,就從擁有parameter sets的NAL單元中獲取幌甘。如果是解碼CMSampleBuffer的話,就直接將CMVideoFormatDescription對(duì)象從中抽出來甘晤。接下來含潘,我們需要使用pixelBufferAttribute字典來做為輸出的pixelBuffers的描述。最后线婚,我們需要實(shí)現(xiàn)VTDecompressionOutputCallback這個(gè)代碼塊回調(diào)遏弱。
當(dāng)我們需要輸出的pixelBuffers兼容OpenGL ES時(shí),我們只需要?jiǎng)?chuàng)建一個(gè)CFDictionary或者NSDictionary指定kCVPixelBufferOpenGLESCompatibilityKey為true塞弊。
在輸出回調(diào)中CVPixelBuffers是不帶時(shí)間戳的漱逸,所以我們會(huì)獲取到當(dāng)前的時(shí)間戳。當(dāng)發(fā)生錯(cuò)誤或者丟幀時(shí)游沿,我們都可以從回調(diào)方法中得到相應(yīng)的錯(cuò)誤信息饰抒。
?使用VTDecompressionSessionDecodeFrame這個(gè)方法來為VTDecompressionSession提供Frames,這個(gè)方法默認(rèn)是同步執(zhí)行的诀黍。如果想要異步執(zhí)行的話需要傳入標(biāo)志EnableAsynchronousDecompression袋坑。當(dāng)異步執(zhí)行這個(gè)方法時(shí),解碼器只能提供有限的管道來解碼眯勾,所以當(dāng)管道是滿的時(shí)枣宫,方法將會(huì)阻塞。所以不要將UI層的代碼放入這個(gè)方法當(dāng)中執(zhí)行吃环。
當(dāng)解碼一段視頻時(shí)也颤,CMVideoFormatDescription會(huì)發(fā)生改變。當(dāng)收到Elementary Stream時(shí)郁轻,我們根據(jù)第一個(gè)獲取到的parameter sets來創(chuàng)建formatDescription翅娶,并且通過這個(gè)formatDescription來創(chuàng)建VTDecompressionSession來解碼接下來的視頻幀,直到收到新的parameter sets好唯。這時(shí)竭沫,我們要?jiǎng)?chuàng)建新的formatDescription并且調(diào)用VTDecompressionSessionCanAcceptFormatDescription來確認(rèn)decompressionSession是否能夠在這些formaDescription中切換。如果不能切換的話骑篙,我們就需要?jiǎng)?chuàng)建新的VTDecompressionSession输吏,并且確保舊的VTDecompressionSession被銷毀。
?總結(jié)一下替蛉,這片文章主要講了:
1贯溅、如何創(chuàng)建VTDecompressionSession
2、如何做一個(gè)最優(yōu)決策來創(chuàng)建pixelBuffer(通過pixelBufferAttribute字典來指定輸出的需求)
3躲查、如何同步或異步執(zhí)行decompressionSession
4它浅、當(dāng)CMVideoFormatDescription變化時(shí),如何處理
本文翻譯自WWDC14:Direct Access to Video Encoding and Decoding