1 // Capture support for WinRT 2 3 // Copyright (c) Microsoft Open Technologies, Inc. 4 // All rights reserved. 5 // 6 // (3 - clause BSD License) 7 // 8 // Redistribution and use in source and binary forms, with or without modification, are permitted provided that 9 // the following conditions are met: 10 // 11 // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the 12 // following disclaimer. 13 // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 14 // following disclaimer in the documentation and/or other materials provided with the distribution. 15 // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 16 // promote products derived from this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 19 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 // PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, 22 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING 24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 // POSSIBILITY OF SUCH DAMAGE. 26 27 28 #include "precomp.hpp" 29 #include "cap_winrt_capture.hpp" 30 #include "cap_winrt_bridge.hpp" 31 #include "cap_winrt_video.hpp" 32 #include <opencv2\videoio\cap_winrt.hpp> 33 34 using namespace Windows::Foundation; 35 using namespace Windows::Media::Capture; 36 using namespace Windows::Media::MediaProperties; 37 using namespace Windows::Devices::Enumeration; 38 39 using namespace Platform; 40 41 using namespace Windows::UI::Xaml::Media::Imaging; 42 using namespace Microsoft::WRL; 43 44 using namespace ::std; 45 46 namespace cv { 47 48 /******************************* exported API functions **************************************/ 49 50 template <typename ...Args> winrt_startMessageLoop(std::function<void (Args...)> && callback,Args...args)51 void winrt_startMessageLoop(std::function<void(Args...)>&& callback, Args... args) 52 { 53 auto asyncTask = ::concurrency::create_async([=](::concurrency::progress_reporter<int> reporter) 54 { 55 VideoioBridge::getInstance().setReporter(reporter); 56 57 // frame reading loop 58 callback(args...); 59 }); 60 61 asyncTask->Progress = ref new AsyncActionProgressHandler<int>([=](IAsyncActionWithProgress<int>^ act, int progress) 62 { 63 int action = progress; 64 65 // these actions will be processed on the UI thread asynchronously 66 switch (action) 67 { 68 case OPEN_CAMERA: 69 VideoioBridge::getInstance().openCamera(); 70 break; 71 case CLOSE_CAMERA: 72 Video::getInstance().closeGrabber(); 73 break; 74 case UPDATE_IMAGE_ELEMENT: 75 VideoioBridge::getInstance().updateFrameContainer(); 76 break; 77 } 78 }); 79 } 80 81 template <typename ...Args> winrt_startMessageLoop(void callback (Args...),Args...args)82 void winrt_startMessageLoop(void callback(Args...), Args... args) 83 { 84 winrt_startMessageLoop(std::function<void(Args...)>(callback), args...); 85 } 86 winrt_onVisibilityChanged(bool visible)87 void winrt_onVisibilityChanged(bool visible) 88 { 89 if (visible) 90 { 91 VideoioBridge& bridge = VideoioBridge::getInstance(); 92 93 // only start the grabber if the camera was opened in OpenCV 94 if (bridge.backInputPtr != nullptr) 95 { 96 if (Video::getInstance().isStarted()) return; 97 98 int device = bridge.getDeviceIndex(); 99 int width = bridge.getWidth(); 100 int height = bridge.getHeight(); 101 102 Video::getInstance().initGrabber(device, width, height); 103 } 104 } else 105 { 106 //grabberStarted = false; 107 Video::getInstance().closeGrabber(); 108 } 109 } 110 winrt_imshow()111 void winrt_imshow() 112 { 113 VideoioBridge::getInstance().imshow(); 114 } 115 116 void winrt_setFrameContainer(::Windows::UI::Xaml::Controls::Image^ image) 117 { 118 VideoioBridge::getInstance().cvImage = image; 119 } 120 121 /********************************* VideoCapture_WinRT class ****************************/ 122 VideoCapture_WinRT(int device)123 VideoCapture_WinRT::VideoCapture_WinRT(int device) : started(false) 124 { 125 VideoioBridge::getInstance().setDeviceIndex(device); 126 } 127 isOpened() const128 bool VideoCapture_WinRT::isOpened() const 129 { 130 return true; // started; 131 } 132 133 // grab a frame: 134 // this will NOT block per spec 135 // should be called on the image processing thread, not the UI thread grabFrame()136 bool VideoCapture_WinRT::grabFrame() 137 { 138 // if device is not started we must return true so retrieveFrame() is called to start device 139 // nb. we cannot start the device here because we do not know the size of the input Mat 140 if (!started) return true; 141 142 if (VideoioBridge::getInstance().bIsFrameNew) 143 { 144 return true; 145 } 146 147 // nb. if blocking is to be added: 148 // unique_lock<mutex> lock(VideoioBridge::getInstance().frameReadyMutex); 149 // VideoioBridge::getInstance().frameReadyEvent.wait(lock); 150 return false; 151 } 152 153 // should be called on the image processing thread after grabFrame 154 // see VideoCapture::read retrieveFrame(int channel,cv::OutputArray outArray)155 bool VideoCapture_WinRT::retrieveFrame(int channel, cv::OutputArray outArray) 156 { 157 if (!started) { 158 159 int width, height; 160 width = outArray.size().width; 161 height = outArray.size().height; 162 if (width == 0) width = 640; 163 if (height == 0) height = 480; 164 165 VideoioBridge::getInstance().setWidth(width); 166 VideoioBridge::getInstance().setHeight(height); 167 168 // nb. Mats will be alloc'd on UI thread 169 170 // request device init on UI thread - this does not block, and is async 171 VideoioBridge::getInstance().requestForUIthreadAsync(OPEN_CAMERA); 172 173 started = true; 174 return false; 175 } 176 177 if (!started) return false; 178 179 return VideoioBridge::getInstance().bIsFrameNew; 180 } 181 182 setProperty(int property_id,double value)183 bool VideoCapture_WinRT::setProperty(int property_id, double value) 184 { 185 switch (property_id) 186 { 187 case CAP_PROP_FRAME_WIDTH: 188 size.width = (int)value; 189 break; 190 case CAP_PROP_FRAME_HEIGHT: 191 size.height = (int)value; 192 break; 193 default: 194 return false; 195 } 196 return true; 197 } 198 } 199 200 // end