1. 程式人生 > >H.265/HEVC在Web視訊播放的實踐

H.265/HEVC在Web視訊播放的實踐

H.265

以下是百度百科對於H.265的介紹: H.265是ITU-T VCEG繼H.264之後所制定的新的視訊編碼標準。H.265標準圍繞著現有的視訊編碼標準H.264,保留原來的某些技術,同時對一些相關的技術加以改進。新技術使用先進的技術用以改善碼流、編碼質量、延時和演算法複雜度之間的關係,達到最優化設定。具體的研究內容包括:提高壓縮效率、提高魯棒性和錯誤恢復能力、減少實時的時延、減少通道獲取時間和隨機接入時延、降低複雜度等。H.264由於演算法優化,可以低於1Mbps的速度實現標清(解析度在1280P720以下)數字影象傳送;H.265則可以實現利用1~2Mbps的傳輸速度傳送720P(解析度1280

720)普通高清音視訊傳送。

相比H.264帶來了很多質的提升,相關對比可以訪問H.265與H.264的差異詳解。總之,H.265, HEVC 作為當前非常火的視訊壓縮方式,相對於大家熟知的 H.264 ,平均可以帶來接近於 50% 的寬度節省。

在這裡插入圖片描述

相關知識

視訊播放器架構

一個典型的現代播放器可以分為三個部分:UI、多媒體引擎和解碼器,架構模型如下圖:

在這裡插入圖片描述

硬解碼支援

隨著 4K 視訊越來越流行,Apple公司的最新的作業系統版本(Mac Hight Sierra和iOS 11)迎來了 HEVC (高效視訊編碼,也稱 H.265) 這一新的行業標準[6]。與現行的 H.264 視訊壓縮標準相比,它的視訊壓縮率最高可提升 50% 之多。使用H.265,在保持視訊畫質不變的情況下,視訊流媒體傳輸效果更好。而在相同位元速率下,能給質量帶來近兩倍的提升。下圖是兩張相同位元速率相同解析度(400kpbs 1080p)的圖片,左邊的採用H.265編碼,右邊的採用H.264編碼。

在這裡插入圖片描述
一般來說作業系統藉助硬體(顯示卡)進行H.265編碼視訊的解碼工作,其好處是硬解的功耗低,解碼速度快。但目前H.265編碼在瀏覽器中的硬體解碼支援情況並不普及。經測試只在定製的Chromium[7] 及Edge 14瀏覽器中支援,可以通過此頁面,測試瀏覽器對H.265編碼的點播視訊的播放情況。下圖是H.265視訊在Chromium 64中播放的截圖:
在這裡插入圖片描述
需要注意的是硬體解碼需要使用者的顯示卡支援H.265 codec, 目前支援H.265解碼的顯示卡主要包括:Intel HD Graphic 4400/4600/5000/5500/6000/620, Iris Graphics 5100/5200/6100,NVIDIA GeForce GTX 745, GTX 750, GTX 750 Ti, GTX 850M, GTX 860M,GeForce 830M, 840M,GeForce GTX 970, GTX 980, GTX 970M, GTX 980M,GeForce GTX TITAN X, GeForce GTX 980 Ti, GeForce GTX 750 SE, GTX 950, GTX 960, GeForce GTX 1070, GTX 1080, GeForce GTX 1060, NVIDIA TITAN XP, GeForce GTX 1050, GTX 1050 Ti。

Web軟解方案

除了硬解碼方案之外,軟體解碼也成為一種有效的選擇,由於H.265視訊的解碼是一個對效能要求很高的CPU密集任務,Web端指令碼語言實現的解碼器的效能很難達到要求。基於此,我們可以通過基於Flash的H.265解碼方案,即通過FlasCC[11]編譯器把C語言編寫的解碼器編譯成swc庫,然後在Flash播放器中用Action Script呼叫swc庫。

另一種方案是基於HTML5的,即通過WebAssembly技術將金山雲自研的高效能解碼器編譯為wasm庫,wasm檔案是以二進位制形式存在的,其中包含平臺無關的虛擬指令(類似彙編指令)。這也是很多移動平臺採用的方案。

相關HTML5技術

下圖是播放器核心主要模組與依賴的背景技術。

在這裡插入圖片描述
其中Audio MSE Controller依賴於Media Source Extension API,Stream Loader依賴於Stream標準,H.265 Decoder依賴於WebAssembly技術,而各個模組被劃分在不同的執行緒中,依賴於Web Workers。

Media Source Extensions(簡稱MSE):

提供了實現無外掛且基於 Web 的流媒體的功能。使用MSE API(主要包括:Media Source,Source Buffer等),媒體流能夠通過 JavaScript 建立,並且能通過HTMLMediaElement元素(包括:video和audio元素)進行播放。IE11(win8+)及其他現代瀏覽器都支援。

Streams

標準提供了一套API,來建立和操作流資料,具體地,包括ReadableStream, WritableStream, 以及TransformStream。這允許我們可以增量地處理資料,而不必將所有資料快取到記憶體中統一處理。我們可以採用Fetch API獲取視訊資料,返回的body是一個ReadableStream物件。該物件代表一個數據源,內部維護了一個佇列來記錄尚未被讀取的底層資料來源。可以通過ReadableStream的getReader()介面讀取內部佇列中chunk資料。

Web Workers

