다음을 통해 공유


원격 카메라에 연결

이 문서에서는 하나 이상의 원격 카메라에 연결하고 각 카메라에서 프레임을 읽을 수 있는 MediaFrameSourceGroup 개체를 가져오는 방법을 보여 줍니다. 미디어 원본에서 프레임을 읽는 방법에 대한 자세한 내용은 mediaFrameReader사용하여 미디어 프레임 처리 참조하세요. 디바이스와 페어링하는 방법에 대한 자세한 내용은 장치 연결항목을 참조하세요.

메모

이 문서에서 설명하는 기능은 Windows 10 버전 1903부터 사용할 수 있습니다.

DeviceWatcher 클래스를 만들어 사용 가능한 원격 카메라를 감시합니다.

DeviceWatcher 클래스는 앱에서 사용할 수 있는 디바이스를 모니터링하고 디바이스가 추가되거나 제거될 때 앱에 알깁니다. DeviceInformation.CreateWatcher를 호출하여 모니터링하려는 장치 유형을 식별하는 고급 쿼리 구문(AQS) 문자열을 전달함으로써 DeviceWatcher 인스턴스를 가져옵니다. 네트워크 카메라 디바이스를 지정하는 AQS 문자열은 다음과 같습니다.

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

메모

MediaFrameSourceGroup.GetDeviceSelector 도우미 메서드는 로컬로 연결된 원격 네트워크 카메라를 모니터링하는 AQS 문자열을 반환합니다. 네트워크 카메라만 모니터링하려면 위에 표시된 AQS 문자열을 사용해야 합니다.

Start 메서드를 호출하여 반환된 DeviceWatcher를 시작하면, 현재 사용 가능한 모든 네트워크 카메라에 대해 Added 이벤트가 발생합니다. 중지호출하여 감시자를 중지할 때까지 새 네트워크 카메라 디바이스가 이용 가능해지면 추가된 이벤트가 발생하고, 카메라 디바이스가 이용 불가능해지면 제거된 이벤트가 발생합니다.

추가된 전달된 이벤트 인수 및 제거된 이벤트 처리기는 각각 DeviceInformation 또는 DeviceInformationUpdate 개체입니다. 이러한 각 개체에는 이벤트가 발생한 네트워크 카메라의 식별자인 ID 속성이 있습니다. 이 ID를 MediaFrameSourceGroup.FromIdAsync 메서드에 전달하여 카메라에서 프레임을 검색하는 데 사용할 수 있는 MediaFrameSourceGroup 개체를 가져옵니다.

원격 카메라 페어링 지원 클래스

다음 예제는 DeviceWatcher를 사용하여 MediaFrameSourceGroup 개체의 ObservableCollection을 생성하고 업데이트하는 도우미 클래스를 보여 주며, 이는 카메라 목록에 대한 데이터 바인딩을 지원합니다. 일반적인 앱은 사용자 지정 모델 클래스 내에서 MediaFrameSourceGroup를 래핑합니다. 헬퍼 클래스는 앱의 DispatcherQueue에 대한 참조를 유지하며, UI 스레드에서 카메라 컬렉션을 업데이트합니다.

또한 이 예제에서는 추가제거 이벤트 외에도 DeviceWatcher.Updated 이벤트를 처리합니다. 업데이트된 처리기에서 연결된 원격 카메라 장치가 컬렉션에서 제거되었다가 다시 추가됩니다.

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