Path: blob/master/modules/videoio/src/cap_winrt/CaptureFrameGrabber.cpp
16348 views
// Copyright (c) Microsoft. All rights reserved.1//2// The MIT License (MIT)3//4// Permission is hereby granted, free of charge, to any person obtaining a copy5// of this software and associated documentation files(the "Software"), to deal6// in the Software without restriction, including without limitation the rights7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell8// copies of the Software, and to permit persons to whom the Software is9// furnished to do so, subject to the following conditions :10//11// The above copyright notice and this permission notice shall be included in12// all copies or substantial portions of the Software.13//14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN20// THE SOFTWARE.2122#include "MediaStreamSink.hpp"23#include "MediaSink.hpp"24#include "CaptureFrameGrabber.hpp"2526using namespace Media;27using namespace Platform;28using namespace Windows::Foundation;29using namespace Windows::Media;30using namespace Windows::Media::Capture;31using namespace Windows::Media::MediaProperties;32using namespace concurrency;33using namespace Microsoft::WRL::Details;34using namespace Microsoft::WRL;3536task<Media::CaptureFrameGrabber^> Media::CaptureFrameGrabber::CreateAsync(_In_ MediaCapture^ capture, _In_ VideoEncodingProperties^ props, CaptureStreamType streamType)37{38auto reader = ref new Media::CaptureFrameGrabber(capture, props, streamType);3940auto profile = ref new MediaEncodingProfile();41profile->Video = props;4243task<void> task;44if (reader->_streamType == CaptureStreamType::Preview)45{46task = create_task(capture->StartPreviewToCustomSinkAsync(profile, reader->_mediaExtension));47}48else49{50task = create_task(capture->StartRecordToCustomSinkAsync(profile, reader->_mediaExtension));51}5253return task.then([reader]()54{55reader->_state = State::Started;56return reader;57});58}5960Media::CaptureFrameGrabber::CaptureFrameGrabber(_In_ MediaCapture^ capture, _In_ VideoEncodingProperties^ props, CaptureStreamType streamType)61: _state(State::Created)62, _streamType(streamType)63, _capture(capture)64{65auto videoSampleHandler = ref new MediaSampleHandler(this, &Media::CaptureFrameGrabber::ProcessSample);6667_mediaSink = Make<MediaSink>(nullptr, props, nullptr, videoSampleHandler);68_mediaExtension = reinterpret_cast<IMediaExtension^>(static_cast<AWM::IMediaExtension*>(_mediaSink.Get()));69}7071Media::CaptureFrameGrabber::~CaptureFrameGrabber()72{73if (_state == State::Started)74{75if (_streamType == CaptureStreamType::Preview)76{77(void)_capture->StopPreviewAsync();78}79else80{81(void)_capture->StopRecordAsync();82}83}8485if (_mediaSink != nullptr)86{87(void)_mediaSink->Shutdown();88_mediaSink = nullptr;89}90_mediaExtension = nullptr;91_capture = nullptr;92}9394void Media::CaptureFrameGrabber::ShowCameraSettings()95{96#if WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP97if (_state == State::Started)98{99CameraOptionsUI::Show(_capture.Get());100}101#endif102}103104task<void> Media::CaptureFrameGrabber::FinishAsync()105{106auto lock = _lock.LockExclusive();107108if (_state != State::Started)109{110throw ref new COMException(E_UNEXPECTED, L"State");111}112_state = State::Closing;113114if (_mediaSink != nullptr)115{116(void)_mediaSink->Shutdown();117_mediaSink = nullptr;118}119_mediaExtension = nullptr;120121task<void> task;122if (_streamType == CaptureStreamType::Preview)123{124task = create_task(_capture->StopPreviewAsync());125}126else127{128task = create_task(_capture->StopRecordAsync());129}130131return task.then([this]()132{133auto lock = _lock.LockExclusive();134_state = State::Closed;135_capture = nullptr;136});137}138139task<ComPtr<IMF2DBuffer2>> Media::CaptureFrameGrabber::GetFrameAsync()140{141auto lock = _lock.LockExclusive();142143if (_state != State::Started)144{145throw ref new COMException(E_UNEXPECTED, L"State");146}147148_mediaSink->RequestVideoSample();149150task_completion_event<ComPtr<IMF2DBuffer2>> taskEvent;151_videoSampleRequestQueue.push(taskEvent);152153return create_task(taskEvent);154}155156void Media::CaptureFrameGrabber::ProcessSample(_In_ MediaSample^ sample)157{158task_completion_event<ComPtr<IMF2DBuffer2>> t;159160{161auto lock = _lock.LockExclusive();162163t = _videoSampleRequestQueue.front();164_videoSampleRequestQueue.pop();165}166167ComPtr<IMFMediaBuffer> buffer;168CHK(sample->Sample->ConvertToContiguousBuffer(&buffer));169170// Dispatch without the lock taken to avoid deadlocks171t.set(As<IMF2DBuffer2>(buffer));172}173174