zoukankan      html  css  js  c++  java
  • H.264格式,iOS硬编解码 以及 iOS 11对HEVC硬编解码的支持

    H.264格式,iOS硬编解码 以及 iOS 11对HEVC硬编解码的支持

    1,H.264格式

    网络表示层NAL,如图H.264流由一帧一帧的NALU组成; 
    SPS:序列参数集,作用于一系列连续的编码图像; 
    PPS:图像参数集,作用于编码视频序列中一个或多个独立的图像; 
    这两个帧也是独立的NALU。

    I-Frame:关键帧,帧内编码后的帧,显示比较完全的一帧; 
    P-Frame:参考前一帧,可能只是对比前一帧的运动估计的变化部分; 
    B-Frame:会参照前后的帧,其他类似P-Frame。B和P Frame均包含了 帧间编码帧内编码。 
    每个NALU以 start code 分隔:00 00 01(3 bytes) 或 00 00 00 01(4 bytes)。

    2,iOS对H.264硬编解码

    iOS 8以后通过VideoToolBox支持对H.264的硬编码; 
    其中的CMSampleBufferRef结构很有意思,需要理解,如图


    CMVideoFormatDesc中含有SPS,PPS和其他有用信息;

    • 编码时,CVPixelBuffer—>CMSampleBufferRef(其中包含已压缩的CMBlockBuffer);
    • 解码时,通过VTDecompressionSession来解码, CMSampleBufferRef(内含CMBlockBuffer)—>CVImageBufferRef(解码后的帧数据);

    2.1 编码

    下图参照WWDC 2014的PDF,从相机或读取视频文件输出的CVPixelBuffer—>Encoder—>CMSampleBufferRef—>NALUs。

    经典的编码器 推荐直播推流的LFLiveKit,代码结构良好,数据流向非常清晰,很适合阅读; 
    https://github.com/LaiFengiOS/LFLiveKit/blob/master/LFLiveKit/coder/LFHardwareVideoEncoder.m
    编码步骤大致是:

    • 1,VTCompressionSessionCreate 通过宽,高,codecType(kCMVideoCodecType_H264),编码回调VTCompressionOutputCallback 等初始化VTCompressionSessionRef实例compressionSession;
    • 2,VTSessionSetProperty设置比较重要的编码属性,如 
      kVTCompressionPropertyKey_MaxKeyFrameInterval,关键帧间隔 
      kVTCompressionPropertyKey_RealTime 
      kVTCompressionPropertyKey_AverageBitRate 
      kVTCompressionPropertyKey_ProfileLevel 
      kVTCompressionPropertyKey_AllowFrameReordering等;最后VTCompressionSessionPrepareToEncodeFrames;
    • 3,往 VTCompressionSessionEncodeFrame添加原始CVPixelBuffer和pts
    根据frameCount 计算出的pts
    CMTime presentationTimeStamp = CMTimeMake(frameCount, (int32_t)_configuration.videoFrameRate);

    和是否I-Frame:

    if (frameCount % (int32_t)_configuration.videoMaxKeyframeInterval == 0) {
      properties = @{(__bridge NSString *)kVTEncodeFrameOptionKey_ForceKeyFrame: @YES};
    }
    • 4,VTCompressionOutputCallback回调中通过解析 CMSampleBufferRef 分别处理SPS,PPS,I-Frame和非I-Frame,添加startcode: 00 00 00 01 然后通过RTMP推出去。

    2.2 解码

    编码的逆过程,通常在播放器等场景应用,NALU + SPS,PPS—>CMBlockBuffer—>CMSampleBufferRef,再将CMSampleBufferRef包装的帧数据输入到 VTDecompressionSessionDecodeFrame,通过回调中CVImageBufferRef 直接上传OpenGL ES 显示)。 
    我写了一个简单的iOS H.264 stream decoder: 
    https://github.com/edisongz/ffmpeg_codec_demo

    3,iOS 11 对HEVC的支持

    iOS 11 + A9芯片开始对HEVC的支持,系统控件AVPlayer,以及Safari浏览器的支持;HEVC相对于H.264压缩效率高40%。 
    硬编码需要iOS11 + A10芯片

    硬解码需要iOS 11 + A9芯片

    iOS 11 新API

    //decoder
    let hardwareDecodeSupported = VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)
    
    //encoder
    let error = VTCompressionSessionCreate(
     kCFAllocatorDefault,
     3840, 2160,
     kCMVideoCodecType_HEVC,
     encoderSpecification,
     nil, nil, nil, nil, // using VTCompressionSessionEncodeFrameWithOutputHandler
     &session);
    if error == kVTCouldNotFindVideoEncoderErr {
        // no HEVC encoder
    }

    具体的HEVC的VideoToolBox的硬件编解码还有待完善;后续完成会添加到这里: 
    https://github.com/edisongz/ffmpeg_codec_demo

    小结

    H.264 iOS环境下的硬编解码都是比较老的WWDC的session了,今年的WWDC 2017,增加的硬编解码HEVC代码,还需要找一台机器测试下。

  • 相关阅读:
    1028 List Sorting (25分)
    CSS通用样式类讲解
    异常处理机制
    修饰符及接口和内部类
    用python实现基础的数据类型
    类属性和实例化属性
    命名空间和作用域
    python super()函数有无参数的调用
    编写html页面常常犯的错误
    多态
  • 原文地址:https://www.cnblogs.com/edisongz/p/7062098.html
Copyright © 2011-2022 走看看