蘋果于北京時間2017年6月6日凌晨召開WWDC 2017大會,在此次發(fā)布會上按照慣例推出了iOS 11系統(tǒng),同時也帶來了許多新鮮特性粒梦,如錄屏功能晦嵌、相冊查看gif圖片同辣、Siri支持翻譯等拷姿。作為音視頻開發(fā)者,我們更著重關注的是此次蘋果為iPhone為推出了兩種全新的媒體格式"HEVC和HEIF":視頻方面使用HEVC來代替H.264旱函,而圖片則是用HEIF來代替JPG响巢。這兩種格式號稱可以在保證畫質的情況下,大大減少視頻棒妨、照片的大小踪古,經常因為容量不足而頭疼的朋友將成為最大受益者逛万。
由此可見迟蜜,如果在直播過程中使用H.265的視頻編碼格式庇勃,可使用較少的帶寬征炼,得到更優(yōu)的畫質疫粥。在iOS系統(tǒng)推出H.265的硬編硬解功能之前牲尺,我們在iphone手機上使用的H.265編解碼功能活翩,均為軟件編解碼畜埋,其缺點是cpu占用高辱魁,手機發(fā)熱量大烟瞧,無法支撐高分辨、高幀率的實時場景商叹。相信此次iOS11的發(fā)布燕刻,會推動H.265在直播市場的發(fā)展。
本文我們會著重介紹如果在iOS11上使用系統(tǒng)API進行265硬編硬解功能剖笙,讀者需要有使用VideoToolBox進行H.264硬編/解碼的相關經驗卵洗。
一、什么是HEVC(H.265)
HEVC全稱High Efficiency Video Coding(高效率視頻編碼)弥咪,是比H.264更加優(yōu)秀的一種視頻壓縮標準(也稱為H.265)过蹂。HEVC在低碼率視頻壓縮上,提升質量聚至、減少容量和節(jié)省帶寬方面都有突出表現(xiàn)酷勺,因此除了拍攝占用的容量減少外,在視頻通話時也能更加流暢清晰扳躬。據9to5Mac的測試結果脆诉,原來的H.264標準需要需要60MB才能達到的畫質,HEVC僅需要33MB贷币。從下圖的壓縮效果可以看出击胜,HEVC的壓縮算法更加智能,雖然圖片細節(jié)丟失的情況更高役纹,但是卻不會嚴重影響視頻的畫質偶摔。
需要注意的是,H.265的硬編/解功能促脉,并不是ios的所有設備升級到新系統(tǒng)上都可以使用辰斋,目前蘋果公布可使用HEVC編/解碼的移動設備要求如下:
iOS 11 HEVC Encode
iOS 11 HEVC Decode
二策州、VideoToolBox編碼
使用VideoToolBox進行H.264和H.265編碼的流程完全相同,只在創(chuàng)建和配置編碼器上存在少量差異宫仗,下面以VideoToolBox的編碼流程為線索够挂,說明使用兩種編碼格式時的區(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
需要設置為kCMVideoCodecType_H264
下硕; - 如果使用H.265編碼功能,參數(shù)
codecType
需要設置為kCMVideoCodecType_HEVC
;
其他參數(shù)在使用兩種編碼格式時沒有區(qū)別汁胆。
2. 設置編碼相關參數(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
屬性時梭姓,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. 循環(huán)輸入源數(shù)據(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ù)據
通過在創(chuàng)建VTCompressionSession
傳入回調函數(shù)誉尖,獲取編碼后的數(shù)據。
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的解碼主要涉及以下幾個函數(shù):
VTDecompressionSessionCreate 創(chuàng)建解碼session
VTDecompressionSessionDecodeFrame 解碼一個frame
VTDecompressionSessionInvalidate 銷毀解碼session
其中VTDecompressionSessionCreate
創(chuàng)建session時需要CMVideoFormatDescriptionRef
類型的視頻格式描述,而對于CMVideoFormatDescriptionRef
丢间,VideoToolBox中提供了多個方法可以創(chuàng)建:
CMVideoFormatDescriptionCreate
CMVideoFormatDescriptionCreateForImageBuffer
CMVideoFormatDescriptionCreateFromH264ParameterSets
在iOS11中新增了一個方法:
CMVideoFormatDescriptionCreateFromHEVCParameterSets
用以創(chuàng)建H.265視頻格式的描述探熔。
對于H.264和H.265的解碼,在VideoToolBox層面的操作完全一致烘挫,唯一不同的就是視頻格式的描述類型不同诀艰。最常使用也最容易理解的為后兩個通過ParameterSets來創(chuàng)建的函數(shù),前兩個函數(shù)的創(chuàng)建方式未作詳細了解饮六。
至此其垄,對使用VideoToolBox解碼H.265視頻的重點就放在如何獲取ParameterSets(即VPS、SPS和PPS)上卤橄。
3.1 H.265 NALU類型
同H.264一樣绿满,H.265數(shù)據也是以NALU
的形式組織起來,區(qū)別在于H.264的NALU Header為一個字節(jié)窟扑,而H.265的為兩個字節(jié)喇颁,其結構如下:
所以,H.265編碼格式的NALU
類型判斷方式如下嚎货,code為NALU Header
的第一個字節(jié):
int type = (code & 0x7E)>>1;
其中type類型為32橘霎、33、34的NALU分別為VPS
厂抖、SPS
和PPS
,其他類型參見H.265規(guī)范《T-REC-H.265-201304-I!!PDF-E》克懊。
3.2 HEVCDecoderConfigurationRecord
使用ffmpeg讀取MP4文件后忱辅,視頻的AVCodecContext
結構的extradata
存儲的即為包含有SPS
七蜘、PPS
信息的數(shù)據結構。
對于H.264格式的視頻來說墙懂,為AVCDecoderConfigurationRecord
橡卤,該結構在標準文檔《ISO-14496-15 AVC file format》中有詳細說明。
對于H.265格式的視頻來說损搬,為HEVCDecoderConfigurationRecord
碧库,此結構的定義目前未找到官方的定義,參考 https://lists.matroska.org/pipermail/matroska-devel/2013-September/004567.html 及ffmpeg中hevc.c文件中的實現(xiàn)巧勤,該結構詳細如下:
// 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;
}
}
其中最后的nalUnit存儲的即為VPS嵌灰、SPS和PPS信息。
獲取到VPS颅悉、SPS和PPS之后沽瞭,就可以通過
CMVideoFormatDescriptionCreateFromHEVCParameterSets
來創(chuàng)建H.265視頻格式的描述信息,再創(chuàng)建解碼session即可使用VideoToolBox進行解碼剩瓶。
3.3 說明
iOS 11 beta2的版本中
VTDecompressionSessionWaitForAsynchronousFrames
此函數(shù)調用會失敗驹溃,目前不確定是beta系統(tǒng)的問題還是什么其他原因,在該版本的iOS系統(tǒng)上使用ijkplayer VideoToolBox解碼會發(fā)現(xiàn)播放卡頓延曙,就是因為該函數(shù)的問題導致豌鹤,留待后續(xù)版本觀察(7月10日已經推出beta3版本,還未確認)
四枝缔、結束語
本文僅僅簡單介紹了在iOS11系統(tǒng)上如何使用VideoTooBox進行HEVC硬編/硬解功能布疙,目前我們的SDK中已經支持該功能,但是由于iOS11系統(tǒng)還未正式發(fā)布魂仍,所以該功能暫時未上線拐辽。如果您想嘗鮮使用,可以通過下面的聯(lián)系方式向我們獲取擦酌。iOS11系統(tǒng)發(fā)布后俱诸,我們會第一時間上線該功能。
轉載請注明:
作者金山視頻云赊舶,首發(fā)簡書 Jianshu.com
也歡迎大家使用我們的直播/短視頻SDK睁搭,支持高效H.265軟編,同時也適配了iOS 11 HEVC系統(tǒng)編解碼能力:
iOS直播版(推流 + 播放):https://github.com/ksvc/KSYLive_iOS
iOS播放 :https://github.com/ksvc/KSYMediaPlayer_iOS
有關音視頻的更多精彩內容笼平,請參考https://github.com/ksvc
金山云SDK相關的QQ交流群:
- 視頻云技術交流群:574179720
- 視頻云iOS技術交流:621137661