Koneksi ke kamera jarak jauh

Artikel ini menunjukkan kepada Anda cara terhubung ke satu atau beberapa kamera jarak jauh dan mendapatkan objek MediaFrameSourceGroup yang memungkinkan Anda membaca bingkai dari setiap kamera. Untuk informasi selengkapnya tentang membaca bingkai dari sumber media, lihat Memproses bingkai media dengan MediaFrameReader. Untuk informasi selengkapnya tentang pemasangan dengan perangkat, lihat Memasangkan perangkat.

Catatan

Fitur yang dibahas dalam artikel ini tersedia dimulai dengan Windows 10, versi 1903.

Membuat kelas DeviceWatcher untuk mengawasi kamera jarak jauh yang tersedia

Kelas DeviceWatcher memantau perangkat yang tersedia untuk aplikasi Anda dan memberi tahu aplikasi Anda saat perangkat ditambahkan atau dihapus. Dapatkan instance DeviceWatcher dengan memanggil DeviceInformation.CreateWatcher, meneruskan string Advanced Query Syntax (AQS) yang mengidentifikasi jenis perangkat yang ingin Anda pantau. String AQS yang menentukan perangkat kamera jaringan adalah sebagai berikut:

@"System.Devices.InterfaceClassGuid:=""{B8238652-B500-41EB-B4F3-4234F7F5AE99}"" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True"

Catatan

Metode pembantu MediaFrameSourceGroup.GetDeviceSelector mengembalikan string AQS yang akan memantau kamera jaringan yang terhubung secara lokal dan jarak jauh. Untuk memantau hanya kamera jaringan, Anda harus menggunakan string AQS yang ditunjukkan di atas.

Saat Anda memulai DeviceWatcher yang dikembalikan dengan memanggil metode Start , itu akan meningkatkan acara Tambahan untuk setiap kamera jaringan yang saat ini tersedia. Sampai Anda menghentikan pengamat dengan memanggil Stop, acara Tambahan akan dinaikkan saat perangkat kamera jaringan baru tersedia dan acara Dihapus akan dinaikkan saat perangkat kamera menjadi tidak tersedia.

Peristiwa args diteruskan ke penangan peristiwa Yang Ditambahkan dan Dihapus adalah objek DeviceInformation atau DeviceInformationUpdate , masing-masing. Masing-masing objek ini memiliki properti Id yang merupakan pengenal untuk kamera jaringan tempat acara tersebut dipecat. Berikan ID ini ke metode MediaFrameSourceGroup.FromIdAsync untuk mendapatkan objek MediaFrameSourceGroup yang dapat Anda gunakan untuk mengambil frame dari kamera.

Kelas pembantu pemasangan kamera jarak jauh

Contoh berikut menunjukkan kelas pembantu yang menggunakan DeviceWatcher untuk membuat dan memperbarui ObservableCollection objek MediaFrameSourceGroup untuk mendukung pengikatan data ke daftar kamera. Aplikasi khas akan membungkus MediaFrameSourceGroup dalam kelas model kustom. Perhatikan bahwa kelas pembantu mempertahankan referensi ke CoreDispatcher aplikasi dan memperbarui koleksi kamera dalam panggilan ke RunAsync untuk memastikan bahwa UI yang terikat pada koleksi diperbarui pada utas UI.

Selain itu, contoh ini menangani acara DeviceWatcher.Updated selain peristiwa Yang Ditambahkan dan Dihapus . Di penangan yang diperbarui , perangkat kamera jarak jauh terkait dihapus dari dan kemudian ditambahkan kembali ke koleksi.

