iOS HEVC(H.265)

2018-07-23  本文已影响500人  Goning

一、HEVC(H.265)介绍

HEVC全称High Efficiency Video Coding(高效率视频编码),是比H.264更加优秀的一种视频压缩标准(也称为H.265)。H.265的压缩性能要高于H.264一倍左右。
苹果于北京时间2017年6月6日凌晨召开的WWDC 2017大会上推出了iOS 11系统,并推出了使用VideoToolBox对H.265的硬编硬解的支持。
但是并不是所有的iOS设备升级到iOS 11都可以使用H.265的硬编/解功能,H.265硬解最少需要A9芯片的iPhone 6s/iPhone 6s Plus/iPhone SE,H.265硬编则最少需要A10芯片的iPhone 7/iPhone 7 Plus。


二、VideoToolBox编码

使用VideoToolBox进行H.264和H.265编码的流程完全相同,只在创建和配置编码器上存在少量差异,下面以VideoToolBox的编码流程为线索,说明使用两种编码格式时的区别。

1. 创建VTCompressionSession
VT_EXPORT OSStatus 
VTCompressionSessionCreate(
    CM_NULLABLE CFAllocatorRef                          allocator,
    int32_t                                             width,
    int32_t                                             height,
    CMVideoCodecType                                    codecType,
    CM_NULLABLE CFDictionaryRef                         encoderSpecification,
    CM_NULLABLE CFDictionaryRef                         sourceImageBufferAttributes,
    CM_NULLABLE CFAllocatorRef                          compressedDataAllocator,
    CM_NULLABLE VTCompressionOutputCallback             outputCallback,
    void * CM_NULLABLE                                  outputCallbackRefCon,
    CM_RETURNS_RETAINED_PARAMETER CM_NULLABLE VTCompressionSessionRef * CM_NONNULL compressionSessionOut) API_AVAILABLE(macosx(10.8), ios(8.0), tvos(10.2));

其他参数在使用两种编码格式时没有区别。

2. 设置编码相关参数
VT_EXPORT OSStatus 
VTSessionSetProperty(
  CM_NONNULL VTSessionRef       session,
  CM_NONNULL CFStringRef        propertyKey,
  CM_NULLABLE CFTypeRef         propertyValue ) API_AVAILABLE(macosx(10.8), ios(8.0), tvos(10.2));

其中在配置kVTCompressionPropertyKey_ProfileLevel属性时,H.264和H.265有各自不同的ProfileLevel定义,与H.265相关的只有两个,如下所示:

VT_EXPORT const CFStringRef kVTProfileLevel_HEVC_Main_AutoLevel API_AVAILABLE(macosx(10.13), ios(11.0), tvos(11.0));
VT_EXPORT const CFStringRef kVTProfileLevel_HEVC_Main10_AutoLevel API_AVAILABLE(macosx(10.13), ios(11.0), tvos(11.0));
3. 启动编码
VT_EXPORT OSStatus
VTCompressionSessionPrepareToEncodeFrames( CM_NONNULL VTCompressionSessionRef session ) API_AVAILABLE(macosx(10.9), ios(8.0), tvos(10.2));
4. 循环输入源数据(yuv类型)
VT_EXPORT OSStatus
VTCompressionSessionEncodeFrame(
    CM_NONNULL VTCompressionSessionRef  session,
    CM_NONNULL CVImageBufferRef         imageBuffer,
    CMTime                              presentationTimeStamp,
    CMTime                              duration, // may be kCMTimeInvalid
    CM_NULLABLE CFDictionaryRef         frameProperties,
    void * CM_NULLABLE                  sourceFrameRefCon,
    VTEncodeInfoFlags * CM_NULLABLE     infoFlagsOut ) API_AVAILABLE(macosx(10.8), ios(8.0), tvos(10.2));
5. 获取编码后的数据

通过在创建VTCompressionSession传入回调函数,获取编码后的数据。

typedef void (*VTCompressionOutputCallback)(
        void * CM_NULLABLE outputCallbackRefCon,
        void * CM_NULLABLE sourceFrameRefCon, 
        OSStatus status, 
        VTEncodeInfoFlags infoFlags,
        CM_NULLABLE CMSampleBufferRef sampleBuffer );

至此针对使用VideoToolBox进行H.264/H.265编码的基本流程已经介绍完毕。


三、VideoToolBox解码

VideoToolBox的解码主要涉及以下几个函数:

VTDecompressionSessionCreate 创建解码session
VTDecompressionSessionDecodeFrame 解码一个frame
VTDecompressionSessionInvalidate 销毁解码session

其中VTDecompressionSessionCreate创建session时需要CMVideoFormatDescriptionRef类型的视频格式描述,而对于CMVideoFormatDescriptionRef,VideoToolBox中提供了多个方法可以创建:

CMVideoFormatDescriptionCreate
CMVideoFormatDescriptionCreateForImageBuffer
CMVideoFormatDescriptionCreateFromH264ParameterSets
CMVideoFormatDescriptionCreateFromHEVCParameterSets

其中最后一个CMVideoFormatDescriptionCreateFromHEVCParameterSets是在iOS11中新增的一个方法,用以创建H.265视频格式的描述。

对于H.264和H.265的解码,在VideoToolBox层面的操作完全一致,唯一不同的就是视频格式的描述类型不同。最常使用也最容易理解的为后两个通过ParameterSets来创建的函数,前两个函数的创建方式未作详细了解。

至此,对使用VideoToolBox解码H.265视频的重点就放在如何获取ParameterSets(即VPS、SPS和PPS)上。


四、H.265 NALU

与H.264的NALU Header相比(H.264的NALU Header为一个字节),H.265的NALU Header由两个字节构成:
0----------------1----------------
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| F | Type | LayerId | TID |
+------------ - +---------------- - +

H265 nalu header

HEVC加入了NAL所在的时间层的ID,去除了nal_ref_idc,此信息合并到了naltype中。通常情况下F为0,layerid为0, TID为1。

类型判断方式为分隔符之后的第一个字节右移一位的值。
所以,H.265编码格式的NALU类型判断方式如下,code为NALU Header的第一个字节:

int type = (code & 0x7E)>>1;

00 00 00 01 40 01 的nuh_unit_type的值为 32, 语义为视频参数集 VPS
00 00 00 01 42 01 的nuh_unit_type的值为 33, 语义为序列参数集 SPS
00 00 00 01 44 01 的nuh_unit_type的值为 34, 语义为图像参数集 PPS
00 00 00 01 4E 01 的nuh_unit_type的值为 39, 语义为补充增强信息 SEI
00 00 00 01 26 01 的nuh_unit_type的值为 19, 语义为可能有RADL图像的IDR图像的SS编码数据 IDR
00 00 00 01 02 01 的nuh_unit_type的值为1, 语义为被参考的后置图像,且非TSA、非STSA的SS编码数据

在编码过程中,从编码器获取码流的时候,1、2、3、4、5是在一帧数据当中。相当于H.264的I帧。


本文主要参考并转载来自于作者:金山视频云
地址:基于iOS11的HEVC(H.265)硬编码/硬解码功能开发指南

上一篇下一篇

猜你喜欢

热点阅读