?

一種基于多通道視頻同步采集的多投影環幕顯示系統

2020-10-15 11:01程夢龍姜忠鼎
計算機應用與軟件 2020年10期
關鍵詞:緩沖區線程解碼

程夢龍 姜忠鼎

(復旦大學上海市數據科學重點實驗室 上海 201203) (復旦大學軟件學院 上海 201203)

0 引 言

近年來,隨著科技水平的提高以及圖形技術的進步,虛擬現實得到了快速的發展。虛擬現實使用計算機模擬生成可交互式的虛擬三維場景,向用戶提供沉浸式的環境,給人身臨其境的感覺[1]。相比于頭戴式的虛擬現實頭盔,使用多投影或多顯示器拼接而成的環幕系統能夠支持多人同時交互,并且往往具有更大尺寸、更高分辨率的顯示表面,在教育、娛樂和虛擬仿真等領域具有重要的應用價值[2]。

傳統環幕系統的畫面源與顯示環境耦合度較高,外部應用需要修改自身代碼才能實現在環幕的顯示,環幕系統不具有通用性。本文提出一種基于多通道視頻同步采集的多投影環幕顯示系統,系統使用視頻采集卡對畫面源內容進行采集,通過網絡傳輸畫面內容到多投影環幕呈現。渲染與顯示的分離降低了畫面源與環幕的耦合度,提高系統的通用性。

關于使用渲染顯示分離的方法降低系統耦合度的思想,目前已有許多相關的研究與應用。Lamberti等[3]在2007年提出基于視頻流實現復雜3D圖形在移動設備中呈現的方案,使用集群主機渲染復雜3D模型,將渲染畫面以MPEG視頻流的形式發送給呈現客戶端,解決移動端圖形處理能力不足的問題。文獻[4-5]提出使用遠程渲染的方式來實現3D視頻在移動設備的呈現,提出基于代理的框架,3D視頻流在代理中渲染,然后將渲染畫面通過無線網絡發送給移動設備顯示。文獻[6]提出使用遠程渲染的方式來保護畫面源不被篡改。文獻[18]提出使用渲染顯示分離的方法實現3D地圖在移動設備的呈現。云技術的發展也使得云游戲逐漸變為現實[7],國內外也已有一些云游戲系統,如GamingAnywhere[8]、UBCGaming[9]和文獻[10]提出的游戲云等。云游戲的基本思想為:在云端遠程運行游戲應用,將渲染畫面壓縮,以像素流的形式傳輸給客戶端,如手機等;客戶端對畫面數據進行解碼呈現,客戶端的交互指令通過網絡發送給云端主機,從而模擬本地場景交互。云游戲能夠大大降低對客戶端的設備性能要求,使得玩家能夠隨時隨地享受高質量的游戲體驗[11]。文獻[19]提出一種使用分布式渲染的方式來降低系統交互延遲的方案,通過服務器提供的背景圖和客戶端GPU加速技術對畫面進行變形與插值,降低交互延遲,提高云游戲的用戶體驗。隨著5G時代的來臨,遠端渲染傳輸的方式會得到更一步的發展與推廣。

在本文系統中,畫面源以像素流的形式傳輸至環幕呈現,內容類型與呈現流程無關,因而支持多種類型的畫面源,例如視頻播放應用、游戲、可視化和VR仿真等。畫面源只需提供符合環幕顯示規范的輸出畫面,即可實現在多投影環幕顯示系統中的呈現。

本文系統的設計與實現可分為兩個模塊:多通道視頻采集模塊與集群顯示模塊。多通道視頻采集模塊負責畫面采集、壓縮與傳輸;集群顯示模塊負責畫面接收、解碼與顯示。將一款使用Unity游戲引擎開發的第一人稱射擊游戲使用本系統進行實驗,結果表明本文系統具有可行性與實用性,并且畫面延遲較低。

1 多通道視頻采集

多通道視頻采集包含多通道視頻同步采集、視頻幀壓縮與重組、視頻幀傳輸三個部分。

為了充分利用多核主機的計算性能,降低畫面延遲,提高系統的運行效率和數據吞吐量,采集服務器使用多線程來完成多通道視頻采集工作。相比于單線程方法,多線程的流水線架構能夠提高并發性,降低視頻畫面從采集到傳輸的總耗時,從而降低整個系統的畫面延遲。