class RemoteCameraPairingHelper : IDisposable
{
    private CoreDispatcher _dispatcher;
    private DeviceWatcher _watcher;
    private ObservableCollection<MediaFrameSourceGroup> _remoteCameraCollection;
    public RemoteCameraPairingHelper(CoreDispatcher uiDispatcher)
    {
        _dispatcher = uiDispatcher;
        _remoteCameraCollection = new ObservableCollection<MediaFrameSourceGroup>();
        var remoteCameraAqs = @"System.Devices.InterfaceClassGuid:=""{B8238652-B500-41EB-B4F3-4234F7F5AE99}"" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True";
        _watcher = DeviceInformation.CreateWatcher(remoteCameraAqs);
        _watcher.Added += Watcher_Added;
        _watcher.Removed += Watcher_Removed;
        _watcher.Updated += Watcher_Updated;
        _watcher.Start();
    }
    public void Dispose()
    {
        _watcher.Stop();
        _watcher.Updated -= Watcher_Updated;
        _watcher.Removed -= Watcher_Removed;
        _watcher.Added -= Watcher_Added;
    }
    public IReadOnlyList<MediaFrameSourceGroup> FrameSourceGroups
    {
        get { return _remoteCameraCollection; }
    }
    private async void Watcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args)
    {
        await RemoveDevice(args.Id);
        await AddDeviceAsync(args.Id);
    }
    private async void Watcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
    {
        await RemoveDevice(args.Id);
    }
    private async void Watcher_Added(DeviceWatcher sender, DeviceInformation args)
    {
        await AddDeviceAsync(args.Id);
    }
    private async Task AddDeviceAsync(string id)
    {
        var group = await MediaFrameSourceGroup.FromIdAsync(id);
        if (group != null)
        {
            await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                _remoteCameraCollection.Add(group);
            });
        }
    }
    private async Task RemoveDevice(string id)
    {
        await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            var existing = _remoteCameraCollection.FirstOrDefault(item => item.Id == id);
            if (existing != null)
            {
                _remoteCameraCollection.Remove(existing);
            }
        });
    }
#include <winrt/Windows.Devices.Enumeration.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Media.Capture.Frames.h>
#include <winrt/Windows.UI.Core.h>
using namespace winrt;
using namespace winrt::Windows::Devices::Enumeration;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Media::Capture::Frames;
using namespace winrt::Windows::UI::Core;

struct RemoteCameraPairingHelper
{
    RemoteCameraPairingHelper(CoreDispatcher uiDispatcher) :
        m_dispatcher(uiDispatcher)
    {
        m_remoteCameraCollection = winrt::single_threaded_observable_vector<MediaFrameSourceGroup>();
        auto remoteCameraAqs =
            LR"(System.Devices.InterfaceClassGuid:=""{B8238652-B500-41EB-B4F3-4234F7F5AE99}"")"
            LR"(AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True)";
        m_watcher = DeviceInformation::CreateWatcher(remoteCameraAqs);
        m_watcherAddedAutoRevoker = m_watcher.Added(winrt::auto_revoke, { this, &RemoteCameraPairingHelper::Watcher_Added });
        m_watcherRemovedAutoRevoker = m_watcher.Removed(winrt::auto_revoke, { this, &RemoteCameraPairingHelper::Watcher_Removed });
        m_watcherUpdatedAutoRevoker = m_watcher.Updated(winrt::auto_revoke, { this, &RemoteCameraPairingHelper::Watcher_Updated });
        m_watcher.Start();
    }
    ~RemoteCameraPairingHelper()
    {
        m_watcher.Stop();
    }
    IObservableVector<MediaFrameSourceGroup> FrameSourceGroups()
    {
        return m_remoteCameraCollection;
    }
    winrt::fire_and_forget Watcher_Added(DeviceWatcher /* sender */, DeviceInformation args)
    {
        co_await AddDeviceAsync(args.Id());
    }
    winrt::fire_and_forget Watcher_Removed(DeviceWatcher /* sender */, DeviceInformationUpdate args)
    {
        co_await RemoveDevice(args.Id());
    }
    winrt::fire_and_forget Watcher_Updated(DeviceWatcher /* sender */, DeviceInformationUpdate args)
    {
        co_await RemoveDevice(args.Id());
        co_await AddDeviceAsync(args.Id());
    }
    Windows::Foundation::IAsyncAction AddDeviceAsync(winrt::hstring id)
    {
        auto group = co_await MediaFrameSourceGroup::FromIdAsync(id);
        if (group)
        {
            co_await m_dispatcher;
            m_remoteCameraCollection.Append(group);
        }
    }
    Windows::Foundation::IAsyncAction RemoveDevice(winrt::hstring id)
    {
        co_await m_dispatcher;

        uint32_t ix{ 0 };
        for (auto const&& item : m_remoteCameraCollection)
        {
            if (item.Id() == id)
            {
                m_remoteCameraCollection.RemoveAt(ix);
                break;
            }
            ++ix;
        }
    }

private:
    CoreDispatcher m_dispatcher{ nullptr };
    DeviceWatcher m_watcher{ nullptr };
    IObservableVector<MediaFrameSourceGroup> m_remoteCameraCollection;
    DeviceWatcher::Added_revoker m_watcherAddedAutoRevoker;
    DeviceWatcher::Removed_revoker m_watcherRemovedAutoRevoker;
    DeviceWatcher::Updated_revoker m_watcherUpdatedAutoRevoker;
};