Connettersi a fotocamere remoteConnect to remote cameras

Questo articolo illustra come connettersi a una o più Fotocamere remote e ottenere un oggetto MediaFrameSourceGroup che consente di leggere i frame di ogni fotocamera.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. Per altre informazioni sulla lettura di frame da un'origine multimediale, vedere elaborare i frame multimediali con MediaFrameReader.For more information on reading frames from a media source, see Process media frames with MediaFrameReader. Per altre informazioni sull'associazione con i dispositivi, vedere associare i dispositivi.For more information on pairing with devices, see Pair devices.

Nota

Le funzionalità descritte in questo articolo sono disponibili a partire da Windows 10, versione 1903.The features discussed in this article are available starting with Windows 10, version 1903.

Creare una classe DeviceWatcher per controllare le fotocamere remote disponibiliCreate a DeviceWatcher class to watch for available remote cameras

La classe DeviceWatcher monitora i dispositivi disponibili per l'app e invia una notifica all'app quando i dispositivi vengono aggiunti o rimossi.The DeviceWatcher class monitors the devices available to your app and notifies your app when devices are added or removed. Ottenere un'istanza di DeviceWatcher chiamando DeviceInformation. CreateWatcher, passando una stringa di sintassi di query avanzata (AQS) che identifichi il tipo di dispositivi che si desidera monitorare.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. La stringa AQS che specifica i dispositivi della fotocamera di rete è la seguente: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"

Nota

Il metodo helper MediaFrameSourceGroup. GetDeviceSelector restituisce una stringa AQS che eseguirà il monitoraggio di telecamere di rete connesse localmente e remote.The helper method MediaFrameSourceGroup.GetDeviceSelector returns an AQS string that will monitor locally-connected and remote network cameras. Per monitorare solo le videocamere di rete, è necessario usare la stringa AQS mostrata in precedenza.To monitor only network cameras, you should use the AQS string shown above.

Quando si avvia il DeviceWatcher restituito chiamando il metodo Start , viene generato l'evento aggiunto per ogni videocamera di rete attualmente disponibile.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. Fino a quando non si arresta il Watcher chiamando Stop, l'evento aggiunto viene generato quando i nuovi dispositivi della fotocamera di rete diventano disponibili e l'evento rimosso viene generato quando un dispositivo della fotocamera diventa non disponibile.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.

Gli argomenti dell'evento passati nei gestori eventi aggiunti e rimossi sono rispettivamente un oggetto DeviceInformation o DeviceInformationUpdate .The event args passed into the Added and Removed event handlers are a DeviceInformation or a DeviceInformationUpdate object, respectively. Ognuno di questi oggetti dispone di una proprietà ID che corrisponde all'identificatore per la videocamera di rete per cui è stato generato l'evento.Each of these objects has an Id property that is the identifier for the network camera for which the event was fired. Passare questo ID al metodo MediaFrameSourceGroup. FromIdAsync per ottenere un oggetto MediaFrameSourceGroup che è possibile usare per recuperare i frame dalla fotocamera.Pass this ID into the MediaFrameSourceGroup.FromIdAsync method to get a MediaFrameSourceGroup object that you can use to retrieve frames from the camera.

Classe helper per l'associazione di Fotocamere remoteRemote camera pairing helper class

Nell'esempio seguente viene illustrata una classe helper che utilizza un DeviceWatcher per creare e aggiornare un oggetto ObservableCollection di oggetti MediaFrameSourceGroup per supportare data binding all'elenco di fotocamere.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. Le app tipiche eseguiranno il wrapping di MediaFrameSourceGroup in una classe di modello personalizzata.Typical apps would wrap the MediaFrameSourceGroup in a custom model class. Si noti che la classe helper mantiene un riferimento al CoreDispatcher dell'app e aggiorna la raccolta di fotocamere all'interno delle chiamate a RunAsync per assicurarsi che l'interfaccia utente associata alla raccolta venga aggiornata nel thread UI.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.

In questo esempio viene inoltre gestito l'evento DeviceWatcher. updated oltre agli eventi aggiunti e rimossi .Also, this example handles the DeviceWatcher.Updated event in addition to the Added and Removed events. Nel gestore aggiornato , il dispositivo della fotocamera remota associato viene rimosso da e quindi aggiunto nuovamente alla raccolta.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;
};