Dela via


Ansluta till fjärrkameror

Den här artikeln visar hur du ansluter till en eller flera fjärrkameror och får ett MediaFrameSourceGroup- objekt som gör att du kan läsa bildrutor från varje kamera. Mer information om hur du läser bildrutor från en mediekälla finns i Bearbeta medieramar med MediaFrameReader. Mer information om hur du parkopplar med enheter finns i Parparenheter.

Not

De funktioner som beskrivs i den här artikeln är tillgängliga från och med Windows 10 version 1903.

Skapa en DeviceWatcher-klass för att titta efter tillgängliga fjärrkameror

Klassen DeviceWatcher övervakar de enheter som är tillgängliga för din app och meddelar appen när enheter läggs till eller tas bort. Hämta en instans av DeviceWatcher- genom att anropa DeviceInformation.CreateWatcheroch skicka in en AQS-sträng (Advanced Query Syntax) som identifierar vilken typ av enheter du vill övervaka. AQS-strängen som anger nätverkskameraenheter är följande:

@"System.Devices.InterfaceClassGuid:=""{B8238652-B500-41EB-B4F3-4234F7F5AE99}"" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True"

Not

Hjälpmetoden MediaFrameSourceGroup.GetDeviceSelector returnerar en AQS-sträng som övervakar lokalt anslutna kameror och fjärrnätverkskameror. Om du bara vill övervaka nätverkskameror bör du använda AQS-strängen som visas ovan.

När du startar den returnerade DeviceWatcher- genom att anropa metoden Start genereras händelsen Added för varje nätverkskamera som för närvarande är tillgänglig. Tills du stoppar övervakaren genom att anropa Stop, aktiveras händelsen Tillagd när nya nätverkskameraenheter blir tillgängliga och händelsen Borttagen aktiveras när en kameraenhet blir otillgänglig.

Händelseargumenten som skickas till Tillagda och Borttagna händelsehanterarna är ett DeviceInformation--objekt eller ett DeviceInformationUpdate--objekt, respektive. Vart och ett av dessa objekt har en ID egenskap som är identifieraren för nätverkskameran som händelsen utlöstes för. Skicka det här ID:t till metoden MediaFrameSourceGroup.FromIdAsync för att hämta ett MediaFrameSourceGroup- objekt som du kan använda för att hämta bildrutor från kameran.

Hjälpklass för fjärrkameraparkoppling

I följande exempel visas en hjälpklass som använder en DeviceWatcher- för att skapa och uppdatera en ObservableCollection- av MediaFrameSourceGroup objekt som stöder databindning till listan över kameror. Typiska appar omsluter MediaFrameSourceGroup- i en anpassad modellklass. Observera att hjälpklassen har en referens till appens DispatcherQueue och uppdaterar samlingen kameror i användargränssnittstråden.

Dessutom hanterar det här exemplet händelserna DeviceWatcher.Updated utöver händelserna Added och Removed. I Uppdaterad-hanteraren tas den associerade fjärrkameraenheten bort från och läggs sedan tillbaka till samlingen.

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