撰寫自訂全像攝影遠端播放程式應用程式
如果您不熟悉全像攝影遠端功能,建議您 閱讀我們的概觀。
重要
本檔說明如何建立自訂播放機應用程式以進行HoloLens 2。 針對 HoloLens 2撰寫的自訂播放機與針對 HoloLens 1 撰寫的遠端應用程式不相容。 這表示這兩個應用程式都必須使用 NuGet 套件 2.x.x版。
藉由建立自訂全像攝影遠端播放程式應用程式,您可以建立自訂應用程式,以便從HoloLens 2上的遠端電腦上顯示沉浸式檢視。 此頁面上的所有程式碼和工作專案都可以在 Holographic Remoting 範例 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 上的呼叫都可能會導致非預期的行為。 建議的方法是在與任何Mixed Reality 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();
顯示遠端轉譯的框架
若要顯示遠端轉譯的內容,請在轉譯全像攝影框架時呼叫 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
檔。
選擇性:自訂資料通道
自訂資料通道可用來透過已建立的遠端連線傳送使用者資料。 如需詳細資訊,請參閱 自訂資料通道。
選擇性:Over-Rendering
全像攝影遠端會預測使用者在呈現的影像出現在顯示器上時,使用者頭部的位置。 不過,此預測是近似值。 因此,遠端應用程式上的預測檢視區,以及播放機應用程式上稍後的實際檢視區可能會有所不同。 例如,由於無法預測的動作) 而導致檢視 frustum 框線的黑色區域,因此 (較強的偏差。 從 2.6.0 版開始,您可以使用 Over-Rendering 來減少黑色區域,並藉由手動增加檢視區超出檢視範圍來增強視覺品質。
Over-Rendering可以透過 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 版 開始,座標系統同步處理可用來對齊播放機與遠端應用程式之間的空間資料。 如需詳細資訊,請參閱 使用全像攝影遠端處理協調系統同步處理概觀。