iOS-H264 硬解碼

iOS系統中H264硬解及顯示說明

蘋果在iOS 8.0系統之前,沒有開放系統的硬件編碼解碼功能,不過Mac OS系統一直有,被稱為Video ToolBox的框架來處理硬件的編碼和解碼,終于在iOS 8.0后,蘋果將該框架引入iOS系統。

一、VideoToolbox基本數據結構:

1、CVPixelBuffer:編碼前和解碼后的圖像數據結構;

2、CMTime、CMClock和CMTimebase:時間戳相關。時間以64-bit/32-bit的形式出現;

3、CMBlockBuffer:編碼后,結果圖像的數據結構;

4、CMVideoFormatDescription:圖像存儲方式,編解碼器等格式描述;

5、CMSampleBuffer:存放編解碼前后的視頻圖像的容器數據結構。

下圖為H264解碼前后數據結構示意圖:

二、硬解使用方法:

H264的碼流由NALU單元組成,NALU單元包含視頻圖像數據和H264的參數信息。其中視頻圖像數據就是CMBlockBuffer,而H264的參數信息則可以組合成FormatDesc。具體來說參數信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set)。下圖顯示一個H264碼流的結構:

解碼方式一:(通過系統提供的AVSampleBufferDisplayLayer來解碼并顯示)

1、初始化H264硬解param:

1) 提取sps和pps生成format description;


//sps

_spsSize =format.getCsd_0_size()-4;_sps = (uint8_t *)malloc(_spsSize);memcpy(_sps,format.getCsd_0()+4, _spsSize);

//pps

_ppsSize =format.getCsd_1_size()-4;_pps = (uint8_t *)malloc(_ppsSize);memcpy(_pps,format.getCsd_1()+4, _ppsSize);


2) 使用CMVideoFormatDescriptionCreateFromH264ParameterSets函數來構建CMVideoFormatDescriptionRef。


CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

2, //param count? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? parameterSetPointers,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? parameterSetSizes,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 4, //nalstartcodesize&_decoderFormatDescription);


2、將H264碼流轉換成解碼前的CMSampleBuffer:

? 1) 使用CMBlockBufferCreateWithMemoryBlock接口構造CMBlockBufferRef;

CMBlockBufferRef blockBuffer=NULL;CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (void*)frame.bytes,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? frame.length,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? kCFAllocatorNull,NULL,0, frame.length,0,&blockBuffer);

? 2)根據上述得到CMVideoFormatDescriptionRef、CMBlockBufferRef和可選的時間信息,使用CMSampleBufferCreate接口得到CMSampleBuffer數據這個待解碼的原始的數據。

CMSampleBufferRef sampleBuffer =NULL;CMSampleBufferCreateReady(kCFAllocatorDefault,? ? ? ? ? ? ? ? ? ? ? ? ? blockBuffer,? ? ? ? ? ? ? ? ? ? ? ? ? _decoderFormatDescription,1,0,NULL,1, sampleSizeArray,? ? ? ? ? ? ? ? ? ? ? ? ? &sampleBuffer);

3、硬解圖像顯示:

通過系統提供的AVSampleBufferDisplayLayer來解碼并顯示。

AVSampleBufferDisplayLayer是蘋果提供的一個專門顯示編碼后的H264數據的顯示層,它是CALayer的子類,因此使用方式和其它CALayer類似。該層內置了硬件解碼功能,將原始的CMSampleBuffer解碼后的圖像直接顯示在屏幕上面,非常的簡單方便。

CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer,YES);CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments,0);CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);if(status == kCMBlockBufferNoErr) {

if([_avslayer isReadyForMoreMediaData]) ? ? ? ? ? ??{dispatch_sync(dispatch_get_main_queue(),^{ ? ? ? ?

? ? [_avslayer enqueueSampleBuffer:sampleBuffer]; ? ? ?

? ? });? ?

? }? ??

CFRelease(sampleBuffer);

}


解碼方式二:(通過VTDecompression接口,將CMSampleBuffer解碼成圖像,將圖像通過UIImageView或者OpenGL來顯示)

1、初始化H264硬解param:

在方式一的基礎上,使用VTDecompressionSessionCreate接口構造VTDecompressionSessionRef;(初始化VTDecompressionSession,設置解碼器的相關信息)

VTDecompressionSessionRef _deocderSession;VTDecompressionSessionCreate(kCFAllocatorDefault,? ? ? ? ? ? ? ? ? ? ? ? ? ? _decoderFormatDescription,NULL, attrs,? ? ? ? ? ? ? ? ? ? ? ? ? ? &callBackRecord,? ? ? ? ? ? ? ? ? ? ? ? ? ? &_deocderSession);

2、將H264碼流轉換成解碼前的CMSampleBuffer:

同方式一

3、將CMSampleBuffer數據使用VTDecompressionSessionDecodeFrame接口解碼成CVPixelBufferRef數據:

CVPixelBufferRef outputPixelBuffer=NULL;

VTDecompressionSessionDecodeFrame(_deocderSession,

sampleBuffer,

flags,

&outputPixelBuffer,

&flagOut);

4、將CVPixelBufferRef數據轉換成UIImage并顯示:

CIImage*ciImage= [CIImage imageWithCVPixelBuffer:outputPixelBuffer];UIImage*uiImage= [UIImage imageWithCIImage:ciImage];

三、程序流程框圖:

解碼方式一

解碼方式二

四、兩種解碼方式比較:

解碼方式一:

優點: 該方式通過系統提供的AVSampleBufferDisplayLayer顯示層來解碼并顯示。該層內置了硬件解碼功能,將原始的CMSampleBuffer解碼后的圖像直接顯示在屏幕上,非常的簡單方便,且執行效率高,占用內存相對較少。

缺點: 從解碼的數據中不能直接獲取圖像數據并對其做相應處理,解碼后的數據不能直接進行其他方面的應用(一般要做較復雜的轉換)。

解碼方式二:

優點: 該方式通過VTDecompressionSessionDecodeFrame接口,得到CVPixelBufferRef數據,我們可以直接從CVPixelBufferRef數據中獲取圖像數據并對其做相應處理,方便于其他應用。

缺點: 解碼中執行效率相對降低,占用的內存也會相對較大。

').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('

').text(i)); }; $numbering.fadeIn(1700); }); });

以上就介紹了iOS系統中H264硬解及顯示說明,包括了方面的內容,希望對IOS開發有興趣的朋友有所幫助。


加一條個人github上demo地址:h264硬解碼demo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • iOS系統中H264硬解及顯示說明蘋果在iOS 8.0系統之前,沒有開放系統的硬件編碼解碼功能,不過Mac OS系...
    rogerwu1228閱讀 1,896評論 0 4
  • 公司項目原因,接觸了一下視頻流H264的編解碼知識,之前項目使用的是FFMpeg多媒體庫,利用CPU做視頻的編碼和...
    sillen閱讀 805評論 0 6
  • 近期開始學習H264的視頻流解析。寫此文章,作為記錄,也梳理下相應的知識點。 1. 解碼前我們先看一下H264的部...
    E31231V3閱讀 2,068評論 0 1
  • 硬件編碼相關知識(H264,H265) 閱讀人群:研究硬件編碼器應用于iOS開發中,從0研究關于硬件編解碼,碼流中...
    小東邪啊閱讀 12,830評論 0 18
  • 當一個視圖控制器被創建,并在屏幕上顯示的時候。 代碼的執行順序 1、 alloc ...
    KimiY閱讀 304評論 0 0