Bagikan melalui


Menulis aplikasi Jarak Jauh Akses Jauh Holografik menggunakan HolographicSpace API

Jika Anda baru menggunakan Akses Jauh Holografik, Anda mungkin ingin membaca gambaran umum kami.

Penting

Dokumen ini menjelaskan pembuatan aplikasi jarak jauh untuk HoloLens 2 menggunakan HolographicSpace API. Aplikasi jarak jauh untuk HoloLens (generasi ke-1) harus menggunakan paket NuGet versi 1.x.x. Ini menyiratkan bahwa aplikasi jarak jauh yang ditulis untuk HoloLens 2 tidak kompatibel dengan HoloLens 1 dan sebaliknya. Dokumentasi untuk HoloLens 1 dapat ditemukan di sini.

Pemberitahuan penghentian: Baris rilis 2.9.x akan menjadi yang terakhir untuk mendukung WINDOWS Holographic API untuk pengembangan aplikasi. Versi yang akan datang hanya akan mendukung OpenXR untuk pengembangan aplikasi. Terlepas dari itu kami merekomendasikan penggunaan OpenXR dalam aplikasi Anda untuk semua pengembangan aplikasi baru. Aplikasi yang ada yang menggunakan 2.9 atau yang lebih lama akan terus bekerja tanpa terpengaruh oleh perubahan yang akan datang.

Aplikasi Akses Jauh Holografik dapat melakukan streaming konten yang dirender dari jarak jauh ke headset HoloLens 2 dan Windows Mixed Reality imersif. Anda juga dapat mengakses lebih banyak sumber daya sistem dan mengintegrasikan tampilan imersif jarak jauh ke perangkat lunak PC desktop yang ada. Aplikasi jarak jauh menerima aliran data input dari HoloLens 2, merender konten dalam tampilan imersif virtual, dan mengalirkan bingkai konten kembali ke HoloLens 2. Koneksi dibuat menggunakan Wi-Fi standar. Akses Jauh Holografik ditambahkan ke desktop atau aplikasi UWP melalui paket NuGet. Kode tambahan diperlukan yang menangani koneksi dan dirender dalam tampilan imersif. Koneksi jarak jauh yang khas akan memiliki latensi serendah 50 mdtk. Aplikasi pemutar dapat melaporkan latensi secara real time.

Semua kode di halaman ini dan proyek yang berfungsi dapat ditemukan di repositori github sampel Akses Jauh Holografik.

Prasyarat

Titik awal yang baik adalah aplikasi Desktop atau UWP berbasis DirectX yang berfungsi yang menargetkan API Windows Mixed Reality. Untuk detailnya, lihat Gambaran umum pengembangan DirectX. Templat proyek holografik C++ adalah titik awal yang baik.

Penting

Aplikasi apa pun yang menggunakan Akses Jauh Holografik harus ditulis untuk menggunakan apartemen multi-utas. Penggunaan apartemen berulir tunggal didukung tetapi akan menyebabkan performa sub-optimal dan mungkin gagap selama pemutaran. Saat menggunakan C++/WinRT winrt::init_apartment apartemen multi-utas adalah default.

Mendapatkan paket NuGet Akses Jauh Holografik

Langkah-langkah berikut diperlukan untuk menambahkan paket NuGet ke proyek di Visual Studio.

  1. Buka proyek di Visual Studio.
  2. Klik kanan simpul proyek dan pilih Kelola Paket NuGet...
  3. Di panel yang muncul, pilih Telusuri lalu cari "Akses Jauh Holografik".
  4. Pilih Microsoft.Holographic.Remoting, pastikan untuk memilih versi 2.x.x terbaru dan pilih Instal.
  5. Jika dialog Pratinjau muncul, pilih OK.
  6. Pilih Saya Terima saat dialog perjanjian lisensi muncul.

Catatan

Paket NuGet versi 1.x.x masih tersedia untuk pengembang yang ingin menargetkan HoloLens 1. Untuk detailnya lihat Menambahkan Akses Jauh Holografik (HoloLens (generasi ke-1)) .

Membuat konteks jarak jauh

Sebagai langkah pertama, aplikasi harus membuat konteks jarak jauh.

// class declaration
#include <winrt/Microsoft.Holographic.AppRemoting.h>

...

private:
    // RemoteContext used to connect with a Holographic Remoting player and display rendered frames
    winrt::Microsoft::Holographic::AppRemoting::RemoteContext m_remoteContext = nullptr;
// class implementation
#include <HolographicAppRemoting\Streamer.h>

...

CreateRemoteContext(m_remoteContext, 20000, false, PreferredVideoCodec::Default);

Peringatan