系統啟動后,采集模塊創建采集線程、壓縮線程、重組線程、網絡傳輸線程四種類型的線程,并初始化采集緩沖區、壓縮緩沖區、發送緩沖區三種類型的數據緩沖區。多線程之間使用數據緩沖區進行數據的共享,數據緩沖區通過加鎖的方式保證多線程訪問的互斥性。多線程流程圖如圖1所示。

圖1 多線程流程圖

1.1 多通道視頻同步采集

多通道視頻同步采集包含兩個關鍵步驟:通道視頻幀數據的正確讀取,多通道視頻幀的采集同步。本文系統使用Magewell Pro Capture Quad HDMI Video Capture Card視頻采集卡,每個采集卡支持4通道高清視頻采集[12],以及Magewell提供的采集卡SDK(MWCaptureSDK 3.3.1.1004)來完成視頻幀的讀取與同步。為了減少視頻幀大小,提高視頻幀壓縮速度,本文系統使用I420顏色格式采集視頻幀。

采集模塊啟動后創建一個采集線程,采集線程額外創建信號監聽線程與視頻幀讀取線程兩個線程,分別負責監聽通道狀態和從通道讀取視頻幀數據。

信號監聽線程包含以下三個基本步驟:

步驟1使用MWRegisterNotify函數為每個通道注冊通知事件hNotifyEvent。當通道狀態發生改變時,hNotifyEvent變為Signal狀態。

步驟2在線程主循環內使用WaitForMultipleObjects函數等待所有通道的通知事件hNotifyEvent。當某個通道狀態發生變化時,使用MWGetNotifyStatus函數獲取通知事件的具體類型。

步驟3當通知事件類型包含MWCAP_NOTIFY_VIDEO_FRAME_BUFFERED,即有新的視頻幀數據時,設置本通道的待讀取狀態為True。當所有通道的待讀取狀態為True時,設置m_dwCapMask為True,表示所有通道數據已準備好。

視頻幀讀取線程包含以下三個基本步驟:

步驟1使用MWRegisterTimer函數注冊定時事件hTimerEvent。每隔一段時間,hTimerEvent變為Signal狀態。

步驟2在線程主循環內使用WaitForMultipleObjects函數等待定時事件hTimerEvent。然后判斷m_dwCapMask是否為True,即是否所有通道的數據均已準備完成。

步驟3當m_dwCapMask為False時,不執行數據讀取等操作,直接等待下一個定時事件。當m_dwCapMask為True時,使用MWCaptureVideoFrameToVirtualAddress函數依次從所有通道讀取視頻幀數據至指定的內存區域。視頻幀讀取完成后,為所有通道視頻幀賦予相同的幀號,然后將所有通道采集到的視頻幀數據放入采集緩沖區等待壓縮,最后將m_dwCapMask設置為False。

1.2 視頻幀壓縮與重組

采集的原始視頻幀數據量較大,直接傳輸會占用較多的帶寬。為了減少網絡帶寬占用,提高視頻幀傳輸效率,對采集的視頻幀進行壓縮,減少視頻幀數據大小。本文系統使用LibJpegTurbo插件[13]對視頻幀進行JPEG壓縮。

采集模塊啟動后,創建壓縮線程池,壓縮線程池中包含與通道數量相同個數的壓縮線程。在壓縮線程主循環中,從采集緩沖區獲取一幀視頻幀,對視頻幀數據進行壓縮得到壓縮視頻幀,將壓縮視頻幀數據放入壓縮緩沖區等待重組,然后進入下一個獲取數據、壓縮數據、放入壓縮緩沖區循環。壓縮視頻幀幀號與壓縮前的視頻幀幀號相同。

為了保證多通道畫面顯示的同步性,在壓縮視頻幀傳輸前需要將多個通道的壓縮視頻幀重組。重組線程根據幀號將所有通道同一幀號的壓縮視頻幀打包為重組視頻幀,具體重組過程包含以下三個步驟:

步驟1根據采集線程記錄的幀號序列,獲取下一個等待重組的幀號,稱為目標幀號。

步驟2依次從壓縮緩沖區中獲取各個通道的壓縮視頻幀隊列中對應目標幀號的壓縮視頻幀。若某個通道的視頻幀還未壓縮完成,則等待直至收集齊所有通道目標幀號的壓縮視頻幀。

