天天看點

IOS 視訊寫死H.264VTCompressionSession Summary

前言

在學習了落影大神的相關部落格及WWDC有關編解碼的視訊後準備總結下所思所得,先寫有關寫死的内容之後會再寫關于硬解碼的内容.

概念簡要

衆所周知,我們平時在網絡上收看視訊會經曆視訊編碼及解碼的過程.編碼是為了減小視訊網絡傳輸消耗的資源,解碼是為了将壓縮後的視訊恢複成可以觀看的格式,目前編碼大多采用的是H.264規格.

H.264是一種廣為認可的編碼格式, 包含由一系列NALU組成的碼流,這些NALU承載着SPS,PPS,I Frame,P Frame,B Frame資訊,其組成如下圖圖一(圖源資料來自WWDC).其中SPS,即Sequence Parameter Set(序列參數集)以及PPS, Picture Parameter Set(圖像參數集)在I幀中擷取.I幀為關鍵幀,在序列中處于關鍵位置,為後面的P幀乃至B幀提供參考對象(編碼中有關空間編碼與時間編碼這裡不作贅述).

IOS 視訊寫死H.264VTCompressionSession Summary

                                                                                                             圖一

編碼周知

IOS提供了VideoToolbox來處理有關視訊編解碼内容,其中提供編碼作用的是VTCompressionSession,相應解碼為VTDecompressionSession.

1.針對編碼所需了解的概念:

  • CVPixelBuffers :存儲未壓縮像素緩存
  • CMSampleBuffers :存儲壓縮或未壓縮像素緩存

2.編碼資料導向流程

       将CVPixelBuffers裡視訊内容經由VTCompression Session相應編碼處理後将編碼後的資料儲存在CMSampleBuffers,再将其上傳網絡傳輸等.如下圖圖二所示

IOS 視訊寫死H.264VTCompressionSession Summary

                                                                                                    圖二

編碼實作

第一:建立VTCompressionSession

利用VTCompressionSessionCreate()建立VTCompressionSession,主要有以下幾個參數

  1. 編碼後輸出資料尺寸
  2. 編碼格式,如(kCMVideoCodecType_H264)
  3. PixelBufferAttributes(可選)
  4. 編碼輸出回調方法(VTCompressionOutputCallback)

第二:配置VTCompressionSession

利用VTSessionSetProperty() 配置VTCompressionSession相關參數,如:

kVTCompressionPropertyKeyAllowFrameReordering 

kVTCompressionPropertyKeyAverageBitRate

kVTCompressionPropertyKeyH264EntropyMode 

kVTH264EntropyModeCAVLC/kVTH264EntropyModeCABAC 

kVTCompressionPropertyKeyRealTime 

kVTCompressionPropertyKey_ProfileLevel

第三:對硬體捕獲到的資料進行編碼

利用VTCompressionSessionEncodeFrame()對資料進行編碼,這裡有代碼如下,可先從捕捉到的CMSampleBufferRef中擷取未壓縮的CVImageBufferRef資料,再調用壓縮方法進行編碼.

注:用 VTCompressionSessionCompleteFrames()方法結束編碼.

- (void) encode:(CMSampleBufferRef )sampleBuffer
{
    CVImageBufferRef imageBuffer = (CVImageBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
    // 幀時間,如果不設定會導緻時間軸過長。
    CMTime presentationTimeStamp = CMTimeMake(frameID++, 1000);
    VTEncodeInfoFlags flags;
    OSStatus statusCode = VTCompressionSessionEncodeFrame(EncodingSession,
                                                          imageBuffer,
                                                          presentationTimeStamp,
                                                          kCMTimeInvalid,
                                                          NULL, NULL, &flags);
    if (statusCode != noErr) {
        NSLog(@"H264: VTCompressionSessionEncodeFrame failed with %d", (int)statusCode);
        
        VTCompressionSessionInvalidate(EncodingSession);
        CFRelease(EncodingSession);
        EncodingSession = NULL;
        return;
    }
    NSLog(@"H264: VTCompressionSessionEncodeFrame Success");
}
           

第四:VTCompressionOutputCallback

功能

VTCompressionOutputCallback 相應函數中主要作用是應實作将編碼後得到的 CMSampleBuffers資料轉換到H.264基礎碼流包功能.(咳咳,總感覺這句話還是看看英文的好 ,Converting CMSampleBuffers into H.264 elementary stream packaging).其流程功能如圖三圖四所示

IOS 視訊寫死H.264VTCompressionSession Summary

                                                                                                     圖三

IOS 視訊寫死H.264VTCompressionSession Summary

                                                                                                    圖四

具體實作

  • 轉變參數集

利用CMVideoFormatDescriptionGetH264ParameterSetAtIndex()分别将CMVideoFormatDescription中的SPS以及PPS單獨擷取出來,當然這是針對I幀操作的.

  • 更改NAL Unit headers 需要将每個NALU 頭部由00 00 80 00 更改為 00 00 01 或00 00 00 01

    VTCompressionSession Summary

    Creation of VTCompressionSession

    Configuring the compressor

    Providing CVPixelBuffers to VTCompressionSession

    Converting CMSampleBuffers into H.264 elementary stream packaging 

    這是最後有關VTCompressionSession總結,寫的太好,我就不班門弄斧了.

繼續閱讀