Akses Jauh Holografik bekerja dengan mengganti runtime Windows Mixed Reality yang merupakan bagian dari Windows dengan runtime khusus jarak jauh. Ini dilakukan selama pembuatan konteks jarak jauh. Untuk alasan itu, setiap panggilan pada API Windows Mixed Reality apa pun sebelum membuat konteks jarak jauh dapat mengakibatkan perilaku yang tidak terduga. Pendekatan yang disarankan adalah membuat konteks jarak jauh sedini mungkin sebelum interaksi dengan API Mixed Reality apa pun. Jangan pernah mencampur objek yang dibuat atau diambil melalui API Windows Mixed Reality apa pun sebelum panggilan ke CreateRemoteContext dengan objek yang dibuat atau diambil setelahnya.

Selanjutnya ruang holografik perlu dibuat. Menentukan CoreWindow tidak diperlukan. Aplikasi desktop yang tidak memiliki CoreWindow hanya dapat melewati nullptr.

m_holographicSpace = winrt::Windows::Graphics::Holographic::HolographicSpace::CreateForCoreWindow(nullptr);

Menyambungkan ke perangkat

Saat aplikasi jarak jauh siap untuk merender konten, koneksi ke perangkat pemutar dapat dibuat.

Koneksi dapat dilakukan dengan salah satu dari dua cara.

  1. Aplikasi jarak jauh terhubung ke pemutar yang berjalan di perangkat.
  2. Pemutar yang berjalan pada perangkat terhubung ke aplikasi jarak jauh.

Untuk membuat koneksi dari aplikasi jarak jauh ke perangkat pemutar, panggil Connect metode pada konteks jarak jauh yang menentukan nama host dan port. Port yang digunakan oleh Pemutar Akses Jauh Holografik adalah 8265.

try
{
    m_remoteContext.Connect(m_hostname, m_port);
}
catch(winrt::hresult_error& e)
{
    DebugLog(L"Connect failed with hr = 0x%08X", e.code());
}

Penting

Seperti halnya C++/WinRT API Connect mungkin melempar winrt::hresult_error yang perlu ditangani.

Tip

Untuk menghindari penggunaan proyeksi bahasa C++/WinRT , file build\native\include\<windows sdk version>\abi\Microsoft.Holographic.AppRemoting.h yang terletak di dalam paket NuGet Akses Jauh Holografik dapat disertakan. Ini berisi deklarasi antarmuka COM yang mendasar. Penggunaan C++/WinRT disarankan.

Mendengarkan koneksi masuk pada aplikasi jarak jauh dapat dilakukan dengan memanggil Listen metode . Port jabat tangan dan port transportasi dapat ditentukan selama panggilan ini. Port jabat tangan digunakan untuk jabat tangan awal. Data kemudian dikirim melalui port transportasi. Secara default 8265 dan 8266 digunakan.

try
{
    m_remoteContext.Listen(L"0.0.0.0", m_port, m_port + 1);
}
catch(winrt::hresult_error& e)
{
    DebugLog(L"Listen failed with hr = 0x%08X", e.code());
}

Penting

Bagian build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl dalam paket NuGet berisi dokumentasi terperinci untuk API yang diekspos oleh Akses Jauh Holografik.

Menangani peristiwa khusus Jarak Jauh

Konteks jarak jauh mengekspos tiga peristiwa, yang penting untuk memantau status koneksi.

  1. OnConnected: Dipicu ketika koneksi ke perangkat telah berhasil dibuat.
winrt::weak_ref<winrt::Microsoft::Holographic::AppRemoting::IRemoteContext> remoteContextWeakRef = m_remoteContext;

m_onConnectedEventRevoker = m_remoteContext.OnConnected(winrt::auto_revoke, [this, remoteContextWeakRef]() {
    if (auto remoteContext = remoteContextWeakRef.get())
    {
        // Update UI state
    }
});
  1. OnDisconnected: Dipicu jika koneksi yang dibuat ditutup atau koneksi tidak dapat dibuat.
m_onDisconnectedEventRevoker =
    m_remoteContext.OnDisconnected(winrt::auto_revoke, [this, remoteContextWeakRef](ConnectionFailureReason failureReason) {
        if (auto remoteContext = remoteContextWeakRef.get())
        {
            DebugLog(L"Disconnected with reason %d", failureReason);
            // Update UI

            // Reconnect if this is a transient failure.
            if (failureReason == ConnectionFailureReason::HandshakeUnreachable ||
                failureReason == ConnectionFailureReason::TransportUnreachable ||
                failureReason == ConnectionFailureReason::ConnectionLost)
            {
                DebugLog(L"Reconnecting...");

                ConnectOrListen();
            }
            // Failure reason None indicates a normal disconnect.
            else if (failureReason != ConnectionFailureReason::None)
            {
                DebugLog(L"Disconnected with unrecoverable error, not attempting to reconnect.");
            }
        }
    });
  1. OnListening: Saat mendengarkan koneksi masuk dimulai.
