次の方法で共有


リモート カメラへの接続

この記事では、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 文字列を使用する必要があります。

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

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

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

次の例に示すヘルパー クラスでは、DeviceWatcher を使用して MediaFrameSourceGroup オブジェクトの ObservableCollection を作成および更新することで、カメラのリストへのデータ バインディングをサポートします。 一般的なアプリでは、カスタム モデル クラスに MediaFrameSourceGroup をラップします。 このヘルパー クラスでは、アプリの CoreDispatcher への参照を維持し、RunAsync の呼び出し内でカメラのコレクションを更新することで、コレクションにバインドされた UI が UI スレッド上で確実に更新されるようにします。

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

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