Freigeben über


Herstellen einer Verbindung mit Remotekameras

In diesem Artikel erfahren Sie, wie Sie eine Verbindung mit einer oder mehreren Remotekameras herstellen und ein MediaFrameSourceGroup-Objekt abrufen, mit dem Sie Frames von jeder Kamera lesen können. Weitere Informationen zum Lesen von Frames aus einer Medienquelle finden Sie unter Verarbeiten von Medienframes mit MediaFrameReader. Weitere Informationen zum Koppeln mit Geräten finden Sie unter "Koppeln von Geräten".

Hinweis

Die in diesem Artikel beschriebenen Features sind ab Windows 10, Version 1903, verfügbar.

Erstellen einer DeviceWatcher-Klasse zum Überwachen verfügbarer Remotekameras

Die DeviceWatcher-Klasse überwacht die für Ihre App verfügbaren Geräte und benachrichtigt Ihre App, wenn Geräte hinzugefügt oder entfernt werden. Rufen Sie eine Instanz von DeviceWatcher ab, indem Sie "DeviceInformation.CreateWatcher" aufrufen und eine AQS-Zeichenfolge (Advanced Query Syntax) übergeben, die den Typ der Geräte identifiziert, die Sie überwachen möchten. Die AQS-Zeichenfolge, die Netzwerkkamerageräte angibt, ist Folgendes:

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

Hinweis

Die Hilfsmethode MediaFrameSourceGroup.GetDeviceSelector gibt eine AQS-Zeichenfolge zurück, die lokal verbundene und Remotenetzwerkkameras überwacht. Um nur Netzwerkkameras zu überwachen, sollten Sie die oben gezeigte AQS-Zeichenfolge verwenden.

Wenn Sie die zurückgegebene DeviceWatcher-Methode starten, indem Sie die Startmethode aufrufen, löst es das "Added"-Ereignis für jede Netzwerkkamera aus, die derzeit verfügbar ist. Bis Sie die Überwachung beenden, indem Sie "Stop" aufrufen, wird das "Added"-Ereignis ausgelöst, wenn neue Netzwerkkamerageräte verfügbar werden und das Removed-Ereignis ausgelöst wird, wenn ein Kameragerät nicht verfügbar ist.

Die Ereignisargumente, die an die Ereignishandler "Hinzugefügt" bzw. "Removed" übergeben werden, sind ein DeviceInformation- oder deviceInformationUpdate-Objekt. Jedes dieser Objekte verfügt über eine ID-Eigenschaft , die der Bezeichner für die Netzwerkkamera ist, für die das Ereignis ausgelöst wurde. Übergeben Sie diese ID an die MediaFrameSourceGroup.FromIdAsync-Methode, um ein MediaFrameSourceGroup-Objekt abzurufen, mit dem Sie Frames aus der Kamera abrufen können.

Hilfsklasse für Remotekamerapaarung

Das folgende Beispiel zeigt eine Hilfsklasse, die ein DeviceWatcher verwendet, um eine ObservableCollection von MediaFrameSourceGroup-Objekten zu erstellen und zu aktualisieren, um die Datenbindung an die Liste der Kameras zu unterstützen. Typische Apps würden die MediaFrameSourceGroup in einer benutzerdefinierten Modellklasse umschließen. Beachten Sie, dass die Hilfsklasse einen Verweis auf den CoreDispatcher der App verwaltet und die Sammlung von Kameras in Aufrufen von RunAsync aktualisiert, um sicherzustellen, dass die an die Sammlung gebundene Benutzeroberfläche im UI-Thread aktualisiert wird.

Außerdem behandelt dieses Beispiel das DeviceWatcher.Updated-Ereignis zusätzlich zu den Ereignissen "Added " und "Removed ". Im aktualisierten Handler wird das zugeordnete Remotekameragerät entfernt und dann wieder zur Sammlung hinzugefügt.

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;
};