m_onListeningEventRevoker = m_remoteContext.OnListening(winrt::auto_revoke, [this, remoteContextWeakRef]() {
    if (auto remoteContext = remoteContextWeakRef.get())
    {
        // Update UI state
    }
});

Selain itu, status koneksi dapat dikueri menggunakan ConnectionState properti pada konteks jarak jauh.

auto connectionState = m_remoteContext.ConnectionState();

Menangani peristiwa ucapan

Menggunakan antarmuka ucapan jarak jauh dimungkinkan untuk mendaftarkan pemicu ucapan dengan HoloLens 2 dan membuatnya jarak jauh ke aplikasi jarak jauh.

Anggota tambahan berikut diperlukan untuk melacak status ucapan jarak jauh:

winrt::Microsoft::Holographic::AppRemoting::IRemoteSpeech::OnRecognizedSpeech_revoker m_onRecognizedSpeechRevoker;

Pertama, ambil antarmuka ucapan jarak jauh.

if (auto remoteSpeech = m_remoteContext.GetRemoteSpeech())
{
    InitializeSpeechAsync(remoteSpeech, m_onRecognizedSpeechRevoker, weak_from_this());
}

Menggunakan metode pembantu asinkron, Anda kemudian dapat menginisialisasi ucapan jarak jauh. Ini harus dilakukan secara asinkron karena inisialisasi mungkin membutuhkan waktu yang cukup lama. Operasi konkurensi dan asinkron dengan C++/WinRT menjelaskan cara menulis fungsi asinkron dengan C++/WinRT.

winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFile> LoadGrammarFileAsync()
{
    const wchar_t* speechGrammarFile = L"SpeechGrammar.xml";
    auto rootFolder = winrt::Windows::ApplicationModel::Package::Current().InstalledLocation();
    return rootFolder.GetFileAsync(speechGrammarFile);
}

winrt::fire_and_forget InitializeSpeechAsync(
    winrt::Microsoft::Holographic::AppRemoting::IRemoteSpeech remoteSpeech,
    winrt::Microsoft::Holographic::AppRemoting::IRemoteSpeech::OnRecognizedSpeech_revoker& onRecognizedSpeechRevoker,
    std::weak_ptr<SampleRemoteMain> sampleRemoteMainWeak)
{
    onRecognizedSpeechRevoker = remoteSpeech.OnRecognizedSpeech(
        winrt::auto_revoke, [sampleRemoteMainWeak](const winrt::Microsoft::Holographic::AppRemoting::RecognizedSpeech& recognizedSpeech) {
            if (auto sampleRemoteMain = sampleRemoteMainWeak.lock())
            {
                sampleRemoteMain->OnRecognizedSpeech(recognizedSpeech.RecognizedText);
            }
        });

    auto grammarFile = co_await LoadGrammarFileAsync();

    std::vector<winrt::hstring> dictionary;
    dictionary.push_back(L"Red");
    dictionary.push_back(L"Blue");
    dictionary.push_back(L"Green");
    dictionary.push_back(L"Default");
    dictionary.push_back(L"Aquamarine");

    remoteSpeech.ApplyParameters(L"", grammarFile, dictionary);
}

Ada dua cara untuk menentukan frasa yang akan dikenali.

  1. Spesifikasi di dalam file xml tata bahasa ucapan. Lihat Cara membuat Tata Bahasa XML dasar untuk detailnya.
  2. Tentukan dengan meneruskannya di dalam vektor kamus ke ApplyParameters.

Di dalam panggilan balik OnRecognizedSpeech, peristiwa ucapan kemudian dapat diproses:

void SampleRemoteMain::OnRecognizedSpeech(const winrt::hstring& recognizedText)
{
    bool changedColor = false;
    DirectX::XMFLOAT4 color = {1, 1, 1, 1};

    if (recognizedText == L"Red")
    {
        color = {1, 0, 0, 1};
        changedColor = true;
    }
    else if (recognizedText == L"Blue")
    {
        color = {0, 0, 1, 1};
        changedColor = true;
    }
    else if (recognizedText == L"Green")
    {
        ...
    }

    ...
}

Pratinjau konten yang dialirkan secara lokal

Untuk menampilkan konten yang sama di aplikasi jarak jauh yang dikirim ke perangkat OnSendFrame , peristiwa konteks jarak jauh dapat digunakan. Peristiwa OnSendFrame ini dipicu setiap kali pustaka Akses Jauh Holografik mengirimkan bingkai saat ini ke perangkat jarak jauh. Ini adalah waktu yang ideal untuk mengambil konten dan juga menyamarkannya ke desktop atau jendela UWP.

