WWDC 2022 音視頻相關(guān) Session 概覽(EDR 相關(guān))丨音視頻工程示例

這個公眾號會路線圖式的遍歷分享音視頻技術(shù):音視頻基礎(chǔ)(完成)音視頻工具(完成)音視頻工程示例(進(jìn)行中) → 音視頻工業(yè)實戰(zhàn)(準(zhǔn)備)。**關(guān)注一下成本不高,錯過干貨損失不小 **

蘋果用 EDR 這個詞是為了跟 HDR 區(qū)分開,因為 HDR 在不同的場景可能對應(yīng)著不同的理解:

  • HDR 顯示:更生動的顯示亮色和暗色
  • HDR 格式:HDR10、Dolby Vision
  • HDR 轉(zhuǎn)換函數(shù):PQ、HLG
  • 色調(diào)映射(Tone Mapping):HDR → SDR

而 EDR(Extended Dynamic Range)是蘋果推出的一套渲染管線技術(shù),以支持在不同的屏幕上同時正確顯示 SDR 和 HDR 內(nèi)容。當(dāng)顯示 HDR 的內(nèi)容時,EDR 并不會直接將 HDR 區(qū)域變得更亮,而是識別到 HDR 內(nèi)容后提高整體屏幕亮度的同時,降低非 HDR 區(qū)域的白點值,使得其看起來沒有那么亮。

下圖展示了 EDR 在 Pro Display XDR 顯示器上的預(yù)設(shè):

Pro Display XDR preset
Pro Display XDR preset

一般臺式電腦顯示器的持續(xù)亮度在 350 尼特左右,有些專業(yè)顯示器的會高一點,但大部分持續(xù)不了較長時間。Pro Display XDR 則可以達(dá)到 1000 尼特全屏持續(xù)亮度,峰值亮度達(dá)到 1600 尼特。這樣的性能,可以提供持續(xù)的高亮度。配合高效的背光控制,出色的明暗對比范圍從最亮的白一直跨越到最深的黑,可實現(xiàn) 1000000:1 對比度和格外逼真的 XDR 影像。

1、在 iOS 上探索 EDR

參見:Explore EDR on iOS[1]

這個 Session 的內(nèi)容包含了下面幾點:

1)介紹了 EDR API 的新增特性

  • EDR API 開始支持 iOS 和 iPadOS。
  • 12.9 英寸 iPad Pro 新增兩個新特性:Reference 模式支持 EDR 渲染;Sidecar 支持 EDR 渲染(Sidecar 是蘋果的一項技術(shù),支持將 iPad 作為 Mac 的擴(kuò)展屏)。

其中,Reference 模式對 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 等功能);
  • 支持白點和亮度的手動校準(zhǔn);
  • Reference 模式支持的最常見 5 種 HDR/SDR 視頻格式如下圖(不在下表中的格式,會使用默認(rèn)模式):
Reference 模式支持的最常見 5 種 HDR:SDR 視頻格式

2)回顧了 EDR 的技術(shù)方案

如下圖所示,SDR 的像素浮點數(shù)表示范圍為 [0.0, 1.0],其中 0.0 表示黑色,1.0 表示白色。在 EDR 的像素浮點數(shù)表示中,SDR 的部分映射到 [0.0, 1.0],而大于 1.0 的部分就是比 SDR 更亮的 HDR 部分。

不像其他的 HDR 格式那樣,EDR 不會做 Tone Mapping 將像素值都映射到 [0.0, 1.0] 的范圍。這就意味著在渲染時,它有一套新的機(jī)制。

EDR Range

當(dāng)渲染時,像素浮點值范圍為 [0.0, 1.0] 的 SDR 內(nèi)容是始終會正常渲染的。(1.0, EDR headroom] 范圍的 HDR 內(nèi)容也是可以渲染的。但是,超過了 EDR headroom 的部分就會被丟掉。

EDR Rendering

EDR headroom 的存在支持了亮度更高的 HDR 內(nèi)容,但是它具體是多少呢?其實,EDR headroom 是動態(tài)的,它的值受到多種因素的影響,比如:設(shè)備的顯示技術(shù)、當(dāng)前的顯示亮度等等。

