iOS11系统增加了对HEVC视频格式,对于调用AVFoundation里的系统API实现视频播放编辑的应用不需要做任何适配,系统API已经很好的兼容了HEVC视频格式。但是如果使用了FFmpeg做跨平台开发,或是使用到VideoToolbox做视频硬解,就必须做适配了。
创建VideoToolBox
VideoToolBox解码需要调用VTDecompressionSessionCreate方法创建session,创建session时需要CMVideoFormatDescriptionRef类型的视频格式描述。
对于解码H264视频,做法是调用CMVideoFormatDescriptionCreateFromH264ParameterSets方法,传入SPS,PPS完成创建。
对于解码HEVC视频,需要调用iOS11新提供的接口CMVideoFormatDescriptionCreateFromHEVCParameterSets创建。所以,我们的主要任务是获取HEVC视频的ParameterSets,调用上述接口,剩下的工作就和解码H264视频一样了。
获取ParameterSets
HEVC视频存放SPS,PPS的数据结构与H264类似
官方定义参考 https://lists.matroska.org/pipermail/matroska-devel/2013-September/004567.html
HEVCDecoderConfigurationRecord:
// The CodecPrivate syntax shall follow the
// syntax of HEVCDecoderConfigurationRecord
// defined in ISO/IEC 14496-15.
//
// The number zero (0) shall be written to
// the configurationVersion variable until
// official finalization of 14496-15, 3rd ed.
//
// After its finalization, this field and the
// following CodecPrivate structure shall
// follow the definition of the
// HEVCDecoderConfigurationRecord in 14496-15.
unsigned int(8) configurationVersion;
unsigned int(2) general_profile_space;
unsigned int(1) general_tier_flag;
unsigned int(5) general_profile_idc;
unsigned int(32) general_profile_compatibility_flags;
unsigned int(48) general_constraint_indicator_flags;
unsigned int(8) general_level_idc;
bit(4) reserved = ‘1111’b;
unsigned int(12) min_spatial_segmentation_idc;
bit(6) reserved = ‘111111’b;
unsigned int(2) parallelismType;
bit(6) reserved = ‘111111’b;
unsigned int(2) chromaFormat;
bit(5) reserved = ‘11111’b;
unsigned int(3) bitDepthLumaMinus8;
bit(5) reserved = ‘11111’b;
unsigned int(3) bitDepthChromaMinus8;
bit(16) avgFrameRate;
bit(2) constantFrameRate;
bit(3) numTemporalLayers;
bit(1) temporalIdNested;
unsigned int(2) lengthSizeMinusOne;
unsigned int(8) numOfArrays;
for (j=0; j < numOfArrays; j++) {
bit(1) array_completeness;
unsigned int(1) reserved = 0;
unsigned int(6) NAL_unit_type;
unsigned int(16) numNalus;
for (i=0; i< numNalus; i++) {
unsigned int(16) nalUnitLength;
bit(8*nalUnitLength) nalUnit;
}
}
存放在extradata中,对应FFmpeg中AVCodecContext结构体的extradata数据段。
我们需要解析其中的SPS,PPS,VPS,作为ParameterSets传给解码器完成创建工作。从上述的定义我们可以直接跳过21个字节,遍历之后的数据段,根据的NAL_unit_type类型32、33、34别对应VPS、SPS和PPS,获取所有SPS,PPS,VPS。
剩下的就和解码H264无任何区别了,VideoToolBox解码网上有很多demo,这里就不在赘述。