一、HEVC(H.265)介紹
HEVC全稱High Efficiency Video Coding(高效率視頻編碼)餐茵,是比H.264更加優(yōu)秀的一種視頻壓縮標(biāo)準(zhǔn)(也稱為H.265)休吠。H.265的壓縮性能要高于H.264一倍左右廊宪。
蘋果于北京時(shí)間2017年6月6日凌晨召開的WWDC 2017大會上推出了iOS 11系統(tǒng)爪喘,并推出了使用VideoToolBox對H.265的硬編硬解的支持。
但是并不是所有的iOS設(shè)備升級到iOS 11都可以使用H.265的硬編/解功能根盒,H.265硬解最少需要A9芯片的iPhone 6s/iPhone 6s Plus/iPhone SE,H.265硬編則最少需要A10芯片的iPhone 7/iPhone 7 Plus物蝙。
二郑象、VideoToolBox編碼
使用VideoToolBox進(jìn)行H.264和H.265編碼的流程完全相同,只在創(chuàng)建和配置編碼器上存在少量差異茬末,下面以VideoToolBox的編碼流程為線索,說明使用兩種編碼格式時(shí)的區(qū)別盖矫。
1. 創(chuàng)建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編碼功能丽惭,參數(shù)
codecType
需要設(shè)置為kCMVideoCodecType_H264
; - 如果使用H.265編碼功能辈双,參數(shù)
codecType
需要設(shè)置為kCMVideoCodecType_HEVC
;
其他參數(shù)在使用兩種編碼格式時(shí)沒有區(qū)別责掏。
2. 設(shè)置編碼相關(guān)參數(shù)
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
屬性時(shí),H.264和H.265有各自不同的ProfileLevel定義湃望,與H.265相關(guān)的只有兩個(gè)换衬,如下所示:
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. 啟動(dòng)編碼
VT_EXPORT OSStatus
VTCompressionSessionPrepareToEncodeFrames( CM_NONNULL VTCompressionSessionRef session ) API_AVAILABLE(macosx(10.9), ios(8.0), tvos(10.2));
4. 循環(huán)輸入源數(shù)據(jù)(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. 獲取編碼后的數(shù)據(jù)
通過在創(chuàng)建VTCompressionSession
傳入回調(diào)函數(shù),獲取編碼后的數(shù)據(jù)证芭。
typedef void (*VTCompressionOutputCallback)(
void * CM_NULLABLE outputCallbackRefCon,
void * CM_NULLABLE sourceFrameRefCon,
OSStatus status,
VTEncodeInfoFlags infoFlags,
CM_NULLABLE CMSampleBufferRef sampleBuffer );
至此針對使用VideoToolBox進(jìn)行H.264/H.265編碼的基本流程已經(jīng)介紹完畢瞳浦。
三、VideoToolBox解碼
VideoToolBox的解碼主要涉及以下幾個(gè)函數(shù):
VTDecompressionSessionCreate 創(chuàng)建解碼session
VTDecompressionSessionDecodeFrame 解碼一個(gè)frame
VTDecompressionSessionInvalidate 銷毀解碼session
其中VTDecompressionSessionCreate
創(chuàng)建session時(shí)需要CMVideoFormatDescriptionRef
類型的視頻格式描述废士,而對于CMVideoFormatDescriptionRef
叫潦,VideoToolBox中提供了多個(gè)方法可以創(chuàng)建:
CMVideoFormatDescriptionCreate
CMVideoFormatDescriptionCreateForImageBuffer
CMVideoFormatDescriptionCreateFromH264ParameterSets
CMVideoFormatDescriptionCreateFromHEVCParameterSets
其中最后一個(gè)CMVideoFormatDescriptionCreateFromHEVCParameterSets
是在iOS11中新增的一個(gè)方法,用以創(chuàng)建H.265視頻格式的描述官硝。
對于H.264和H.265的解碼矗蕊,在VideoToolBox層面的操作完全一致,唯一不同的就是視頻格式的描述類型不同氢架。最常使用也最容易理解的為后兩個(gè)通過ParameterSets來創(chuàng)建的函數(shù)傻咖,前兩個(gè)函數(shù)的創(chuàng)建方式未作詳細(xì)了解。
至此岖研,對使用VideoToolBox解碼H.265視頻的重點(diǎn)就放在如何獲取ParameterSets(即VPS卿操、SPS和PPS)上。
四孙援、H.265 NALU
與H.264的NALU Header相比(H.264的NALU Header為一個(gè)字節(jié))硬纤,H.265的NALU Header由兩個(gè)字節(jié)構(gòu)成:
0----------------1----------------
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| F | Type | LayerId | TID |
+------------ - +---------------- - +
HEVC加入了NAL所在的時(shí)間層的ID,去除了nal_ref_idc赃磨,此信息合并到了naltype中筝家。通常情況下F為0,layerid為0, TID為1邻辉。
類型判斷方式為分隔符之后的第一個(gè)字節(jié)右移一位的值溪王。
所以腮鞍,H.265編碼格式的NALU類型判斷方式如下,code為NALU Header的第一個(gè)字節(jié):
int type = (code & 0x7E)>>1;
00 00 00 01 40
01 的nuh_unit_type的值為 32
莹菱, 語義為視頻參數(shù)集 VPS
00 00 00 01 42
01 的nuh_unit_type的值為 33
移国, 語義為序列參數(shù)集 SPS
00 00 00 01 44
01 的nuh_unit_type的值為 34
, 語義為圖像參數(shù)集 PPS
00 00 00 01 4E
01 的nuh_unit_type的值為 39
道伟, 語義為補(bǔ)充增強(qiáng)信息 SEI
00 00 00 01 26
01 的nuh_unit_type的值為 19
迹缀, 語義為可能有RADL圖像的IDR圖像的SS編碼數(shù)據(jù) IDR
00 00 00 01 02
01 的nuh_unit_type的值為1
, 語義為被參考的后置圖像蜜徽,且非TSA祝懂、非STSA的SS編碼數(shù)據(jù)
在編碼過程中,從編碼器獲取碼流的時(shí)候拘鞋,1砚蓬、2、3盆色、4灰蛙、5是在一幀數(shù)據(jù)當(dāng)中。相當(dāng)于H.264的I幀隔躲。
本文主要參考并轉(zhuǎn)載來自于作者:金山視頻云
地址:基于iOS11的HEVC(H.265)硬編碼/硬解碼功能開發(fā)指南