讓單執行緒的JavaScript具備了多執行緒程式設計的能力,讓視訊播放器核心可以分離解複用、解碼、渲染、UI操作監聽等任務到不同的執行緒中,並行地處理計算密集型任務和介面顯示等。worker間通訊是通過MessageChannel進行。IE10+及其他現代瀏覽器都支援。

WebAssembly

是Web端的位元組碼技術,它定義了一個通用的、體積緊湊、載入迅捷的二進位制格式為編譯目標,能發揮通用硬體的效能,以更接近原生應用的速度執行。在瀏覽器中對H.265編碼的視訊進行軟體解碼,是一項對效能非常有挑戰的任務,JavaScript等指令碼語言無法勝任此項工作。因此可以將C/C++語言編寫的高效能解碼庫編譯成位元組碼,再通過JavaScript呼叫來執行。目前此項技術在Chrome、Firefox、Safari和Edge瀏覽器的較新版本中都可以使用(如Chrome57+,Firefox 52+)。

H.265 Vs H.264

關於H.265 與 H.264更詳細的差異,可以訪問H.265與H.264的差異詳解

H.265/HEVC的編碼架構大致上和H.264/AVC的架構相似,主要也包含:幀內預測(intra prediction)、幀間預測(inter prediction)、轉換(transform)、量化(quantization)、去區塊濾波器(deblocking filter)、熵編碼(entropy coding)等模組。

在這裡插入圖片描述

在HEVC編碼架構中,整體被分為了三個基本單位,分別是編碼單位(coding unit, CU)、預測單位(predict unit, PU)和轉換單位(transform unit, TU)。比起H.264/AVC,H.265/HEVC提供了更多不同的工具來降低位元速率,以編碼單位來說,H.264中每個巨集塊(macroblock/MB)大小都是固定的16x16畫素,而H.265的編碼單位可以選擇從最小的8x8到最大的64x64。

同時,H.265的幀內預測模式支援33種方向(H.264只支援8種),並且提供了更好的運動補償處理和向量預測方法。 反覆的質量比較測試已經表明,在相同的圖象質量下,相比於H.264,通過H.265編碼的視訊大小將減少大約39-44%。由於質量控制的測定方法不同,這個資料也會有相應的變化。

支援情況

ios

目前,根據蘋果官網的資料,對於HEVC的支援情況可以用下面的一句話來說明: iOS 11 and macOS High Sierra introduced support for these new, industry-standard media formats。 也即是說,下面的裝置都是支援的。

  • iPhone 7 or iPhone 7 Plus or later
  • iPad (6th generation)
  • iPad Pro (10.5 inch)
  • iPad Pro 12.9-inch (2nd generation)

Android

在這裡插入圖片描述

瀏覽器

目前,瀏覽器對於H.265支援的並不是很友好:

在這裡插入圖片描述

實戰

目前,HEVC 的普及速度還沒有那麼快,不過我們還是可以嘗試在 Web 中優雅的播放 H265 視訊。

判斷是否支援播放

要判斷平臺是否支援H.265格式的視訊,可以通過H265 的 mimetype 值來判斷:type="video/mp4; codecs=hevc"。例如:

var supportHEVC = function(video) {  
    if (typeof video.canPlayType == ‘ function’) {
        var playable = elem.canPlayType('video/mp4; codecs="hevc"');
        if ((playable.toLowerCase() == 'maybe') || (playable.toLowerCase() == 'probably')) {
            return true;
        }
    }
    return false;
};
複製程式碼

如果,使用H.265無法播放視訊,則使用H.264進行播放,所以我們可以通過 source 設定多種格式:

<video controls autoplay>  
    <source src="your_video.mp4" type="video/mp4; codecs=hevc">
    <source src="your_video.webm" type="video/webm; codecs=vp9">
    <source src="your_video.mp4" type="video/mp4; codecs=avc1">
</video>  
複製程式碼

對於web平臺來說,我們用到的是libde265.js,它是一個通過 JS 來解碼 H.265 視訊的庫,它通過將 視訊的 frame data 轉化為 rgba 畫素,然後繪製到 Canvas 上。下面是使用示例:

<canvas id="canvas"></canvas>

<script src="./libde265.min.j"></script>  
<script>  
var VIDEO_URL = 'h265-test-640.mp4'  
var video = document.getElementById('canvas')  
 // var fpsWrap = document.querySelector('.hevc-fps')
  var status = document.querySelector('.hevc-status')
  var playback = function (event) {
    // event.preventDefault()
    if (player) {
      player.stop()
    }

    player = new libde265.RawPlayer(video)
    player.set_status_callback(function (msg, fps) {
      player.disable_filters(true)
      console.log(msg);
      switch (msg) {
        case 'loading':
          status.innerHTML = 'Loading movie...'
          break
        case 'initializing':
          status.innerHTML = 'Initializing...'
          break
        case 'playing':
          status.innerHTML = 'Playing...'
          break
        case 'stopped':
          status.innerHTML = 'stopped'
          break
        case 'fps':
          // fpsWrap.innerHTML = Number(fps).toFixed(2) + ' fps'
          break
        default:
          status.innerHTML = msg
      }
    })
    player.playback(VIDEO_URL)
  }
  playback()
</script>  
複製程式碼

測試地址:events.jackpu.com/h265。

在這裡插入圖片描述
可以發現,canvas 繪製和 video 原生解碼差距還是很大,但是我們可以看到 Video 的大小相比原有的縮小了 31% ,因此 H265 的前景值得期待的。

參考:H.265 / HEVC WiKi H.265 Vs H.264