Oculus CTO卡馬克經(jīng)驗(yàn)分享:如何最大程度地優(yōu)化360視頻體驗(yàn)
來源:映維網(wǎng) 作者?黃顏
為了最大程度地優(yōu)化沉浸式360視頻體驗(yàn),Oculus首席技術(shù)官約翰·卡馬克一直在測試和實(shí)驗(yàn) VR 視頻技術(shù)。日前,他通過博文介紹了自己從中積累的經(jīng)驗(yàn)教訓(xùn)。下面是映維網(wǎng)的具體整理:
文件下載
大多數(shù)移動(dòng)VR開發(fā)者最終都會(huì)把某種標(biāo)準(zhǔn)的 媒體 播放器來支持視頻播放(如ExoPlayer)。盡管存在一系列優(yōu)秀的通用播放器,但大多數(shù)都不適合60fps視頻,而且把生成的表面繪制到3D世界中的標(biāo)準(zhǔn)行為會(huì)丟失大量的質(zhì)量。
這是我多年來所做的實(shí)驗(yàn)的集合,其演示了用于管理視頻解碼管道和在VR中實(shí)現(xiàn)最佳質(zhì)量顯示的底層技術(shù)。關(guān)鍵的技術(shù)是:
在合成器層顯示視頻表面,不要將其繪制到3D世界中。根據(jù)視頻內(nèi)容選擇正確的VR刷新率:60fps或72fps。將解碼幀復(fù)制到深層交換鏈,不要直接使用Surface來減輕小故障。使用多個(gè)線程和條件變量來有效地管理編解碼器。使用sRGB格式的交換鏈和幀緩沖器進(jìn)行伽瑪校正過濾。精確地將視頻和音頻速率鎖定為顯示速率。
上面所述同樣適用于虛擬屏幕所顯示的常規(guī)視頻,以及沉浸式媒體內(nèi)容。
我通常建議用5120(5k)作為360度或并排180視頻的最高分辨率。Quest的綠色子像素密度更高(紅色和藍(lán)色的密度更低),所以5760十分合理,但最好將比特率用在5120。
分辨率的安全選擇是:60fps時(shí)為4096×2048或30fps時(shí)為3840×3840,但在大多數(shù)情況下,你可以超出這個(gè)范圍。請(qǐng)注意,對(duì)于Go和Quest,不同的視頻編解碼器有不同的限制:
盡管能夠以60fps解碼4096×2048,但H264無法以30fps解碼4096×4096視頻。這是由于限制了65535 16×16像素宏塊的限制。大多數(shù)人只將3840×3840用于30fps的視頻,但如果需要,你可以拉升到4096×4080。
H264的寬度或高度沒有硬性限制,只要不超過宏塊限制即可。這意味著你可以擁有5760×2880的視頻。
H265的限制為4096寬,但沒有高度限制。所以,如果要實(shí)現(xiàn)5120×2560的視頻,則需要將其轉(zhuǎn)置為2560×5120的視頻,然后再轉(zhuǎn)置回顯示。這可能是標(biāo)準(zhǔn)播放器選擇自上而下180度立體視圖的原因,但我通常只是為實(shí)驗(yàn)而進(jìn)行視頻轉(zhuǎn)置,而這同樣適用于360度視頻。
H265可以30fps的速率解碼4096×4096,并且在較低幀速率下似乎有超過62k的余量。
某種程度上講,你可以解碼視頻的確切幀速率取決于內(nèi)容。規(guī)范僅保證60fps下的4096×2048,但H264似乎存在一定的余量,而且我們已經(jīng)看到4800×2400或以下的視頻依然能夠流暢解碼。然而,這是自找麻煩。H265似乎受限于實(shí)際規(guī)格。
上面鏈接的代碼包括一個(gè)通用的BufferedVideo類,其可以有效地將視頻解碼為深度緩沖交換鏈,將播放與實(shí)際屏幕的刷新率(不完全是60.0或72.0 fps)同步,并對(duì)音頻進(jìn)行細(xì)微的重新采樣以令其完全匹配所述速率。這個(gè)核心類用于沉浸式視頻或常規(guī)視頻的通用表示,以及少數(shù)的專用化。
裁剪視頻:如果垂直裁剪到100度左右(即5120×1536),則可以以5k分辨率和60fps獲得完整的180度水平視場。對(duì)于體育比賽等具有大量左右視圖變化的內(nèi)容,這可能是一個(gè)很好的折衷方案。
插入視頻:如果你希望獲得完整180×180度的視場,但想繼續(xù)以中心區(qū)域作為焦點(diǎn),則可以將峰值分辨率的視頻覆蓋在90×90度的中心區(qū)域,而其他地方則采用較低分辨率的背景。
交錯(cuò)視頻:對(duì)于3D電影,存在對(duì)沉浸式視頻特別有用的專用視頻編解碼器版本,但遺憾的是,我們的芯片組都不支持它們。我發(fā)現(xiàn),僅交錯(cuò)編碼3D視頻而非并排,同時(shí)對(duì)x265使用-preset veryslow選項(xiàng),這可以帶來一系列的好處,這使它可以檢查不僅只是前一幀的運(yùn)動(dòng)預(yù)測源。根據(jù)內(nèi)容的不同,壓縮效果最高可達(dá)到30%。其他編解碼器和選項(xiàng)對(duì)交錯(cuò)視頻的壓縮具有災(zāi)難性的糟糕效果,所以適用范圍有限。
標(biāo)準(zhǔn)的視頻播放器無法處理交錯(cuò)3D幀,因?yàn)槟阈枰瑫r(shí)訪問兩個(gè)解碼后的幀,而不僅僅是最新的幀,但通過深度緩沖交換鏈,操作非常簡單。
可以用以下命令將Ffmpeg重新編碼成交錯(cuò):ffmpeg -i SideBySideVideo.mp4 -c:a copy -vf stereo3d=sbsl:al -crf 18 -preset veryslow -c:v libx265 interleavedVideo.mp4。
雙重視頻:某些立體180度相機(jī)會(huì)產(chǎn)生兩個(gè)帶有魚眼鏡頭變形的獨(dú)立視頻文件。對(duì)于這一點(diǎn),通常會(huì)用軟件工具將其轉(zhuǎn)換成180度等距投影視頻。直接播放兩個(gè)視頻文件,并在VR合成器中進(jìn)行失真映射可以實(shí)現(xiàn)最小的質(zhì)量損失。普通視頻播放器無法令兩個(gè)視頻流保持幀同步,但兩個(gè)緩沖的視頻播放器實(shí)例則有可能。它同時(shí)包括一定的計(jì)算機(jī)視覺代碼以對(duì)透鏡進(jìn)行最簡單校準(zhǔn)。對(duì)于制作用例來說,這并不是非常實(shí)際,但它是一個(gè)優(yōu)秀的參考點(diǎn)。
我曾為Oculus Go開發(fā)了Z CAM播放器,而這是關(guān)于它的第一篇博文,而后續(xù)博文包括立體音頻軌道,以及添加校準(zhǔn)文件的功能。
最極端的代碼專用化是我去年開發(fā)的基于視圖的5k×5k,60fps立體視頻播放器的改進(jìn)版本。
原始版本中的四個(gè)同步視頻流解碼已證明存在問題。由于我們依然不清楚的原因,視頻解碼系統(tǒng)會(huì)降低已使用數(shù)周的頭顯的性能,最終導(dǎo)致5k播放器開始出現(xiàn)慢動(dòng)作和音頻失真。重新啟動(dòng)可以解決這一問題,但我們?nèi)晕窗l(fā)現(xiàn)系統(tǒng)級(jí)別的緩解措施。
我一直有計(jì)劃以某種方式將各個(gè)strip整合到能夠更有效解碼的單一視頻文件中,但我最終找到了一種相當(dāng)簡單的方法。
不是將詳細(xì)的區(qū)域分成十個(gè)獨(dú)立的視頻文件,而是將其分成三個(gè)文件(每個(gè)文件包含四個(gè)strip),并將視頻顯式編碼為四個(gè)h265 slice,這意味著它們位于獨(dú)立的網(wǎng)絡(luò)抽象層(Network Abstraction Layer;NAL)單元。這允許你通過簡單的字節(jié)掃描尋找邊界,無需對(duì)整個(gè)比特流進(jìn)行解碼。
在運(yùn)行時(shí),對(duì)于每個(gè)幀,通過將最初創(chuàng)建的十二個(gè)slice中的四個(gè)slice拼湊在一起來創(chuàng)建合成的視頻樣本。這具有單個(gè)視頻解碼而不是四個(gè)的效率。
我最初的計(jì)劃是調(diào)整低分辨率基礎(chǔ)視圖的大小并對(duì)其進(jìn)行轉(zhuǎn)置,從而將其與高分辨率的slice連接成一個(gè)完整的視頻解碼器,但另一個(gè)取得了足夠優(yōu)秀結(jié)果的實(shí)驗(yàn)令我們改變了方向。
2048×2048基礎(chǔ)層顯然十分模糊。我認(rèn)為在2880×2880基礎(chǔ)層上花費(fèi)相同數(shù)量的像素解碼速率(僅以30fps而非60fps進(jìn)行動(dòng)畫處理)可能是更好的選擇。事實(shí)證明,這確實(shí)是一筆好買賣,但大小和幀速率使其不兼容高分辨率的strip,所以確實(shí)需要兩個(gè)獨(dú)立的視頻解碼。
由于基礎(chǔ)層總是要與高分辨率層分開解碼,所以不用提供strip實(shí)現(xiàn)快速切換所需的半秒視頻GoP大小。為基礎(chǔ)層提供更長的GoP只會(huì)影響搜索粒度,而不會(huì)影響視圖適應(yīng)速度,所以可以提高壓縮率。
事實(shí)證明,挑戰(zhàn)比我預(yù)期的要多,你確實(shí)需要對(duì)x265編碼器進(jìn)行一定的調(diào)整,但我現(xiàn)在有了一種變通的方法:
有必要確保所有slice視頻具有完全相同的參考幀,以便可以將它們混合在一起。僅設(shè)置scenecut = 0來禁用自動(dòng)iFrame插入并不足,當(dāng)看起來像是節(jié)省了壓縮成本時(shí),它依然會(huì)將B幀轉(zhuǎn)換為P幀。Scenecut-bias允許你為不同的編碼調(diào)整比特率的比較,從而確定什么時(shí)候是場景剪輯,但它限制在0到100之間,而且為了確保不存在場景剪輯,我們希望將其設(shè)為負(fù)數(shù)。將其設(shè)置為“nan”是一個(gè)可怕的技巧,它可以令其通過參數(shù)檢查,并且導(dǎo)致is-scenecut計(jì)算始終返回false。我認(rèn)為scenecut = 0根本不應(yīng)該強(qiáng)制提升B幀。
啟用slice編碼會(huì)導(dǎo)致壓縮率的大幅降低。x265中的多線程運(yùn)動(dòng)估計(jì)似乎是一個(gè)問題,但現(xiàn)在設(shè)置-frame-threads = 1仍然是一種解決方法,并且不會(huì)嚴(yán)重?fù)p害編碼速度。
x265編碼器不僅將運(yùn)動(dòng)矢量搜索限制在它正在編碼的slice上,所以如果你不走運(yùn),當(dāng)相鄰文件的一個(gè)slice混入時(shí),它可能會(huì)引用實(shí)際上并不存在的像素,而這偶爾會(huì)造成高分辨率區(qū)域上方或下方的偽影。x265編碼器源中有關(guān)于這一點(diǎn)的FIXME注釋,并可以有效地解決這個(gè)問題,但就目前而言,我用一點(diǎn)點(diǎn)粉紅色的填充和一對(duì)牢固交叉的手指來將其分開。注意,理想情況下,運(yùn)動(dòng)和幀內(nèi)搜索范圍將足夠大,可以令strip的右眼部分在已解碼的左眼部分中找到有用的像素。
所以,與原來的5K播放器相比,我們有了下面的優(yōu)勢:
1.減速?zèng)]有問題。
2.解碼高分辨率的4/12而非3/10,這樣你在看到低分辨率之前能夠再看到10%的像素。
3.《Dear Angelica》中的額外邊緣和時(shí)間漸隱效果可減少細(xì)節(jié)溢出。
4.低分辨率基礎(chǔ)是翻倍分辨率,但只需幀速率的一半。
請(qǐng)注意,你需要安裝最新版本的ffmpeg。
原文鏈接:https://yivian.com/news/67859.html