Condividi tramite


Connettersi a fotocamere remote

Questo articolo illustra come connettersi a una o più fotocamere remote e ottenere un oggetto MediaFrameSourceGroup che consente di leggere fotogrammi da ogni fotocamera. Per ulteriori informazioni sulla lettura dei frame da un'origine multimediale, vedere Elaborare frame multimediali con MediaFrameReader. Per altre informazioni sull'associazione con i dispositivi, vedere Associare dispositivi.

Nota

Le funzionalità descritte in questo articolo sono disponibili a partire da Windows 10 versione 1903.

Creare una classe DeviceWatcher per controllare la disponibilità di fotocamere remote disponibili

La classe DeviceWatcher monitora i dispositivi disponibili per l'app e invia una notifica all'app quando i dispositivi vengono aggiunti o rimossi. Ottenere un'istanza di DeviceWatcher chiamando DeviceInformation.CreateWatcher, passando una stringa AQS (Advanced Query Syntax) che identifica il tipo di dispositivi da monitorare. La stringa AQS che specifica i dispositivi della fotocamera di rete è la seguente:

@"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 monitora le fotocamere di rete connesse in locale e remote. Per monitorare solo le fotocamere di rete, è consigliabile usare la stringa AQS illustrata in precedenza.

Quando si avvia DeviceWatcher restituito chiamando il metodo Start, solleva l'evento Aggiunto per ogni camera in rete attualmente disponibile. Finché non si arresta il watcher chiamando Stop, l'evento Aggiunto verrà generato quando i nuovi dispositivi della fotocamera in rete diventano disponibili e l'evento Rimosso viene generato quando un dispositivo fotocamera diventa non disponibile.

Gli argomenti dell'evento passati ai gestori eventi Added e Removed sono rispettivamente un oggetto DeviceInformation o DeviceInformationUpdate rispettivamente. Ognuno di questi oggetti ha una proprietà pd che rappresenta l'identificatore per la fotocamera di rete per cui è stato generato l'evento. Passare questo ID nel metodo MediaFrameSourceGroup.FromIdAsync per ottenere un oggetto MediaFrameSourceGroup che è possibile usare per recuperare fotogrammi dalla fotocamera.

Classe helper per l'associazione di fotocamere remote

L'esempio seguente mostra una classe helper che usa un oggetto DeviceWatcher per creare e aggiornare un oggetto ObservableCollection di oggetti MediaFrameSourceGroup per supportare il data binding all'elenco di fotocamere. Le app tipiche includono MediaFrameSourceGroup in una classe modello personalizzata. 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 garantire che l'interfaccia utente associata alla raccolta venga aggiornata nel thread dell'interfaccia utente.

Inoltre, questo esempio gestisce l'evento DeviceWatcher.Updated oltre agli eventi Added e Removed. Nel gestore Aggiornato il dispositivo fotocamera remota associato viene rimosso e quindi aggiunto di nuovo alla raccolta.

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