次の方法で共有


リモート カメラに接続する

この記事では、1 つ以上のリモート カメラに接続し、各カメラからフレームを読み取ることを可能にする MediaFrameSourceGroup オブジェクトを取得する方法について説明します。 メディア ソースからフレームを読み取る方法の詳細については、「MediaFrameReaderを使用したメディア フレームの処理」を参照してください。 デバイスとのペアリングの詳細については、「デバイスのペアリング」を参照してください。

手記

この記事で説明する機能は、Windows 10 バージョン 1903 以降で使用できます。

使用可能なリモート カメラを監視する DeviceWatcher クラスを作成する

DeviceWatcher クラスは、アプリで使用できるデバイスを監視し、デバイスが追加または削除されたときにアプリに通知します。 DeviceWatcher のインスタンスを取得するには、DeviceInformation.CreateWatcherを呼び出し、監視するデバイスの種類を識別する高度なクエリ構文 (AQS) 文字列を渡します。 ネットワーク カメラ デバイスを指定する AQS 文字列は次のとおりです。

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

手記

MediaFrameSourceGroup.GetDeviceSelector ヘルパー メソッドは、ローカルに接続されたリモート ネットワーク カメラを監視する AQS 文字列を返します。 ネットワーク カメラのみを監視するには、上記の AQS 文字列を使用する必要があります。

Start メソッドを呼び出して、返された DeviceWatcher を起動すると、現在使用可能なすべてのネットワーク カメラに対して Added イベントが発生します。 Stopを呼び出してウォッチャーを停止するまで、新しいネットワーク カメラ デバイスが使用可能になったときに Added イベントが発生し、カメラ デバイスが使用できなくなったときに Removed イベントが発生します。

Added および Removed イベント ハンドラーに渡されるイベント引数は、それぞれ DeviceInformation および DeviceInformationUpdate オブジェクトです。 これらの各オブジェクトには、イベントが発生したネットワーク カメラの識別子である Id プロパティがあります。 この ID を MediaFrameSourceGroup.FromIdAsync メソッドに渡して、カメラからフレームを取得するために使用できる MediaFrameSourceGroup オブジェクトを取得します。

リモート カメラ ペアリング ヘルパー クラス

次の例は、DeviceWatcher を使用して、MediaFrameSourceGroup オブジェクトの ObservableCollection を作成および更新し、カメラのリストへのデータ バインディングをサポートするヘルパー クラスを示しています。 一般的なアプリでは、MediaFrameSourceGroup をカスタム モデル クラスでラップします。 ヘルパー クラスは、アプリの DispatcherQueue への参照を保持し、UI スレッド上のカメラのコレクションを更新します。

また、この例では、DeviceWatcher.Updated イベントに加えて、追加された および Removed イベントも処理します。 更新された ハンドラーでは、関連付けられているリモート カメラ デバイスがコレクションから削除され、コレクションに追加されます。

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