我們通常可以使用下面這個公式粗略估計 EDR headroom:

Headroom ≈ Display Peak / SDR

比如,上面提到的 Reference 模式下的 EDR headroom 就是 1000 nits / 100 nits,即 10 倍。

下表中列出了部分設(shè)備的 EDR headroom:

一些設(shè)備的 EDR headroom .png

3)EDR 內(nèi)容的讀取

對于 HDR 圖片文件的處理流程如下:

HDR 圖片文件的渲染流程

示例代碼如下:

HDR 圖片文件的渲染示例代碼
HDR 圖片文件的渲染示例代碼

4)使用 EDR

要使用 EDR 有下面幾個注意點:

  • 要使用 CAMetalLayer;
  • 設(shè)置 wantsExtendedDynamicRangeContent 為 YES;
  • 內(nèi)容支持 EDR:
    • 支持像素緩沖區(qū)格式;
    • 支持轉(zhuǎn)換函數(shù);
    • 使用擴(kuò)展的顏色空間。

5)查詢 EDR headroom

EDR headroom 的信息可以通過 NSScreen(macOS)或 UIScreen(iOS)來獲取。

比如,通過 UIScreen(iOS)可以獲取這些信息:

  • 顏色的動態(tài)值:
    • 當(dāng)前屏幕可能的最大值;
    • 當(dāng)前的最大值;
  • Reference 模式的狀態(tài);
  • Reference 模式狀態(tài)變化的通知。

示例代碼如下:

查詢 EDR headroom
監(jiān)聽 Reference 模式變化通知

通過查詢 EDR headroom 的信息,可以用來做自定義的 Tone Mapping 算法。

6)色調(diào)映射(Tone Mapping)

如果你不想去做自己的 Tone Mapping 算法,而是想用 Apple 內(nèi)置的算法,需要用到這些能力:

  • CoreAnimation 庫提供了跟 EDR metadata 相關(guān)的接口;
  • 支持多種 metadata 參數(shù)設(shè)置,包括 HDR10 和 HLG 格式;
  • 注意,內(nèi)置的 Tone Mapping 算法不是全局支持的,使用之前要檢查一下。

如下圖所示,在使用之前要檢查當(dāng)前設(shè)備是否可以支持 EDR metadata,然后去初始化對應(yīng)格式的 EDR metadata,最后將其應(yīng)用到 CAMetalLayer 來渲染時,就用使用系統(tǒng)自帶的 Tone Mapping 算法了。

![初始化不同格式的 CAEDRMetadata](https://upload-images.jianshu.io/upload_images/27498310-dfe0ddf0bd7453ff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

下圖展示了如何初始化不同格式的 EDR Metadata:

初始化不同格式的 CAEDRMetadata

下圖展示了不同顏色空間格式建議的 EDR Metadata 的構(gòu)造方法:

初始化不同格式的 CAEDRMetadata 2

2、基于 CoreImage、Metal、SwiftUI 展示 EDR 內(nèi)容

參見:Display EDR content with Core Image, Metal, and SwiftUI[2]

在這個 Session 中,回顧了一下 EDR 相關(guān)的概念和術(shù)語,然后展示了一個基于 Core Image 來添加 EDR 支持的 Demo,最后提到了如何用 CIFilter 來創(chuàng)建支持 EDR 的圖像去服務(wù)于相關(guān)內(nèi)容的生產(chǎn)。

1)EDR 相關(guān)的概念和術(shù)語

EDR 相關(guān)的概念和術(shù)語,在前面的內(nèi)容已經(jīng)介紹過了,這里就不再贅述了。

不過,這里提到了可以獲取到 EDR 圖像內(nèi)容的幾種途徑,可以了解一下:

  • 使用 TIFF、OpenEXR 等支持浮點數(shù)存儲像素值的圖像格式來獲取 EDR 圖像;
  • 通過 AVFoundation 從 HDR 的視頻中截幀獲得 EDR 圖像;
  • 使用 Metal API 可以將 EDR 環(huán)境渲染到紋理上;
  • ProRAW、DNG 等存儲原始圖像信息的格式,可以用于渲染來還原 EDR 的高亮特性。

