我是 Chromium 媒體播放工程的工程部門主管 Dale Curtis本團隊負責為視訊播放 API (例如 MSE 和 WebCodecs) 以及面向網路的 API 負責,以及與去多工處理、解碼及轉譯音訊和影片相關的平台內部人員。
本文將逐步引導您瞭解 Chromium 的影片轉譯架構。 儘管一些與擴充功能相關的詳細資料可能是 Chromium 特有的,但本文提及的大部分概念和設計都適用於其他轉譯引擎,甚至是原生播放應用程式。
這些年來,Chromium 的播放架構已大幅改變。 雖然我們沒有從本系列第一篇文章中說明的成功金字塔開始構思成功原則,但最後還是按照類似的步驟著手:可靠性、效能和擴充性。
開頭的影片轉譯程序相當簡單,只是一個迴圈,也就是選擇要傳送至合成器的軟體已解碼視訊影格。多年來,這個做法已足夠可靠,但隨著網路變得越來越複雜,需要提高效能和效率才能因應架構上的變化。許多改善項目都需要使用 OS 專屬的基本版本,因此,我們的架構也必須更加靈活,才能觸及所有 Chromium 平台。
影片轉譯可分為兩個步驟:選擇要有效率地放送及提交資訊的內容。為了確保你可以閱讀,我會先介紹高效率的傳送方式,再深入探討 Chromium 如何選擇要傳遞的內容。
部分字詞和版面配置
由於本文的重點在於轉譯 因此我只會簡短介紹管道的去開發和解碼
在我們注重安全性的現代世界中,需要進行解碼和去背,需要有點注意。二進位檔剖析器是豐富的目標環境,且播放媒體為完整的二進位檔剖析。因此,媒體剖析器中的安全性問題極為常見。
Chromium 採取深入防禦機制,降低使用者遇到安全性問題的風險。實際上,這意味著解碼和軟體解碼一律會在低權限程序中發生,而硬體解碼是在具備足夠的權限才能與系統 GPU 通訊的程序中發生。
Chromium 的跨程序通訊機制稱為 Mojo。本文將詳細說明 Mojo 的細節,但既然程序之間的抽象層,也是 Chromium 可擴充媒體管道的基礎。我們在逐步執行播放管道時,請務必留意這一點,因為這個管道會告知與接收、解碼、解碼和最終顯示媒體互動的跨程序元件複雜自動化調度管理。
非常多
想要瞭解現今的影片轉譯管道,必須具備影片特別的理由:頻寬。3840x2160 (4K) 解析度的播放解析度是以每秒 60 個影格為單位,會使用介於每秒 9 至 12 GB 的記憶體頻寬。雖然現代系統可能擁有高達每秒數百 GB 的尖峰頻寬,但影片播放仍佔了很大比例。在不注意的情況下,由於 GPU 和 CPU 記憶體之間的複製或行程,總頻寬很容易增加。
我們的目標是盡可能提升新式影片播放引擎的效率,藉此將解碼器和最終轉譯步驟之間的頻寬降到最低。因此,影片轉譯作業主要與 Chromium 的主要轉譯管道分離。 具體來說,從我們的主要轉譯管道的角度來看,影片只是一個不透明的固定大小孔。Chromium 會使用名為「Surfaces」的概念實現這一點,其中每部影片都會直接與 Viz 對話。
由於行動運算的普及,電力和效率已成為當前世代的一大重點。因為這樣,解碼和轉譯在硬體層級比以往更為緊密,進而使影片看起來像是不透明度的缺口,甚至在 OS 上也是如此!平台層級解碼器通常只會提供不透明緩衝區,而 Chromium 會以疊加層的形式,傳遞至平台層級合成系統。
每個平台都有自己的疊加層形式,讓其平台解碼 API 可與 API 搭配使用。Windows 具備 Direct Composition 和 Media Foundation Transforms,macOS 具備 CoreAnimation Layers 和 VideoToolbox,Android 則具備 SurfaceView 和 MediaCodec,而 Linux 則具備 VASurfaces 和 VA-API。 Chromium 針對這些概念的抽象化會分別由 OverlayProcessor 和 mojo::VideoDecoder 介面處理。
在某些情況下,這些緩衝區可能會對應至系統記憶體,因此甚至不需要不透明,而要在存取前使用任何頻寬,Chromium 會呼叫這些 GpuMemoryBuffers。在 Windows 上,這些內容會以 DXGI 緩衝區、macOS IOSurfaces、Android AHardwareBuffers 及 Linux DMA 緩衝區等加以支援。雖然影片播放通常不需要此存取權,但這些緩衝區對影片擷取來說非常重要,可確保擷取裝置和最終編碼器之間的頻寬降到最低。
由於 GPU 通常負責解碼與顯示,因此使用這些不透明緩衝區可確保高頻寬影片資料實際上不會離開 GPU。如先前所述,在 GPU 上保留資料對於提升效率至關重要,尤其對於高解析度和畫面更新率而言更是重要。
我們能充分利用 OS 基本功能 (例如重疊和 GPU 緩衝區) 的效益越大,用來在非必要時重組影片位元組所耗用的頻寬就越少。無論是解碼程式碼還是算繪作業,所有一切要素都集中在一處,有助於提升電力效率。舉例來說,Chromium 在 macOS 啟用重疊功能後,全螢幕影片播放期間的耗電量會暫停!在 Windows、Android 和 ChromeOS 等其他平台,我們甚至可以在非全螢幕的情況下使用重疊,幾乎可省下高達 50% 的費用。
轉譯
瞭解完最佳交付機制後,接下來可以談談 Chromium 如何選擇要交付的內容。 Chromium 的播放堆疊採用「提取」架構,也就是說,堆疊中的每個元件都會依照階層順序要求其輸入來源。堆疊頂端是音訊和視訊影格的轉譯,次低的是解碼,然後是 demux,最後為 I/O。每個轉譯的音訊影格都會提前調整時鐘,以便在搭配呈現時間間隔時,用來選擇要轉譯的影格。
在每個呈現間隔 (每次重新整理螢幕) 上,影片轉譯器都會透過先前提及的 SurfaceLayer 附加的 CompositorFrameSink 提供影片影格。如果內容的影格速率低於顯示速率,也就是重複顯示同一個影格一次,但影格速率高於顯示速率,則系統一律不會顯示某些影格。
想將音訊和影片同步處理,還有其他疑問,讓觀眾感到賞心悅目。 如要進一步瞭解如何在 Chromium 中提升視訊流暢度,請參閱「Project Butter」一文。說明如何將影片算繪細分為理想的序列,以代表每個影格應顯示的次數。例如:「每個顯示間隔 ([1],每 60 Hz 每秒 60 個影格)」、「1 個影格 ([2],以 60 Hz 為 30 fps)」或更複雜的模式,例如 [2:3:2:3:2](以 60 Hz 的每秒影格數和 25 個影格為單位)影片轉譯器越接近理想模式,使用者就越可能認為影片播放順暢。
雖然大多數 Chromium 平台都是逐個頁框轉譯,但並非萬無一失。 我們的延伸架構也支援批次轉譯。 批次轉譯是一種效率提陞技術,系統會預先告知作業系統層級的合成器多個影格,並依照應用程式提供的時間排程發布這些影格。
未來就在眼前嗎?
我們專注在 Chromium 如何利用作業系統基本功能,提供一流的播放體驗。 但要推出比基本影片播放外的網站嗎? 能否提供和 Chromium 一樣強大的基本功能,就讓我們在新一代的網頁內容中扮演同樣重要的角色?
答案是,當然可以! 擴充性是現今網路平台的核心。我們持續與其他瀏覽器和開發人員合作,開發出 WebGPU 和 WebCodecs 等新技術,方便網頁程式開發人員使用 Chromium 與 OS 相同的基本技術。WebGPU 支援 GPU 緩衝區,WebCodecs 則提供與前述重疊和 GPU 緩衝區系統相容的平台解碼和編碼基本功能。
直播結束
感謝閱讀!希望您已經進一步瞭解現代播放系統,以及 Chromium 每天如何提供數億小時的觀看時間。如果您想進一步瞭解轉碼器和現代網路影片,推薦您推薦 Sid Bala 的 H.264 is 魔法、Erica Beaves 的 How Modern Video Players Work,以及 Cyril Concolato 的包裝獲獎節目。
Una Kravets 的一張插圖 (完美!)。