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 que você possa 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.
Nota
Os recursos discutidos neste artigo estão disponíveis a partir do Windows 10, versão 1903.
Criar uma classe DeviceWatcher para observar as 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 de DeviceWatcher chamando DeviceInformation.CreateWatcher, passando uma cadeia de caracteres AQS (Sintaxe de consulta avançada) que identifica o tipo de dispositivos que você quer 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"
Nota
O método auxiliar MediaFrameSourceGroup.GetDeviceSelector retorna uma cadeia de caracteres do 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 gerará o evento Added para todas as câmeras de rede que estão disponíveis no momento. Até que você interrompa o observador chamando Stop, o evento Added será disparado quando novos dispositivos de câmera de rede estiverem disponíveis e o evento Removed será disparado 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 um objeto 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 esse identificador para o método
Classe auxiliar de emparelhamento de câmera remota
O exemplo a seguir mostra uma classe auxiliar que usa um DeviceWatcher para criar e atualizar uma ObservableCollection de 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 à DispatcherQueue do aplicativo e atualiza a coleção de câmeras 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 e adicionado novamente à coleção.
class RemoteCameraPairingHelper : IDisposable
{
private DispatcherQueue _dispatcherQueue;
private DeviceWatcher _watcher;
private ObservableCollection<MediaFrameSourceGroup> _remoteCameraCollection;
public RemoteCameraPairingHelper(DispatcherQueue uiDispatcherQueue)
{
_dispatcherQueue = uiDispatcherQueue;
_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)
{
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () => {
_remoteCameraCollection.Add(group);
});
}
}
private async Task RemoveDevice(string id)
{
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
{
var existing = _remoteCameraCollection.FirstOrDefault(item => item.Id == id);
if (existing != null)
{
_remoteCameraCollection.Remove(existing);
}
});
}
struct RemoteCameraPairingHelper
{
RemoteCameraPairingHelper(DispatcherQueue uiDispatcher) :
m_dispatcherQueue(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, nullptr);
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_dispatcherQueue;
co_await wil::resume_foreground(m_dispatcherQueue);
m_remoteCameraCollection.Append(group);
}
}
Windows::Foundation::IAsyncAction RemoveDevice(winrt::hstring id)
{
//co_await m_dispatcherQueue;
co_await wil::resume_foreground(m_dispatcherQueue);
uint32_t ix{ 0 };
for (auto const&& item : m_remoteCameraCollection)
{
if (item.Id() == id)
{
m_remoteCameraCollection.RemoveAt(ix);
break;
}
++ix;
}
}
private:
DispatcherQueue m_dispatcherQueue{ nullptr };
DeviceWatcher m_watcher{ nullptr };
IObservableVector<MediaFrameSourceGroup> m_remoteCameraCollection;
DeviceWatcher::Added_revoker m_watcherAddedAutoRevoker;
DeviceWatcher::Removed_revoker m_watcherRemovedAutoRevoker;
DeviceWatcher::Updated_revoker m_watcherUpdatedAutoRevoker;
};
Tópicos relacionados
Windows developer