iOS硬解码H264视频流

        苹果在iOS 8.0系统之前若要做音视频开发需使用第三方软件进行编解码(FFmpeg软解码H264视频流可看到这里),学习成本较大,项目开发进度也可能超出预期。在iOS 8.0之后开放了视频编解码框架VideoToolbox,在此之后对于音视频开发变得相对简单。

 

 

 

一、硬解码名词(结构)解释

1、VTDecompressionSessionRef:解码器对象数据结构;

2、CMVideoFormatDescriptionRef:图形解码相关格式及描述;

3、CVPixelBufferRef:编码前和解码后的图像数据结构;

4、CMBlockBufferRef:存在解码前图像数据内存结构;

5、CMSampleBufferRef:存放解码前的视频图像的容器数据结构;

6、AVSampleBufferDisplayLayer:以CMSampleBufferRef进行解码并显示Layer图层;

7、SPSPPS:h.264解码参数信息;IDR:h.264视频流I帧;

二、H264硬解码流程图

 

三:IDR(I帧)网络裸流数据结构

        一般情况下网络视频裸流I帧中基本会包含SPS、PPS、SEI、IDR帧数据,如下图所示,但是部分只含有IDR帧数据,其他解码参数信息被单独已Slice获取。

 

四、硬解码相关接口

 

1、初始化H264硬解解码器

1)使用CMVideoFormatDescriptionCreateFromH264ParameterSets函数构建解码描述结构CMVideoFormatDescriptionRef

    const uint8_t *const parameterSetPointers[2] = {pSPS,pPPS};
    const size_t parameterSetSizes[2] = {mSpsSize, mPpsSize};
    
    OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,
                                                                          2,    //参数个数,主要包含SPS、PPS
                                                                          parameterSetPointers,
                                                                          parameterSetSizes,
                                                                          4,    //NALU起始位个数
                                                                          &mDecoderFormatDescription);

2)使用VTDecompressionSessionCreate函数构建解码器结构VTDecompressionSessionRef

 

    uint32_t pixelFormatType = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange;  //NV12
    const void *keys[] = { kCVPixelBufferPixelFormatTypeKey };
    const void *values[] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &pixelFormatType) };    //32位
    CFDictionaryRef attrs = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    
    VTDecompressionOutputCallbackRecord callBackRecord;
    callBackRecord.decompressionOutputCallback = didDecompress;    
    callBackRecord.decompressionOutputRefCon = NULL;
    
    status = VTDecompressionSessionCreate(kCFAllocatorDefault,
                                          mDecoderFormatDescription,
                                          NULL, attrs,
                                          &callBackRecord,
                                          &mDeocderSession);
    CFRelease(attrs);

2、H264硬件解码

1)将视频裸流数据构建成CMBlockBufferRef,主要目的是进一步转换为CMSampleBufferRef

    CMBlockBufferRef blockBuffer = NULL;
    OSStatus status  = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, (void *)videoBuffer, videoBufferSize, kCFAllocatorNull, NULL, 0, videoBufferSize, 0, &blockBuffer);
    CMSampleBufferRef sampleBuffer = NULL;
    const size_t sampleSizeArray[] = { videoBufferSize };
    OSStatus status = CMSampleBufferCreateReady(kCFAllocatorDefault, blockBuffer, mDecoderFormatDescription , 1, 0, NULL, 1, sampleSizeArray, &sampleBuffer);

2)将CMSampleBufferRef结构送入VTDecompressionSessionDecodeFrame函数进行解码处理:

    VTDecodeFrameFlags flags = 0;
    VTDecodeInfoFlags flagOut = 0;
    CVPixelBufferRef outputPixelBuffer = NULL;
    OSStatus decodeStatus = VTDecompressionSessionDecodeFrame(mDeocderSession, sampleBuffer, flags, &outputPixelBuffer, &flagOut);

3)若使用AVSampleBufferDisplayLayer图层进行直接显示,可忽略上一步的还行,直接将CMSampleBufferRef送入AVSampleBufferDisplayLayer进行显示:

    CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
    CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
    CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
    if ([self.displayLayer isReadyForMoreMediaData]) {
        @weaki
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值