// Capture support for WinRT // Copyright (c) Microsoft Open Technologies, Inc. // All rights reserved. // // (3 - clause BSD License) // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that // the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the // following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the // following disclaimer in the documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or // promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "precomp.hpp" #include "cap_winrt_capture.hpp" #include "cap_winrt_bridge.hpp" #include "cap_winrt_video.hpp" #include using namespace Windows::Foundation; using namespace Windows::Media::Capture; using namespace Windows::Media::MediaProperties; using namespace Windows::Devices::Enumeration; using namespace Platform; using namespace Windows::UI::Xaml::Media::Imaging; using namespace Microsoft::WRL; using namespace ::std; namespace cv { /******************************* exported API functions **************************************/ template void winrt_startMessageLoop(std::function&& callback, Args... args) { auto asyncTask = ::concurrency::create_async([=](::concurrency::progress_reporter reporter) { VideoioBridge::getInstance().setReporter(reporter); // frame reading loop callback(args...); }); asyncTask->Progress = ref new AsyncActionProgressHandler([=](IAsyncActionWithProgress^ act, int progress) { int action = progress; // these actions will be processed on the UI thread asynchronously switch (action) { case OPEN_CAMERA: VideoioBridge::getInstance().openCamera(); break; case CLOSE_CAMERA: Video::getInstance().closeGrabber(); break; case UPDATE_IMAGE_ELEMENT: VideoioBridge::getInstance().updateFrameContainer(); break; } }); } template void winrt_startMessageLoop(void callback(Args...), Args... args) { winrt_startMessageLoop(std::function(callback), args...); } void winrt_onVisibilityChanged(bool visible) { if (visible) { VideoioBridge& bridge = VideoioBridge::getInstance(); // only start the grabber if the camera was opened in OpenCV if (bridge.backInputPtr != nullptr) { if (Video::getInstance().isStarted()) return; int device = bridge.getDeviceIndex(); int width = bridge.getWidth(); int height = bridge.getHeight(); Video::getInstance().initGrabber(device, width, height); } } else { //grabberStarted = false; Video::getInstance().closeGrabber(); } } void winrt_imshow() { VideoioBridge::getInstance().imshow(); } void winrt_setFrameContainer(::Windows::UI::Xaml::Controls::Image^ image) { VideoioBridge::getInstance().cvImage = image; } /********************************* VideoCapture_WinRT class ****************************/ VideoCapture_WinRT::VideoCapture_WinRT(int device) : started(false) { VideoioBridge::getInstance().setDeviceIndex(device); } bool VideoCapture_WinRT::isOpened() const { return true; // started; } // grab a frame: // this will NOT block per spec // should be called on the image processing thread, not the UI thread bool VideoCapture_WinRT::grabFrame() { // if device is not started we must return true so retrieveFrame() is called to start device // nb. we cannot start the device here because we do not know the size of the input Mat if (!started) return true; if (VideoioBridge::getInstance().bIsFrameNew) { return true; } // nb. if blocking is to be added: // unique_lock lock(VideoioBridge::getInstance().frameReadyMutex); // VideoioBridge::getInstance().frameReadyEvent.wait(lock); return false; } // should be called on the image processing thread after grabFrame // see VideoCapture::read bool VideoCapture_WinRT::retrieveFrame(int channel, cv::OutputArray outArray) { if (!started) { int width, height; width = outArray.size().width; height = outArray.size().height; if (width == 0) width = 640; if (height == 0) height = 480; VideoioBridge::getInstance().setWidth(width); VideoioBridge::getInstance().setHeight(height); // nb. Mats will be alloc'd on UI thread // request device init on UI thread - this does not block, and is async VideoioBridge::getInstance().requestForUIthreadAsync(OPEN_CAMERA); started = true; return false; } if (!started) return false; return VideoioBridge::getInstance().bIsFrameNew; } bool VideoCapture_WinRT::setProperty(int property_id, double value) { switch (property_id) { case CAP_PROP_FRAME_WIDTH: size.width = (int)value; break; case CAP_PROP_FRAME_HEIGHT: size.height = (int)value; break; default: return false; } return true; } } // end