步驟3將所有通道的壓縮視頻幀數據拷貝至重組視頻幀,重組視頻幀的幀號被賦值為目標幀號。將重組視頻幀放入重組緩沖區中,等待網絡傳輸線程使用。

圖2給出三個通道時的壓縮視頻幀重組示例,采集線程記錄采集的視頻幀幀號序列為1、2、3、4等。重組線程首先重組1號幀:從壓縮緩沖區中的三個通道的壓縮視頻幀隊列取出幀號為1的壓縮視頻幀,重組為重組視頻幀,然后放入重組緩沖區。2號幀的重組過程與1號幀相同。在重組3號幀時,通道1的壓縮視頻幀隊列沒有3號幀,說明通道1的3號幀還未壓縮完成,等待直至通道1的3號幀壓縮完成,然后對3號幀進行重組。

圖2 重組示例

1.3 視頻幀傳輸

若要實現畫面在環幕的顯示,須將重組視頻幀數據發送至集群顯示模塊,集群顯示模塊渲染顯示畫面。為了保證重組視頻幀數據的可靠到達,防止丟包帶來的異常行為,采集模塊與集群顯示模塊使用TCP完成重組視頻幀數據的傳輸。

網絡傳輸線程負責將重組視頻幀發送至集群主節點。網絡線程與集群主節點建立TCP連接,在線程主循環內,每次從重組緩沖區取出一幀重組視頻幀,發送至集群主節點;若重組緩沖區內無重組視頻幀,則線程休眠5秒后再次嘗試。采集模塊與顯示模塊傳輸的數據格式如圖3所示。

圖3 數據包格式

數據包頭部數據包含幀號、寬度、高度和通道數量共四個字段,每個字段均為整數類型,占用4個字節長度。接下來為通道數據列表,每個通道數據項包含通道ID、壓縮視頻幀數據長度和壓縮視頻幀內容三個字段。通道ID和壓縮視頻幀數據長度為整數類型,占用4個字段。壓縮視頻幀內容為字節數組,占用長度不固定,接收方根據壓縮視頻幀數據長度字段來確定字節數組的邊界。

1.4 數據緩沖區

為了降低線程之間的耦合度,提高數據處理的并發性,采集模塊使用生產者-消費者模式[14],多線程之間使用數據緩沖區實現數據的傳遞。生產者-消費者模式如圖4所示,生產者向數據緩沖區存入數據,消費者從數據緩沖區讀取數據,數據的存入與讀取使用加鎖的方式保證同步性與互斥性。

圖4 生產者-消費者模式

采集模塊中,數據緩沖區包含采集緩沖區、壓縮緩沖區和重組緩沖區三種。

對于采集緩沖區,采集線程充當生產者的角色,將所有通道的視頻幀放入同一視頻幀隊列。壓縮線程充當消費者的角色,從視頻幀隊列獲取視頻幀,對視頻幀進行壓縮。

對于壓縮緩沖區,壓縮線程充當生產者的角色,對視頻幀進行壓縮后,根據視頻幀的通道號,將其放入對應的壓縮視頻幀隊列。壓縮緩沖區為每個通道分配一個壓縮視頻幀隊列。重組線程充當消費者的角色,從壓縮緩沖區的壓縮視頻幀隊列獲取所有對應序號的壓縮視頻幀進行重組。

對于重組緩沖區,重組線程充當生產者角色,對壓縮視頻幀進行重組后,將重組視頻幀數據放入重組視頻幀隊列。網絡傳輸線程充當消費者的角色,從重組視頻幀隊列獲取重組視頻幀,然后發送至集群主節點。

對于采集緩沖區和壓縮緩沖區,本文系統能夠確保消費者取數據的頻率大于等于生產者存數據的頻率,因此兩者均無容量限制。對于重組緩沖區,其與集群主節點間的網絡狀況不確定,將其緩存隊列容量設為10。當網絡傳輸速率低于重組速率時,需要對部分重組視頻幀進行主動丟棄,防止隊列溢出。

緩沖區丟棄數據的策略有兩種。一是在放入隊列前進行檢測,若隊列已滿,則將隊列中的已有的數據全部丟棄,放入最新的數據;二是根據消費者反饋選擇性丟幀,如每三幀丟棄一幀。第一種方式畫面延遲較小,但是可能會出現畫面變化幅度較大,畫面偶爾不連貫的現象;第二種方式畫面看起來比較連貫,但是相對第一種畫面延遲會比較高。為了保證較低的畫面延遲以及多線程之間的低耦合度,本文選用第一種丟棄策略。

2 集群顯示

集群顯示模塊包包含視頻幀接收與轉發、解碼與顯示兩個部分。

由于單臺主機的輸出分辨率有限且不具有擴展性,本文使用集群來搭建多投影環幕顯示系統。集群包含一個集群主節點與多個集群從節點,主節點負責保證所有節點狀態的同步,每個從節點都是顯示節點,負責渲染一塊顯示區域,所有節點畫面通過拼接組成完整的畫面。

2.1 視頻幀接收與轉發

視頻幀數據的接收由集群主節點負責。集群主節點創建單獨的網絡線程,網絡線程與采集模塊建立TCP網絡連接,從采集模塊接收重組視頻幀數據,兩者之間的網絡狀況影響重組視頻幀的接收速率。

集群主節點使用生產者消費者模式,網絡線程接收到重組視頻幀后,將其放入接收緩沖區。在每幀的Unity主線程的LateUpdate階段,從接收緩沖區取一幀重組視頻幀,然后發送至集群從節點。重組緩沖區的接收隊列容量為10,當緩沖區將要溢出時,使用直接丟棄緩沖區內已有數據的丟棄策略,保證具有較低的畫面延遲。重組視頻幀在集群主節點內部的流向如圖5所示。

圖5 集群主節點數據流向

集群主節點接收到重組視頻幀數據后,需要將數據通過網絡轉發給所有集群從節點。

TCP為點對點的可靠網絡傳輸協議,能夠保證數據的按序可靠到達,TCP傳輸如圖6所示。在數據量為M,從節點數量為N的情況下,主節點需要傳輸的數據量為M×N。在節點較多時,使用TCP不僅耗時較且多占用很高的網絡帶寬,系統運行效率較低且不具有可擴展性。

圖6 TCP點對點傳輸

本文使用復旦大學交互式圖形學實驗室開發的基于可靠多播的集群同步協議,UDP多播傳輸如圖7所示。在數據量為M,從節點為N的情況下,主節點只需傳輸M的數據量。相比于TCP的點對點,使用集群同步協議能夠減少網絡帶寬占用,提高系統運行效率與可擴展性。

圖7 UDP多播傳輸

2.2 解碼與顯示

集群從節點應用中包含與通道數量相同的紋理,將接收到的多個通道的畫面數據上傳至紋理顯示。

紋理上傳可使用Unity提供的Texture2D.LoadImage函數[15]或者Texture2D.LoadRawTextureData函數[16]將各個通道的畫面數據上傳至對應的紋理,然而這種方法的紋理數據加載與上傳過程均在主線程執行。在上傳紋理數量較多或者紋理數據較大時,主線程耗時過多,嚴重影響系統運行幀率。

本文系統使用Unity提供的多線程渲染技術[17],開發渲染插件NativeRenderingPlugin.dll,在Unity渲染線程中實現紋理上傳,從而提高系統幀率。渲染線程中執行紋理上傳的操作需要對各個通道的壓縮視頻幀進行解碼操作,并且紋理上傳的起始指令只能在Unity主線程中調用。為了提高系統效率以及保證多通道畫面顯示的同步性,集群從節點額外創建解碼線程與紋理上傳線程,多線程的流程圖如圖8所示。

圖8 集群從節點多線程流程圖

集群從節點的基本行為可分為如下三部分:

1)Unity主線程在LateUpdate階段,從主節點接收重組視頻幀數據,然后將數據放入接收緩沖區。接收緩沖區容量為10,使用前文提到的第一種丟棄策略:在隊列已滿時將隊列清空。

2)從節點在啟動后,創建一個解碼管理線程和與通道數量相同個數的解碼線程,每個解碼線程負責一個通道的壓縮視頻幀解碼。主線程每次在LateUpdate階段接收到重組視頻幀數據后,使用信號通知解碼管理線程。解碼管理線程從接收緩沖區獲取一幀重組視頻幀,使用信號通知所有解碼線程開始解碼。解碼線程使用LibJpegTurbo插件將其負責的通道壓縮視頻幀數據解碼為RGBA格式的原始視頻幀數據,解碼完成后使用信號通知解碼管理線程。解碼管理線程接收到所有解碼線程的信號后,表示所有通道的視頻幀均已解碼完成,使用信號通知紋理上傳線程。

3)紋理上傳線程接收到信號后,在下一個LateUpdate階段調用GL.IssuePluginEvent函數開始上傳紋理數據。每個通道的數據被用于解碼單獨的原始視頻幀數據,執行獨立的紋理上傳動作。在Unity中,渲染線程的紋理上傳只能夠保證在下一幀的相機渲染之前完成,在本幀的相機渲染階段紋理上傳的完成狀態難以確保。在一個從節點上,多個通道的原始視頻幀同時開始執行紋理上傳動作,但不同紋理上傳的速度可能不同:在本幀渲染階段之前上傳完成的紋理能夠在本幀顯示;在本幀渲染階段之后上傳完成的紋理只能夠在下一幀顯示。因此一個節點內多通道的畫面顯示可能會有一幀的差異。對于多個從節點,由于紋理上傳的開始只發生在LateUpdate階段,因此在解碼能力足夠,即解碼速率快于接收速率時,從節點之間的顯示畫面可能會有一至兩幀的差異。

經過之前的解碼和紋理上傳步驟,集群從節點的多幅紋理能夠正確顯示多個通道的畫面。多幅紋理根據畫面顯示區域排列,根據當前從節點的顯示區域配置,使用Unity正交相機獲取節點顯示畫面至RenderTexture,根據投影儀的矯正文件對該RenderTexture進行矯正,最終通過多臺投影呈現在環幕表面。圖9給出六通道畫面顯示實例,六幅紋理排列成一排,呈現六個通道的畫面數據。在六個通道的畫面數據為360度場景且投影有融合區域的情況下,在第六幅紋理后面復制一幅第一幅紋理畫面,從而實現首尾的畫面相連。然后根據從配置文件讀取當前節點的顯示區域信息,包含起始位置與顯示范圍,使用正交相機渲染顯示畫面至渲染紋理。最后對渲染紋理進行校正,校正后的畫面如圖10所示。

圖9 可視區域畫面截取

圖10 畫面校正結果

3 實 驗

3.1 實驗系統

本文基于上文描述實現系統并設計兩個實驗,以驗證本文系統的可用性,兩個實驗的畫面源主機與采集服務器配置相同。

畫面源主機使用兩臺NVIDIA Quadro P620顯卡,輸出六個通道的畫面。在畫面源主機全屏運行FPS游戲《泰坦英雄》,在六個通道輸出360度的畫面,每個通道負責60度的畫面。畫面源主機多通道輸出的360度畫面如圖11所示。

圖11 畫面源多通道畫面

采集服務器使用兩臺Magewell Pro Capture Quad HDMI Video Capture Card視頻采集卡,通過HDMI連接線采集畫面源主機輸出的六個通道的畫面。每個通道的采集分辨率均為1 920×1 080,共11 520×1 080的分辨率,采集目標幀率為60,采集畫面格式為I420格式。在對采集到的畫面進行JPEG壓縮時,壓縮質量為85。

3.2 實驗一

為了驗證本文系統的有效性,實驗在復旦大學交互式圖形學實驗室的環幕環境中運行,該環幕提供120度視角。集群顯示模塊使用三臺主機,包括一臺主節點與兩臺集群從節點,所有主機之間使用千兆網絡相連。每臺集群從節點連接三臺投影儀,顯示從30度至150度的輸出畫面,運行效果如圖12所示。

圖12 環幕運行效果

表1給出了實驗運行過程中各階段速率的統計數據。

表1 各階段速率統計表

可以看出,多通道同步采集每秒采集53幀的視頻幀數據,壓縮、重組和發送速率都能夠達到采集速率,說明在采集模塊不會發生數據包的丟棄,采集端以每秒53幀的速率向集群模塊發送多通道畫面數據。在集群模塊,集群主節點發送、集群從節點接收和解碼的速率與采集模塊的速率一致,說明所有的畫面數據都被集群從節點接收并解碼顯示。圖13為系統運行過程中的帶寬占用變化曲線,圖14為系統運行過程中集群畫面刷新率變化曲線,系統平均帶寬占用為554 Mbit/s,平均畫面刷新率為53幀/s。

圖13 帶寬變化曲線

圖14 集群畫面刷新率變化曲線

除了畫面刷新速率外,畫面的延遲也是系統非常重要的評價指標。本文系統中,各個階段的耗時統計如表2所示。

表2 各階段耗時統計表

可以看出,系統各個模塊的耗時都較短,三個階段耗時總計47.3 ms,加上采集模塊到集群主節點的網絡延遲和紋理從上傳到顯示的平均一幀的延遲,本實驗畫面平均延遲在80 ms左右。

3.3 實驗二

實驗使用更多的集群主機數量來模擬本文系統在360度環幕下的運行狀況。集群顯示模塊使用五臺主機,包含一臺集群主節點與四臺集群從節點,所有主機通過千兆網絡相連。每臺集群從節點連接四個高清顯示屏,負責180度的畫面渲染,四臺從節點共顯示兩個360度的畫面,模擬360度的被動立體環幕。系統運行效果如圖15所示。

圖15 模擬360度環幕運行效果

表3給出了實驗運行過程中各階段速率的統計數據。

表3 各階段速率統計表

可以看出,多通道同步采集每秒采集57.4幀的視頻幀數據,壓縮、合并和發送速率都能夠達到采集速率,說明在采集模塊不會發生數據包的丟棄,采集端以每秒57.4幀的速率向集群模塊發送多通道畫面數據。在集群模塊,集群主節點發送、集群從節點接收和解碼的速率都只為每秒51.2幀,即在集群模塊每秒鐘轉發51.2幀畫面的數據,這是由于集群節點間的網絡出現波動,導致集群主節點轉發重組視頻幀的速率低于網絡線程接收重組視頻幀的速率,從而在集群主節點的接收緩沖區中主動丟棄部分重組視頻幀。圖16為系統運行過程中的帶寬占用變化曲線,圖17為系統運行過程中集群畫面刷新率變化曲線。系統平均帶寬占用為500 Mbit/s,平均畫面刷新率為51.2幀/s。

圖16 帶寬變化曲線

圖17 集群畫面刷新率變化曲線

除了畫面刷新速率外,畫面的延遲也是系統非常重要的評價指標。本文系統中,各個階段的耗時統計如表4所示。

表4 各階段耗時統計表

可以看出,多通道同步采集到發送、集群從節點接收到上傳的耗時與實驗一相近,耗時都較短,兩個階段共耗時總計45.1 ms。集群主節點接收到發送的耗時多的原因為集群主節點轉發的速率低于網絡線程接收重組視頻幀的速率,部分視頻幀在接收緩沖區中等待了一段時間才被轉發,從而導致從接收到發送的平均耗時變長。三個階段的總耗時為127.0 ms,加上采集模塊到集群主節點的網絡延遲和紋理從上傳到顯示的平均1幀的延遲,本實驗畫面平均延遲在160 ms左右。

4 結 語

本文提出一種基于多通道視頻同步采集的多投影環幕顯示系統。使用視頻采集卡多通道同步采集畫面源畫面,將畫面數據壓縮,通過網絡傳輸給集群顯示模塊。集群主節點接收到畫面數據后,使用可靠多播協議將畫面數據轉發至集群顯示節點。顯示節點對畫面數據進行解碼,上傳至紋理顯示,然后根據顯示區域配置,對視角內紋理畫面進行變形與矯正,最終通過多臺投影機呈現在環幕顯示表面。本文系統通過多通道采集的方法降低了畫面源與顯示環境的耦合度,具有較好的通用性。實驗結果表明,本文系統具有很好的通用性,并且系統畫面延遲較低。

猜你喜歡
緩沖區線程解碼
5G終端模擬系統隨機接入過程的設計與實現
實時操作系統mbedOS 互斥量調度機制剖析
淺析體育賽事售票系統錯票問題的對策研究
文化解碼
解碼eUCP2.0
文化 解碼
文明 解碼
緩沖區溢出漏洞攻擊及其對策探析
初涉緩沖區
本期導讀
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合