2)在 SwiftUI 應(yīng)用中使用 CoreImage 和 Metal 并為其添加 EDR 支持

相關(guān)源碼見:Generating an Animation with a Core Image Render Destination[3]

這個 Demo 中繪制了一幅動畫的 CIImage 并通過 Metal 來渲染它,這里使用了 MTKView。

Animate a filtered image to a Metal view

大致流程如下圖所示,即 MetalView 調(diào)用其 delegate 來繪制,作為代理的 Renderer 在 draw() 方法中調(diào)用 ContentView 來提供圖像去繪制:

MetalView、Renderer、ContentView

其中,最核心的代碼分別是:

  • MetalView 的 makeView() 方法:
MetalView makeView()
  • Renderer 的 draw() 方法:
Renderer draw()
Renderer draw()
  • ContentView 的 provider() 方法:
ContentView provider()

接下來,則是在這個流程中添加 EDR 支持,包括 3 個步驟:

  • 1、初始化 MetalView 時,為其添加 EDR 配置;
  • 2、每次渲染動作前,計算 EDR headroom;
  • 3、基于 EDR headroom 構(gòu)造 CIImage。

對應(yīng)的代碼改動如下:

  • MetalView 的 makeView() 方法中,當(dāng)構(gòu)建 MetalView 時,要設(shè)置對應(yīng) layer 的幾個屬性如下:
MetalView makeView() 改動
  • Renderer 的 draw() 方法中,每次渲染前需要獲取 EDR headroom,并傳給 provider:
Renderer draw() 改動
  • ContentView 的 provider() 方法中,要增加 headroom 參數(shù),并使用這個 headroom 參數(shù)和 CIFilter 來一起構(gòu)建 CIImage,這個 CIImage 就可以實現(xiàn) EDR 渲染展示了:
ContentView provider() 改動

3)使用內(nèi)置的 CIFilter 來支持 EDR

CoreImage 中有超過 150 款 內(nèi)置的 CIFilter 支持 EDR。

CIFilters with EDR

在使用一款 CIFilter 時,要想知道它是否支持 EDR,可以用如下的代碼來做一下檢查:

Check if a filter supports EDR

下面展示了如何基于 headroom 編寫一個可以生成高亮白色的 shading image,并結(jié)合一個 Ripple 效果的 CIFilter 來生成 EDR 的圖像。

Ripple CIFilter supports EDR
Ripple CIFilter supports EDR 2

4)基于 CIColorCube filters 編寫自定義的 CIFilter 來支持 EDR

其中 CIColorCubeWithColorSpace 是一個比較受歡迎的用于 SDR 圖片的濾鏡。以前,在使用它時有一個嚴(yán)格的限制:輸入和輸出的 RGB 顏色值都在 0-1 的范圍內(nèi)。當(dāng)我們要支持 EDR 時,可以配置 CIColorCubeWithColorSpace 濾鏡的顏色空間為 EDR 格式的顏色空間,比如:HLG 或 PQ,這時候就可以突破 RGB 顏色值只在 0-1 范圍的限制了,從而生產(chǎn)出最佳效果的 EDR 的內(nèi)容。但是,需要注意,對應(yīng)的 cube data 需要在對應(yīng)顏色空間的有效范圍內(nèi)。同時,還可能需要增加 cube data 的維度。

有時候,你可能想要使用 SDR cube data 用于 EDR 圖像,在最新的 API 中,可以設(shè)置 extrapolate 屬性為 true 來告訴 filter 來對 SDR cube data 進(jìn)行推斷,這時候你就可以給一個 filter 輸入一個 EDR 圖像,并從輸出獲得 EDR 圖像。

SDR Cube Data for EDR Image

5)編寫自定義 CIKernel 的最佳實踐

以往對于 RGB 的值必須保持在 0-1 范圍內(nèi)的限制可以去掉了,超過這個范圍,CIKernel 也可以正常工作。

CIKernel 最佳實踐:RGB 可以大于 1

但是,alpha 值仍然需要保持在 0-1 的范圍內(nèi)。

CIKernel 最佳實踐:Alpha 必須小于 1

3、基于 AVFoundation、Metal 展示 HDR 視頻

