This source file includes following definitions.
- getInstance
 
- isStarted
 
- closeGrabber
 
- initGrabber
 
- _GrabFrameAsync
 
- CopyOutput
 
- listDevicesTask
 
- listDevices
 
#include "cap_winrt_video.hpp"
#include <ppl.h>
#include <ppltasks.h>
#include <concrt.h>
#include <agile.h>
#include <atomic>
#include <future>
#include <vector>
using namespace ::concurrency;
using namespace ::Windows::Foundation;
using namespace ::std;
using namespace Microsoft::WRL;
using namespace Windows::Media::Devices;
using namespace Windows::Media::MediaProperties;
using namespace Windows::Media::Capture;
using namespace Windows::UI::Xaml::Media::Imaging;
using namespace Windows::Devices::Enumeration;
#include "cap_winrt/CaptureFrameGrabber.hpp"
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mf")
#pragma comment(lib, "mfuuid")
#if (WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP) && !defined(_M_ARM)
#pragma comment(lib, "Shlwapi")
#endif
#include "cap_winrt_bridge.hpp"
Video::Video() {}
Video &Video::getInstance() {
    static Video v;
    return v;
}
bool Video::isStarted() {
    return bGrabberInited.load();
}
void Video::closeGrabber() {
    
    m_frameGrabber = nullptr;
    bGrabberInited = false;
    bGrabberInitInProgress = false;
}
bool Video::initGrabber(int device, int w, int h) {
    
    if (bGrabberInited || bGrabberInitInProgress) return false;
    width = w;
    height = h;
    bGrabberInited = false;
    bGrabberInitInProgress = true;
    m_deviceID = device;
    create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture))
        .then([this](task<DeviceInformationCollection^> findTask)
    {
        m_devices = findTask.get();
        
        if ((unsigned)m_deviceID >= m_devices.Get()->Size)
        {
            OutputDebugStringA("Video::initGrabber - no video device found\n");
            return false;
        }
        auto devInfo = m_devices.Get()->GetAt(m_deviceID);
        auto settings = ref new MediaCaptureInitializationSettings();
        settings->StreamingCaptureMode = StreamingCaptureMode::Video; 
        settings->VideoDeviceId = devInfo->Id;
        auto location = devInfo->EnclosureLocation;
        bFlipImageX = true;
        if (location != nullptr && location->Panel == Windows::Devices::Enumeration::Panel::Back)
        {
            bFlipImageX = false;
        }
        m_capture = ref new MediaCapture();
        create_task(m_capture->InitializeAsync(settings)).then([this](){
            auto props = safe_cast<VideoEncodingProperties^>(m_capture->VideoDeviceController->GetMediaStreamProperties(MediaStreamType::VideoPreview));
            
            props->Subtype = MediaEncodingSubtypes::Rgb24;      bytesPerPixel = 3;
            
            
            props->Width = width;
            props->Height = height;
            return ::Media::CaptureFrameGrabber::CreateAsync(m_capture.Get(), props);
        }).then([this](::Media::CaptureFrameGrabber^ frameGrabber)
        {
            m_frameGrabber = frameGrabber;
            bGrabberInited = true;
            bGrabberInitInProgress = false;
            
            _GrabFrameAsync(frameGrabber);
        });
        return true;
    });
    
    return true;
}
void Video::_GrabFrameAsync(::Media::CaptureFrameGrabber^ frameGrabber) {
    
    create_task(frameGrabber->GetFrameAsync()).then([this, frameGrabber](const ComPtr<IMF2DBuffer2>& buffer)
    {
        
        BYTE *pbScanline;
        LONG plPitch;
        unsigned int colBytes = width * bytesPerPixel;
        CHK(buffer->Lock2D(&pbScanline, &plPitch));
        
        if (bFlipImageX)
        {
            std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().inputBufferMutex);
            
            auto buf = VideoioBridge::getInstance().backInputPtr;
            for (unsigned int row = 0; row < height; row++)
            {
                unsigned int i = 0;
                unsigned int j = colBytes - 1;
                while (i < colBytes)
                {
                    
                    
                    buf[j--] = pbScanline[i++];
                    buf[j--] = pbScanline[i++];
                    buf[j--] = pbScanline[i++];
                }
                pbScanline += plPitch;
                buf += colBytes;
            }
            VideoioBridge::getInstance().bIsFrameNew = true;
        } else
        {
            std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().inputBufferMutex);
            
            auto buf = VideoioBridge::getInstance().backInputPtr;
            for (unsigned int row = 0; row < height; row++)
            {
                
                
                
                
                for (unsigned int i = 0; i < colBytes; i += bytesPerPixel)
                {
                    
                    buf[i] = pbScanline[i + 2];
                    buf[i + 1] = pbScanline[i + 1];
                    buf[i + 2] = pbScanline[i];
                    
                    
                    
                    
                }
                pbScanline += plPitch;
                buf += colBytes;
            }
            VideoioBridge::getInstance().bIsFrameNew = true;
        }
        CHK(buffer->Unlock2D());
        VideoioBridge::getInstance().frameCounter++;
        if (bGrabberInited)
        {
            _GrabFrameAsync(frameGrabber);
        }
    }, task_continuation_context::use_current());
}
void Video::CopyOutput() {
    {
        std::lock_guard<std::mutex> lock(VideoioBridge::getInstance().outputBufferMutex);
        auto inAr = VideoioBridge::getInstance().frontInputPtr;
        auto outAr = GetData(VideoioBridge::getInstance().frontOutputBuffer->PixelBuffer);
        const unsigned int bytesPerPixel = 3;
        auto pbScanline = inAr;
        auto plPitch = width * bytesPerPixel;
        auto buf = outAr;
        unsigned int colBytes = width * 4;
        
        for (unsigned int row = 0; row < height; row++)
        {
            
            
            
            
            
            for (unsigned int i = 0, j = 0; i < plPitch; i += bytesPerPixel, j += 4)
            {
                
                buf[j] = pbScanline[i + 2];
                buf[j + 1] = pbScanline[i + 1];
                buf[j + 2] = pbScanline[i];
                buf[j + 3] = 0xff;
                
                
                
                
                
            }
            pbScanline += plPitch;
            buf += colBytes;
        }
        VideoioBridge::getInstance().frontOutputBuffer->PixelBuffer->Length = width * height * 4;
    }
}
bool Video::listDevicesTask() {
    std::atomic<bool> ready(false);
    auto settings = ref new MediaCaptureInitializationSettings();
    create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture))
        .then([this, &ready](task<DeviceInformationCollection^> findTask)
    {
        m_devices = findTask.get();
        
        
        
        
        
        
        
        
        
        ready = true;
    });
    
    int count = 0;
    while (!ready)
    {
        count++;
    }
    return true;
}
bool Video::listDevices() {
    
    std::future<bool> result = std::async(std::launch::async, &Video::listDevicesTask, this);
    return result.get();
}