Se connecter à des caméras à distance
Cet article vous montre comment vous connecter à une ou plusieurs caméras distantes et obtenir un objet MediaFrameSourceGroup qui vous permet de lire des images à partir de chaque caméra. Pour plus d’informations sur la lecture de trames à partir d’une source multimédia, consultez Traiter les trames multimédias avec MediaFrameReader. Pour plus d’informations sur le jumelage avec les appareils, consultez Appairer des appareils.
Remarque
Les fonctionnalités décrites dans cet article sont disponibles à partir de Windows 10, version 1903.
Créer une classe DeviceWatcher pour surveiller les caméras distantes disponibles
La classe DeviceWatcher surveille les appareils disponibles pour votre application et avertit votre application lorsque les appareils sont ajoutés ou supprimés. Obtenez une instance de DeviceWatcher en appelant DeviceInformation.CreateWatcher, en passant une chaîne AQS (Advanced Query Syntax) qui identifie le type d’appareils que vous souhaitez surveiller. La chaîne AQS spécifiant des appareils photo réseau est la suivante :
@"System.Devices.InterfaceClassGuid:=""{B8238652-B500-41EB-B4F3-4234F7F5AE99}"" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True"
Remarque
La méthode d’assistance MediaFrameSourceGroup.GetDeviceSelector retourne une chaîne AQS qui surveillera les caméras réseau connectées localement et distantes. Pour surveiller uniquement les caméras réseau, vous devez utiliser la chaîne AQS indiquée ci-dessus.
Lorsque vous démarrez deviceWatcher retourné en appelant la méthode Start, il déclenche l’événement Ajouté pour chaque caméra réseau actuellement disponible. Jusqu’à ce que vous arrêtiez l’observateur en appelant Stop, l’événement Ajouté sera déclenché lorsque de nouveaux appareils photo réseau deviennent disponibles et que l’événement Supprimé sera déclenché lorsqu’un appareil photo devient indisponible.
Les arguments d’événement passés dans les gestionnaires d’événements Added et Removed sont respectivement un objet DeviceInformation ou DeviceInformationUpdate. Chacun de ces objets a une propriété ID qui est l’identificateur de la caméra réseau pour laquelle l’événement a été déclenché. Transmettez cet ID à la méthode MediaFrameSourceGroup.FromIdAsync pour obtenir un objet MediaFrameSourceGroup que vous pouvez utiliser pour récupérer des images à partir de la caméra.
Classe d’assistance d’appairage de caméras distantes
L’exemple suivant montre une classe d’assistance qui utilise un DeviceWatcher pour créer et mettre à jour un ObservableCollection d’objets MediaFrameSourceGroup pour prendre en charge la liaison de données à la liste des caméras. Les applications classiques encapsulent le MediaFrameSourceGroup dans une classe de modèle personnalisée. Notez que la classe d’assistance conserve une référence au CoreDispatcher de l’application et met à jour la collection de caméras dans les appels à RunAsync pour vous assurer que l’interface utilisateur liée à la collection est mise à jour sur le thread d’interface utilisateur.
En outre, cet exemple gère l’événement DeviceWatcher.Updated en plus des événements ajoutés et supprimés. Dans le gestionnaire mis à jour , l’appareil photo distant associé est supprimé, puis ajouté à la 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;
};