Compartilhar via


Conectar-se a câmeras remotas

Este artigo mostra como se conectar a uma ou mais câmeras remotas e obter um objeto MediaFrameSourceGroup que permite ler quadros de cada câmera. Para obter mais informações sobre como ler quadros de uma fonte de mídia, consulte Processar quadros de mídia com MediaFrameReader. Para obter mais informações sobre emparelhamento com dispositivos, consulte Emparelhar dispositivos.

Observação

Os recursos discutidos neste artigo estão disponíveis a partir do Windows 10, versão 1903.

Criar uma classe DeviceWatcher para watch para câmeras remotas disponíveis

A classe DeviceWatcher monitora os dispositivos disponíveis para seu aplicativo e notifica seu aplicativo quando os dispositivos são adicionados ou removidos. Obtenha uma instância do DeviceWatcher chamando DeviceInformation.CreateWatcher, passando uma cadeia de caracteres AQS (Sintaxe de Consulta Avançada) que identifica o tipo de dispositivos que você deseja monitorar. A cadeia de caracteres do AQS que especifica dispositivos de câmera de rede é a seguinte:

@"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á câmeras de rede remotas e conectadas localmente. Para monitorar apenas as câmeras de rede, você deve usar a cadeia de caracteres do AQS mostrada acima.

Quando você iniciar o DeviceWatcher retornado chamando o método Start , ele acionará o evento Added para cada câmera de rede disponível no momento. Até que você interrompa o observador chamando Parar, o evento Added será acionado quando novos dispositivos de câmera de rede estiverem disponíveis e o evento Removed for acionado quando um dispositivo de câmera ficar indisponível.

Os argumentos de evento passados para os manipuladores de eventos Added e Removed são um objeto DeviceInformation ou DeviceInformationUpdate , respectivamente. Cada um desses objetos tem uma propriedade ID que é o identificador da câmera de rede para a qual o evento foi acionado. Passe essa ID para o método MediaFrameSourceGroup.FromIdAsync para obter um objeto MediaFrameSourceGroup que você pode usar para recuperar quadros da câmera.

Classe auxiliar de emparelhamento de câmera remota

O exemplo a seguir mostra uma classe auxiliar que usa um DeviceWatcher para criar e atualizar um ObservableCollection de objetos MediaFrameSourceGroup para dar suporte à associação de dados à lista de câmeras. Aplicativos típicos encapsulariam o MediaFrameSourceGroup em uma classe de modelo personalizada. 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 associada à coleção seja atualizada no thread da interface do usuário.

Além disso, este exemplo manipula o evento DeviceWatcher.Updated , além dos eventos Added e Removed . No manipulador Atualizado , o dispositivo de câmera remota associado é removido de e, em seguida, adicionado de volta à coleção.

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