這個(gè)公眾號(hào)會(huì)路線圖式的遍歷分享音視頻技術(shù):音視頻基礎(chǔ)(完成) → 音視頻工具(完成) → 音視頻工程示例(進(jìn)行中) → 音視頻工業(yè)實(shí)戰(zhàn)(準(zhǔn)備)唆迁。**關(guān)注一下成本不高鳞溉,錯(cuò)過(guò)干貨損失不小 **
蘋果用 EDR 這個(gè)詞是為了跟 HDR 區(qū)分開(kāi),因?yàn)?HDR 在不同的場(chǎng)景可能對(duì)應(yīng)著不同的理解:
- HDR 顯示:更生動(dòng)的顯示亮色和暗色
- HDR 格式:HDR10、Dolby Vision
- HDR 轉(zhuǎn)換函數(shù):PQ呆贿、HLG
- 色調(diào)映射(Tone Mapping):HDR → SDR
而 EDR(Extended Dynamic Range)是蘋果推出的一套渲染管線技術(shù)谴垫,以支持在不同的屏幕上同時(shí)正確顯示 SDR 和 HDR 內(nèi)容。當(dāng)顯示 HDR 的內(nèi)容時(shí)前弯,EDR 并不會(huì)直接將 HDR 區(qū)域變得更亮,而是識(shí)別到 HDR 內(nèi)容后提高整體屏幕亮度的同時(shí)浙巫,降低非 HDR 區(qū)域的白點(diǎn)值,使得其看起來(lái)沒(méi)有那么亮。
下圖展示了 EDR 在 Pro Display XDR 顯示器上的預(yù)設(shè):
一般臺(tái)式電腦顯示器的持續(xù)亮度在 350 尼特左右,有些專業(yè)顯示器的會(huì)高一點(diǎn),但大部分持續(xù)不了較長(zhǎng)時(shí)間强经。Pro Display XDR 則可以達(dá)到 1000 尼特全屏持續(xù)亮度,峰值亮度達(dá)到 1600 尼特炬称。這樣的性能,可以提供持續(xù)的高亮度棘利。配合高效的背光控制,出色的明暗對(duì)比范圍從最亮的白一直跨越到最深的黑茅郎,可實(shí)現(xiàn) 1000000:1 對(duì)比度和格外逼真的 XDR 影像。
1、在 iOS 上探索 EDR
參見(jiàn):Explore EDR on iOS[1]
這個(gè) Session 的內(nèi)容包含了下面幾點(diǎn):
1)介紹了 EDR API 的新增特性
- EDR API 開(kāi)始支持 iOS 和 iPadOS涝开。
- 12.9 英寸 iPad Pro 新增兩個(gè)新特性:Reference 模式支持 EDR 渲染拄养;Sidecar 支持 EDR 渲染(Sidecar 是蘋果的一項(xiàng)技術(shù)跛梗,支持將 iPad 作為 Mac 的擴(kuò)展屏)。
其中,Reference 模式對(duì) EDR 的支持如下:
- 修正 SDR 峰值亮度為 100 nits尼荆;
- 修正 HDR 峰值亮度為 1000 nits(這樣就留出了 10 倍(1000 nits / 100 nits)的 EDR headroom);
- 支持關(guān)閉 HDR Tone Mapping鞭莽;
- 支持關(guān)閉環(huán)境光自適應(yīng)(比如,iPhone 的 True Tone丹拯、Auto Brightness、Night Shift 等功能);
- 支持白點(diǎn)和亮度的手動(dòng)校準(zhǔn)县昂;
- Reference 模式支持的最常見(jiàn) 5 種 HDR/SDR 視頻格式如下圖(不在下表中的格式,會(huì)使用默認(rèn)模式):
2)回顧了 EDR 的技術(shù)方案
如下圖所示,SDR 的像素浮點(diǎn)數(shù)表示范圍為 [0.0, 1.0]
创淡,其中 0.0 表示黑色琳彩,1.0 表示白色。在 EDR 的像素浮點(diǎn)數(shù)表示中部凑,SDR 的部分映射到 [0.0, 1.0]
露乏,而大于 1.0 的部分就是比 SDR 更亮的 HDR 部分。
不像其他的 HDR 格式那樣涂邀,EDR 不會(huì)做 Tone Mapping 將像素值都映射到 [0.0, 1.0]
的范圍。這就意味著在渲染時(shí)必孤,它有一套新的機(jī)制猾骡。
當(dāng)渲染時(shí)瑞躺,像素浮點(diǎn)值范圍為 [0.0, 1.0]
的 SDR 內(nèi)容是始終會(huì)正常渲染的。(1.0, EDR headroom]
范圍的 HDR 內(nèi)容也是可以渲染的兴想。但是幢哨,超過(guò)了 EDR headroom 的部分就會(huì)被丟掉。
EDR headroom 的存在支持了亮度更高的 HDR 內(nèi)容嫂便,但是它具體是多少呢捞镰?其實(shí),EDR headroom 是動(dòng)態(tài)的毙替,它的值受到多種因素的影響岸售,比如:設(shè)備的顯示技術(shù)、當(dāng)前的顯示亮度等等厂画。
我們通惩雇瑁可以使用下面這個(gè)公式粗略估計(jì) EDR headroom:
Headroom ≈ Display Peak / SDR
比如,上面提到的 Reference 模式下的 EDR headroom 就是 1000 nits / 100 nits
袱院,即 10 倍屎慢。
下表中列出了部分設(shè)備的 EDR headroom:
3)EDR 內(nèi)容的讀取
對(duì)于 HDR 圖片文件的處理流程如下:
示例代碼如下:
4)使用 EDR
要使用 EDR 有下面幾個(gè)注意點(diǎn):
- 要使用
CAMetalLayer
; - 設(shè)置
wantsExtendedDynamicRangeContent
為 YES忽洛; - 內(nèi)容支持 EDR:
- 支持像素緩沖區(qū)格式腻惠;
- 支持轉(zhuǎn)換函數(shù);
- 使用擴(kuò)展的顏色空間欲虚。
5)查詢 EDR headroom
EDR headroom 的信息可以通過(guò) NSScreen(macOS)或 UIScreen(iOS)來(lái)獲取集灌。
比如,通過(guò) UIScreen(iOS)可以獲取這些信息:
- 顏色的動(dòng)態(tài)值:
- 當(dāng)前屏幕可能的最大值复哆;
- 當(dāng)前的最大值欣喧;
- Reference 模式的狀態(tài);
- Reference 模式狀態(tài)變化的通知寂恬。
示例代碼如下:
通過(guò)查詢 EDR headroom 的信息,可以用來(lái)做自定義的 Tone Mapping 算法莱没。
6)色調(diào)映射(Tone Mapping)
如果你不想去做自己的 Tone Mapping 算法初肉,而是想用 Apple 內(nèi)置的算法,需要用到這些能力:
- CoreAnimation 庫(kù)提供了跟 EDR metadata 相關(guān)的接口饰躲;
- 支持多種 metadata 參數(shù)設(shè)置牙咏,包括 HDR10 和 HLG 格式;
- 注意嘹裂,內(nèi)置的 Tone Mapping 算法不是全局支持的妄壶,使用之前要檢查一下。
如下圖所示寄狼,在使用之前要檢查當(dāng)前設(shè)備是否可以支持 EDR metadata丁寄,然后去初始化對(duì)應(yīng)格式的 EDR metadata氨淌,最后將其應(yīng)用到 CAMetalLayer 來(lái)渲染時(shí),就用使用系統(tǒng)自帶的 Tone Mapping 算法了伊磺。
下圖展示了如何初始化不同格式的 EDR Metadata:
下圖展示了不同顏色空間格式建議的 EDR Metadata 的構(gòu)造方法:
2盛正、基于 CoreImage、Metal屑埋、SwiftUI 展示 EDR 內(nèi)容
參見(jiàn):Display EDR content with Core Image, Metal, and SwiftUI[2]
在這個(gè) Session 中豪筝,回顧了一下 EDR 相關(guān)的概念和術(shù)語(yǔ),然后展示了一個(gè)基于 Core Image 來(lái)添加 EDR 支持的 Demo摘能,最后提到了如何用 CIFilter 來(lái)創(chuàng)建支持 EDR 的圖像去服務(wù)于相關(guān)內(nèi)容的生產(chǎn)续崖。
1)EDR 相關(guān)的概念和術(shù)語(yǔ)
EDR 相關(guān)的概念和術(shù)語(yǔ),在前面的內(nèi)容已經(jīng)介紹過(guò)了团搞,這里就不再贅述了严望。
不過(guò),這里提到了可以獲取到 EDR 圖像內(nèi)容的幾種途徑莺丑,可以了解一下:
- 使用 TIFF著蟹、OpenEXR 等支持浮點(diǎn)數(shù)存儲(chǔ)像素值的圖像格式來(lái)獲取 EDR 圖像;
- 通過(guò) AVFoundation 從 HDR 的視頻中截幀獲得 EDR 圖像梢莽;
- 使用 Metal API 可以將 EDR 環(huán)境渲染到紋理上萧豆;
- ProRAW、DNG 等存儲(chǔ)原始圖像信息的格式昏名,可以用于渲染來(lái)還原 EDR 的高亮特性涮雷。
2)在 SwiftUI 應(yīng)用中使用 CoreImage 和 Metal 并為其添加 EDR 支持
相關(guān)源碼見(jiàn):Generating an Animation with a Core Image Render Destination[3]
這個(gè) Demo 中繪制了一幅動(dòng)畫的 CIImage 并通過(guò) Metal 來(lái)渲染它,這里使用了 MTKView轻局。
大致流程如下圖所示洪鸭,即 MetalView 調(diào)用其 delegate
來(lái)繪制,作為代理的 Renderer 在 draw()
方法中調(diào)用 ContentView 來(lái)提供圖像去繪制:
其中,最核心的代碼分別是:
- MetalView 的
makeView()
方法:
- Renderer 的
draw()
方法:
- ContentView 的
provider()
方法:
接下來(lái)镇饮,則是在這個(gè)流程中添加 EDR 支持蜓竹,包括 3 個(gè)步驟:
- 1、初始化 MetalView 時(shí)储藐,為其添加 EDR 配置俱济;
- 2、每次渲染動(dòng)作前钙勃,計(jì)算 EDR headroom蛛碌;
- 3、基于 EDR headroom 構(gòu)造 CIImage辖源。
對(duì)應(yīng)的代碼改動(dòng)如下:
- MetalView 的
makeView()
方法中蔚携,當(dāng)構(gòu)建 MetalView 時(shí)希太,要設(shè)置對(duì)應(yīng) layer 的幾個(gè)屬性如下:
- Renderer 的
draw()
方法中,每次渲染前需要獲取 EDR headroom浮梢,并傳給 provider:
- ContentView 的
provider()
方法中跛十,要增加 headroom 參數(shù),并使用這個(gè) headroom 參數(shù)和 CIFilter 來(lái)一起構(gòu)建 CIImage秕硝,這個(gè) CIImage 就可以實(shí)現(xiàn) EDR 渲染展示了:
3)使用內(nèi)置的 CIFilter 來(lái)支持 EDR
CoreImage 中有超過(guò) 150 款 內(nèi)置的 CIFilter 支持 EDR芥映。
在使用一款 CIFilter 時(shí),要想知道它是否支持 EDR远豺,可以用如下的代碼來(lái)做一下檢查:
下面展示了如何基于 headroom 編寫一個(gè)可以生成高亮白色的 shading image奈偏,并結(jié)合一個(gè) Ripple 效果的 CIFilter 來(lái)生成 EDR 的圖像。
4)基于 CIColorCube filters 編寫自定義的 CIFilter 來(lái)支持 EDR
其中 CIColorCubeWithColorSpace 是一個(gè)比較受歡迎的用于 SDR 圖片的濾鏡躯护。以前惊来,在使用它時(shí)有一個(gè)嚴(yán)格的限制:輸入和輸出的 RGB 顏色值都在 0-1 的范圍內(nèi)。當(dāng)我們要支持 EDR 時(shí)棺滞,可以配置 CIColorCubeWithColorSpace 濾鏡的顏色空間為 EDR 格式的顏色空間裁蚁,比如:HLG 或 PQ,這時(shí)候就可以突破 RGB 顏色值只在 0-1 范圍的限制了继准,從而生產(chǎn)出最佳效果的 EDR 的內(nèi)容枉证。但是,需要注意移必,對(duì)應(yīng)的 cube data 需要在對(duì)應(yīng)顏色空間的有效范圍內(nèi)室谚。同時(shí),還可能需要增加 cube data 的維度崔泵。
有時(shí)候秒赤,你可能想要使用 SDR cube data 用于 EDR 圖像,在最新的 API 中憎瘸,可以設(shè)置 extrapolate
屬性為 true
來(lái)告訴 filter 來(lái)對(duì) SDR cube data 進(jìn)行推斷入篮,這時(shí)候你就可以給一個(gè) filter 輸入一個(gè) EDR 圖像,并從輸出獲得 EDR 圖像幌甘。
5)編寫自定義 CIKernel 的最佳實(shí)踐
以往對(duì)于 RGB 的值必須保持在 0-1 范圍內(nèi)的限制可以去掉了潮售,超過(guò)這個(gè)范圍,CIKernel 也可以正常工作含潘。
但是饲做,alpha 值仍然需要保持在 0-1 的范圍內(nèi)线婚。
3遏弱、基于 AVFoundation、Metal 展示 HDR 視頻
參見(jiàn):Display HDR video in EDR with AVFoundation and Metal[4]
這個(gè) Session 中介紹了如何基于 AVFoundation 和 Metal 來(lái)構(gòu)建高效的 EDR 渲染管線塞弊。其中漱逸,包括:
- 介紹如何支持 EDR 視頻的播放泪姨。不僅是簡(jiǎn)單的基于黑盒的 AVPlayer 來(lái)實(shí)現(xiàn),會(huì)深入的介紹如何基于 AVFoundation 來(lái)解碼 HDR 視頻饰抒,并在自定義的 EDR layer/view 上渲染肮砾。
- 介紹如何支持 EDR 視頻的后處理〈樱基于 CoreVideo Display Link 實(shí)時(shí)訪問(wèn)解碼后的的視頻幀并送給 CoreImage filter 或 Metal shader 來(lái)進(jìn)行圖像或特效處理仗处,最后將處理后的視頻幀交給 Metal 來(lái)渲染。
整個(gè) Session 的內(nèi)容從下面幾個(gè)方面展開(kāi):
1)Apple EDR 視頻框架
Apple EDR 視頻框架如下圖所示:
首先是 AVKit 框架枣宫,我們可以基于 AVKit 來(lái)創(chuàng)建支持視頻播放的用戶界面婆誓,完成傳輸控制、章節(jié)導(dǎo)航也颤、畫中畫播放洋幻、字幕、隱藏式字幕顯示等功能翅娶,AVKit 可以將 HDR 內(nèi)容在 EDR 管線中播放文留。這些都可以通過(guò) AVPlayerViewController 來(lái)實(shí)現(xiàn)。不過(guò)竭沫,如果想要進(jìn)一步處理視頻幀燥翅,那就要使用更底層的媒體框架來(lái)控制整個(gè) pipeline。
接下來(lái)是 AVFoundation 框架输吏,AVFoundation 是處理基于時(shí)間的音視頻媒體的全功能框架权旷。使用 AVFoundation 可以輕松的播放、創(chuàng)建和編輯 QuickTime 電影和 MP4 文件贯溅,播放 HLS 流拄氯,并在應(yīng)用中構(gòu)建強(qiáng)大的媒體功能。本次演講中會(huì)探索 AVPlayer 和相關(guān) AVPlayerLayer 接口的使用它浅。
Core Video 是一個(gè)為數(shù)字視頻提供管道模型的框架译柏。它通過(guò)將流程劃分為離散的步驟來(lái)簡(jiǎn)化處理視頻的方式。Core Video 還可以更輕松地訪問(wèn)和操作單個(gè)幀姐霍,而不必?fù)?dān)心數(shù)據(jù)類型之間的轉(zhuǎn)換或顯示同步鄙麦。我們將演示如何結(jié)合使用 DisplayLink、CVPixelBuffer镊折、Core Image胯府,以及如何配合使用 CVMetalTextureCache、Metal恨胚。
接著是 Video Toolbox 框架骂因,這是一個(gè)底層框架,提供對(duì)硬件編碼器和解碼器的直接訪問(wèn)赃泡。Video Toolbox 提供視頻壓縮和解壓縮服務(wù)寒波,以及存儲(chǔ)在 Core Video 像素緩沖區(qū)中的光柵圖像格式之間的轉(zhuǎn)換乘盼。VTDecompressionSession 是一個(gè)強(qiáng)大的底層接口,本次不會(huì)討論俄烁,但高級(jí)開(kāi)發(fā)人員可以進(jìn)一步研究绸栅。
最后是 Core Media 框架,該框架定義了 AVFoundation 和其他高級(jí)媒體框架使用的媒體管道页屠〈饪瑁可以使用 Core Media 的底層數(shù)據(jù)類型和接口來(lái)有效地處理媒體樣本、管理媒體數(shù)據(jù)隊(duì)列辰企。
對(duì)于不同的應(yīng)用場(chǎng)景矛双,我們可以選擇不同的框架來(lái)實(shí)現(xiàn):
- 簡(jiǎn)單的播放 HDR 視頻,可以使用 AVKit 和 AVFoundation蟆豫;
- 在指定的 layer 上播放 HDR 視頻议忽,可以使用 AVPlayerLayer;
- 對(duì) HDR 視頻幀做后處理十减,可以使用 AVPlayer栈幸、CADisplayLink 將 CVPixelBuffer 發(fā)送給 CoreImage 進(jìn)行圖像處理;
- 對(duì) HDR 視頻幀做后處理和渲染帮辟,可以使用 AVPlayer速址、CVMetalTextureCache 將 MetalTexture 發(fā)送給 Metal 進(jìn)行圖像處理和渲染。
2)使用 AVKit 和 AVFoundation
如果需要簡(jiǎn)單的播放 HDR 視頻媒體渲染到 EDR由驹,可以使用 AVPlayerViewController 渲染 AVPlayer芍锚,也可以使用 AVPlayer 和 AVPlayerLayer 在 iOS 或 macOS 上播放自己的視圖。
示例代碼如下:
如果需要實(shí)現(xiàn)實(shí)時(shí)視頻效果蔓榄,比如:
- 特效:
- Color grading
- Chroma keying
- 圖像處理:
- CoreImage filters
- Metal shaders
大致流程如下:
最終渲染一般都使用 CAMetalLayer并炮,要支持正確的渲染 HDR 視頻,還需要為 CAMetalLayer 設(shè)置一些屬性:
CAMetalLayer 屬性設(shè)置
接下來(lái)甥郑,繼續(xù)展示如何結(jié)合 AVPlayer 和 CADisplayLink 來(lái)實(shí)時(shí)訪問(wèn)解碼的視頻幀逃魄,大致流程如下:
下面是各個(gè)步驟對(duì)應(yīng)的示例代碼:
接下在 CADisplayLink 的回調(diào)中,我們就可以從 AVPlayerItemVideoOutput 中來(lái)讀取 CVPixelBuffer 圖像信息進(jìn)行后處理了澜搅。
一種方式是將 CVPixelBuffer 發(fā)送到 Core Image 進(jìn)行處理伍俘。Core Image 可以將一個(gè)或多個(gè) CIFilter 串起來(lái),為視頻幀提供 GPU 加速的圖像處理勉躺。但是需要注意癌瘾,并非所有的 CIFilter 都支持 EDR,可以通過(guò) CIFilter.filterNames(inCategory: kCICategoryHighDynamicRange)
來(lái)遍歷支持 EDR 的濾鏡來(lái)使用饵溅。在下面的示例代碼中妨退,我們來(lái)添加一個(gè)簡(jiǎn)單的濾鏡效果:
另一種方式是使用 Metal 和自定義的 Metal shader 來(lái)處理和渲染 CVPixelBuffer。我們來(lái)簡(jiǎn)單介紹一下將 CVPixelBuffer 轉(zhuǎn)換為 Metal 紋理的過(guò)程:
- 從 CVPixelBuffer 中獲取 IOSurface 對(duì)象;
- 創(chuàng)建一個(gè) MetalTextureDescriptor碧注;
- 把這個(gè) MetalTextureDescriptor 作為參數(shù),使用
newTextureWithDescriptor
從 MetalDevice 創(chuàng)建一個(gè) MetalTexture糖赔。
這里要小心可能存在紋理被重復(fù)使用和過(guò)度繪制的問(wèn)題萍丐,所以要小心的加鎖;此外放典,并非所有的 PixelBuffer 格式都被 MetalTexture 支持逝变,這也是為什么我們?cè)谑纠杏?half float 格式的原因。同時(shí)奋构,實(shí)現(xiàn)這種轉(zhuǎn)換以保持最佳性能是一個(gè)深入的話題壳影,這里先不探討了。
正因?yàn)檫@些復(fù)雜性弥臼,我們才建議從 Core Video Metal 紋理緩存中獲取 Metal 紋理宴咧,這是我們?cè)谙乱还?jié)內(nèi)容中要介紹的。
3)使用 CoreVideo 和 Metal
CVMetalTextureCache 是一種將 CVPixelBuffer 與 Metal 結(jié)合使用的簡(jiǎn)單有效的方法径缅。CVMetalTextureCache 很方便掺栅,可以直接從緩存中獲取 Metal 紋理,無(wú)需進(jìn)一步轉(zhuǎn)換纳猪。CVMetalTextureCache 自動(dòng)橋接 CVPixelBuffer 和 MetalTexture氧卧,從而既簡(jiǎn)化了代碼,又保持了高效氏堤。通過(guò)保持 MTLTexture 到 IOSurface 的映射沙绝,CVMetalTextureCache 與 CVPixelBufferPools 配合使用還提供了性能優(yōu)勢(shì)。最后鼠锈,使用 CVMetalTextureCache 消除了手動(dòng)跟蹤 IOSurfaces 的需要闪檬。下面的示例將展示如何使用 CVMetalTextureCache 從 Core Video 中直接提取 Metal 紋理,大致流程如下圖所示:
下面是各個(gè)步驟對(duì)應(yīng)的示例代碼:
注意,在用 Objective-C 時(shí)需要保證在釋放 CVMetalTextureRef 之前要完成對(duì) Metal 紋理的使用由桌,可以借助 Metal 命令緩沖區(qū)的 completion 回調(diào)來(lái)實(shí)現(xiàn)为黎。
參考資料
[1]Explore EDR on iOS: https://developer.apple.com/videos/play/wwdc2022/10113/
[2]Display EDR content with Core Image, Metal, and SwiftUI: https://developer.apple.com/videos/play/wwdc2022/10114
[3]Animation with a Core Image Render: https://developer.apple.com/documentation/coreimage/generating_an_animation_with_a_core_image_render_destination
[4]Display HDR video in EDR with AVFoundation and Metal: https://developer.apple.com/videos/play/wwdc2022/110565/
- 完 -
推薦閱讀《WWDC 2022 音視頻相關(guān) Session 概覽(HLS 相關(guān))》《iOS 視頻處理框架及重點(diǎn) API 合集》《iOS 音頻處理框架及重點(diǎn) API 合集》