一、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));
- 如果使用H.264编码功能,参数
codecType
需要设置为kCMVideoCodecType_H264
; - 如果使用H.265编码功能,参数
codecType
需要设置为kCMVideoCodecType_HEVC
;
其他参数在使用两种编码格式时没有区别。
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 |
+------------ - +---------------- - +
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)硬编码/硬解码功能开发指南