基于iOS11的HEVC(H.265)硬編碼/硬解碼功能開發(fā)指南

蘋果于北京時間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.264與H.265的壓縮效果對比.png

需要注意的是,H.265的硬編/解功能促脉,并不是ios的所有設備升級到新系統(tǒng)上都可以使用辰斋,目前蘋果公布可使用HEVC編/解碼的移動設備要求如下:

iOS 11 HEVC Encode

H.265硬編.png

iOS 11 HEVC Decode

H.265硬解.png

二策州、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é)喇颁,其結構如下:

H265 nalu header

所以,H.265編碼格式的NALU類型判斷方式如下嚎货,code為NALU Header的第一個字節(jié):

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

其中type類型為32橘霎、33、34的NALU分別為VPS厂抖、SPSPPS,其他類型參見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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末园骆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子寓调,更是在濱河造成了極大的恐慌锌唾,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異晌涕,居然都是意外死亡滋捶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門余黎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來重窟,“玉大人,你說我怎么就攤上這事惧财⊙采龋” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵垮衷,是天一觀的道長厅翔。 經常有香客問我,道長帘靡,這世上最難降的妖魔是什么知给? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮描姚,結果婚禮上涩赢,老公的妹妹穿的比我還像新娘。我一直安慰自己轩勘,他們只是感情好筒扒,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绊寻,像睡著了一般花墩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澄步,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天冰蘑,我揣著相機與錄音,去河邊找鬼村缸。 笑死祠肥,一個胖子當著我的面吹牛,可吹牛的內容都是我干的梯皿。 我是一名探鬼主播仇箱,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼东羹!你這毒婦竟也來了剂桥?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤属提,失蹤者是張志新(化名)和其女友劉穎权逗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡斟薇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年火惊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奔垦。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖尸疆,靈堂內的尸體忽然破棺而出椿猎,到底是詐尸還是另有隱情,我是刑警寧澤寿弱,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布犯眠,位于F島的核電站,受9級特大地震影響症革,放射性物質發(fā)生泄漏筐咧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一噪矛、第九天 我趴在偏房一處隱蔽的房頂上張望量蕊。 院中可真熱鬧,春花似錦艇挨、人聲如沸残炮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽势就。三九已至,卻和暖如春脉漏,著一層夾襖步出監(jiān)牢的瞬間苞冯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工侧巨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舅锄,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓刃泡,卻偏偏與公主長得像巧娱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子烘贴,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353