Commit 44848d32 authored by Vitaly Tuzov's avatar Vitaly Tuzov

MSMF-based CameraCapture reworked to use SourceReader

parent 65c46d0c
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <string> #include <string>
#include <algorithm>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
...@@ -106,19 +107,33 @@ template <class T> void SafeRelease(T **ppT) ...@@ -106,19 +107,33 @@ template <class T> void SafeRelease(T **ppT)
} }
#ifdef _DEBUG #ifdef _DEBUG
/// Class for printing info into console void DPOprintOut(const wchar_t *format, ...)
class DPO
{ {
public: int i = 0;
~DPO(void); wchar_t *p = NULL;
static DPO& getInstance(); va_list args;
void printOut(const wchar_t *format, ...); va_start(args, format);
void setVerbose(bool state); if (::IsDebuggerPresent())
bool verbose; {
private: WCHAR szMsg[512];
DPO(void); ::StringCchVPrintfW(szMsg, sizeof(szMsg) / sizeof(szMsg[0]), format, args);
}; ::OutputDebugStringW(szMsg);
#define DebugPrintOut(...) DPO::getInstance().printOut(__VA_ARGS__) }
else
{
if (wcscmp(format, L"%i"))
{
i = va_arg(args, int);
}
if (wcscmp(format, L"%s"))
{
p = va_arg(args, wchar_t *);
}
wprintf(format, i, p);
}
va_end(args);
}
#define DebugPrintOut(...) DPOprintOut(__VA_ARGS__)
#else #else
#define DebugPrintOut(...) void() #define DebugPrintOut(...) void()
#endif #endif
...@@ -334,7 +349,6 @@ public: ...@@ -334,7 +349,6 @@ public:
void setParametrs(CamParametrs parametrs); void setParametrs(CamParametrs parametrs);
void setEmergencyStopEvent(void *userData, void(*func)(int, void *)); void setEmergencyStopEvent(void *userData, void(*func)(int, void *));
long readInfoOfDevice(IMFActivate *pActivate, unsigned int Num); long readInfoOfDevice(IMFActivate *pActivate, unsigned int Num);
wchar_t *getName();
int getCountFormats(); int getCountFormats();
unsigned int getWidth(); unsigned int getWidth();
unsigned int getHeight(); unsigned int getHeight();
...@@ -357,7 +371,6 @@ private: ...@@ -357,7 +371,6 @@ private:
} vd_LockOut; } vd_LockOut;
wchar_t *vd_pFriendlyName; wchar_t *vd_pFriendlyName;
ImageGrabberThread *vd_pImGrTh; ImageGrabberThread *vd_pImGrTh;
CamParametrs vd_PrevParametrs;
unsigned int vd_Width; unsigned int vd_Width;
unsigned int vd_Height; unsigned int vd_Height;
unsigned int vd_FrameRate; unsigned int vd_FrameRate;
...@@ -372,8 +385,7 @@ private: ...@@ -372,8 +385,7 @@ private:
long setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex); long setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex);
void buildLibraryofTypes(); void buildLibraryofTypes();
int findType(unsigned int size, unsigned int frameRate = 0); int findType(unsigned int size, unsigned int frameRate = 0);
long resetDevice(IMFActivate *pActivate); long checkDevice(IMFActivate **pDevice);
long checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice);
long initDevice(); long initDevice();
}; };
...@@ -382,14 +394,8 @@ class videoDevices ...@@ -382,14 +394,8 @@ class videoDevices
{ {
public: public:
~videoDevices(void); ~videoDevices(void);
long initDevices(IMFAttributes *pAttributes); static cv::Ptr<videoDevice> getDevice(unsigned int i, bool fallback = false);
static videoDevices& getInstance();
videoDevice *getDevice(unsigned int i);
unsigned int getCount();
void clearDevices();
private: private:
UINT32 count;
std::vector<videoDevice *> vds_Devices;
videoDevices(void); videoDevices(void);
}; };
...@@ -407,118 +413,6 @@ private: ...@@ -407,118 +413,6 @@ private:
Media_Foundation(void) { CV_Assert(SUCCEEDED(MFStartup(MF_VERSION))); } Media_Foundation(void) { CV_Assert(SUCCEEDED(MFStartup(MF_VERSION))); }
}; };
/// The only visiable class for controlling of video devices in format singelton
class videoInput
{
public:
virtual ~videoInput(void);
// Getting of static instance of videoInput class
static videoInput& getInstance();
// Closing video device with deviceID
void closeDevice(int deviceID);
// Setting callback function for emergency events(for example: removing video device with deviceID) with userData
void setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *));
// Closing all devices
void closeAllDevices();
// Getting of parametrs of video device with deviceID
CamParametrs getParametrs(int deviceID);
// Setting of parametrs of video device with deviceID
void setParametrs(int deviceID, CamParametrs parametrs);
// Getting numbers of existence videodevices with listing in consol
unsigned int listDevices(bool silent = false);
// Getting numbers of formats, which are supported by videodevice with deviceID
unsigned int getCountFormats(int deviceID) const;
// Getting width of image, which is getting from videodevice with deviceID
unsigned int getWidth(int deviceID) const;
// Getting height of image, which is getting from videodevice with deviceID
unsigned int getHeight(int deviceID) const;
// Getting frame rate, which is getting from videodevice with deviceID
unsigned int getFrameRate(int deviceID) const;
// Getting name of videodevice with deviceID
const wchar_t *getNameVideoDevice(int deviceID);
// Getting interface MediaSource for Media Foundation from videodevice with deviceID
IMFMediaSource *getMediaSource(int deviceID);
// Getting format with id, which is supported by videodevice with deviceID
MediaType getFormat(int deviceID, int unsigned id);
// Checking of existence of the suitable video devices
bool isDevicesAcceable();
// Checking of using the videodevice with deviceID
bool isDeviceSetup(int deviceID);
// Checking of using MediaSource from videodevice with deviceID
bool isDeviceMediaSource(int deviceID);
// Checking of using Raw Data of pixels from videodevice with deviceID
bool isDeviceRawDataSource(int deviceID);
#ifdef _DEBUG
// Setting of the state of outprinting info in console
static void setVerbose(bool state);
#endif
// Initialization of video device with deviceID by media type with id
bool setupDevice(int deviceID, unsigned int id = 0);
// Initialization of video device with deviceID by wisth w, height h and fps idealFramerate
bool setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate = 30);
// Checking of recivig of new frame from video device with deviceID
bool isFrameNew(int deviceID);
// Writing of Raw Data pixels from video device with deviceID with correction of RedAndBlue flipping flipRedAndBlue and vertical flipping flipImage
bool getPixels(int deviceID, unsigned char * pixels, bool flipRedAndBlue = false, bool flipImage = false);
static void processPixels(unsigned char * src, unsigned char * dst, unsigned int width, unsigned int height, unsigned int bpp, bool bRGB, bool bFlip);
private:
Media_Foundation& MF;
bool accessToDevices;
videoInput(void);
void updateListOfDevices();
};
#ifdef _DEBUG
DPO::DPO(void):verbose(true)
{
}
DPO::~DPO(void)
{
}
DPO& DPO::getInstance()
{
static DPO instance;
return instance;
}
void DPO::printOut(const wchar_t *format, ...)
{
if(verbose)
{
int i = 0;
wchar_t *p = NULL;
va_list args;
va_start(args, format);
if( ::IsDebuggerPresent() )
{
WCHAR szMsg[512];
::StringCchVPrintfW(szMsg, sizeof(szMsg)/sizeof(szMsg[0]), format, args);
::OutputDebugStringW(szMsg);
}
else
{
if(wcscmp(format, L"%i"))
{
i = va_arg (args, int);
}
if(wcscmp(format, L"%s"))
{
p = va_arg (args, wchar_t *);
}
wprintf(format, i,p);
}
va_end (args);
}
}
void DPO::setVerbose(bool state)
{
verbose = state;
}
#endif
LPCWSTR GetGUIDNameConstNew(const GUID& guid); LPCWSTR GetGUIDNameConstNew(const GUID& guid);
HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz); HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz);
HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index); HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index);
...@@ -1558,6 +1452,7 @@ void videoDevice::setParametrs(CamParametrs parametrs) ...@@ -1558,6 +1452,7 @@ void videoDevice::setParametrs(CamParametrs parametrs)
{ {
if(vd_pSource) if(vd_pSource)
{ {
CamParametrs vd_PrevParametrs = getParametrs();
Parametr *pParametr = (Parametr *)(&parametrs); Parametr *pParametr = (Parametr *)(&parametrs);
Parametr *pPrevParametr = (Parametr *)(&vd_PrevParametrs); Parametr *pPrevParametr = (Parametr *)(&vd_PrevParametrs);
IAMVideoProcAmp *pProcAmp = NULL; IAMVideoProcAmp *pProcAmp = NULL;
...@@ -1632,141 +1527,25 @@ CamParametrs videoDevice::getParametrs() ...@@ -1632,141 +1527,25 @@ CamParametrs videoDevice::getParametrs()
return out; return out;
} }
long videoDevice::resetDevice(IMFActivate *pActivate)
{
HRESULT hr = E_FAIL;
vd_CurrentFormats.clear();
if(vd_pFriendlyName)
CoTaskMemFree(vd_pFriendlyName);
vd_pFriendlyName = NULL;
if(pActivate)
{
IMFMediaSource *pSource = NULL;
hr = pActivate->GetAllocatedString(
MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
&vd_pFriendlyName,
NULL
);
if (SUCCEEDED(hr))
hr = pActivate->ActivateObject(
__uuidof(IMFMediaSource),
(void**)&pSource
);
if (SUCCEEDED(hr) && pSource)
{
enumerateCaptureFormats(pSource);
buildLibraryofTypes();
SafeRelease(&pSource);
}//end if (SUCCEEDED(hr) && pSource)
if(FAILED(hr))
{
vd_pFriendlyName = NULL;
DebugPrintOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber);
}
}
return hr;
}
long videoDevice::readInfoOfDevice(IMFActivate *pActivate, unsigned int Num) long videoDevice::readInfoOfDevice(IMFActivate *pActivate, unsigned int Num)
{ {
vd_CurrentNumber = Num; vd_CurrentNumber = Num;
return resetDevice(pActivate); HRESULT hr = E_FAIL;
} vd_CurrentFormats.clear();
if (pActivate)
long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice)
{
IMFActivate **ppDevices = NULL;
UINT32 count;
wchar_t *newFriendlyName = NULL;
HRESULT hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
if (SUCCEEDED(hr))
{
if(count > 0)
{
if(count > vd_CurrentNumber)
{
hr = ppDevices[vd_CurrentNumber]->GetAllocatedString(
MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
&newFriendlyName,
NULL
);
if (SUCCEEDED(hr))
{
if(wcscmp(newFriendlyName, vd_pFriendlyName) != 0)
{
DebugPrintOut(L"VIDEODEVICE %i: Chosen device cannot be found \n", vd_CurrentNumber);
hr = E_INVALIDARG;
pDevice = NULL;
}
else
{
*pDevice = ppDevices[vd_CurrentNumber];
(*pDevice)->AddRef();
}
}
else
{
DebugPrintOut(L"VIDEODEVICE %i: Name of device cannot be gotten \n", vd_CurrentNumber);
}
}
else
{
DebugPrintOut(L"VIDEODEVICE %i: Number of devices more than corrent number of the device \n", vd_CurrentNumber);
hr = E_INVALIDARG;
}
for(UINT32 i = 0; i < count; i++)
{
SafeRelease(&ppDevices[i]);
}
SafeRelease(ppDevices);
}
else
hr = E_FAIL;
}
else
{
DebugPrintOut(L"VIDEODEVICE %i: List of DeviceSources cannot be enumerated \n", vd_CurrentNumber);
}
return hr;
}
long videoDevice::initDevice()
{
HRESULT hr = S_OK;
CoInitialize(NULL);
_ComPtr<IMFAttributes> pAttributes = NULL;
IMFActivate *vd_pActivate = NULL;
hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1);
if (SUCCEEDED(hr))
{
hr = pAttributes->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
);
}
if (SUCCEEDED(hr))
{
hr = checkDevice(pAttributes.Get(), &vd_pActivate);
if (SUCCEEDED(hr) && vd_pActivate)
{ {
SafeRelease(&vd_pSource); SafeRelease(&vd_pSource);
hr = vd_pActivate->ActivateObject( hr = pActivate->ActivateObject(
__uuidof(IMFMediaSource), __uuidof(IMFMediaSource),
(void**)&vd_pSource (void**)&vd_pSource
); );
if (SUCCEEDED(hr)) if (SUCCEEDED(hr) && vd_pSource)
{
}
SafeRelease(&vd_pActivate);
}
else
{ {
DebugPrintOut(L"VIDEODEVICE %i: Device there is not \n", vd_CurrentNumber); enumerateCaptureFormats(vd_pSource);
} buildLibraryofTypes();
} }//end if (SUCCEEDED(hr) && pSource)
else else
{ DebugPrintOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber);
DebugPrintOut(L"VIDEODEVICE %i: The attribute of video cameras cannot be getting \n", vd_CurrentNumber);
} }
return hr; return hr;
} }
...@@ -1906,7 +1685,7 @@ void videoDevice::buildLibraryofTypes() ...@@ -1906,7 +1685,7 @@ void videoDevice::buildLibraryofTypes()
for(; i != vd_CurrentFormats.end(); i++) for(; i != vd_CurrentFormats.end(); i++)
{ {
// Count only supported video formats. // Count only supported video formats.
if( (*i).MF_MT_SUBTYPE == MFVideoFormat_RGB24 ) if( (*i).MF_MT_SUBTYPE == MFVideoFormat_RGB24 || (*i).MF_MT_SUBTYPE == MFVideoFormat_NV12 )
{ {
size = (*i).MF_MT_FRAME_SIZE; size = (*i).MF_MT_FRAME_SIZE;
framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR / (*i).MF_MT_FRAME_RATE_DENOMINATOR; framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR / (*i).MF_MT_FRAME_RATE_DENOMINATOR;
...@@ -2015,9 +1794,7 @@ bool videoDevice::setupDevice(unsigned int id) ...@@ -2015,9 +1794,7 @@ bool videoDevice::setupDevice(unsigned int id)
{ {
if(!vd_IsSetuped) if(!vd_IsSetuped)
{ {
HRESULT hr = initDevice(); HRESULT hr;
if(SUCCEEDED(hr))
{
vd_Width = vd_CurrentFormats[id].width; vd_Width = vd_CurrentFormats[id].width;
vd_Height = vd_CurrentFormats[id].height; vd_Height = vd_CurrentFormats[id].height;
vd_FrameRate = vd_CurrentFormats[id].MF_MT_FRAME_RATE_NUMERATOR / vd_FrameRate = vd_CurrentFormats[id].MF_MT_FRAME_RATE_NUMERATOR /
...@@ -2026,16 +1803,9 @@ bool videoDevice::setupDevice(unsigned int id) ...@@ -2026,16 +1803,9 @@ bool videoDevice::setupDevice(unsigned int id)
vd_IsSetuped = (SUCCEEDED(hr)); vd_IsSetuped = (SUCCEEDED(hr));
if(vd_IsSetuped) if(vd_IsSetuped)
DebugPrintOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber); DebugPrintOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber);
vd_PrevParametrs = getParametrs();
return vd_IsSetuped; return vd_IsSetuped;
} }
else else
{
DebugPrintOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber);
return false;
}
}
else
{ {
DebugPrintOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber); DebugPrintOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber);
return false; return false;
...@@ -2051,11 +1821,6 @@ bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int ideal ...@@ -2051,11 +1821,6 @@ bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int ideal
return setupDevice(id); return setupDevice(id);
} }
wchar_t *videoDevice::getName()
{
return vd_pFriendlyName;
}
videoDevice::~videoDevice(void) videoDevice::~videoDevice(void)
{ {
closeDevice(); closeDevice();
...@@ -2116,73 +1881,60 @@ done: ...@@ -2116,73 +1881,60 @@ done:
return hr; return hr;
} }
videoDevices::videoDevices(void): count(0) videoDevices::videoDevices(void)
{
}
void videoDevices::clearDevices()
{ {
std::vector<videoDevice *>::iterator i = vds_Devices.begin(); DebugPrintOut(L"\n***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****\n\n");
for(; i != vds_Devices.end(); ++i)
delete (*i);
vds_Devices.clear();
} }
videoDevices::~videoDevices(void) videoDevices::~videoDevices(void)
{ {
clearDevices(); DebugPrintOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n");
} }
videoDevice * videoDevices::getDevice(unsigned int i) cv::Ptr<videoDevice> videoDevices::getDevice(unsigned int i, bool fallback)
{ {
if(i >= vds_Devices.size()) static videoDevices instance;
{
return NULL;
}
if(i < 0)
{
return NULL;
}
return vds_Devices[i];
}
long videoDevices::initDevices(IMFAttributes *pAttributes) cv::Ptr<videoDevice> res;
{
clearDevices(); _ComPtr<IMFAttributes> pAttributes = NULL;
if (SUCCEEDED(MFCreateAttributes(pAttributes.GetAddressOf(), 1)) &&
SUCCEEDED(pAttributes->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
)))
{
IMFActivate **ppDevices = NULL; IMFActivate **ppDevices = NULL;
HRESULT hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); UINT32 count;
if (SUCCEEDED(hr)) if (SUCCEEDED(MFEnumDeviceSources(pAttributes.Get(), &ppDevices, &count)))
{ {
if(count > 0) if (count > 0)
{ {
for(UINT32 i = 0; i < count; i++) if (fallback)
i = std::min(std::max(0U, i), count - 1);
for (UINT32 ind = 0; ind < count; ind++)
{
if (ind == i)
{ {
videoDevice *vd = new videoDevice; res = cv::Ptr<videoDevice>(new videoDevice);
vd->readInfoOfDevice(ppDevices[i], i); res->readInfoOfDevice(ppDevices[ind], ind);
vds_Devices.push_back(vd); res->setupDevice(0, 0, 0);
SafeRelease(&ppDevices[i]); if (!res->isDeviceSetup() || !res->isFrameNew())
res.release();
}
SafeRelease(&ppDevices[ind]);
} }
SafeRelease(ppDevices);
} }
else
hr = E_INVALIDARG;
} }
else else
{
DebugPrintOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n"); DebugPrintOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n");
CoTaskMemFree(ppDevices);
} }
return hr;
}
unsigned int videoDevices::getCount() if (res.empty())
{ DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", i);
return (unsigned int)vds_Devices.size(); return res;
}
videoDevices& videoDevices::getInstance()
{
static videoDevices instance;
return instance;
} }
Parametr::Parametr() Parametr::Parametr()
...@@ -2236,733 +1988,347 @@ void MediaType::Clear() ...@@ -2236,733 +1988,347 @@ void MediaType::Clear()
memset(&MF_MT_SUBTYPE, 0, sizeof(GUID)); memset(&MF_MT_SUBTYPE, 0, sizeof(GUID));
} }
videoInput::videoInput(void): MF(Media_Foundation::getInstance()), accessToDevices(false)
{
DebugPrintOut(L"\n***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****\n\n");
updateListOfDevices();
if(!accessToDevices)
DebugPrintOut(L"INITIALIZATION: There is not any suitable video device\n");
} }
void videoInput::updateListOfDevices() /******* Capturing video from camera via Microsoft Media Foundation **********/
class CvCaptureCAM_MSMF : public CvCapture
{ {
HRESULT hr = S_OK; public:
_ComPtr<IMFAttributes> pAttributes = NULL; CvCaptureCAM_MSMF();
CoInitialize(NULL); virtual ~CvCaptureCAM_MSMF();
hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1); virtual bool open( int index );
if (SUCCEEDED(hr)) virtual void close();
{ virtual double getProperty(int) const CV_OVERRIDE;
hr = pAttributes->SetGUID( virtual bool setProperty(int, double) CV_OVERRIDE;
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, virtual bool grabFrame() CV_OVERRIDE;
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID virtual IplImage* retrieveFrame(int) CV_OVERRIDE;
); virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_MSMF; } // Return the type of the capture object: CV_CAP_VFW, etc...
} protected:
if (SUCCEEDED(hr)) double getFramerate(MediaType MT) const;
{ bool configureOutput(unsigned int width, unsigned int height, unsigned int prefFramerate);
videoDevices *vDs = &videoDevices::getInstance(); Media_Foundation& MF;
hr = vDs->initDevices(pAttributes.Get()); _ComPtr<IMFSourceReader> videoFileSource;
} DWORD dwStreamIndex;
if (FAILED(hr)) MediaType captureFormat;
{ _ComPtr<IMFSample> videoSample;
DebugPrintOut(L"MEDIA FOUNDATION: The access to the video cameras denied\n"); IplImage* frame;
} bool isOpened;
};
accessToDevices = (SUCCEEDED(hr));
if(!accessToDevices)
DebugPrintOut(L"UPDATING: There is not any suitable video device\n");
}
videoInput::~videoInput(void) CvCaptureCAM_MSMF::CvCaptureCAM_MSMF():
MF(Media_Foundation::getInstance()),
videoFileSource(NULL),
videoSample(NULL),
frame(NULL),
isOpened(false)
{ {
DebugPrintOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n"); CoInitialize(0);
} }
IMFMediaSource *videoInput::getMediaSource(int deviceID) CvCaptureCAM_MSMF::~CvCaptureCAM_MSMF()
{ {
if(accessToDevices) close();
{ CoUninitialize();
videoDevice * VD = videoDevices::getInstance().getDevice(deviceID);
if(VD)
{
IMFMediaSource *out = VD->getMediaSource();
if(!out)
DebugPrintOut(L"VideoDevice %i: There is not any suitable IMFMediaSource interface\n", deviceID);
return out;
}
}
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
}
return NULL;
} }
bool videoInput::setupDevice(int deviceID, unsigned int id) void CvCaptureCAM_MSMF::close()
{ {
if (deviceID < 0 ) if (isOpened)
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); isOpened = false;
return false; if (videoSample)
} videoSample.Reset();
if(accessToDevices) if (videoFileSource)
{ videoFileSource.Reset();
videoDevices *VDS = &videoDevices::getInstance(); if (frame)
videoDevice * VD = VDS->getDevice(deviceID); cvReleaseImage(&frame);
if(VD)
{
bool out = VD->setupDevice(id);
if(!out)
DebugPrintOut(L"VIDEODEVICE %i: This device cannot be started\n", deviceID);
return out;
}
}
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
}
return false;
}
bool videoInput::setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate)
{
if (deviceID < 0 )
{
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
return false;
}
if(accessToDevices)
{
videoDevices *VDS = &videoDevices::getInstance();
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
{
bool out = VD->setupDevice(w, h, idealFramerate);
if(!out)
DebugPrintOut(L"VIDEODEVICE %i: this device cannot be started\n", deviceID);
return out;
}
}
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n", deviceID);
} }
return false;
} }
MediaType videoInput::getFormat(int deviceID, unsigned int id) bool CvCaptureCAM_MSMF::configureOutput(unsigned int width, unsigned int height, unsigned int prefFramerate)
{ {
if (deviceID < 0) HRESULT hr = S_OK;
{ int dwStreamFallback = -1;
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); MediaType MTFallback;
return MediaType(); int dwStreamBest = -1;
} MediaType MTBest;
if(accessToDevices)
{
videoDevices *VDS = &videoDevices::getInstance();
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
return VD->getFormat(id);
}
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
}
return MediaType();
}
bool videoInput::isDeviceSetup(int deviceID) DWORD dwMediaTypeTest = 0;
{ DWORD dwStreamTest = 0;
if (deviceID < 0) while (SUCCEEDED(hr))
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); _ComPtr<IMFMediaType> pType;
return false; hr = videoFileSource->GetNativeMediaType(dwStreamTest, dwMediaTypeTest, &pType);
} if (hr == MF_E_NO_MORE_TYPES)
if(accessToDevices)
{ {
videoDevices *VDS = &videoDevices::getInstance(); hr = S_OK;
videoDevice * VD = VDS->getDevice(deviceID); ++dwStreamTest;
if(VD) dwMediaTypeTest = 0;
return VD->isDeviceSetup();
} }
else else if (SUCCEEDED(hr))
{ {
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); MediaType MT = FormatReader::Read(pType.Get());
} if (MT.MF_MT_MAJOR_TYPE == MFMediaType_Video)
return false;
}
bool videoInput::isDeviceMediaSource(int deviceID)
{
if (deviceID < 0)
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); if (dwStreamFallback < 0 ||
return false; ((MT.width * MT.height) > (MTFallback.width * MTFallback.height)) ||
} (((MT.width * MT.height) == (MTFallback.width * MTFallback.height)) && getFramerate(MT) > getFramerate(MTFallback) && (prefFramerate == 0 || getFramerate(MT) <= prefFramerate)))
if(accessToDevices)
{ {
videoDevices *VDS = &videoDevices::getInstance(); dwStreamFallback = (int)dwStreamTest;
videoDevice * VD = VDS->getDevice(deviceID); MTFallback = MT;
if(VD)
return VD->isDeviceMediaSource();
} }
else if (MT.width == width && MT.height == height)
{ {
DebugPrintOut(L"Device(s): There is not any suitable video device\n"); if (dwStreamBest < 0 ||
} (getFramerate(MT) > getFramerate(MTBest) && (prefFramerate == 0 || getFramerate(MT) <= prefFramerate)))
return false;
}
bool videoInput::isDeviceRawDataSource(int deviceID)
{
if (deviceID < 0)
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); dwStreamBest = (int)dwStreamTest;
return false; MTBest = MT;
} }
if(accessToDevices)
{
videoDevices *VDS = &videoDevices::getInstance();
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
{
bool isRaw = VD->isDeviceRawDataSource();
return isRaw;
} }
} }
else ++dwMediaTypeTest;
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
} }
return false;
}
bool videoInput::isFrameNew(int deviceID)
{
if (deviceID < 0)
{
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
return false;
} }
if(accessToDevices) if (dwStreamBest >= 0 || dwStreamFallback >= 0)
{ {
if(!isDeviceSetup(deviceID)) // Retrieved stream media type
DWORD tryStream = (DWORD)(dwStreamBest >= 0 ? dwStreamBest : dwStreamFallback);
MediaType tryMT = dwStreamBest >= 0 ? MTBest : MTFallback;
_ComPtr<IMFMediaType> mediaTypeOut;
if (// Set the output media type.
SUCCEEDED(MFCreateMediaType(&mediaTypeOut)) &&
SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)) &&
SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24)) &&
SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) &&
SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1)) &&
SUCCEEDED(MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, tryMT.width, tryMT.height)) &&
SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_DEFAULT_STRIDE, 3 * tryMT.width)))//Assume BGR24 input
{ {
if(isDeviceMediaSource(deviceID)) if (SUCCEEDED(videoFileSource->SetStreamSelection((DWORD)MF_SOURCE_READER_ALL_STREAMS, false)) &&
return false; SUCCEEDED(videoFileSource->SetStreamSelection(tryStream, true)) &&
} SUCCEEDED(videoFileSource->SetCurrentMediaType(tryStream, NULL, mediaTypeOut.Get()))
videoDevices *VDS = &videoDevices::getInstance(); )
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
{ {
return VD->isFrameNew(); dwStreamIndex = tryStream;
} captureFormat = tryMT;
return true;
} }
else else
{ close();
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
}
return false;
}
unsigned int videoInput::getCountFormats(int deviceID) const
{
if (deviceID < 0)
{
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
return 0;
}
if(accessToDevices)
{
videoDevices *VDS = &videoDevices::getInstance();
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
return VD->getCountFormats();
} }
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
} }
return 0; return false;
} }
void videoInput::closeAllDevices() // Initialize camera input
bool CvCaptureCAM_MSMF::open(int _index)
{ {
videoDevices *VDS = &videoDevices::getInstance(); close();
for(unsigned int i = 0; i < VDS->getCount(); i++)
closeDevice(i);
}
void videoInput::setParametrs(int deviceID, CamParametrs parametrs) _ComPtr<IMFAttributes> msAttr = NULL;
{ if (SUCCEEDED(MFCreateAttributes(msAttr.GetAddressOf(), 1)) &&
if (deviceID < 0) SUCCEEDED(msAttr->SetGUID(
{ MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
return; )))
}
if(accessToDevices)
{ {
videoDevices *VDS = &videoDevices::getInstance(); IMFActivate **ppDevices = NULL;
videoDevice *VD = VDS->getDevice(deviceID); UINT32 count;
if(VD) if (SUCCEEDED(MFEnumDeviceSources(msAttr.Get(), &ppDevices, &count)))
VD->setParametrs(parametrs);
}
else
{ {
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); if (count > 0)
}
}
CamParametrs videoInput::getParametrs(int deviceID)
{
CamParametrs out;
if (deviceID < 0)
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); _index = std::min(std::max(0, _index), (int)count - 1);
return out; for (int ind = 0; ind < (int)count; ind++)
}
if(accessToDevices)
{ {
videoDevices *VDS = &videoDevices::getInstance(); if (ind == _index && ppDevices[ind])
videoDevice *VD = VDS->getDevice(deviceID);
if(VD)
out = VD->getParametrs();
}
else
{ {
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); // Set source reader parameters
} _ComPtr<IMFMediaSource> mSrc;
return out; _ComPtr<IMFAttributes> srAttr;
} if (SUCCEEDED(ppDevices[ind]->ActivateObject(__uuidof(IMFMediaSource), (void**)&mSrc)) && mSrc &&
SUCCEEDED(MFCreateAttributes(&srAttr, 10)) &&
void videoInput::closeDevice(int deviceID) SUCCEEDED(srAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)) &&
{ SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, false)) &&
if (deviceID < 0) SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, false)) &&
SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, true)) &&
//ToDo: Enable D3D MF_SOURCE_READER_D3D_MANAGER attribute
SUCCEEDED(MFCreateSourceReaderFromMediaSource(mSrc.Get(), srAttr.Get(), &videoFileSource)))
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); isOpened = true;
return; configureOutput(0, 0, 0);
} }
if(accessToDevices)
{
videoDevices *VDS = &videoDevices::getInstance();
videoDevice *VD = VDS->getDevice(deviceID);
if(VD)
VD->closeDevice();
} }
else SafeRelease(&ppDevices[ind]);
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
} }
}
unsigned int videoInput::getWidth(int deviceID) const
{
if (deviceID < 0)
{
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
return 0;
} }
if(accessToDevices)
{
videoDevices *VDS = &videoDevices::getInstance();
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
return VD->getWidth();
} }
else CoTaskMemFree(ppDevices);
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
} }
return 0;
}
unsigned int videoInput::getHeight(int deviceID) const return isOpened;
{
if (deviceID < 0)
{
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
return 0;
}
if(accessToDevices)
{
videoDevices *VDS = &videoDevices::getInstance();
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
return VD->getHeight();
}
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
}
return 0;
} }
bool CvCaptureCAM_MSMF::grabFrame()
unsigned int videoInput::getFrameRate(int deviceID) const
{ {
if (deviceID < 0) if (isOpened)
{
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
return 0;
}
if(accessToDevices)
{
videoDevice * VD = videoDevices::getInstance().getDevice(deviceID);
if(VD)
return VD->getFrameRate();
}
else
{ {
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); DWORD streamIndex, flags;
} LONGLONG llTimeStamp;
return 0; if (videoSample)
} videoSample.Reset();
HRESULT hr;
const wchar_t *videoInput::getNameVideoDevice(int deviceID) while(SUCCEEDED(hr = videoFileSource->ReadSample(
{ dwStreamIndex, // Stream index.
if (deviceID < 0) 0, // Flags.
&streamIndex, // Receives the actual stream index.
&flags, // Receives status flags.
&llTimeStamp, // Receives the time stamp.
&videoSample // Receives the sample or NULL.
)) &&
streamIndex == dwStreamIndex && !(flags & (MF_SOURCE_READERF_ERROR|MF_SOURCE_READERF_ALLEFFECTSREMOVED|MF_SOURCE_READERF_ENDOFSTREAM)) &&
!videoSample
)
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); if (flags & MF_SOURCE_READERF_STREAMTICK)
return NULL;
}
if(accessToDevices)
{ {
videoDevices *VDS = &videoDevices::getInstance(); DebugPrintOut(L"\tStream tick detected. Retrying to grab the frame\n");
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
return VD->getName();
} }
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
} }
return L"Empty";
}
unsigned int videoInput::listDevices(bool silent) if (SUCCEEDED(hr))
{
int out = 0;
if(accessToDevices)
{ {
videoDevices *VDS = &videoDevices::getInstance(); if (streamIndex != dwStreamIndex)
out = VDS->getCount();
if(!silent) DebugPrintOut(L"\nVIDEOINPUT SPY MODE!\n\n");
if(!silent) DebugPrintOut(L"SETUP: Looking For Capture Devices\n");
for(int i = 0; i < out; i++)
{ {
if(!silent) DebugPrintOut(L"SETUP: %i) %s \n",i, getNameVideoDevice(i)); DebugPrintOut(L"\tWrong stream readed. Abort capturing\n");
} close();
if(!silent) DebugPrintOut(L"SETUP: %i Device(s) found\n\n", out);
} }
else else if (flags & MF_SOURCE_READERF_ERROR)
{ {
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); DebugPrintOut(L"\tStream reading error. Abort capturing\n");
close();
} }
return out; else if (flags & MF_SOURCE_READERF_ALLEFFECTSREMOVED)
}
videoInput& videoInput::getInstance()
{
static videoInput instance;
return instance;
}
bool videoInput::isDevicesAcceable()
{
return accessToDevices;
}
#ifdef _DEBUG
void videoInput::setVerbose(bool state)
{
DPO *dpo = &DPO::getInstance();
dpo->setVerbose(state);
}
#endif
void videoInput::setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *))
{
if (deviceID < 0)
{ {
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); DebugPrintOut(L"\tStream decoding error. Abort capturing\n");
return; close();
} }
if(accessToDevices) else if (flags & MF_SOURCE_READERF_ENDOFSTREAM)
{
if(func)
{ {
videoDevices *VDS = &videoDevices::getInstance(); DebugPrintOut(L"\tEnd of stream detected\n");
videoDevice * VD = VDS->getDevice(deviceID);
if(VD)
VD->setEmergencyStopEvent(userData, func);
}
} }
else else
{ {
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); if (flags & MF_SOURCE_READERF_NEWSTREAM)
}
}
bool videoInput::getPixels(int deviceID, unsigned char * dstBuffer, bool flipRedAndBlue, bool flipImage)
{
bool success = false;
if (deviceID < 0)
{
DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
return success;
}
if(accessToDevices)
{
bool isRaw = isDeviceRawDataSource(deviceID);
if(isRaw)
{
videoDevice *VD = videoDevices::getInstance().getDevice(deviceID);
RawImage *RIOut = VD->getRawImageOut();
if(RIOut)
{
const unsigned int bytes = 3;
const unsigned int height = VD->getHeight();
const unsigned int width = VD->getWidth();
const unsigned int size = bytes * width * height;
if(size == RIOut->getSize())
{ {
processPixels(RIOut->getpPixels(), dstBuffer, width, height, bytes, flipRedAndBlue, flipImage); DebugPrintOut(L"\tNew stream detected\n");
success = true;
} }
else if (flags & MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED)
{ {
DebugPrintOut(L"ERROR: GetPixels() - bufferSizes do not match!\n"); DebugPrintOut(L"\tStream native media type changed\n");
}
} }
else if (flags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)
{ {
DebugPrintOut(L"ERROR: GetPixels() - Unable to grab frame for device %i\n", deviceID); DebugPrintOut(L"\tStream current media type changed\n");
}
} }
else return true;
{
DebugPrintOut(L"ERROR: GetPixels() - Not raw data source device %i\n", deviceID);
} }
} }
else
{
DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
} }
return success; return false;
} }
void videoInput::processPixels(unsigned char * src, unsigned char * dst, unsigned int width, IplImage* CvCaptureCAM_MSMF::retrieveFrame(int)
unsigned int height, unsigned int bpp, bool bRGB, bool bFlip)
{ {
unsigned int widthInBytes = width * bpp; unsigned int width = captureFormat.width;
unsigned int numBytes = widthInBytes * height; unsigned int height = captureFormat.height;
int *dstInt, *srcInt; unsigned int bytes = 3; //Suppose output format is BGR24
if(!bRGB) if (!frame || (int)width != frame->width || (int)height != frame->height)
{
if(bFlip)
{
for(unsigned int y = 0; y < height; y++)
{
dstInt = (int *)(dst + (y * widthInBytes));
srcInt = (int *)(src + ( (height -y -1) * widthInBytes));
memcpy(dstInt, srcInt, widthInBytes);
}
}
else
{ {
memcpy(dst, src, numBytes); if (frame)
} cvReleaseImage(&frame);
frame = cvCreateImage(cvSize(width, height), 8, bytes);
} }
else
{ unsigned int size = bytes * width * height;
if(bFlip) DWORD bcnt;
{ if (videoSample && SUCCEEDED(videoSample->GetBufferCount(&bcnt)) && bcnt > 0)
unsigned int x = 0;
unsigned int y = (height - 1) * widthInBytes;
src += y;
for(unsigned int i = 0; i < numBytes; i+=3)
{ {
if(x >= width) _ComPtr<IMFMediaBuffer> buf = NULL;
if (SUCCEEDED(videoSample->GetBufferByIndex(0, &buf)))
{ {
x = 0; DWORD maxsize, cursize;
src -= widthInBytes*2; BYTE* ptr = NULL;
} if (SUCCEEDED(buf->Lock(&ptr, &maxsize, &cursize)))
*dst = *(src+2);
dst++;
*dst = *(src+1);
dst++;
*dst = *src;
dst++;
src+=3;
x++;
}
}
else
{ {
for(unsigned int i = 0; i < numBytes; i+=3) if ((unsigned int)cursize == size)
{ {
*dst = *(src+2); memcpy(frame->imageData, ptr, size);
dst++; buf->Unlock();
*dst = *(src+1); return frame;
dst++;
*dst = *src;
dst++;
src+=3;
} }
buf->Unlock();
} }
} }
}
}
/******* Capturing video from camera via Microsoft Media Foundation **********/
class CvCaptureCAM_MSMF : public CvCapture
{
public:
CvCaptureCAM_MSMF();
virtual ~CvCaptureCAM_MSMF();
virtual bool open( int index );
virtual void close();
virtual double getProperty(int) const CV_OVERRIDE;
virtual bool setProperty(int, double) CV_OVERRIDE;
virtual bool grabFrame() CV_OVERRIDE;
virtual IplImage* retrieveFrame(int) CV_OVERRIDE;
virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_MSMF; } // Return the type of the capture object: CV_CAP_VFW, etc...
protected:
void init();
int index, width, height, fourcc;
IplImage* frame;
videoInput VI;
};
#ifdef _DEBUG
struct SuppressVideoInputMessages
{
SuppressVideoInputMessages() { videoInput::setVerbose(true); }
};
static SuppressVideoInputMessages do_it;
#endif
CvCaptureCAM_MSMF::CvCaptureCAM_MSMF():
index(-1),
width(-1),
height(-1),
fourcc(-1),
frame(NULL),
VI(videoInput::getInstance())
{
CoInitialize(0);
}
CvCaptureCAM_MSMF::~CvCaptureCAM_MSMF()
{
close();
CoUninitialize();
}
void CvCaptureCAM_MSMF::close()
{
if( index >= 0 )
{
VI.closeDevice(index);
index = -1;
cvReleaseImage(&frame);
} }
width = height = -1;
}
// Initialize camera input
bool CvCaptureCAM_MSMF::open( int _index )
{
int try_index = _index;
int devices = 0;
close();
devices = VI.listDevices(true);
if (devices == 0)
return false;
try_index = try_index < 0 ? 0 : (try_index > devices-1 ? devices-1 : try_index);
VI.setupDevice(try_index, 0, 0, 0); // With maximum frame size.
if( !VI.isFrameNew(try_index) )
return false;
index = try_index;
return true;
}
bool CvCaptureCAM_MSMF::grabFrame() return NULL;
{
while (VI.isDeviceSetup(index) && !VI.isFrameNew(index))
Sleep(1);
return VI.isDeviceSetup(index);
} }
IplImage* CvCaptureCAM_MSMF::retrieveFrame(int) double CvCaptureCAM_MSMF::getFramerate(MediaType MT) const
{ {
const int w = (int)VI.getWidth(index); if (MT.MF_MT_SUBTYPE == MFVideoFormat_MP43) //Unable to estimate FPS for MP43
const int h = (int)VI.getHeight(index); return 0;
if( !frame || w != frame->width || h != frame->height ) return MT.MF_MT_FRAME_RATE_DENOMINATOR != 0 ? ((double)MT.MF_MT_FRAME_RATE_NUMERATOR) / ((double)MT.MF_MT_FRAME_RATE_DENOMINATOR) : 0;
{
if (frame)
cvReleaseImage( &frame );
frame = cvCreateImage( cvSize(w,h), 8, 3 );
}
VI.getPixels( index, (uchar*)frame->imageData, false, true );
return frame;
} }
double CvCaptureCAM_MSMF::getProperty( int property_id ) const double CvCaptureCAM_MSMF::getProperty( int property_id ) const
{ {
// image format proprrties // image format properties
switch( property_id ) if (isOpened)
switch (property_id)
{ {
case CV_CAP_PROP_FRAME_WIDTH: case CV_CAP_PROP_FRAME_WIDTH:
return VI.getWidth(index); return captureFormat.width;
case CV_CAP_PROP_FRAME_HEIGHT: case CV_CAP_PROP_FRAME_HEIGHT:
return VI.getHeight(index); return captureFormat.height;
case CV_CAP_PROP_FOURCC:
return captureFormat.MF_MT_SUBTYPE.Data1;
case CV_CAP_PROP_FPS: case CV_CAP_PROP_FPS:
return VI.getFrameRate(index); return getFramerate(captureFormat);
default:
break;
} }
return 0;
return -1;
} }
bool CvCaptureCAM_MSMF::setProperty( int property_id, double value ) bool CvCaptureCAM_MSMF::setProperty( int property_id, double value )
{ {
// image capture properties // image capture properties
unsigned int fps = 0; if (isOpened)
bool handled = false; {
switch( property_id ) unsigned int width = captureFormat.width;
unsigned int height = captureFormat.height;
unsigned int fps = getProperty(CV_CAP_PROP_FPS);
switch (property_id)
{ {
case CV_CAP_PROP_FRAME_WIDTH: case CV_CAP_PROP_FRAME_WIDTH:
width = cvRound(value); width = cvRound(value);
fps = VI.getFrameRate(index);
handled = true;
break; break;
case CV_CAP_PROP_FRAME_HEIGHT: case CV_CAP_PROP_FRAME_HEIGHT:
height = cvRound(value); height = cvRound(value);
fps = VI.getFrameRate(index);
handled = true;
break; break;
case CV_CAP_PROP_FPS: case CV_CAP_PROP_FPS:
width = (int)VI.getHeight(index);
height = (int)VI.getWidth(index);
fps = cvRound(value); fps = cvRound(value);
break; break;
} }
if ( handled ) { if (width > 0 && height > 0 && fps >= 0)
if( width > 0 && height > 0 )
{
if( (width != (int)VI.getWidth(index) || height != (int)VI.getHeight(index) || fps != VI.getFrameRate(index))
&& VI.isDeviceSetup(index))//|| fourcc != VI.getFourcc(index) )
{ {
VI.closeDevice(index); if (width != captureFormat.width || height != captureFormat.height || fps != getFramerate(captureFormat))
VI.setupDevice(index, width, height, fps); return configureOutput(width, height, fps);
} else
width = height = -1;
return VI.isDeviceSetup(index);
}
return true; return true;
} }
}
return false; return false;
} }
...@@ -3008,7 +2374,6 @@ CvCaptureFile_MSMF::~CvCaptureFile_MSMF() ...@@ -3008,7 +2374,6 @@ CvCaptureFile_MSMF::~CvCaptureFile_MSMF()
bool CvCaptureFile_MSMF::open(const char* filename) bool CvCaptureFile_MSMF::open(const char* filename)
{ {
if (isOpened)
close(); close();
if (!filename) if (!filename)
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment