撰寫自定義全像攝影遠端播放程式應用程式
如果您不熟悉全像攝影遠端處理,您可能想要 閱讀我們的概觀。
重要
本文件說明如何建立 HoloLens 2 的自定義播放機應用程式。 針對 HoloLens 2 撰寫的自定義播放機與針對 HoloLens 1 撰寫的遠端應用程式不相容。 這表示這兩個應用程式都必須使用 NuGet 套件 2.x.x 版。
藉由建立自定義全像攝影遠端播放程式應用程式,您可以建立能夠從 HoloLens 2 遠端電腦上顯示 沈浸式檢視 的自定義應用程式。 此頁面上的所有程式代碼和工作專案都可以在 全像攝影遠端範例 github 存放庫中找到。
全像攝影遠端播放程式可讓您的應用程式在桌面電腦或 UWP 裝置上顯示轉譯的全像攝影內容,例如 Xbox One 可存取更多系統資源。 全像攝影遠端播放程式應用程式會將輸入數據串流至全像攝影遠端應用程式,並接收沉浸式檢視作為視訊和音訊串流。 線上是使用標準 Wi-Fi 進行。 若要建立播放程式應用程式,請使用 NuGet 套件將全像攝影遠端功能新增至您的 UWP 應用程式。 然後撰寫程式代碼來處理連線,並顯示沈浸式檢視。
必要條件
良好的起點是以 Windows Mixed Reality API 為目標的工作 DirectX 型 UWP 應用程式。 如需詳細資訊,請參閱 DirectX 開發概觀。 如果您沒有現有的應用程式,而且想要從頭開始, C++全像攝影項目範本 是不錯的起點。
重要
任何使用全像攝影遠端處理的應用程式都應該撰寫成使用 多線程 Apartment。 支援使用 單個線程 Apartment ,但會導致次佳的效能,而且在播放期間可能很吃。 使用 C++/WinRT winrt::init_apartment 多線程 Apartment 是預設值。
取得全像攝影遠端 NuGet 套件
若要將 NuGet 套件新增至 Visual Studio 中的專案,必須執行下列步驟。
- 在 Visual Studio 中開啟專案。
- 以滑鼠右鍵按兩下項目節點,然後選取[ 管理 NuGet 套件...
- 在出現的面板中,選取 [ 流覽 ],然後搜尋 [全像攝影遠端]。
- 選取 [Microsoft.Holographic.Remoting],確定要挑選最新的 2.x.x 版本,然後選取 [ 安裝]。
- 如果出現 [ 預覽] 對話框,請選取 [ 確定]。
- 當許可協定對話框出現時,選取 [ 我接受 ]。
重要
build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl
NuGet 套件內的 包含全像攝影遠端公開 API 的詳細檔。
修改應用程式的 Package.appxmanifest
若要讓應用程式知道 NuGet 套件新增的 Microsoft.Holographic.AppRemoting.dll,必須在專案上採取下列步驟:
- 在 方案總管 中,以滑鼠右鍵按兩下 Package.appxmanifest 檔案,然後選取 [開啟...
- 選取 [XML(文字) 編輯器 ],然後選取 [ 確定]
- 將下列幾行新增至檔案並儲存
</Capabilities>
<!--Add lines below -->
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>Microsoft.Holographic.AppRemoting.dll</Path>
<ActivatableClass ActivatableClassId="Microsoft.Holographic.AppRemoting.PlayerContext" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
<!--Add lines above -->
</Package>
建立播放機內容
在第一個步驟中,應用程式應該建立播放機內容。
// class declaration:
#include <winrt/Microsoft.Holographic.AppRemoting.h>
...
private:
// PlayerContext used to connect with a Holographic Remoting remote app and display remotely rendered frames
winrt::Microsoft::Holographic::AppRemoting::PlayerContext m_playerContext = nullptr;
// class implementation:
// Create the player context
// IMPORTANT: This must be done before creating the HolographicSpace (or any other call to the Holographic API).
m_playerContext = winrt::Microsoft::Holographic::AppRemoting::PlayerContext::Create();
警告
自定義播放機會在播放機應用程式與 Windows 隨附的 Windows Mixed Reality 運行時間之間插入中繼層。 這會在建立播放程式內容期間完成。 基於這個理由,任何 Windows Mixed Reality API 上的呼叫,建立播放程式內容可能會導致非預期的行為。 建議的方法是在與任何混合實境 API 互動之前,儘早建立播放機內容。 在呼叫 PlayerContext::Create
之前,請勿混合透過任何 Windows Mixed Reality API 建立或擷取的物件,之後建立或擷取物件。
接下來,您可以呼叫 HolographicSpace.CreateForCoreWindow 來建立 HolographicSpace。
m_holographicSpace = winrt::Windows::Graphics::Holographic::HolographicSpace::CreateForCoreWindow(window);
線上到遠端應用程式
一旦播放機應用程式準備好轉譯內容,就可以建立與遠端應用程式的連線。
您可以透過下列其中一種方式來建立連線:
- 在 HoloLens 2 上執行的播放機應用程式會連線到遠端應用程式。
- 遠端應用程式會連線到在 HoloLens 2 上執行的播放程式應用程式。
若要從播放機應用程式連線到遠端應用程式,請在指定主機名和埠的播放機內容上呼叫 Connect
方法。 默認埠為 8265。
try
{
m_playerContext.Connect(m_hostname, m_port);
}
catch(winrt::hresult_error& e)
{
// Failed to connect. Get an error details via e.code() and e.message()
}
重要
如同任何C++/WinRT API Connect
可能會擲回需要處理的 winrt::hresult_error。
您可以藉由呼叫 Listen
方法來接聽播放程式應用程式上的連入連線。 您可以在此呼叫期間指定交握埠和傳輸埠。 交握埠用於初始交握。 然後,數據會透過傳輸埠傳送。 預設會使用埠號碼 8265 和 8266 。
try
{
m_playerContext.Listen(L"0.0.0.0", m_port, m_port + 1);
}
catch(winrt::hresult_error& e)
{
// Failed to listen. Get an error details via e.code() and e.message()
}
處理連線相關事件
會 PlayerContext
公開三個事件來監視連線的狀態
- OnConnected:成功建立遠端應用程式的連線時觸發。
m_onConnectedEventToken = m_playerContext.OnConnected([]()
{
// Handle connection successfully established
});
- OnDisconnected:如果已建立的連線已終止或無法建立連線,則觸發。
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
switch (failureReason)
{
// Handle connection failed or terminated.
// See ConnectionFailureReason for possible reasons.
}
}
注意
可能的ConnectionFailureReason
值記載於 檔案中Microsoft.Holographic.AppRemoting.idl
。
- OnListening:接聽傳入連線開始時。
m_onListeningEventToken = m_playerContext.OnListening([]()
{
// Handle start listening for incoming connections
});
此外,可以使用播放機內容上的屬性來查詢 ConnectionState
連線狀態。
winrt::Microsoft::Holographic::AppRemoting::ConnectionState state = m_playerContext.ConnectionState();
顯示遠端轉譯的畫面格
若要顯示遠端轉譯的內容,請在轉譯 HolographicFrame 時呼叫 PlayerContext::BlitRemoteFrame
。
BlitRemoteFrame
要求目前 HolographicFrame 的後台緩衝區系結為轉譯目標。 後端緩衝區可以透過 Direct3D11BackBuffer 屬性從 HolographicCameraRenderingParameters 接收。
呼叫 時, BlitRemoteFrame
會將最新的接收框架從遠端應用程式複製到 HolographicFrame 的 BackBuffer。 此外,如果遠端應用程式已在遠端畫面呈現期間指定焦點點,則會設定焦點集。
// Blit the remote frame into the backbuffer for the HolographicFrame.
winrt::Microsoft::Holographic::AppRemoting::BlitResult result = m_playerContext.BlitRemoteFrame();
注意
PlayerContext::BlitRemoteFrame
可能會覆寫目前畫面的焦點。
- 若要指定後援焦點點,請在 之前
PlayerContext::BlitRemoteFrame
呼叫 HolographicCameraRenderingParameters::SetFocusPoint。 - 若要覆寫遠端焦點點,請在 之後
PlayerContext::BlitRemoteFrame
呼叫 HolographicCameraRenderingParameters::SetFocusPoint。
成功時, BlitRemoteFrame
會傳 BlitResult::Success_Color
回 。 否則會傳回失敗原因:
BlitResult::Failed_NoRemoteFrameAvailable
:失敗,因為沒有遠端畫面可用。BlitResult::Failed_NoCamera
:失敗,因為沒有相機存在。BlitResult::Failed_RemoteFrameTooOld
:因為遠端框架太舊而失敗(請參閱 PlayerContext::BlitRemoteFrameTimeout 屬性)。
重要
從 2.1.0 版開始,自定義播放機可以透過全像攝影遠端使用深度重現。
BlitResult
也可以在下列情況下傳回 BlitResult::Success_Color_Depth
:
- 遠程應用程式已透過 HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer 認可深度緩衝區。
- 自定義播放機應用程式在呼叫
BlitRemoteFrame
之前已系結有效的深度緩衝區。
如果符合這些條件, BlitRemoteFrame
將會將遠端深度點入目前系結的本機深度緩衝區。 然後,您可以轉譯其他本機內容,其深度會與遠端轉譯的內容交集。 此外,您可以透過 HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer 在您的自定義播放機中認可本機深度緩衝區,以針對遠端和本機轉譯的內容進行深度重現。
投影轉換模式
透過全像攝影遠端處理使用深度重現時,其中一個問題是,遠端內容可以使用與自定義播放機應用程式直接轉譯的本機內容不同的投影轉換來轉譯。 常見的使用案例是針對玩家端和遠端端的近遠平面指定不同的值(透過 HolographicCamera::SetNearPlaneDistance 和 HolographicCamera::SetFarPlaneDistance)。 在此情況下,目前還不清楚玩家端的投影轉換是否應該反映遠近/遠平面距離或本機距離。
從 2.1.0 版開始,您可以透過 PlayerContext::ProjectionTransformConfig
控制投影轉換模式。 支援的值為:
Local
- HolographicCameraPose::P rojectionTransform 會傳回投影轉換,以反映 HolographicCamera 上自定義播放機應用程式所設定的近/遠平面距離。Remote
- 投影轉換會反映遠端應用程式所指定的近/遠平面距離。Merged
- 距離遠端應用程式和自定義播放機應用程式的近/遠平面距離會合併。 根據預設,這會以接近平面距離的最小值和遠平面距離的最大值來完成。 如果遠端或本機側被反轉,例如很近 < ,則會翻轉遠端近/遠平面距離。
選擇性:設定BlitRemoteFrameTimeout
重要
PlayerContext::BlitRemoteFrameTimeout
從 2.0.9 版開始支援。
屬性 PlayerContext::BlitRemoteFrameTimeout
會指定如果未收到新的遠端畫面,則會重複使用遠端畫面的時間量。
常見的使用案例是讓BlitRemoteFrame逾時在一段時間內未收到新畫面時顯示空白畫面。 啟用 時,方法的 BlitRemoteFrame
傳回類型也可以用來切換至本機轉譯的後援內容。
若要啟用逾時,請將屬性值設定為等於或大於 100 毫秒的持續時間。 若要停用逾時,請將 屬性設定為零持續時間。 如果啟用逾時,且未在設定期間收到任何遠程畫面,BlitRemoteFrame 將會失敗並傳回 Failed_RemoteFrameTooOld
,直到收到新的遠端畫面為止。
using namespace std::chrono_literals;
// Set the BlitRemoteFrame timeout to 0.5s
m_playerContext.BlitRemoteFrameTimeout(500ms);
選擇性:取得最後一個遠端畫面的相關統計數據
若要診斷效能或網路問題,可以透過 PlayerContext::LastFrameStatistics
屬性擷取最後一個遠端畫面的統計數據。 統計數據會在呼叫 HolographicFrame::P resentUsingCurrentPrediction 期間更新。
// Get statistics for the last presented frame.
winrt::Microsoft::Holographic::AppRemoting::PlayerFrameStatistics statistics = m_playerContext.LastFrameStatistics();
如需詳細資訊,請參閱 PlayerFrameStatistics
檔案中的Microsoft.Holographic.AppRemoting.idl
檔。
選擇性:自定義數據通道
自訂數據通道可用來透過已建立的遠端連線傳送用戶數據。 如需詳細資訊,請參閱 自定義數據通道。
選擇性:過度轉譯
全像攝影遠程會預測用戶在轉譯影像出現在顯示器上的位置。 不過,此預測是近似值。 因此,遠端應用程式上的預測檢視區,以及玩家應用程式上稍後的實際檢視區可能會有所不同。 更強的偏差(例如,由於無法預測的動作)可能會導致檢視邊緣的黑色區域。 從 2.6.0 版開始,您可以使用過度轉譯來減少黑色區域,並藉由人為地增加檢視區超出檢視範圍來增強視覺品質。
您可以透過 PlayerContext::ConfigureOverRendering
啟用過度轉譯。
OverRenderingConfig
會指定實際檢視區的小數大小增加,讓預測的檢視區變大且減少切割。
隨著檢視區大小增加,圖元密度會降低,因此 OverRenderingConfig 也可讓您增加解析度。
如果檢視區增加等於解析度增加,圖元密度會維持不變。
OverRenderingConfig
會定義為:
struct OverRenderingConfig
{
float HorizontalViewportIncrease; // The fractional horizontal viewport increase. (e.g. 10% -> 0.1).
float VerticalViewportIncrease; // The fractional vertical viewport increase. (e.g. 10% -> 0.1).
float HorizontalResolutionIncrease; // The fractional horizontal resolution increase. (e.g. 10% -> 0.1).
float VerticalResolutionIncrease; // The fractional vertical resolution increase. (e.g. 10% -> 0.1).
};
選擇性:座標系統同步處理
從 2.7.0 版開始,座標系統同步處理可用來對齊播放機與遠端應用程式之間的空間數據。 如需詳細資訊,請參閱 使用全像攝影遠端處理協調系統同步處理概觀。