Home | History | Annotate | Download | only in src
      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>
     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>
     82     void winrt_startMessageLoop(void callback(Args...), Args... args)
     83     {
     84         winrt_startMessageLoop(std::function<void(Args...)>(callback), args...);
     85     }
     86 
     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 
    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 
    123     VideoCapture_WinRT::VideoCapture_WinRT(int device) : started(false)
    124     {
    125         VideoioBridge::getInstance().setDeviceIndex(device);
    126     }
    127 
    128     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
    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
    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 
    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