#include <windows.graphics.directx.direct3d11.interop.h>

...

m_onSendFrameEventRevoker = m_remoteContext.OnSendFrame(
    winrt::auto_revoke, [this](const winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface& texture) {
        winrt::com_ptr<ID3D11Texture2D> texturePtr;
        {
            winrt::com_ptr<ID3D11Resource> resource;
            winrt::com_ptr<::IInspectable> inspectable = texture.as<::IInspectable>();
            winrt::com_ptr<Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess> dxgiInterfaceAccess;
            winrt::check_hresult(inspectable->QueryInterface(__uuidof(dxgiInterfaceAccess), dxgiInterfaceAccess.put_void()));
            winrt::check_hresult(dxgiInterfaceAccess->GetInterface(__uuidof(resource), resource.put_void()));
            resource.as(texturePtr);
        }

        // Copy / blit texturePtr into the back buffer here.
    });

Proyeksi Ulang Kedalaman

Dimulai dengan versi 2.1.0, Akses Jauh Holografik mendukung Reproyeksi Kedalaman. Ini membutuhkan buffer warna dan buffer kedalaman untuk dialirkan dari aplikasi Jarak Jauh ke HoloLens 2. Secara default, streaming buffer kedalaman diaktifkan dan dikonfigurasi untuk menggunakan setengah resolusi buffer warna. Ini dapat diubah sebagai berikut:

// class implementation
#include <HolographicAppRemoting\Streamer.h>

...

CreateRemoteContext(m_remoteContext, 20000, false, PreferredVideoCodec::Default);

// Configure for half-resolution depth.
m_remoteContext.ConfigureDepthVideoStream(DepthBufferStreamResolution::Half_Resolution);

Perhatikan, jika nilai default tidak boleh digunakan harus dipanggil ConfigureDepthVideoStream sebelum membuat koneksi ke HoloLens 2. Tempat terbaik tepat setelah Anda membuat konteks jarak jauh. Nilai yang mungkin untuk DepthBufferStreamResolution adalah:

  • Full_Resolution
  • Half_Resolution
  • Quarter_Resolution
  • Dinonaktifkan (ditambahkan dengan versi 2.1.3 dan jika digunakan tidak ada aliran video kedalaman tambahan yang dibuat)

Perlu diingat bahwa menggunakan buffer kedalaman resolusi penuh juga memengaruhi persyaratan bandwidth dan perlu dipertimbangkan dalam nilai bandwidth maksimum yang Anda berikan kepada CreateRemoteContext.

Selain mengonfigurasi resolusi, Anda juga harus menerapkan buffer kedalaman melalui HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer.


void SampleRemoteMain::Render(HolographicFrame holographicFrame)
{
    ...

    m_deviceResources->UseHolographicCameraResources([this, holographicFrame](auto& cameraResourceMap) {
        
        ...

        for (auto cameraPose : prediction.CameraPoses())
        {
            DXHelper::CameraResources* pCameraResources = cameraResourceMap[cameraPose.HolographicCamera().Id()].get();

            ...

            m_deviceResources->UseD3DDeviceContext([&](ID3D11DeviceContext3* context) {
                
                ...

                // Commit depth buffer if available and enabled.
                if (m_canCommitDirect3D11DepthBuffer && m_commitDirect3D11DepthBuffer)
                {
                    auto interopSurface = pCameraResources->GetDepthStencilTextureInteropObject();
                    HolographicCameraRenderingParameters renderingParameters = holographicFrame.GetRenderingParameters(cameraPose);
                    renderingParameters.CommitDirect3D11DepthBuffer(interopSurface);
                }
            });
        }
    });
}

Untuk memverifikasi apakah proyeksi ulang kedalaman berfungsi dengan benar pada HoloLens 2, Anda dapat mengaktifkan visualizer kedalaman melalui Portal Perangkat. Lihat Memverifikasi Kedalaman Diatur dengan Benar untuk detailnya.

Opsional: Saluran data kustom

Saluran data kustom dapat digunakan untuk mengirim data pengguna melalui koneksi jarak jauh yang sudah dibuat. Untuk informasi selengkapnya, lihat Saluran Data Kustom.

Opsional: Sinkronisasi Sistem Koordinat

Dimulai dengan versi 2.7.0, sinkronisasi sistem koordinat dapat digunakan untuk menyelaraskan data spasial antara pemutar dan aplikasi jarak jauh. Untuk informasi selengkapnya, lihat Mengoordinasikan Sinkronisasi Sistem dengan Gambaran Umum Jarak Jauh Holografik.

Lihat juga