參見:Display HDR video in EDR with AVFoundation and Metal[4]

這個 Session 中介紹了如何基于 AVFoundation 和 Metal 來構(gòu)建高效的 EDR 渲染管線。其中,包括:

  • 介紹如何支持 EDR 視頻的播放。不僅是簡單的基于黑盒的 AVPlayer 來實現(xiàn),會深入的介紹如何基于 AVFoundation 來解碼 HDR 視頻,并在自定義的 EDR layer/view 上渲染。
  • 介紹如何支持 EDR 視頻的后處理?;?CoreVideo Display Link 實時訪問解碼后的的視頻幀并送給 CoreImage filter 或 Metal shader 來進(jìn)行圖像或特效處理,最后將處理后的視頻幀交給 Metal 來渲染。
HDR 視頻的播放
HDR 視頻后處理

整個 Session 的內(nèi)容從下面幾個方面展開:

1)Apple EDR 視頻框架

Apple EDR 視頻框架如下圖所示:

Apple EDR 視頻框架

首先是 AVKit 框架,我們可以基于 AVKit 來創(chuàng)建支持視頻播放的用戶界面,完成傳輸控制、章節(jié)導(dǎo)航、畫中畫播放、字幕、隱藏式字幕顯示等功能,AVKit 可以將 HDR 內(nèi)容在 EDR 管線中播放。這些都可以通過 AVPlayerViewController 來實現(xiàn)。不過,如果想要進(jìn)一步處理視頻幀,那就要使用更底層的媒體框架來控制整個 pipeline。

接下來是 AVFoundation 框架,AVFoundation 是處理基于時間的音視頻媒體的全功能框架。使用 AVFoundation 可以輕松的播放、創(chuàng)建和編輯 QuickTime 電影和 MP4 文件,播放 HLS 流,并在應(yīng)用中構(gòu)建強(qiáng)大的媒體功能。本次演講中會探索 AVPlayer 和相關(guān) AVPlayerLayer 接口的使用。

Core Video 是一個為數(shù)字視頻提供管道模型的框架。它通過將流程劃分為離散的步驟來簡化處理視頻的方式。Core Video 還可以更輕松地訪問和操作單個幀,而不必?fù)?dān)心數(shù)據(jù)類型之間的轉(zhuǎn)換或顯示同步。我們將演示如何結(jié)合使用 DisplayLink、CVPixelBuffer、Core Image,以及如何配合使用 CVMetalTextureCache、Metal。

接著是 Video Toolbox 框架,這是一個底層框架,提供對硬件編碼器和解碼器的直接訪問。Video Toolbox 提供視頻壓縮和解壓縮服務(wù),以及存儲在 Core Video 像素緩沖區(qū)中的光柵圖像格式之間的轉(zhuǎn)換。VTDecompressionSession 是一個強(qiáng)大的底層接口,本次不會討論,但高級開發(fā)人員可以進(jìn)一步研究。

最后是 Core Media 框架,該框架定義了 AVFoundation 和其他高級媒體框架使用的媒體管道。可以使用 Core Media 的底層數(shù)據(jù)類型和接口來有效地處理媒體樣本、管理媒體數(shù)據(jù)隊列。

對于不同的應(yīng)用場景,我們可以選擇不同的框架來實現(xiàn):

  • 簡單的播放 HDR 視頻,可以使用 AVKit 和 AVFoundation;
  • 在指定的 layer 上播放 HDR 視頻,可以使用 AVPlayerLayer;
  • 對 HDR 視頻幀做后處理,可以使用 AVPlayer、CADisplayLink 將 CVPixelBuffer 發(fā)送給 CoreImage 進(jìn)行圖像處理;
  • 對 HDR 視頻幀做后處理和渲染,可以使用 AVPlayer、CVMetalTextureCache 將 MetalTexture 發(fā)送給 Metal 進(jìn)行圖像處理和渲染。

2)使用 AVKit 和 AVFoundation

如果需要簡單的播放 HDR 視頻媒體渲染到 EDR,可以使用 AVPlayerViewController 渲染 AVPlayer,也可以使用 AVPlayer 和 AVPlayerLayer 在 iOS 或 macOS 上播放自己的視圖。

