ios硬編解碼videotoolbox---硬解碼

一、videoToolbox的基本數(shù)據(jù)

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

CVPixelBuffer:編碼前和解碼后的圖像數(shù)據(jù)結(jié)構(gòu)。此內(nèi)容包含一系列的CVPixelBufferPool內(nèi)容

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

pixelBufferAttributes:字典設(shè)置.可能包括Width/height、pixel format type、Compatibility (e.g., OpenGL ES, Core Animation)

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

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

CMTimebase: 關(guān)于CMClock的一個(gè)控制視圖,包含CMClock、時(shí)間映射(Time mapping)、速率控制(Rate control)

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

編碼前后的視頻圖像都封裝在 CMSampleBuffer中,編碼前以 CVPixelBuffer 進(jìn)行存儲(chǔ);編碼后以 CMBlockBuffer進(jìn)行存儲(chǔ)。除此之外兩者都括 CMTim 、 CMVideoFormatDesc。

二、硬解碼基本流程

1、由sps和pps創(chuàng)建CMVideoFormatDescription,每次重新來(lái)sps和pps都要重新創(chuàng)建。

const uint8_t* parameterSetPointers[2] = {mSPS, mPPS};
const size_t parameterSetSizes[2] = {mSPSSize, mPPSSize};
OSStatus status = 
CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,
                                                                 2, //param count
                                                                 parameterSetPointers,
                                                                 parameterSetSizes,
                                                                 4, //nal start code size
                                                                 &mFormatDescription);

2、由CMVideoFormatDescription創(chuàng)建mDecodeSession,以及指定獲取解碼數(shù)據(jù)的回調(diào)函數(shù)。創(chuàng)建解碼會(huì)話需要提供回調(diào)函數(shù)以便系統(tǒng)解碼完成時(shí)將解碼數(shù)據(jù)、狀態(tài)等信息返回給用戶。

            CFDictionaryRef attrs = NULL;
            const void *keys[] = { kCVPixelBufferPixelFormatTypeKey };
            //      kCVPixelFormatType_420YpCbCr8Planar is YUV420
            //      kCVPixelFormatType_420YpCbCr8BiPlanarFullRange is NV12
            uint32_t v = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange;
            const void *values[] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &v) };
            attrs = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
            
            VTDecompressionOutputCallbackRecord callBackRecord;
            callBackRecord.decompressionOutputCallback = didDecompress;
            callBackRecord.decompressionOutputRefCon = NULL;
//這個(gè)是用來(lái)做異步解碼實(shí)現(xiàn)的,decompressionOutputRefCon 為需要指定的對(duì)象,即自己。didDecompress則為回調(diào)函數(shù)。
            
            status = VTDecompressionSessionCreate(kCFAllocatorDefault,
                                                  mFormatDescription,
                                                  NULL, attrs,
                                                  &callBackRecord,
                                                  &mDecodeSession);
            CFRelease(attrs);

3、由編碼的數(shù)據(jù)(I、P、B幀數(shù)據(jù))創(chuàng)建CMBlockBuffer。

 CMBlockBufferRef blockBuffer = NULL;
 OSStatus status  = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
                                                      (void*)packetBuffer, packetSize,
                                                      kCFAllocatorNull,
                                                      NULL, 0, packetSize,
                                                      0, &blockBuffer);

4、由CMBlockBuffer和CMVideoFormatDescription創(chuàng)建CMSampleBuffer

CMSampleBufferRef sampleBuffer = NULL;
const size_t sampleSizeArray[] = {packetSize};
status = CMSampleBufferCreateReady(kCFAllocatorDefault,
                                               blockBuffer,
                                               mFormatDescription,
                                               1, 0, NULL, 1, sampleSizeArray,
                                               &sampleBuffer);

5、解碼
VideoToolbox支持同、異步解碼,由VTDecodeFrameFlags指定,VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression; ,默認(rèn)為同步解碼。
同步解碼時(shí),調(diào)用解碼函數(shù) VTDecompressionSessionDecodeFrame 后系統(tǒng)回調(diào)我們提供的回調(diào)函數(shù),然后解碼函數(shù)才結(jié)束調(diào)用。異步解碼則回調(diào)順序不確定,故需要自行整理幀序。

VTDecodeFrameFlags flags = 0;
VTDecodeInfoFlags flagOut = 0;
// 默認(rèn)是同步操作。
// 調(diào)用didDecompress,返回后再回調(diào)
OSStatus decodeStatus = VTDecompressionSessionDecodeFrame(mDecodeSession,
                                           sampleBuffer,
                                           flags,
                                           &outputPixelBuffer,//輸出解碼數(shù)據(jù)
                                           &flagOut);

6、異步解碼回調(diào),調(diào)用解碼函數(shù)后回掉函數(shù)didDecompress,用來(lái)獲取解碼出的數(shù)據(jù)。

void didDecompress(void *decompressionOutputRefCon, void *sourceFrameRefCon, 
OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef pixelBuffer, 
CMTime presentationTimeStamp, CMTime presentationDuration ){

    CVPixelBufferRef *outputPixelBuffer = (CVPixelBufferRef *)sourceFrameRefCon;

    *outputPixelBuffer = CVPixelBufferRetain(pixelBuffer);

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 四、視頻的編解碼-編碼篇 時(shí)間2016-08-05 10:22:59Twenty's 時(shí)間念 原文http://b...
    吳霸格07閱讀 3,918評(píng)論 2 3
  • 公司項(xiàng)目原因,接觸了一下視頻流H264的編解碼知識(shí),之前項(xiàng)目使用的是FFMpeg多媒體庫(kù),利用CPU做視頻的編碼和...
    Ethan_Struggle閱讀 35,403評(píng)論 29 124
  • 公司項(xiàng)目原因,接觸了一下視頻流H264的編解碼知識(shí),之前項(xiàng)目使用的是FFMpeg多媒體庫(kù),利用CPU做視頻的編碼和...
    sillen閱讀 849評(píng)論 0 6
  • 我們?cè)诠ぷ髦谢蚨嗷蛏俣加型涎拥拿?,明知道拖延不?duì),可就是控制不住自己,這就是你的惰性心態(tài)在搗鬼。 工作中的惰性心...
    走之兔閱讀 2,664評(píng)論 3 15
  • 滔滔滔江水,溺不住玫瑰的芬芳,抬起頭,揣起迷茫,讓星似的寄語(yǔ),冉冉踏浪。 如果你是真正的船長(zhǎng),我愿伴你遠(yuǎn)航,在風(fēng)囗...
    甘露GL閱讀 736評(píng)論 20 12

友情鏈接更多精彩內(nèi)容