Conectar-se a câmeras remotasConnect to remote cameras

Este artigo mostra como se conectar a uma ou mais câmeras remotas e obter um objeto MediaFrameSourceGroup que permite que você leia quadros de cada câmera.This article shows you how to connect to one or more remote cameras and get a MediaFrameSourceGroup object that allows you to read frames from each camera. Para obter mais informações sobre como ler quadros de uma fonte de mídia, consulte processar quadros de mídia com MediaFrameReader.For more information on reading frames from a media source, see Process media frames with MediaFrameReader. Para obter mais informações sobre emparelhamento com dispositivos, consulte emparelhar dispositivos.For more information on pairing with devices, see Pair devices.

Observação

Os recursos discutidos neste artigo estão disponíveis a partir do Windows 10, versão 1903.The features discussed in this article are available starting with Windows 10, version 1903.

Criar uma classe DeviceWatcher para observar as câmeras remotas disponíveisCreate a DeviceWatcher class to watch for available remote cameras

A classe DeviceWatcher monitora os dispositivos disponíveis para seu aplicativo e notifica seu aplicativo quando os dispositivos são adicionados ou removidos.The DeviceWatcher class monitors the devices available to your app and notifies your app when devices are added or removed. Obtenha uma instância de DeviceWatcher chamando DeviceInformation. createassister, passando uma cadeia de caracteres AQS (sintaxe de consulta avançada) que identifica o tipo de dispositivos que você deseja monitorar.Get an instance of DeviceWatcher by calling DeviceInformation.CreateWatcher, passing in an Advanced Query Syntax (AQS) string that identifies the type of devices you want to monitor. A cadeia de caracteres AQS especificando dispositivos de câmera de rede é a seguinte:The AQS string specifying network camera devices is the following:

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

Observação

O método auxiliar MediaFrameSourceGroup. GetDeviceSelector retorna uma cadeia de caracteres AQS que monitorará as câmeras de rede remota e conectadas localmente.The helper method MediaFrameSourceGroup.GetDeviceSelector returns an AQS string that will monitor locally-connected and remote network cameras. Para monitorar apenas câmeras de rede, você deve usar a cadeia de caracteres AQS mostrada acima.To monitor only network cameras, you should use the AQS string shown above.

Quando você iniciar o DeviceWatcher retornado chamando o método Start , ele gerará o evento adicionado para cada câmera de rede disponível no momento.When you start the returned DeviceWatcher by calling the Start method, it will raise the Added event for every network camera that is currently available. Até que você pare o observador chamando Stop, o evento adicionado será gerado quando novos dispositivos de câmera de rede ficarem disponíveis e o evento removido será gerado quando um dispositivo de câmera ficar indisponível.Until you stop the watcher by calling Stop, the Added event will be raised when new network camera devices become available and the Removed event will be raised when a camera device becomes unavailable.

Os args de evento passados para os manipuladores de eventos adicionados e removidos são um objeto DeviceInformation ou DeviceInformationUpdate , respectivamente.The event args passed into the Added and Removed event handlers are a DeviceInformation or a DeviceInformationUpdate object, respectively. Cada um desses objetos tem uma propriedade ID que é o identificador para a câmera de rede para a qual o evento foi acionado.Each of these objects has an Id property that is the identifier for the network camera for which the event was fired. Passe essa ID para o método MediaFrameSourceGroup. FromIdAsync para obter um objeto MediaFrameSourceGroup que você pode usar para recuperar quadros da câmera.Pass this ID into the MediaFrameSourceGroup.FromIdAsync method to get a MediaFrameSourceGroup object that you can use to retrieve frames from the camera.

Classe auxiliar de emparelhamento de câmera remotaRemote camera pairing helper class

O exemplo a seguir mostra uma classe auxiliar que usa um DeviceWatcher para criar e atualizar uma ObservableCollection de objetos MediaFrameSourceGroup para dar suporte à ligação de dados com a lista de câmeras.The following example shows a helper class that uses a DeviceWatcher to create and update an ObservableCollection of MediaFrameSourceGroup objects to support data binding to the list of cameras. Aplicativos típicos encapsulariam o MediaFrameSourceGroup em uma classe de modelo Personalizada.Typical apps would wrap the MediaFrameSourceGroup in a custom model class. Observe que a classe auxiliar mantém uma referência ao CoreDispatcher do aplicativo e atualiza a coleção de câmeras em chamadas para RunAsync para garantir que a interface do usuário vinculada à coleção seja atualizada no thread da interface do usuário.Note that the helper class maintains a reference to the app's CoreDispatcher and updates the collection of cameras within calls to RunAsync to ensure that the UI bound to the collection is updated on the UI thread.

Além disso, este exemplo manipula o evento DeviceWatcher. updated além dos eventos adicionados e removidos .Also, this example handles the DeviceWatcher.Updated event in addition to the Added and Removed events. No manipulador atualizado , o dispositivo de câmera remota associado é removido de e, em seguida, adicionado de volta à coleção.In the Updated handler, the associated remote camera device is removed from and then added back to the collection.

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