AVPlayer 的用法 .png

示例代碼如下:

AVPlayerViewController 使用示例
AVPlayer+AVPlayerLayer 使用示例

如果需要實現(xiàn)實時視頻效果,比如:

  • 特效:
    • Color grading
    • Chroma keying
  • 圖像處理:
    • CoreImage filters
    • Metal shaders

大致流程如下:

實時視頻效果

最終渲染一般都使用 CAMetalLayer,要支持正確的渲染 HDR 視頻,還需要為 CAMetalLayer 設(shè)置一些屬性:

CAMetalLayer 屬性設(shè)置 .png

CAMetalLayer 屬性設(shè)置

接下來,繼續(xù)展示如何結(jié)合 AVPlayer 和 CADisplayLink 來實時訪問解碼的視頻幀,大致流程如下:

AVPlayer+CADisplayLink 獲取視頻幀 .png

下面是各個步驟對應(yīng)的示例代碼:

步驟 1
步驟 2
步驟 3
步驟 4

接下在 CADisplayLink 的回調(diào)中,我們就可以從 AVPlayerItemVideoOutput 中來讀取 CVPixelBuffer 圖像信息進(jìn)行后處理了。

一種方式是將 CVPixelBuffer 發(fā)送到 Core Image 進(jìn)行處理。Core Image 可以將一個或多個 CIFilter 串起來,為視頻幀提供 GPU 加速的圖像處理。但是需要注意,并非所有的 CIFilter 都支持 EDR,可以通過 CIFilter.filterNames(inCategory: kCICategoryHighDynamicRange) 來遍歷支持 EDR 的濾鏡來使用。在下面的示例代碼中,我們來添加一個簡單的濾鏡效果:

后處理

另一種方式是使用 Metal 和自定義的 Metal shader 來處理和渲染 CVPixelBuffer。我們來簡單介紹一下將 CVPixelBuffer 轉(zhuǎn)換為 Metal 紋理的過程:

  • 從 CVPixelBuffer 中獲取 IOSurface 對象;
  • 創(chuàng)建一個 MetalTextureDescriptor;
  • 把這個 MetalTextureDescriptor 作為參數(shù),使用 newTextureWithDescriptor 從 MetalDevice 創(chuàng)建一個 MetalTexture。

這里要小心可能存在紋理被重復(fù)使用和過度繪制的問題,所以要小心的加鎖;此外,并非所有的 PixelBuffer 格式都被 MetalTexture 支持,這也是為什么我們在示例中用 half float 格式的原因。同時,實現(xiàn)這種轉(zhuǎn)換以保持最佳性能是一個深入的話題,這里先不探討了。

正因為這些復(fù)雜性,我們才建議從 Core Video Metal 紋理緩存中獲取 Metal 紋理,這是我們在下一節(jié)內(nèi)容中要介紹的。

3)使用 CoreVideo 和 Metal

CVMetalTextureCache 是一種將 CVPixelBuffer 與 Metal 結(jié)合使用的簡單有效的方法。CVMetalTextureCache 很方便,可以直接從緩存中獲取 Metal 紋理,無需進(jìn)一步轉(zhuǎn)換。CVMetalTextureCache 自動橋接 CVPixelBuffer 和 MetalTexture,從而既簡化了代碼,又保持了高效。通過保持 MTLTexture 到 IOSurface 的映射,CVMetalTextureCache 與 CVPixelBufferPools 配合使用還提供了性能優(yōu)勢。最后,使用 CVMetalTextureCache 消除了手動跟蹤 IOSurfaces 的需要。下面的示例將展示如何使用 CVMetalTextureCache 從 Core Video 中直接提取 Metal 紋理,大致流程如下圖所示:

CVMetalTextureCache 從 CoreVideo 提取 Metal 紋理

下面是各個步驟對應(yīng)的示例代碼:

步驟 1、2
步驟 3、4

注意,在用 Objective-C 時需要保證在釋放 CVMetalTextureRef 之前要完成對 Metal 紋理的使用,可以借助 Metal 命令緩沖區(qū)的 completion 回調(diào)來實現(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 視頻處理框架及重點 API 合集》《iOS 音頻處理框架及重點 API 合集》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容