Merge pull request #1263 from abidrahmank:pyCLAHE_24
[profile/ivi/opencv.git] / modules / highgui / src / cap_msmf.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 #include "precomp.hpp"
42 #if (defined WIN32 || defined _WIN32) && defined HAVE_MSMF
43 /*
44    Media Foundation-based Video Capturing module is based on
45    videoInput library by Evgeny Pereguda:
46    http://www.codeproject.com/Articles/559437/Capturing-of-video-from-web-camera-on-Windows-7-an
47    Originaly licensed under The Code Project Open License (CPOL) 1.02:
48    http://www.codeproject.com/info/cpol10.aspx
49 */
50 #include <windows.h>
51 #include <guiddef.h>
52 #include <mfidl.h>
53 #include <Mfapi.h>
54 #include <mfplay.h>
55 #include <mfobjects.h>
56 #include <strsafe.h>
57 #include <Mfreadwrite.h>
58 #include <new>
59 #include <map>
60 #include <vector>
61 #include <string>
62 #include <stdio.h>
63 #include <stdarg.h>
64 #include <string.h>
65
66 #pragma warning(disable:4503)
67 #pragma comment(lib, "mfplat")
68 #pragma comment(lib, "mf")
69 #pragma comment(lib, "mfuuid")
70 #pragma comment(lib, "Strmiids")
71 #pragma comment(lib, "Mfreadwrite")
72 #pragma comment(lib, "MinCore_Downlevel")
73
74 // for ComPtr usage
75 #include <wrl/client.h>
76 using namespace Microsoft::WRL;
77
78 struct IMFMediaType;
79 struct IMFActivate;
80 struct IMFMediaSource;
81 struct IMFAttributes;
82
83 namespace
84 {
85
86 template <class T> void SafeRelease(T **ppT)
87 {
88     if (*ppT)
89     {
90         (*ppT)->Release();
91         *ppT = NULL;
92     }
93 }
94
95 /// Class for printing info into consol
96 class DebugPrintOut
97 {
98 public:
99     ~DebugPrintOut(void);
100     static DebugPrintOut& getInstance();
101     void printOut(const wchar_t *format, ...);
102     void setVerbose(bool state);
103     bool verbose;
104 private:
105     DebugPrintOut(void);
106 };
107
108 // Structure for collecting info about types of video, which are supported by current video device
109 struct MediaType
110 {
111     unsigned int MF_MT_FRAME_SIZE;
112     unsigned int height;
113     unsigned int width;
114     unsigned int MF_MT_YUV_MATRIX;
115     unsigned int MF_MT_VIDEO_LIGHTING;
116     int MF_MT_DEFAULT_STRIDE; // stride is negative if image is bottom-up
117     unsigned int MF_MT_VIDEO_CHROMA_SITING;
118     GUID MF_MT_AM_FORMAT_TYPE;
119     wchar_t *pMF_MT_AM_FORMAT_TYPEName;
120     unsigned int MF_MT_FIXED_SIZE_SAMPLES;
121     unsigned int MF_MT_VIDEO_NOMINAL_RANGE;
122     unsigned int MF_MT_FRAME_RATE_NUMERATOR;
123     unsigned int MF_MT_FRAME_RATE_DENOMINATOR;
124     unsigned int MF_MT_PIXEL_ASPECT_RATIO;
125     unsigned int MF_MT_PIXEL_ASPECT_RATIO_low;
126     unsigned int MF_MT_ALL_SAMPLES_INDEPENDENT;
127     unsigned int MF_MT_FRAME_RATE_RANGE_MIN;
128     unsigned int MF_MT_FRAME_RATE_RANGE_MIN_low;
129     unsigned int MF_MT_SAMPLE_SIZE;
130     unsigned int MF_MT_VIDEO_PRIMARIES;
131     unsigned int MF_MT_INTERLACE_MODE;
132     unsigned int MF_MT_FRAME_RATE_RANGE_MAX;
133     unsigned int MF_MT_FRAME_RATE_RANGE_MAX_low;
134     GUID MF_MT_MAJOR_TYPE;
135     GUID MF_MT_SUBTYPE;
136     wchar_t *pMF_MT_MAJOR_TYPEName;
137     wchar_t *pMF_MT_SUBTYPEName;
138     MediaType();
139     ~MediaType();
140     void Clear();
141 };
142
143 /// Class for parsing info from IMFMediaType into the local MediaType
144 class FormatReader
145 {
146 public:
147     static MediaType Read(IMFMediaType *pType);
148     ~FormatReader(void);
149 private:
150     FormatReader(void);
151 };
152
153 DWORD WINAPI MainThreadFunction( LPVOID lpParam );
154 typedef void(*emergensyStopEventCallback)(int, void *);
155
156 class RawImage
157 {
158 public:
159     ~RawImage(void);
160     // Function of creation of the instance of the class
161     static long CreateInstance(RawImage **ppRImage,unsigned int size);
162     void setCopy(const BYTE * pSampleBuffer);
163     void fastCopy(const BYTE * pSampleBuffer);
164     unsigned char * getpPixels();
165     bool isNew();
166     unsigned int getSize();
167 private:
168     bool ri_new;
169     unsigned int ri_size;
170     unsigned char *ri_pixels;
171     RawImage(unsigned int size);
172 };
173
174 // Class for grabbing image from video stream
175 class ImageGrabber : public IMFSampleGrabberSinkCallback
176 {
177 public:
178     ~ImageGrabber(void);
179     HRESULT initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat);
180     HRESULT startGrabbing(void);
181     void pauseGrabbing();
182     void resumeGrabbing();
183     void stopGrabbing();
184     RawImage *getRawImage();
185     // Function of creation of the instance of the class
186     static HRESULT CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, bool synchronous = false);
187
188     const HANDLE ig_hFrameReady;
189     const HANDLE ig_hFrameGrabbed;
190     const HANDLE ig_hFinish;
191
192 private:
193     bool ig_RIE;
194     bool ig_Close;
195     bool ig_Synchronous;
196     long m_cRef;
197     unsigned int ig_DeviceID;
198     IMFMediaSource *ig_pSource;
199     IMFMediaSession *ig_pSession;
200     IMFTopology *ig_pTopology;
201     RawImage *ig_RIFirst;
202     RawImage *ig_RISecond;
203     RawImage *ig_RIOut;
204     ImageGrabber(unsigned int deviceID, bool synchronous);
205     HRESULT CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo);
206     HRESULT AddSourceNode(IMFTopology *pTopology, IMFMediaSource *pSource,
207         IMFPresentationDescriptor *pPD, IMFStreamDescriptor *pSD, IMFTopologyNode **ppNode);
208     HRESULT AddOutputNode(IMFTopology *pTopology, IMFActivate *pActivate, DWORD dwId, IMFTopologyNode **ppNode);
209     // IUnknown methods
210     STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
211     STDMETHODIMP_(ULONG) AddRef();
212     STDMETHODIMP_(ULONG) Release();
213     // IMFClockStateSink methods
214     STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset);
215     STDMETHODIMP OnClockStop(MFTIME hnsSystemTime);
216     STDMETHODIMP OnClockPause(MFTIME hnsSystemTime);
217     STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime);
218     STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate);
219     // IMFSampleGrabberSinkCallback methods
220     STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock);
221     STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags,
222         LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer,
223         DWORD dwSampleSize);
224     STDMETHODIMP OnShutdown();
225 };
226
227 /// Class for controlling of thread of the grabbing raw data from video device
228 class ImageGrabberThread
229 {
230     friend DWORD WINAPI MainThreadFunction( LPVOID lpParam );
231 public:
232     ~ImageGrabberThread(void);
233     static HRESULT CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious = false);
234     void start();
235     void stop();
236     void setEmergencyStopEvent(void *userData, void(*func)(int, void *));
237     ImageGrabber *getImageGrabber();
238 protected:
239     virtual void run();
240 private:
241     ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious);
242     HANDLE igt_Handle;
243     DWORD   igt_ThreadIdArray;
244     ImageGrabber *igt_pImageGrabber;
245     emergensyStopEventCallback igt_func;
246     void *igt_userData;
247     bool igt_stop;
248     unsigned int igt_DeviceID;
249 };
250
251 // Structure for collecting info about one parametr of current video device
252 struct Parametr
253 {
254     long CurrentValue;
255     long Min;
256     long Max;
257     long Step;
258     long Default;
259     long Flag;
260     Parametr();
261 };
262
263 // Structure for collecting info about 17 parametrs of current video device
264 struct CamParametrs
265 {
266         Parametr Brightness;
267         Parametr Contrast;
268         Parametr Hue;
269         Parametr Saturation;
270         Parametr Sharpness;
271         Parametr Gamma;
272         Parametr ColorEnable;
273         Parametr WhiteBalance;
274         Parametr BacklightCompensation;
275         Parametr Gain;
276         Parametr Pan;
277         Parametr Tilt;
278         Parametr Roll;
279         Parametr Zoom;
280         Parametr Exposure;
281         Parametr Iris;
282         Parametr Focus;
283 };
284
285 typedef std::wstring String;
286 typedef std::vector<int> vectorNum;
287 typedef std::map<String, vectorNum> SUBTYPEMap;
288 typedef std::map<UINT64, SUBTYPEMap> FrameRateMap;
289 typedef void(*emergensyStopEventCallback)(int, void *);
290
291 /// Class for controlling of video device
292 class videoDevice
293 {
294 public:
295     videoDevice(void);
296     ~videoDevice(void);
297     void closeDevice();
298     CamParametrs getParametrs();
299     void setParametrs(CamParametrs parametrs);
300     void setEmergencyStopEvent(void *userData, void(*func)(int, void *));
301     long readInfoOfDevice(IMFActivate *pActivate, unsigned int Num);
302     wchar_t *getName();
303     int getCountFormats();
304     unsigned int getWidth();
305     unsigned int getHeight();
306     MediaType getFormat(unsigned int id);
307     bool setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate = 0);
308     bool setupDevice(unsigned int id);
309     bool isDeviceSetup();
310     bool isDeviceMediaSource();
311     bool isDeviceRawDataSource();
312     bool isFrameNew();
313     IMFMediaSource *getMediaSource();
314     RawImage *getRawImageOut();
315 private:
316     enum typeLock
317     {
318         MediaSourceLock,
319         RawDataLock,
320         OpenLock
321     } vd_LockOut;
322     wchar_t *vd_pFriendlyName;
323     ImageGrabberThread *vd_pImGrTh;
324     CamParametrs vd_PrevParametrs;
325     unsigned int vd_Width;
326     unsigned int vd_Height;
327     unsigned int vd_CurrentNumber;
328     bool vd_IsSetuped;
329     std::map<UINT64, FrameRateMap> vd_CaptureFormats;
330     std::vector<MediaType> vd_CurrentFormats;
331     IMFMediaSource *vd_pSource;
332     emergensyStopEventCallback vd_func;
333     void *vd_userData;
334     HRESULT enumerateCaptureFormats(IMFMediaSource *pSource);
335     long setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex);
336     void buildLibraryofTypes();
337     int findType(unsigned int size, unsigned int frameRate = 0);
338     long resetDevice(IMFActivate *pActivate);
339     long initDevice();
340     long checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice);
341 };
342
343 /// Class for managing of list of video devices
344 class videoDevices
345 {
346 public:
347     ~videoDevices(void);
348     long initDevices(IMFAttributes *pAttributes);
349     static videoDevices& getInstance();
350     videoDevice *getDevice(unsigned int i);
351     unsigned int getCount();
352     void clearDevices();
353 private:
354     UINT32 count;
355     std::vector<videoDevice *> vds_Devices;
356     videoDevices(void);
357 };
358
359 // Class for creating of Media Foundation context
360 class Media_Foundation
361 {
362 public:
363     virtual ~Media_Foundation(void);
364     static Media_Foundation& getInstance();
365     bool buildListOfDevices();
366 private:
367     Media_Foundation(void);
368 };
369
370 /// The only visiable class for controlling of video devices in format singelton
371 class videoInput
372 {
373 public:
374     virtual ~videoInput(void);
375     // Getting of static instance of videoInput class
376     static videoInput& getInstance();
377     // Closing video device with deviceID
378     void closeDevice(int deviceID);
379     // Setting callback function for emergency events(for example: removing video device with deviceID) with userData
380     void setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *));
381     // Closing all devices
382     void closeAllDevices();
383     // Getting of parametrs of video device with deviceID
384     CamParametrs getParametrs(int deviceID);
385     // Setting of parametrs of video device with deviceID
386     void setParametrs(int deviceID, CamParametrs parametrs);
387     // Getting numbers of existence videodevices with listing in consol
388     unsigned int listDevices(bool silent = false);
389     // Getting numbers of formats, which are supported by videodevice with deviceID
390     unsigned int getCountFormats(int deviceID);
391     // Getting width of image, which is getting from videodevice with deviceID
392     unsigned int getWidth(int deviceID);
393     // Getting height of image, which is getting from videodevice with deviceID
394     unsigned int getHeight(int deviceID);
395     // Getting name of videodevice with deviceID
396     wchar_t *getNameVideoDevice(int deviceID);
397     // Getting interface MediaSource for Media Foundation from videodevice with deviceID
398     IMFMediaSource *getMediaSource(int deviceID);
399     // Getting format with id, which is supported by videodevice with deviceID
400     MediaType getFormat(int deviceID, int unsigned id);
401     // Checking of existence of the suitable video devices
402     bool isDevicesAcceable();
403     // Checking of using the videodevice with deviceID
404     bool isDeviceSetup(int deviceID);
405     // Checking of using MediaSource from videodevice with deviceID
406     bool isDeviceMediaSource(int deviceID);
407     // Checking of using Raw Data of pixels from videodevice with deviceID
408     bool isDeviceRawDataSource(int deviceID);
409     // Setting of the state of outprinting info in console
410     static void setVerbose(bool state);
411     // Initialization of video device with deviceID by media type with id
412     bool setupDevice(int deviceID, unsigned int id = 0);
413     // Initialization of video device with deviceID by wisth w, height h and fps idealFramerate
414     bool setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate = 30);
415     // Checking of recivig of new frame from video device with deviceID
416     bool isFrameNew(int deviceID);
417     // Writing of Raw Data pixels from video device with deviceID with correction of RedAndBlue flipping flipRedAndBlue and vertical flipping flipImage
418     bool getPixels(int deviceID, unsigned char * pixels, bool flipRedAndBlue = false, bool flipImage = false);
419     static void processPixels(unsigned char * src, unsigned char * dst, unsigned int width, unsigned int height, unsigned int bpp, bool bRGB, bool bFlip);
420 private:
421     bool accessToDevices;
422     videoInput(void);
423     void updateListOfDevices();
424 };
425
426 DebugPrintOut::DebugPrintOut(void):verbose(true)
427 {
428 }
429
430 DebugPrintOut::~DebugPrintOut(void)
431 {
432 }
433
434 DebugPrintOut& DebugPrintOut::getInstance()
435 {
436     static DebugPrintOut instance;
437     return instance;
438 }
439
440 void DebugPrintOut::printOut(const wchar_t *format, ...)
441 {
442     if(verbose)
443     {
444         int i = 0;
445         wchar_t *p = NULL;
446         va_list args;
447         va_start(args, format);
448         if(wcscmp(format, L"%i"))
449         {
450             i = va_arg (args, int);
451         }
452         if(wcscmp(format, L"%s"))
453         {
454             p = va_arg (args, wchar_t *);
455         }
456         wprintf(format, i,p);
457         va_end (args);
458     }
459 }
460
461 void DebugPrintOut::setVerbose(bool state)
462 {
463     verbose = state;
464 }
465
466 LPCWSTR GetGUIDNameConstNew(const GUID& guid);
467 HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz);
468 HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index);
469 HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, MediaType &out);
470
471 unsigned int *GetParametr(GUID guid, MediaType &out)
472 {
473     if(guid == MF_MT_YUV_MATRIX)
474         return &(out.MF_MT_YUV_MATRIX);
475     if(guid == MF_MT_VIDEO_LIGHTING)
476         return &(out.MF_MT_VIDEO_LIGHTING);
477     if(guid == MF_MT_DEFAULT_STRIDE)
478         return (unsigned int*)&(out.MF_MT_DEFAULT_STRIDE);
479     if(guid == MF_MT_VIDEO_CHROMA_SITING)
480         return &(out.MF_MT_VIDEO_CHROMA_SITING);
481     if(guid == MF_MT_VIDEO_NOMINAL_RANGE)
482         return &(out.MF_MT_VIDEO_NOMINAL_RANGE);
483     if(guid == MF_MT_ALL_SAMPLES_INDEPENDENT)
484         return &(out.MF_MT_ALL_SAMPLES_INDEPENDENT);
485     if(guid == MF_MT_FIXED_SIZE_SAMPLES)
486         return &(out.MF_MT_FIXED_SIZE_SAMPLES);
487     if(guid == MF_MT_SAMPLE_SIZE)
488         return &(out.MF_MT_SAMPLE_SIZE);
489     if(guid == MF_MT_VIDEO_PRIMARIES)
490         return &(out.MF_MT_VIDEO_PRIMARIES);
491     if(guid == MF_MT_INTERLACE_MODE)
492         return &(out.MF_MT_INTERLACE_MODE);
493     return NULL;
494 }
495
496 HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType &out)
497 {
498     WCHAR *pGuidName = NULL;
499     WCHAR *pGuidValName = NULL;
500     GUID guid = { 0 };
501     PROPVARIANT var;
502     PropVariantInit(&var);
503     HRESULT hr = pAttr->GetItemByIndex(index, &guid, &var);
504     if (FAILED(hr))
505     {
506         goto done;
507     }
508     hr = GetGUIDNameNew(guid, &pGuidName);
509     if (FAILED(hr))
510     {
511         goto done;
512     }
513     hr = SpecialCaseAttributeValueNew(guid, var, out);
514     unsigned int *p;
515     if (FAILED(hr))
516     {
517         goto done;
518     }
519     if (hr == S_FALSE)
520     {
521         switch (var.vt)
522         {
523         case VT_UI4:
524             p = GetParametr(guid, out);
525             if(p)
526             {
527                 *p = var.ulVal;
528             }
529             break;
530         case VT_UI8:
531             break;
532         case VT_R8:
533             break;
534         case VT_CLSID:
535             if(guid == MF_MT_AM_FORMAT_TYPE)
536             {
537                 hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
538                 if (SUCCEEDED(hr))
539                 {
540                     out.MF_MT_AM_FORMAT_TYPE = MF_MT_AM_FORMAT_TYPE;
541                     out.pMF_MT_AM_FORMAT_TYPEName = pGuidValName;
542                     pGuidValName = NULL;
543                 }
544             }
545             if(guid == MF_MT_MAJOR_TYPE)
546             {
547                 hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
548                 if (SUCCEEDED(hr))
549                 {
550                     out.MF_MT_MAJOR_TYPE = MF_MT_MAJOR_TYPE;
551                     out.pMF_MT_MAJOR_TYPEName = pGuidValName;
552                     pGuidValName = NULL;
553                 }
554             }
555             if(guid == MF_MT_SUBTYPE)
556             {
557                 hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
558                 if (SUCCEEDED(hr))
559                 {
560                     out.MF_MT_SUBTYPE = MF_MT_SUBTYPE;
561                     out.pMF_MT_SUBTYPEName = pGuidValName;
562                     pGuidValName = NULL;
563                 }
564             }
565             break;
566         case VT_LPWSTR:
567             break;
568         case VT_VECTOR | VT_UI1:
569             break;
570         case VT_UNKNOWN:
571             break;
572         default:
573             break;
574         }
575     }
576 done:
577     CoTaskMemFree(pGuidName);
578     CoTaskMemFree(pGuidValName);
579     PropVariantClear(&var);
580     return hr;
581 }
582
583 HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz)
584 {
585     HRESULT hr = S_OK;
586     WCHAR *pName = NULL;
587     LPCWSTR pcwsz = GetGUIDNameConstNew(guid);
588     if (pcwsz)
589     {
590         size_t cchLength = 0;
591         hr = StringCchLengthW(pcwsz, STRSAFE_MAX_CCH, &cchLength);
592         if (FAILED(hr))
593         {
594             goto done;
595         }
596         pName = (WCHAR*)CoTaskMemAlloc((cchLength + 1) * sizeof(WCHAR));
597         if (pName == NULL)
598         {
599             hr = E_OUTOFMEMORY;
600             goto done;
601         }
602         hr = StringCchCopyW(pName, cchLength + 1, pcwsz);
603         if (FAILED(hr))
604         {
605             goto done;
606         }
607     }
608     else
609     {
610         hr = StringFromCLSID(guid, &pName);
611     }
612 done:
613     if (FAILED(hr))
614     {
615         *ppwsz = NULL;
616         CoTaskMemFree(pName);
617     }
618     else
619     {
620         *ppwsz = pName;
621     }
622     return hr;
623 }
624
625 void LogUINT32AsUINT64New(const PROPVARIANT& var, UINT32 &uHigh, UINT32 &uLow)
626 {
627     Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow);
628 }
629
630 float OffsetToFloatNew(const MFOffset& offset)
631 {
632     return offset.value + (static_cast<float>(offset.fract) / 65536.0f);
633 }
634
635 HRESULT LogVideoAreaNew(const PROPVARIANT& var)
636 {
637     if (var.caub.cElems < sizeof(MFVideoArea))
638     {
639         return S_OK;
640     }
641     return S_OK;
642 }
643
644 HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, MediaType &out)
645 {
646     if (guid == MF_MT_DEFAULT_STRIDE)
647     {
648         out.MF_MT_DEFAULT_STRIDE = var.intVal;
649     } else
650     if (guid == MF_MT_FRAME_SIZE)
651     {
652         UINT32 uHigh = 0, uLow = 0;
653         LogUINT32AsUINT64New(var, uHigh, uLow);
654         out.width = uHigh;
655         out.height = uLow;
656         out.MF_MT_FRAME_SIZE = out.width * out.height;
657     }
658     else
659     if (guid == MF_MT_FRAME_RATE)
660     {
661         UINT32 uHigh = 0, uLow = 0;
662         LogUINT32AsUINT64New(var, uHigh, uLow);
663         out.MF_MT_FRAME_RATE_NUMERATOR = uHigh;
664         out.MF_MT_FRAME_RATE_DENOMINATOR = uLow;
665     }
666     else
667     if (guid == MF_MT_FRAME_RATE_RANGE_MAX)
668     {
669         UINT32 uHigh = 0, uLow = 0;
670         LogUINT32AsUINT64New(var, uHigh, uLow);
671         out.MF_MT_FRAME_RATE_RANGE_MAX = uHigh;
672         out.MF_MT_FRAME_RATE_RANGE_MAX_low = uLow;
673     }
674     else
675     if (guid == MF_MT_FRAME_RATE_RANGE_MIN)
676     {
677         UINT32 uHigh = 0, uLow = 0;
678         LogUINT32AsUINT64New(var, uHigh, uLow);
679         out.MF_MT_FRAME_RATE_RANGE_MIN = uHigh;
680         out.MF_MT_FRAME_RATE_RANGE_MIN_low = uLow;
681     }
682     else
683     if (guid == MF_MT_PIXEL_ASPECT_RATIO)
684     {
685         UINT32 uHigh = 0, uLow = 0;
686         LogUINT32AsUINT64New(var, uHigh, uLow);
687         out.MF_MT_PIXEL_ASPECT_RATIO = uHigh;
688         out.MF_MT_PIXEL_ASPECT_RATIO_low = uLow;
689     }
690     else
691     {
692         return S_FALSE;
693     }
694     return S_OK;
695 }
696
697 #ifndef IF_EQUAL_RETURN
698 #define IF_EQUAL_RETURN(param, val) if(val == param) return L#val
699 #endif
700
701 LPCWSTR GetGUIDNameConstNew(const GUID& guid)
702 {
703     IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE);
704     IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE);
705     IF_EQUAL_RETURN(guid, MF_MT_SUBTYPE);
706     IF_EQUAL_RETURN(guid, MF_MT_ALL_SAMPLES_INDEPENDENT);
707     IF_EQUAL_RETURN(guid, MF_MT_FIXED_SIZE_SAMPLES);
708     IF_EQUAL_RETURN(guid, MF_MT_COMPRESSED);
709     IF_EQUAL_RETURN(guid, MF_MT_SAMPLE_SIZE);
710     IF_EQUAL_RETURN(guid, MF_MT_WRAPPED_TYPE);
711     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_NUM_CHANNELS);
712     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_SECOND);
713     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND);
714     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_AVG_BYTES_PER_SECOND);
715     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BLOCK_ALIGNMENT);
716     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BITS_PER_SAMPLE);
717     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_VALID_BITS_PER_SAMPLE);
718     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_BLOCK);
719     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_CHANNEL_MASK);
720     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FOLDDOWN_MATRIX);
721     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKREF);
722     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKTARGET);
723     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGREF);
724     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGTARGET);
725     IF_EQUAL_RETURN(guid, MF_MT_AUDIO_PREFER_WAVEFORMATEX);
726     IF_EQUAL_RETURN(guid, MF_MT_AAC_PAYLOAD_TYPE);
727     IF_EQUAL_RETURN(guid, MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION);
728     IF_EQUAL_RETURN(guid, MF_MT_FRAME_SIZE);
729     IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE);
730     IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MAX);
731     IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MIN);
732     IF_EQUAL_RETURN(guid, MF_MT_PIXEL_ASPECT_RATIO);
733     IF_EQUAL_RETURN(guid, MF_MT_DRM_FLAGS);
734     IF_EQUAL_RETURN(guid, MF_MT_PAD_CONTROL_FLAGS);
735     IF_EQUAL_RETURN(guid, MF_MT_SOURCE_CONTENT_HINT);
736     IF_EQUAL_RETURN(guid, MF_MT_VIDEO_CHROMA_SITING);
737     IF_EQUAL_RETURN(guid, MF_MT_INTERLACE_MODE);
738     IF_EQUAL_RETURN(guid, MF_MT_TRANSFER_FUNCTION);
739     IF_EQUAL_RETURN(guid, MF_MT_VIDEO_PRIMARIES);
740     IF_EQUAL_RETURN(guid, MF_MT_CUSTOM_VIDEO_PRIMARIES);
741     IF_EQUAL_RETURN(guid, MF_MT_YUV_MATRIX);
742     IF_EQUAL_RETURN(guid, MF_MT_VIDEO_LIGHTING);
743     IF_EQUAL_RETURN(guid, MF_MT_VIDEO_NOMINAL_RANGE);
744     IF_EQUAL_RETURN(guid, MF_MT_GEOMETRIC_APERTURE);
745     IF_EQUAL_RETURN(guid, MF_MT_MINIMUM_DISPLAY_APERTURE);
746     IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_APERTURE);
747     IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_ENABLED);
748     IF_EQUAL_RETURN(guid, MF_MT_AVG_BITRATE);
749     IF_EQUAL_RETURN(guid, MF_MT_AVG_BIT_ERROR_RATE);
750     IF_EQUAL_RETURN(guid, MF_MT_MAX_KEYFRAME_SPACING);
751     IF_EQUAL_RETURN(guid, MF_MT_DEFAULT_STRIDE);
752     IF_EQUAL_RETURN(guid, MF_MT_PALETTE);
753     IF_EQUAL_RETURN(guid, MF_MT_USER_DATA);
754     IF_EQUAL_RETURN(guid, MF_MT_AM_FORMAT_TYPE);
755     IF_EQUAL_RETURN(guid, MF_MT_MPEG_START_TIME_CODE);
756     IF_EQUAL_RETURN(guid, MF_MT_MPEG2_PROFILE);
757     IF_EQUAL_RETURN(guid, MF_MT_MPEG2_LEVEL);
758     IF_EQUAL_RETURN(guid, MF_MT_MPEG2_FLAGS);
759     IF_EQUAL_RETURN(guid, MF_MT_MPEG_SEQUENCE_HEADER);
760     IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_0);
761     IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_0);
762     IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_1);
763     IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_1);
764     IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_SRC_PACK);
765     IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_CTRL_PACK);
766     IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_HEADER);
767     IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_FORMAT);
768     IF_EQUAL_RETURN(guid, MF_MT_IMAGE_LOSS_TOLERANT);
769     IF_EQUAL_RETURN(guid, MF_MT_MPEG4_SAMPLE_DESCRIPTION);
770     IF_EQUAL_RETURN(guid, MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY);
771     IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_4CC);
772     IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_WAVE_FORMAT_TAG);
773     // Media types
774     IF_EQUAL_RETURN(guid, MFMediaType_Audio);
775     IF_EQUAL_RETURN(guid, MFMediaType_Video);
776     IF_EQUAL_RETURN(guid, MFMediaType_Protected);
777     IF_EQUAL_RETURN(guid, MFMediaType_SAMI);
778     IF_EQUAL_RETURN(guid, MFMediaType_Script);
779     IF_EQUAL_RETURN(guid, MFMediaType_Image);
780     IF_EQUAL_RETURN(guid, MFMediaType_HTML);
781     IF_EQUAL_RETURN(guid, MFMediaType_Binary);
782     IF_EQUAL_RETURN(guid, MFMediaType_FileTransfer);
783     IF_EQUAL_RETURN(guid, MFVideoFormat_AI44); //     FCC('AI44')
784     IF_EQUAL_RETURN(guid, MFVideoFormat_ARGB32); //   D3DFMT_A8R8G8B8
785     IF_EQUAL_RETURN(guid, MFVideoFormat_AYUV); //     FCC('AYUV')
786     IF_EQUAL_RETURN(guid, MFVideoFormat_DV25); //     FCC('dv25')
787     IF_EQUAL_RETURN(guid, MFVideoFormat_DV50); //     FCC('dv50')
788     IF_EQUAL_RETURN(guid, MFVideoFormat_DVH1); //     FCC('dvh1')
789     IF_EQUAL_RETURN(guid, MFVideoFormat_DVSD); //     FCC('dvsd')
790     IF_EQUAL_RETURN(guid, MFVideoFormat_DVSL); //     FCC('dvsl')
791     IF_EQUAL_RETURN(guid, MFVideoFormat_H264); //     FCC('H264')
792     IF_EQUAL_RETURN(guid, MFVideoFormat_I420); //     FCC('I420')
793     IF_EQUAL_RETURN(guid, MFVideoFormat_IYUV); //     FCC('IYUV')
794     IF_EQUAL_RETURN(guid, MFVideoFormat_M4S2); //     FCC('M4S2')
795     IF_EQUAL_RETURN(guid, MFVideoFormat_MJPG);
796     IF_EQUAL_RETURN(guid, MFVideoFormat_MP43); //     FCC('MP43')
797     IF_EQUAL_RETURN(guid, MFVideoFormat_MP4S); //     FCC('MP4S')
798     IF_EQUAL_RETURN(guid, MFVideoFormat_MP4V); //     FCC('MP4V')
799     IF_EQUAL_RETURN(guid, MFVideoFormat_MPG1); //     FCC('MPG1')
800     IF_EQUAL_RETURN(guid, MFVideoFormat_MSS1); //     FCC('MSS1')
801     IF_EQUAL_RETURN(guid, MFVideoFormat_MSS2); //     FCC('MSS2')
802     IF_EQUAL_RETURN(guid, MFVideoFormat_NV11); //     FCC('NV11')
803     IF_EQUAL_RETURN(guid, MFVideoFormat_NV12); //     FCC('NV12')
804     IF_EQUAL_RETURN(guid, MFVideoFormat_P010); //     FCC('P010')
805     IF_EQUAL_RETURN(guid, MFVideoFormat_P016); //     FCC('P016')
806     IF_EQUAL_RETURN(guid, MFVideoFormat_P210); //     FCC('P210')
807     IF_EQUAL_RETURN(guid, MFVideoFormat_P216); //     FCC('P216')
808     IF_EQUAL_RETURN(guid, MFVideoFormat_RGB24); //    D3DFMT_R8G8B8
809     IF_EQUAL_RETURN(guid, MFVideoFormat_RGB32); //    D3DFMT_X8R8G8B8
810     IF_EQUAL_RETURN(guid, MFVideoFormat_RGB555); //   D3DFMT_X1R5G5B5
811     IF_EQUAL_RETURN(guid, MFVideoFormat_RGB565); //   D3DFMT_R5G6B5
812     IF_EQUAL_RETURN(guid, MFVideoFormat_RGB8);
813     IF_EQUAL_RETURN(guid, MFVideoFormat_UYVY); //     FCC('UYVY')
814     IF_EQUAL_RETURN(guid, MFVideoFormat_v210); //     FCC('v210')
815     IF_EQUAL_RETURN(guid, MFVideoFormat_v410); //     FCC('v410')
816     IF_EQUAL_RETURN(guid, MFVideoFormat_WMV1); //     FCC('WMV1')
817     IF_EQUAL_RETURN(guid, MFVideoFormat_WMV2); //     FCC('WMV2')
818     IF_EQUAL_RETURN(guid, MFVideoFormat_WMV3); //     FCC('WMV3')
819     IF_EQUAL_RETURN(guid, MFVideoFormat_WVC1); //     FCC('WVC1')
820     IF_EQUAL_RETURN(guid, MFVideoFormat_Y210); //     FCC('Y210')
821     IF_EQUAL_RETURN(guid, MFVideoFormat_Y216); //     FCC('Y216')
822     IF_EQUAL_RETURN(guid, MFVideoFormat_Y410); //     FCC('Y410')
823     IF_EQUAL_RETURN(guid, MFVideoFormat_Y416); //     FCC('Y416')
824     IF_EQUAL_RETURN(guid, MFVideoFormat_Y41P);
825     IF_EQUAL_RETURN(guid, MFVideoFormat_Y41T);
826     IF_EQUAL_RETURN(guid, MFVideoFormat_YUY2); //     FCC('YUY2')
827     IF_EQUAL_RETURN(guid, MFVideoFormat_YV12); //     FCC('YV12')
828     IF_EQUAL_RETURN(guid, MFVideoFormat_YVYU);
829     IF_EQUAL_RETURN(guid, MFAudioFormat_PCM); //              WAVE_FORMAT_PCM
830     IF_EQUAL_RETURN(guid, MFAudioFormat_Float); //            WAVE_FORMAT_IEEE_FLOAT
831     IF_EQUAL_RETURN(guid, MFAudioFormat_DTS); //              WAVE_FORMAT_DTS
832     IF_EQUAL_RETURN(guid, MFAudioFormat_Dolby_AC3_SPDIF); //  WAVE_FORMAT_DOLBY_AC3_SPDIF
833     IF_EQUAL_RETURN(guid, MFAudioFormat_DRM); //              WAVE_FORMAT_DRM
834     IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV8); //        WAVE_FORMAT_WMAUDIO2
835     IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV9); //        WAVE_FORMAT_WMAUDIO3
836     IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS
837     IF_EQUAL_RETURN(guid, MFAudioFormat_WMASPDIF); //         WAVE_FORMAT_WMASPDIF
838     IF_EQUAL_RETURN(guid, MFAudioFormat_MSP1); //             WAVE_FORMAT_WMAVOICE9
839     IF_EQUAL_RETURN(guid, MFAudioFormat_MP3); //              WAVE_FORMAT_MPEGLAYER3
840     IF_EQUAL_RETURN(guid, MFAudioFormat_MPEG); //             WAVE_FORMAT_MPEG
841     IF_EQUAL_RETURN(guid, MFAudioFormat_AAC); //              WAVE_FORMAT_MPEG_HEAAC
842     IF_EQUAL_RETURN(guid, MFAudioFormat_ADTS); //             WAVE_FORMAT_MPEG_ADTS_AAC
843     return NULL;
844 }
845
846 FormatReader::FormatReader(void)
847 {
848 }
849
850 MediaType FormatReader::Read(IMFMediaType *pType)
851 {
852     UINT32 count = 0;
853     HRESULT hr = S_OK;
854     MediaType out;
855     hr = pType->LockStore();
856     if (FAILED(hr))
857     {
858         return out;
859     }
860     hr = pType->GetCount(&count);
861     if (FAILED(hr))
862     {
863         return out;
864     }
865     for (UINT32 i = 0; i < count; i++)
866     {
867         hr = LogAttributeValueByIndexNew(pType, i, out);
868         if (FAILED(hr))
869         {
870             break;
871         }
872     }
873     hr = pType->UnlockStore();
874     if (FAILED(hr))
875     {
876         return out;
877     }
878     return out;
879 }
880
881 FormatReader::~FormatReader(void)
882 {
883 }
884
885 #define CHECK_HR(x) if (FAILED(x)) { goto done; }
886
887 ImageGrabber::ImageGrabber(unsigned int deviceID, bool synchronous):
888     m_cRef(1),
889     ig_DeviceID(deviceID),
890     ig_pSource(NULL),
891     ig_pSession(NULL),
892     ig_pTopology(NULL),
893     ig_RIE(true),
894     ig_Close(false),
895     ig_Synchronous(synchronous),
896     ig_hFrameReady(synchronous ? CreateEvent(NULL, FALSE, FALSE, NULL): 0),
897     ig_hFrameGrabbed(synchronous ? CreateEvent(NULL, FALSE, TRUE, NULL): 0),
898     ig_hFinish(CreateEvent(NULL, TRUE, FALSE, NULL))
899 {}
900
901 ImageGrabber::~ImageGrabber(void)
902 {
903     if (ig_pSession)
904     {
905         ig_pSession->Shutdown();
906     }
907
908     CloseHandle(ig_hFinish);
909
910     if (ig_Synchronous)
911     {
912         CloseHandle(ig_hFrameReady);
913         CloseHandle(ig_hFrameGrabbed);
914     }
915
916     SafeRelease(&ig_pSession);
917     SafeRelease(&ig_pTopology);
918     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
919
920     DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroing instance of the ImageGrabber class\n", ig_DeviceID);
921 }
922
923 HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat)
924 {
925     ComPtr<IMFActivate> pSinkActivate = NULL;
926     ComPtr<IMFMediaType> pType = NULL;
927     ComPtr<IMFPresentationDescriptor> pPD = NULL;
928     ComPtr<IMFStreamDescriptor> pSD = NULL;
929     ComPtr<IMFMediaTypeHandler> pHandler = NULL;
930     ComPtr<IMFMediaType> pCurrentType = NULL;
931     HRESULT hr = S_OK;
932     MediaType MT;
933      // Clean up.
934     if (ig_pSession)
935     {
936         ig_pSession->Shutdown();
937     }
938     SafeRelease(&ig_pSession);
939     SafeRelease(&ig_pTopology);
940     ig_pSource = pSource;
941     hr = pSource->CreatePresentationDescriptor(&pPD);
942     if (FAILED(hr))
943     {
944         goto err;
945     }
946     BOOL fSelected;
947     hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD);
948     if (FAILED(hr)) {
949         goto err;
950     }
951     hr = pSD->GetMediaTypeHandler(&pHandler);
952     if (FAILED(hr)) {
953         goto err;
954     }
955     DWORD cTypes = 0;
956     hr = pHandler->GetMediaTypeCount(&cTypes);
957     if (FAILED(hr)) {
958         goto err;
959     }
960     if(cTypes > 0)
961     {
962         hr = pHandler->GetCurrentMediaType(&pCurrentType);
963         if (FAILED(hr)) {
964             goto err;
965         }
966         MT = FormatReader::Read(pCurrentType.Get());
967     }
968 err:
969     unsigned int sizeRawImage = 0;
970     if(VideoFormat == MFVideoFormat_RGB24)
971     {
972         sizeRawImage = MT.MF_MT_FRAME_SIZE * 3;
973     }
974     else if(VideoFormat == MFVideoFormat_RGB32)
975     {
976         sizeRawImage = MT.MF_MT_FRAME_SIZE * 4;
977     }
978     CHECK_HR(hr = RawImage::CreateInstance(&ig_RIFirst, sizeRawImage));
979     CHECK_HR(hr = RawImage::CreateInstance(&ig_RISecond, sizeRawImage));
980     ig_RIOut = ig_RISecond;
981     // Configure the media type that the Sample Grabber will receive.
982     // Setting the major and subtype is usually enough for the topology loader
983     // to resolve the topology.
984     CHECK_HR(hr = MFCreateMediaType(pType.GetAddressOf()));
985     CHECK_HR(hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
986     CHECK_HR(hr = pType->SetGUID(MF_MT_SUBTYPE, VideoFormat));
987     // Create the sample grabber sink.
988     CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pType.Get(), this, pSinkActivate.GetAddressOf()));
989     // To run as fast as possible, set this attribute (requires Windows 7):
990     CHECK_HR(hr = pSinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE));
991     // Create the Media Session.
992     CHECK_HR(hr = MFCreateMediaSession(NULL, &ig_pSession));
993     // Create the topology.
994     CHECK_HR(hr = CreateTopology(pSource, pSinkActivate.Get(), &ig_pTopology));
995 done:
996     // Clean up.
997     if (FAILED(hr))
998     {
999         if (ig_pSession)
1000         {
1001             ig_pSession->Shutdown();
1002         }
1003         SafeRelease(&ig_pSession);
1004         SafeRelease(&ig_pTopology);
1005     }
1006
1007     return hr;
1008 }
1009
1010 void ImageGrabber::stopGrabbing()
1011 {
1012     if(ig_pSession)
1013         ig_pSession->Stop();
1014     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1015     DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Stopping of of grabbing of images\n", ig_DeviceID);
1016 }
1017
1018 HRESULT ImageGrabber::startGrabbing(void)
1019 {
1020     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1021     ComPtr<IMFMediaEvent> pEvent = NULL;
1022     PROPVARIANT var;
1023     PropVariantInit(&var);
1024     HRESULT hr = S_OK;
1025     hr = ig_pSession->SetTopology(0, ig_pTopology);
1026     DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Start Grabbing of the images\n", ig_DeviceID);
1027     hr = ig_pSession->Start(&GUID_NULL, &var);
1028     for(;;)
1029     {
1030         HRESULT hrStatus = S_OK;
1031         MediaEventType met;
1032         if(!ig_pSession) break;
1033         hr = ig_pSession->GetEvent(0, &pEvent);
1034         if(!SUCCEEDED(hr))
1035         {
1036             hr = S_OK;
1037             goto done;
1038         }
1039         hr = pEvent->GetStatus(&hrStatus);
1040         if(!SUCCEEDED(hr))
1041         {
1042             hr = S_OK;
1043             goto done;
1044         }
1045         hr = pEvent->GetType(&met);
1046         if(!SUCCEEDED(hr))
1047         {
1048             hr = S_OK;
1049             goto done;
1050         }
1051         if (met == MESessionEnded)
1052         {
1053             DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionEnded \n", ig_DeviceID);
1054             ig_pSession->Stop();
1055             break;
1056         }
1057         if (met == MESessionStopped)
1058         {
1059             DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionStopped \n", ig_DeviceID);
1060             break;
1061         }
1062         if (met == MEVideoCaptureDeviceRemoved)
1063         {
1064             DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved \n", ig_DeviceID);
1065             break;
1066         }
1067         if ((met == MEError) || (met == MENonFatalError))
1068         {
1069             pEvent->GetStatus(&hrStatus);
1070             DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MEError | MENonFatalError: %u\n", ig_DeviceID, hrStatus);
1071             break;
1072         }
1073     }
1074     DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Finish startGrabbing \n", ig_DeviceID);
1075
1076 done:
1077     SetEvent(ig_hFinish);
1078
1079     return hr;
1080 }
1081
1082 void ImageGrabber::pauseGrabbing()
1083 {
1084 }
1085
1086 void ImageGrabber::resumeGrabbing()
1087 {
1088 }
1089
1090 HRESULT ImageGrabber::CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo)
1091 {
1092     IMFTopology* pTopology = NULL;
1093     ComPtr<IMFPresentationDescriptor> pPD = NULL;
1094     ComPtr<IMFStreamDescriptor> pSD = NULL;
1095     ComPtr<IMFMediaTypeHandler> pHandler = NULL;
1096     ComPtr<IMFTopologyNode> pNode1 = NULL;
1097     ComPtr<IMFTopologyNode> pNode2 = NULL;
1098     HRESULT hr = S_OK;
1099     DWORD cStreams = 0;
1100     CHECK_HR(hr = MFCreateTopology(&pTopology));
1101     CHECK_HR(hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()));
1102     CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams));
1103     for (DWORD i = 0; i < cStreams; i++)
1104     {
1105         // In this example, we look for audio streams and connect them to the sink.
1106         BOOL fSelected = FALSE;
1107         GUID majorType;
1108         CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD));
1109         CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler));
1110         CHECK_HR(hr = pHandler->GetMajorType(&majorType));
1111         if (majorType == MFMediaType_Video && fSelected)
1112         {
1113             CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD.Get(), pSD.Get(), pNode1.GetAddressOf()));
1114             CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivate, 0, pNode2.GetAddressOf()));
1115             CHECK_HR(hr = pNode1->ConnectOutput(0, pNode2.Get(), 0));
1116             break;
1117         }
1118         else
1119         {
1120             CHECK_HR(hr = pPD->DeselectStream(i));
1121         }
1122     }
1123     *ppTopo = pTopology;
1124     (*ppTopo)->AddRef();
1125
1126 done:
1127     return hr;
1128 }
1129
1130 HRESULT ImageGrabber::AddSourceNode(
1131     IMFTopology *pTopology,           // Topology.
1132     IMFMediaSource *pSource,          // Media source.
1133     IMFPresentationDescriptor *pPD,   // Presentation descriptor.
1134     IMFStreamDescriptor *pSD,         // Stream descriptor.
1135     IMFTopologyNode **ppNode)         // Receives the node pointer.
1136 {
1137     ComPtr<IMFTopologyNode> pNode = NULL;
1138     HRESULT hr = S_OK;
1139     CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, pNode.GetAddressOf()));
1140     CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource));
1141     CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD));
1142     CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD));
1143     CHECK_HR(hr = pTopology->AddNode(pNode.Get()));
1144     // Return the pointer to the caller.
1145     *ppNode = pNode.Get();
1146     (*ppNode)->AddRef();
1147
1148 done:
1149     return hr;
1150 }
1151
1152 HRESULT ImageGrabber::AddOutputNode(
1153     IMFTopology *pTopology,     // Topology.
1154     IMFActivate *pActivate,     // Media sink activation object.
1155     DWORD dwId,                 // Identifier of the stream sink.
1156     IMFTopologyNode **ppNode)   // Receives the node pointer.
1157 {
1158     ComPtr<IMFTopologyNode> pNode = NULL;
1159     HRESULT hr = S_OK;
1160     CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, pNode.GetAddressOf()));
1161     CHECK_HR(hr = pNode->SetObject(pActivate));
1162     CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId));
1163     CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE));
1164     CHECK_HR(hr = pTopology->AddNode(pNode.Get()));
1165     // Return the pointer to the caller.
1166     *ppNode = pNode.Get();
1167     (*ppNode)->AddRef();
1168
1169 done:
1170     return hr;
1171 }
1172
1173 HRESULT ImageGrabber::CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, bool synchronious)
1174 {
1175     *ppIG = new (std::nothrow) ImageGrabber(deviceID, synchronious);
1176     if (ppIG == NULL)
1177     {
1178         return E_OUTOFMEMORY;
1179     }
1180     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1181     DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Creating instance of ImageGrabber\n", deviceID);
1182     return S_OK;
1183 }
1184
1185 STDMETHODIMP ImageGrabber::QueryInterface(REFIID riid, void** ppv)
1186 {
1187     HRESULT hr = E_NOINTERFACE;
1188     *ppv = NULL;
1189     if(riid == IID_IUnknown || riid == IID_IMFSampleGrabberSinkCallback)
1190     {
1191         *ppv = static_cast<IMFSampleGrabberSinkCallback *>(this);
1192         hr = S_OK;
1193     }
1194     if(riid == IID_IMFClockStateSink)
1195     {
1196         *ppv = static_cast<IMFClockStateSink *>(this);
1197         hr = S_OK;
1198     }
1199     if(SUCCEEDED(hr))
1200     {
1201         reinterpret_cast<IUnknown *>(*ppv)->AddRef();
1202     }
1203     return hr;
1204 }
1205
1206 STDMETHODIMP_(ULONG) ImageGrabber::AddRef()
1207 {
1208     return InterlockedIncrement(&m_cRef);
1209 }
1210
1211 STDMETHODIMP_(ULONG) ImageGrabber::Release()
1212 {
1213     ULONG cRef = InterlockedDecrement(&m_cRef);
1214     if (cRef == 0)
1215     {
1216         delete this;
1217     }
1218     return cRef;
1219 }
1220
1221 STDMETHODIMP ImageGrabber::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset)
1222 {
1223     (void)hnsSystemTime;
1224     (void)llClockStartOffset;
1225     return S_OK;
1226 }
1227
1228 STDMETHODIMP ImageGrabber::OnClockStop(MFTIME hnsSystemTime)
1229 {
1230     (void)hnsSystemTime;
1231     return S_OK;
1232 }
1233
1234 STDMETHODIMP ImageGrabber::OnClockPause(MFTIME hnsSystemTime)
1235 {
1236     (void)hnsSystemTime;
1237     return S_OK;
1238 }
1239
1240 STDMETHODIMP ImageGrabber::OnClockRestart(MFTIME hnsSystemTime)
1241 {
1242     (void)hnsSystemTime;
1243     return S_OK;
1244 }
1245
1246 STDMETHODIMP ImageGrabber::OnClockSetRate(MFTIME hnsSystemTime, float flRate)
1247 {
1248     (void)flRate;
1249     (void)hnsSystemTime;
1250     return S_OK;
1251 }
1252
1253 STDMETHODIMP ImageGrabber::OnSetPresentationClock(IMFPresentationClock* pClock)
1254 {
1255     (void)pClock;
1256     return S_OK;
1257 }
1258
1259 STDMETHODIMP ImageGrabber::OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags,
1260     LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer,
1261     DWORD dwSampleSize)
1262 {
1263     (void)guidMajorMediaType;
1264     (void)llSampleTime;
1265     (void)dwSampleFlags;
1266     (void)llSampleDuration;
1267     (void)dwSampleSize;
1268
1269     HANDLE tmp[] = {ig_hFinish, ig_hFrameGrabbed, NULL};
1270
1271     DWORD status = WaitForMultipleObjects(2, tmp, FALSE, INFINITE);
1272     if (status == WAIT_OBJECT_0)
1273     {
1274         printf("OnProcessFrame called after ig_hFinish event\n");
1275         return S_OK;
1276     }
1277
1278     if(ig_RIE)
1279     {
1280         ig_RIFirst->fastCopy(pSampleBuffer);
1281         ig_RIOut = ig_RIFirst;
1282     }
1283     else
1284     {
1285         ig_RISecond->fastCopy(pSampleBuffer);
1286         ig_RIOut = ig_RISecond;
1287     }
1288
1289     if (ig_Synchronous)
1290     {
1291         SetEvent(ig_hFrameReady);
1292     }
1293     else
1294     {
1295         ig_RIE = !ig_RIE;
1296     }
1297
1298     return S_OK;
1299 }
1300
1301 STDMETHODIMP ImageGrabber::OnShutdown()
1302 {
1303     SetEvent(ig_hFinish);
1304     return S_OK;
1305 }
1306
1307 RawImage *ImageGrabber::getRawImage()
1308 {
1309     return ig_RIOut;
1310 }
1311
1312 DWORD WINAPI MainThreadFunction( LPVOID lpParam )
1313 {
1314     ImageGrabberThread *pIGT = (ImageGrabberThread *)lpParam;
1315     pIGT->run();
1316     return 0;
1317 }
1318
1319 HRESULT ImageGrabberThread::CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious)
1320 {
1321     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1322     *ppIGT = new (std::nothrow) ImageGrabberThread(pSource, deviceID, synchronious);
1323     if (ppIGT == NULL)
1324     {
1325         DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Memory cannot be allocated\n", deviceID);
1326         return E_OUTOFMEMORY;
1327     }
1328     else
1329         DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Creating of the instance of ImageGrabberThread\n", deviceID);
1330     return S_OK;
1331 }
1332
1333 ImageGrabberThread::ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious):
1334     igt_func(NULL),
1335     igt_Handle(NULL),
1336     igt_stop(false)
1337 {
1338     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1339     HRESULT hr = ImageGrabber::CreateInstance(&igt_pImageGrabber, deviceID, synchronious);
1340     igt_DeviceID = deviceID;
1341     if(SUCCEEDED(hr))
1342     {
1343         hr = igt_pImageGrabber->initImageGrabber(pSource, MFVideoFormat_RGB24);
1344         if(!SUCCEEDED(hr))
1345         {
1346             DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with initialization of the instance of the ImageGrabber class\n", deviceID);
1347         }
1348         else
1349         {
1350             DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Initialization of instance of the ImageGrabber class\n", deviceID);
1351         }
1352     }
1353     else
1354     {
1355         DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i There is a problem with creation of the instance of the ImageGrabber class\n", deviceID);
1356     }
1357 }
1358
1359 void ImageGrabberThread::setEmergencyStopEvent(void *userData, void(*func)(int, void *))
1360 {
1361     if(func)
1362     {
1363         igt_func = func;
1364         igt_userData = userData;
1365     }
1366 }
1367
1368 ImageGrabberThread::~ImageGrabberThread(void)
1369 {
1370     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1371     DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Destroing ImageGrabberThread\n", igt_DeviceID);
1372     if (igt_Handle)
1373         WaitForSingleObject(igt_Handle, INFINITE);
1374     delete igt_pImageGrabber;
1375 }
1376
1377 void ImageGrabberThread::stop()
1378 {
1379     igt_stop = true;
1380     if(igt_pImageGrabber)
1381     {
1382         igt_pImageGrabber->stopGrabbing();
1383     }
1384 }
1385
1386 void ImageGrabberThread::start()
1387 {
1388     igt_Handle = CreateThread(
1389             NULL,                  // default security attributes
1390             0,                     // use default stack size
1391             MainThreadFunction,    // thread function name
1392             this,                  // argument to thread function
1393             0,                     // use default creation flags
1394             &igt_ThreadIdArray);   // returns the thread identifier
1395 }
1396
1397 void ImageGrabberThread::run()
1398 {
1399     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1400     if(igt_pImageGrabber)
1401     {
1402         DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Thread for grabbing images is started\n", igt_DeviceID);
1403         HRESULT hr = igt_pImageGrabber->startGrabbing();
1404         if(!SUCCEEDED(hr))
1405         {
1406             DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with starting the process of grabbing\n", igt_DeviceID);
1407         }
1408     }
1409     else
1410     {
1411         DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i The thread is finished without execution of grabbing\n", igt_DeviceID);
1412     }
1413     if(!igt_stop)
1414     {
1415         DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Emergency Stop thread\n", igt_DeviceID);
1416         if(igt_func)
1417         {
1418             igt_func(igt_DeviceID, igt_userData);
1419         }
1420     }
1421     else
1422         DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Finish thread\n", igt_DeviceID);
1423 }
1424
1425 ImageGrabber *ImageGrabberThread::getImageGrabber()
1426 {
1427     return igt_pImageGrabber;
1428 }
1429
1430 Media_Foundation::Media_Foundation(void)
1431 {
1432     HRESULT hr = MFStartup(MF_VERSION);
1433     if(!SUCCEEDED(hr))
1434     {
1435         DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1436         DPO->printOut(L"MEDIA FOUNDATION: It cannot be created!!!\n");
1437     }
1438 }
1439
1440 Media_Foundation::~Media_Foundation(void)
1441 {
1442     HRESULT hr = MFShutdown();
1443     if(!SUCCEEDED(hr))
1444     {
1445         DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1446         DPO->printOut(L"MEDIA FOUNDATION: Resources cannot be released\n");
1447     }
1448 }
1449
1450 bool Media_Foundation::buildListOfDevices()
1451 {
1452     HRESULT hr = S_OK;
1453     ComPtr<IMFAttributes> pAttributes = NULL;
1454     CoInitialize(NULL);
1455     hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1);
1456     if (SUCCEEDED(hr))
1457     {
1458         hr = pAttributes->SetGUID(
1459             MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
1460             MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
1461             );
1462     }
1463     if (SUCCEEDED(hr))
1464     {
1465         videoDevices *vDs = &videoDevices::getInstance();
1466         hr = vDs->initDevices(pAttributes.Get());
1467     }
1468     else
1469     {
1470        DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1471        DPO->printOut(L"MEDIA FOUNDATION: The access to the video cameras denied\n");
1472     }
1473
1474     return (SUCCEEDED(hr));
1475 }
1476
1477 Media_Foundation& Media_Foundation::getInstance()
1478 {
1479     static Media_Foundation instance;
1480     return instance;
1481 }
1482
1483 RawImage::RawImage(unsigned int size): ri_new(false), ri_pixels(NULL)
1484 {
1485     ri_size = size;
1486     ri_pixels = new unsigned char[size];
1487     memset((void *)ri_pixels,0,ri_size);
1488 }
1489
1490 bool RawImage::isNew()
1491 {
1492     return ri_new;
1493 }
1494
1495 unsigned int RawImage::getSize()
1496 {
1497     return ri_size;
1498 }
1499
1500 RawImage::~RawImage(void)
1501 {
1502     delete []ri_pixels;
1503     ri_pixels = NULL;
1504 }
1505
1506 long RawImage::CreateInstance(RawImage **ppRImage,unsigned int size)
1507 {
1508     *ppRImage = new (std::nothrow) RawImage(size);
1509     if (ppRImage == NULL)
1510     {
1511         return E_OUTOFMEMORY;
1512     }
1513     return S_OK;
1514 }
1515
1516 void RawImage::setCopy(const BYTE * pSampleBuffer)
1517 {
1518     memcpy(ri_pixels, pSampleBuffer, ri_size);
1519     ri_new = true;
1520 }
1521
1522 void RawImage::fastCopy(const BYTE * pSampleBuffer)
1523 {
1524     memcpy(ri_pixels, pSampleBuffer, ri_size);
1525     ri_new = true;
1526 }
1527
1528 unsigned char * RawImage::getpPixels()
1529 {
1530     ri_new = false;
1531     return ri_pixels;
1532 }
1533
1534 videoDevice::videoDevice(void): vd_IsSetuped(false), vd_LockOut(OpenLock), vd_pFriendlyName(NULL),
1535     vd_Width(0), vd_Height(0), vd_pSource(NULL), vd_func(NULL), vd_userData(NULL)
1536 {
1537 }
1538
1539 void videoDevice::setParametrs(CamParametrs parametrs)
1540 {
1541     if(vd_IsSetuped)
1542     {
1543         if(vd_pSource)
1544         {
1545             Parametr *pParametr = (Parametr *)(&parametrs);
1546             Parametr *pPrevParametr = (Parametr *)(&vd_PrevParametrs);
1547             IAMVideoProcAmp *pProcAmp = NULL;
1548             HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp));
1549             if (SUCCEEDED(hr))
1550             {
1551                 for(unsigned int i = 0; i < 10; i++)
1552                 {
1553                     if(pPrevParametr[i].CurrentValue != pParametr[i].CurrentValue || pPrevParametr[i].Flag != pParametr[i].Flag)
1554                         hr = pProcAmp->Set(VideoProcAmp_Brightness + i, pParametr[i].CurrentValue, pParametr[i].Flag);
1555                 }
1556                 pProcAmp->Release();
1557             }
1558             IAMCameraControl *pProcControl = NULL;
1559             hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl));
1560             if (SUCCEEDED(hr))
1561             {
1562                 for(unsigned int i = 0; i < 7; i++)
1563                 {
1564                     if(pPrevParametr[10 + i].CurrentValue != pParametr[10 + i].CurrentValue || pPrevParametr[10 + i].Flag != pParametr[10 + i].Flag)
1565                     hr = pProcControl->Set(CameraControl_Pan+i, pParametr[10 + i].CurrentValue, pParametr[10 + i].Flag);
1566                 }
1567                 pProcControl->Release();
1568             }
1569             vd_PrevParametrs = parametrs;
1570         }
1571     }
1572 }
1573
1574 CamParametrs videoDevice::getParametrs()
1575 {
1576     CamParametrs out;
1577     if(vd_IsSetuped)
1578     {
1579         if(vd_pSource)
1580         {
1581             Parametr *pParametr = (Parametr *)(&out);
1582             IAMVideoProcAmp *pProcAmp = NULL;
1583             HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp));
1584             if (SUCCEEDED(hr))
1585             {
1586                 for(unsigned int i = 0; i < 10; i++)
1587                 {
1588                     Parametr temp;
1589                     hr = pProcAmp->GetRange(VideoProcAmp_Brightness+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag);
1590                     if (SUCCEEDED(hr))
1591                     {
1592                         temp.CurrentValue = temp.Default;
1593                         pParametr[i] = temp;
1594                     }
1595                 }
1596                 pProcAmp->Release();
1597             }
1598             IAMCameraControl *pProcControl = NULL;
1599             hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl));
1600             if (SUCCEEDED(hr))
1601             {
1602                 for(unsigned int i = 0; i < 7; i++)
1603                 {
1604                     Parametr temp;
1605                     hr = pProcControl->GetRange(CameraControl_Pan+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag);
1606                     if (SUCCEEDED(hr))
1607                     {
1608                         temp.CurrentValue = temp.Default;
1609                         pParametr[10 + i] = temp;
1610                     }
1611                 }
1612                 pProcControl->Release();
1613             }
1614         }
1615     }
1616     return out;
1617 }
1618
1619 long videoDevice::resetDevice(IMFActivate *pActivate)
1620 {
1621     HRESULT hr = -1;
1622     vd_CurrentFormats.clear();
1623     if(vd_pFriendlyName)
1624         CoTaskMemFree(vd_pFriendlyName);
1625     vd_pFriendlyName = NULL;
1626     if(pActivate)
1627     {
1628         IMFMediaSource *pSource = NULL;
1629         hr = pActivate->GetAllocatedString(
1630                 MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
1631                 &vd_pFriendlyName,
1632                 NULL
1633                 );
1634         hr = pActivate->ActivateObject(
1635             __uuidof(IMFMediaSource),
1636             (void**)&pSource
1637             );
1638         enumerateCaptureFormats(pSource);
1639         buildLibraryofTypes();
1640         SafeRelease(&pSource);
1641         if(FAILED(hr))
1642         {
1643             vd_pFriendlyName = NULL;
1644             DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1645             DPO->printOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber);
1646         }
1647     }
1648     return hr;
1649 }
1650
1651 long videoDevice::readInfoOfDevice(IMFActivate *pActivate, unsigned int Num)
1652 {
1653     HRESULT hr = -1;
1654     vd_CurrentNumber = Num;
1655     hr = resetDevice(pActivate);
1656     return hr;
1657 }
1658
1659 long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice)
1660 {
1661     HRESULT hr = S_OK;
1662     IMFActivate **ppDevices = NULL;
1663     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1664     UINT32 count;
1665     wchar_t *newFriendlyName = NULL;
1666     hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
1667     if (SUCCEEDED(hr))
1668     {
1669         if(count > 0)
1670         {
1671             if(count > vd_CurrentNumber)
1672             {
1673                 hr = ppDevices[vd_CurrentNumber]->GetAllocatedString(
1674                 MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
1675                 &newFriendlyName,
1676                 NULL
1677                 );
1678                 if (SUCCEEDED(hr))
1679                 {
1680                     if(wcscmp(newFriendlyName, vd_pFriendlyName) != 0)
1681                     {
1682                         DPO->printOut(L"VIDEODEVICE %i: Chosen device cannot be found \n", vd_CurrentNumber);
1683                         hr = -1;
1684                         pDevice = NULL;
1685                     }
1686                     else
1687                     {
1688                         *pDevice = ppDevices[vd_CurrentNumber];
1689                         (*pDevice)->AddRef();
1690                     }
1691                 }
1692                 else
1693                 {
1694                     DPO->printOut(L"VIDEODEVICE %i: Name of device cannot be gotten \n", vd_CurrentNumber);
1695                 }
1696             }
1697             else
1698             {
1699                 DPO->printOut(L"VIDEODEVICE %i: Number of devices more than corrent number of the device \n", vd_CurrentNumber);
1700                 hr = -1;
1701             }
1702             for(UINT32 i = 0; i < count; i++)
1703             {
1704                 SafeRelease(&ppDevices[i]);
1705             }
1706             SafeRelease(ppDevices);
1707         }
1708         else
1709             hr = -1;
1710     }
1711     else
1712     {
1713         DPO->printOut(L"VIDEODEVICE %i: List of DeviceSources cannot be enumerated \n", vd_CurrentNumber);
1714     }
1715     return hr;
1716 }
1717
1718 long videoDevice::initDevice()
1719 {
1720     HRESULT hr = -1;
1721     ComPtr<IMFAttributes> pAttributes = NULL;
1722     IMFActivate *vd_pActivate = NULL;
1723     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1724     CoInitialize(NULL);
1725     hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1);
1726     if (SUCCEEDED(hr))
1727     {
1728         hr = pAttributes->SetGUID(
1729             MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
1730             MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
1731             );
1732     }
1733     if (SUCCEEDED(hr))
1734     {
1735         hr = checkDevice(pAttributes.Get(), &vd_pActivate);
1736         if (SUCCEEDED(hr) && vd_pActivate)
1737         {
1738             SafeRelease(&vd_pSource);
1739             hr = vd_pActivate->ActivateObject(
1740                 __uuidof(IMFMediaSource),
1741                 (void**)&vd_pSource
1742                 );
1743             if (SUCCEEDED(hr))
1744             {
1745             }
1746             SafeRelease(&vd_pActivate);
1747         }
1748         else
1749         {
1750             DPO->printOut(L"VIDEODEVICE %i: Device there is not \n", vd_CurrentNumber);
1751         }
1752     }
1753     else
1754     {
1755         DPO->printOut(L"VIDEODEVICE %i: The attribute of video cameras cannot be getting \n", vd_CurrentNumber);
1756     }
1757
1758     return hr;
1759 }
1760
1761 MediaType videoDevice::getFormat(unsigned int id)
1762 {
1763     if(id < vd_CurrentFormats.size())
1764     {
1765         return vd_CurrentFormats[id];
1766     }
1767     else return MediaType();
1768 }
1769 int videoDevice::getCountFormats()
1770 {
1771     return vd_CurrentFormats.size();
1772 }
1773 void videoDevice::setEmergencyStopEvent(void *userData, void(*func)(int, void *))
1774 {
1775     vd_func = func;
1776     vd_userData = userData;
1777 }
1778 void videoDevice::closeDevice()
1779 {
1780     if(vd_IsSetuped)
1781     {
1782         vd_IsSetuped = false;
1783         vd_pSource->Stop();
1784         SafeRelease(&vd_pSource);
1785         if(vd_LockOut == RawDataLock)
1786         {
1787             vd_pImGrTh->stop();
1788             Sleep(500);
1789             delete vd_pImGrTh;
1790         }
1791         vd_pImGrTh = NULL;
1792         vd_LockOut = OpenLock;
1793         DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1794         DPO->printOut(L"VIDEODEVICE %i: Device is stopped \n", vd_CurrentNumber);
1795     }
1796 }
1797 unsigned int videoDevice::getWidth()
1798 {
1799     if(vd_IsSetuped)
1800         return vd_Width;
1801     else
1802         return 0;
1803 }
1804 unsigned int videoDevice::getHeight()
1805 {
1806     if(vd_IsSetuped)
1807         return vd_Height;
1808     else
1809         return 0;
1810 }
1811 IMFMediaSource *videoDevice::getMediaSource()
1812 {
1813     IMFMediaSource *out = NULL;
1814     if(vd_LockOut == OpenLock)
1815     {
1816         vd_LockOut = MediaSourceLock;
1817         out = vd_pSource;
1818     }
1819     return out;
1820 }
1821 int videoDevice::findType(unsigned int size, unsigned int frameRate)
1822 {
1823     if(vd_CaptureFormats.size() == 0)
1824         return 0;
1825     FrameRateMap FRM = vd_CaptureFormats[size];
1826     if(FRM.size() == 0)
1827         return 0;
1828     UINT64 frameRateMax = 0;  SUBTYPEMap STMMax;
1829     if(frameRate == 0)
1830     {
1831         std::map<UINT64, SUBTYPEMap>::iterator f = FRM.begin();
1832         for(; f != FRM.end(); f++)
1833         {
1834              if((*f).first >= frameRateMax)
1835              {
1836                  frameRateMax = (*f).first;
1837                  STMMax = (*f).second;
1838              }
1839         }
1840     }
1841     else
1842     {
1843         std::map<UINT64, SUBTYPEMap>::iterator f = FRM.begin();
1844         for(; f != FRM.end(); f++)
1845         {
1846              if((*f).first >= frameRateMax)
1847              {
1848                  if(frameRate > (*f).first)
1849                  {
1850                      frameRateMax = (*f).first;
1851                      STMMax = (*f).second;
1852                  }
1853              }
1854         }
1855     }
1856     if(STMMax.size() == 0)
1857         return 0;
1858     std::map<String, vectorNum>::iterator S = STMMax.begin();
1859     vectorNum VN = (*S).second;
1860     if(VN.size() == 0)
1861         return 0;
1862     return VN[0];
1863 }
1864
1865 void videoDevice::buildLibraryofTypes()
1866 {
1867     unsigned int size;
1868     unsigned int framerate;
1869     std::vector<MediaType>::iterator i = vd_CurrentFormats.begin();
1870     int count = 0;
1871     for(; i != vd_CurrentFormats.end(); i++)
1872     {
1873         size = (*i).MF_MT_FRAME_SIZE;
1874         framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR;
1875         FrameRateMap FRM = vd_CaptureFormats[size];
1876         SUBTYPEMap STM = FRM[framerate];
1877         String subType((*i).pMF_MT_SUBTYPEName);
1878         vectorNum VN = STM[subType];
1879         VN.push_back(count);
1880         STM[subType] = VN;
1881         FRM[framerate] = STM;
1882         vd_CaptureFormats[size] = FRM;
1883         count++;
1884     }
1885 }
1886
1887 long videoDevice::setDeviceFormat(IMFMediaSource *pSource, unsigned long  dwFormatIndex)
1888 {
1889     ComPtr<IMFPresentationDescriptor> pPD = NULL;
1890     ComPtr<IMFStreamDescriptor> pSD = NULL;
1891     ComPtr<IMFMediaTypeHandler> pHandler = NULL;
1892     ComPtr<IMFMediaType> pType = NULL;
1893     HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf());
1894     if (FAILED(hr))
1895     {
1896         goto done;
1897     }
1898     BOOL fSelected;
1899     hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf());
1900     if (FAILED(hr))
1901     {
1902         goto done;
1903     }
1904     hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf());
1905     if (FAILED(hr))
1906     {
1907         goto done;
1908     }
1909     hr = pHandler->GetMediaTypeByIndex((DWORD)dwFormatIndex, pType.GetAddressOf());
1910     if (FAILED(hr))
1911     {
1912         goto done;
1913     }
1914     hr = pHandler->SetCurrentMediaType(pType.Get());
1915
1916 done:
1917     return hr;
1918 }
1919
1920 bool videoDevice::isDeviceSetup()
1921 {
1922     return vd_IsSetuped;
1923 }
1924
1925 RawImage * videoDevice::getRawImageOut()
1926 {
1927     if(!vd_IsSetuped) return NULL;
1928     if(vd_pImGrTh)
1929             return vd_pImGrTh->getImageGrabber()->getRawImage();
1930     else
1931     {
1932         DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1933         DPO->printOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class does not exist  \n", vd_CurrentNumber);
1934     }
1935     return NULL;
1936 }
1937
1938 bool videoDevice::isFrameNew()
1939 {
1940     if(!vd_IsSetuped) return false;
1941     if(vd_LockOut == RawDataLock || vd_LockOut == OpenLock)
1942     {
1943         if(vd_LockOut == OpenLock)
1944         {
1945             vd_LockOut = RawDataLock;
1946             HRESULT hr = ImageGrabberThread::CreateInstance(&vd_pImGrTh, vd_pSource, vd_CurrentNumber);
1947             if(FAILED(hr))
1948             {
1949                 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1950                 DPO->printOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class cannot be created.\n", vd_CurrentNumber);
1951                 return false;
1952             }
1953             vd_pImGrTh->setEmergencyStopEvent(vd_userData, vd_func);
1954             vd_pImGrTh->start();
1955             return true;
1956         }
1957         if(vd_pImGrTh)
1958             return vd_pImGrTh->getImageGrabber()->getRawImage()->isNew();
1959     }
1960     return false;
1961 }
1962
1963 bool videoDevice::isDeviceMediaSource()
1964 {
1965     if(vd_LockOut == MediaSourceLock) return true;
1966     return false;
1967 }
1968
1969 bool videoDevice::isDeviceRawDataSource()
1970 {
1971     if(vd_LockOut == RawDataLock) return true;
1972     return false;
1973 }
1974
1975 bool videoDevice::setupDevice(unsigned int id)
1976 {
1977     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1978     if(!vd_IsSetuped)
1979     {
1980         HRESULT hr = -1;
1981         hr = initDevice();
1982         if(SUCCEEDED(hr))
1983         {
1984             vd_Width = vd_CurrentFormats[id].width;
1985             vd_Height = vd_CurrentFormats[id].height;
1986             hr = setDeviceFormat(vd_pSource, (DWORD) id);
1987             vd_IsSetuped = (SUCCEEDED(hr));
1988             if(vd_IsSetuped)
1989                 DPO->printOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber);
1990             vd_PrevParametrs = getParametrs();
1991             return vd_IsSetuped;
1992         }
1993         else
1994         {
1995             DPO->printOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber);
1996             return false;
1997         }
1998     }
1999     else
2000     {
2001         DPO->printOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber);
2002         return false;
2003     }
2004 }
2005
2006 bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate)
2007 {
2008     unsigned int id = findType(w * h, idealFramerate);
2009     return setupDevice(id);
2010 }
2011
2012 wchar_t *videoDevice::getName()
2013 {
2014     return vd_pFriendlyName;
2015 }
2016
2017 videoDevice::~videoDevice(void)
2018 {
2019     closeDevice();
2020     SafeRelease(&vd_pSource);
2021     if(vd_pFriendlyName)
2022         CoTaskMemFree(vd_pFriendlyName);
2023 }
2024
2025 HRESULT videoDevice::enumerateCaptureFormats(IMFMediaSource *pSource)
2026 {
2027     ComPtr<IMFPresentationDescriptor> pPD = NULL;
2028     ComPtr<IMFStreamDescriptor> pSD = NULL;
2029     ComPtr<IMFMediaTypeHandler> pHandler = NULL;
2030     ComPtr<IMFMediaType> pType = NULL;
2031     HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf());
2032     if (FAILED(hr))
2033     {
2034         goto done;
2035     }
2036     BOOL fSelected;
2037     hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf());
2038     if (FAILED(hr))
2039     {
2040         goto done;
2041     }
2042     hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf());
2043     if (FAILED(hr))
2044     {
2045         goto done;
2046     }
2047     DWORD cTypes = 0;
2048     hr = pHandler->GetMediaTypeCount(&cTypes);
2049     if (FAILED(hr))
2050     {
2051         goto done;
2052     }
2053     for (DWORD i = 0; i < cTypes; i++)
2054     {
2055         hr = pHandler->GetMediaTypeByIndex(i, pType.GetAddressOf());
2056         if (FAILED(hr))
2057         {
2058             goto done;
2059         }
2060         MediaType MT = FormatReader::Read(pType.Get());
2061         vd_CurrentFormats.push_back(MT);
2062     }
2063
2064 done:
2065     return hr;
2066 }
2067
2068 videoDevices::videoDevices(void): count(0)
2069 {}
2070
2071 void videoDevices::clearDevices()
2072 {
2073     std::vector<videoDevice *>::iterator i = vds_Devices.begin();
2074     for(; i != vds_Devices.end(); ++i)
2075         delete (*i);
2076     vds_Devices.clear();
2077 }
2078
2079 videoDevices::~videoDevices(void)
2080 {
2081     clearDevices();
2082 }
2083
2084 videoDevice * videoDevices::getDevice(unsigned int i)
2085 {
2086     if(i >= vds_Devices.size())
2087     {
2088         return NULL;
2089     }
2090     if(i < 0)
2091     {
2092         return NULL;
2093     }
2094     return vds_Devices[i];
2095 }
2096
2097 long videoDevices::initDevices(IMFAttributes *pAttributes)
2098 {
2099     HRESULT hr = S_OK;
2100     IMFActivate **ppDevices = NULL;
2101     clearDevices();
2102     hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
2103     if (SUCCEEDED(hr))
2104     {
2105         if(count > 0)
2106         {
2107             for(UINT32 i = 0; i < count; i++)
2108             {
2109                 videoDevice *vd = new videoDevice;
2110                 vd->readInfoOfDevice(ppDevices[i], i);
2111                 vds_Devices.push_back(vd);
2112                 SafeRelease(&ppDevices[i]);
2113             }
2114             SafeRelease(ppDevices);
2115         }
2116         else
2117             hr = -1;
2118     }
2119     else
2120     {
2121         DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2122         DPO->printOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n");
2123     }
2124     return hr;
2125 }
2126
2127 unsigned int videoDevices::getCount()
2128 {
2129     return vds_Devices.size();
2130 }
2131
2132 videoDevices& videoDevices::getInstance()
2133 {
2134     static videoDevices instance;
2135     return instance;
2136 }
2137
2138 Parametr::Parametr()
2139 {
2140     CurrentValue = 0;
2141     Min = 0;
2142     Max = 0;
2143     Step = 0;
2144     Default = 0;
2145     Flag = 0;
2146 }
2147
2148 MediaType::MediaType()
2149 {
2150     pMF_MT_AM_FORMAT_TYPEName = NULL;
2151     pMF_MT_MAJOR_TYPEName = NULL;
2152     pMF_MT_SUBTYPEName = NULL;
2153     Clear();
2154 }
2155
2156 MediaType::~MediaType()
2157 {
2158     Clear();
2159 }
2160
2161 void MediaType::Clear()
2162 {
2163     MF_MT_FRAME_SIZE = 0;
2164     height = 0;
2165     width = 0;
2166     MF_MT_YUV_MATRIX = 0;
2167     MF_MT_VIDEO_LIGHTING = 0;
2168     MF_MT_DEFAULT_STRIDE = 0;
2169     MF_MT_VIDEO_CHROMA_SITING = 0;
2170     MF_MT_FIXED_SIZE_SAMPLES = 0;
2171     MF_MT_VIDEO_NOMINAL_RANGE = 0;
2172     MF_MT_FRAME_RATE_NUMERATOR = 0;
2173     MF_MT_FRAME_RATE_DENOMINATOR = 0;
2174     MF_MT_PIXEL_ASPECT_RATIO = 0;
2175     MF_MT_PIXEL_ASPECT_RATIO_low = 0;
2176     MF_MT_ALL_SAMPLES_INDEPENDENT = 0;
2177     MF_MT_FRAME_RATE_RANGE_MIN = 0;
2178     MF_MT_FRAME_RATE_RANGE_MIN_low = 0;
2179     MF_MT_SAMPLE_SIZE = 0;
2180     MF_MT_VIDEO_PRIMARIES = 0;
2181     MF_MT_INTERLACE_MODE = 0;
2182     MF_MT_FRAME_RATE_RANGE_MAX = 0;
2183     MF_MT_FRAME_RATE_RANGE_MAX_low = 0;
2184     memset(&MF_MT_MAJOR_TYPE, 0, sizeof(GUID));
2185     memset(&MF_MT_AM_FORMAT_TYPE, 0, sizeof(GUID));
2186     memset(&MF_MT_SUBTYPE, 0, sizeof(GUID));
2187 }
2188
2189 videoInput::videoInput(void): accessToDevices(false)
2190 {
2191     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2192     DPO->printOut(L"\n***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****\n\n");
2193     updateListOfDevices();
2194     if(!accessToDevices)
2195         DPO->printOut(L"INITIALIZATION: Ther is not any suitable video device\n");
2196 }
2197
2198 void videoInput::updateListOfDevices()
2199 {
2200     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2201     Media_Foundation *MF = &Media_Foundation::getInstance();
2202     accessToDevices = MF->buildListOfDevices();
2203     if(!accessToDevices)
2204         DPO->printOut(L"UPDATING: Ther is not any suitable video device\n");
2205 }
2206
2207 videoInput::~videoInput(void)
2208 {
2209     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2210     DPO->printOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n");
2211 }
2212
2213 IMFMediaSource *videoInput::getMediaSource(int deviceID)
2214 {
2215     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2216     if(accessToDevices)
2217     {
2218         videoDevices *VDS = &videoDevices::getInstance();
2219         videoDevice * VD = VDS->getDevice(deviceID);
2220         if(VD)
2221         {
2222             IMFMediaSource *out = VD->getMediaSource();
2223             if(!out)
2224                 DPO->printOut(L"VideoDevice %i: There is not any suitable IMFMediaSource interface\n", deviceID);
2225             return out;
2226         }
2227     }
2228     else
2229     {
2230         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2231     }
2232     return NULL;
2233 }
2234
2235 bool videoInput::setupDevice(int deviceID, unsigned int id)
2236 {
2237     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2238     if (deviceID < 0 )
2239     {
2240         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2241         return false;
2242     }
2243     if(accessToDevices)
2244     {
2245         videoDevices *VDS = &videoDevices::getInstance();
2246         videoDevice * VD = VDS->getDevice(deviceID);
2247         if(VD)
2248         {
2249             bool out = VD->setupDevice(id);
2250             if(!out)
2251                 DPO->printOut(L"VIDEODEVICE %i: This device cannot be started\n", deviceID);
2252             return out;
2253         }
2254     }
2255     else
2256     {
2257         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2258     }
2259     return false;
2260 }
2261
2262 bool videoInput::setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate)
2263 {
2264     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2265     if (deviceID < 0 )
2266     {
2267         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2268         return false;
2269     }
2270     if(accessToDevices)
2271     {
2272         videoDevices *VDS = &videoDevices::getInstance();
2273         videoDevice * VD = VDS->getDevice(deviceID);
2274         if(VD)
2275         {
2276             bool out = VD->setupDevice(w, h, idealFramerate);
2277             if(!out)
2278                 DPO->printOut(L"VIDEODEVICE %i: this device cannot be started\n", deviceID);
2279             return out;
2280         }
2281     }
2282     else
2283     {
2284         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n", deviceID);
2285     }
2286     return false;
2287 }
2288
2289 MediaType videoInput::getFormat(int deviceID, unsigned int id)
2290 {
2291     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2292     if (deviceID < 0)
2293     {
2294         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2295         return MediaType();
2296     }
2297     if(accessToDevices)
2298     {
2299         videoDevices *VDS = &videoDevices::getInstance();
2300         videoDevice * VD = VDS->getDevice(deviceID);
2301         if(VD)
2302             return VD->getFormat(id);
2303     }
2304     else
2305     {
2306         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2307     }
2308     return MediaType();
2309 }
2310
2311 bool videoInput::isDeviceSetup(int deviceID)
2312 {
2313     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2314     if (deviceID < 0)
2315     {
2316         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2317         return false;
2318     }
2319     if(accessToDevices)
2320     {
2321         videoDevices *VDS = &videoDevices::getInstance();
2322         videoDevice * VD = VDS->getDevice(deviceID);
2323         if(VD)
2324             return VD->isDeviceSetup();
2325     }
2326     else
2327     {
2328         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2329     }
2330     return false;
2331 }
2332
2333 bool videoInput::isDeviceMediaSource(int deviceID)
2334 {
2335     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2336     if (deviceID < 0)
2337     {
2338         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2339         return false;
2340     }
2341     if(accessToDevices)
2342     {
2343         videoDevices *VDS = &videoDevices::getInstance();
2344         videoDevice * VD = VDS->getDevice(deviceID);
2345         if(VD)
2346             return VD->isDeviceMediaSource();
2347     }
2348     else
2349     {
2350         DPO->printOut(L"Device(s): There is not any suitable video device\n");
2351     }
2352     return false;
2353 }
2354
2355 bool videoInput::isDeviceRawDataSource(int deviceID)
2356 {
2357     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2358     if (deviceID < 0)
2359     {
2360         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2361         return false;
2362     }
2363     if(accessToDevices)
2364     {
2365         videoDevices *VDS = &videoDevices::getInstance();
2366         videoDevice * VD = VDS->getDevice(deviceID);
2367         if(VD)
2368         {
2369             bool isRaw = VD->isDeviceRawDataSource();
2370             return isRaw;
2371         }
2372     }
2373     else
2374     {
2375         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2376     }
2377     return false;
2378 }
2379
2380 bool videoInput::isFrameNew(int deviceID)
2381 {
2382     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2383     if (deviceID < 0)
2384     {
2385         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2386         return false;
2387     }
2388     if(accessToDevices)
2389     {
2390         if(!isDeviceSetup(deviceID))
2391         {
2392             if(isDeviceMediaSource(deviceID))
2393                 return false;
2394         }
2395         videoDevices *VDS = &videoDevices::getInstance();
2396         videoDevice * VD = VDS->getDevice(deviceID);
2397         if(VD)
2398         {
2399             return VD->isFrameNew();
2400         }
2401     }
2402     else
2403     {
2404         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2405     }
2406     return false;
2407 }
2408
2409 unsigned int videoInput::getCountFormats(int deviceID)
2410 {
2411     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2412     if (deviceID < 0)
2413     {
2414         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2415         return 0;
2416     }
2417     if(accessToDevices)
2418     {
2419         videoDevices *VDS = &videoDevices::getInstance();
2420         videoDevice * VD = VDS->getDevice(deviceID);
2421         if(VD)
2422             return VD->getCountFormats();
2423     }
2424     else
2425     {
2426         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2427     }
2428     return 0;
2429 }
2430
2431 void videoInput::closeAllDevices()
2432 {
2433     videoDevices *VDS = &videoDevices::getInstance();
2434     for(unsigned int i = 0; i < VDS->getCount(); i++)
2435         closeDevice(i);
2436 }
2437
2438 void videoInput::setParametrs(int deviceID, CamParametrs parametrs)
2439 {
2440     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2441     if (deviceID < 0)
2442     {
2443         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2444         return;
2445     }
2446     if(accessToDevices)
2447     {
2448         videoDevices *VDS = &videoDevices::getInstance();
2449         videoDevice *VD = VDS->getDevice(deviceID);
2450         if(VD)
2451             VD->setParametrs(parametrs);
2452     }
2453     else
2454     {
2455         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2456     }
2457 }
2458
2459 CamParametrs videoInput::getParametrs(int deviceID)
2460 {
2461     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2462     CamParametrs out;
2463     if (deviceID < 0)
2464     {
2465         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2466         return out;
2467     }
2468     if(accessToDevices)
2469     {
2470         videoDevices *VDS = &videoDevices::getInstance();
2471         videoDevice *VD = VDS->getDevice(deviceID);
2472         if(VD)
2473             out = VD->getParametrs();
2474     }
2475     else
2476     {
2477         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2478     }
2479     return out;
2480 }
2481
2482 void videoInput::closeDevice(int deviceID)
2483 {
2484     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2485     if (deviceID < 0)
2486     {
2487         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2488         return;
2489     }
2490     if(accessToDevices)
2491     {
2492         videoDevices *VDS = &videoDevices::getInstance();
2493         videoDevice *VD = VDS->getDevice(deviceID);
2494         if(VD)
2495             VD->closeDevice();
2496     }
2497     else
2498     {
2499         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2500     }
2501 }
2502
2503 unsigned int videoInput::getWidth(int deviceID)
2504 {
2505     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2506     if (deviceID < 0)
2507     {
2508         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2509         return 0;
2510     }
2511     if(accessToDevices)
2512     {
2513         videoDevices *VDS = &videoDevices::getInstance();
2514         videoDevice * VD = VDS->getDevice(deviceID);
2515         if(VD)
2516             return VD->getWidth();
2517     }
2518     else
2519     {
2520         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2521     }
2522     return 0;
2523 }
2524
2525 unsigned int videoInput::getHeight(int deviceID)
2526 {
2527     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2528     if (deviceID < 0)
2529     {
2530         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2531         return 0;
2532     }
2533     if(accessToDevices)
2534     {
2535         videoDevices *VDS = &videoDevices::getInstance();
2536         videoDevice * VD = VDS->getDevice(deviceID);
2537         if(VD)
2538             return VD->getHeight();
2539     }
2540     else
2541     {
2542         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2543     }
2544     return 0;
2545 }
2546
2547 wchar_t *videoInput::getNameVideoDevice(int deviceID)
2548 {
2549     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2550     if (deviceID < 0)
2551     {
2552         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2553         return NULL;
2554     }
2555     if(accessToDevices)
2556     {
2557         videoDevices *VDS = &videoDevices::getInstance();
2558         videoDevice * VD = VDS->getDevice(deviceID);
2559         if(VD)
2560             return VD->getName();
2561     }
2562     else
2563     {
2564         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2565     }
2566     return L"Empty";
2567 }
2568
2569 unsigned int videoInput::listDevices(bool silent)
2570 {
2571     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2572     int out = 0;
2573     if(accessToDevices)
2574     {
2575         videoDevices *VDS = &videoDevices::getInstance();
2576         out = VDS->getCount();
2577         DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2578         if(!silent)DPO->printOut(L"\nVIDEOINPUT SPY MODE!\n\n");
2579         if(!silent)DPO->printOut(L"SETUP: Looking For Capture Devices\n");
2580         for(int i = 0; i < out; i++)
2581         {
2582             if(!silent)DPO->printOut(L"SETUP: %i) %s \n",i, getNameVideoDevice(i));
2583         }
2584         if(!silent)DPO->printOut(L"SETUP: %i Device(s) found\n\n", out);
2585     }
2586     else
2587     {
2588         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2589     }
2590     return out;
2591 }
2592
2593 videoInput& videoInput::getInstance()
2594 {
2595     static videoInput instance;
2596     return instance;
2597 }
2598
2599 bool videoInput::isDevicesAcceable()
2600 {
2601     return accessToDevices;
2602 }
2603
2604 void videoInput::setVerbose(bool state)
2605 {
2606     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2607     DPO->setVerbose(state);
2608 }
2609
2610 void videoInput::setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *))
2611 {
2612     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2613     if (deviceID < 0)
2614     {
2615         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2616         return;
2617     }
2618     if(accessToDevices)
2619     {
2620         if(func)
2621         {
2622             videoDevices *VDS = &videoDevices::getInstance();
2623             videoDevice * VD = VDS->getDevice(deviceID);
2624             if(VD)
2625                 VD->setEmergencyStopEvent(userData, func);
2626         }
2627     }
2628     else
2629     {
2630         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2631     }
2632 }
2633
2634 bool videoInput::getPixels(int deviceID, unsigned char * dstBuffer, bool flipRedAndBlue, bool flipImage)
2635 {
2636     bool success = false;
2637     unsigned int bytes = 3;
2638     DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2639     if (deviceID < 0)
2640     {
2641         DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2642         return success;
2643     }
2644     if(accessToDevices)
2645     {
2646         bool isRaw = isDeviceRawDataSource(deviceID);
2647         if(isRaw)
2648         {
2649             videoDevices *VDS = &videoDevices::getInstance();
2650             DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2651             RawImage *RIOut = VDS->getDevice(deviceID)->getRawImageOut();
2652             if(RIOut)
2653             {
2654                 unsigned int height = VDS->getDevice(deviceID)->getHeight();
2655                 unsigned int width  = VDS->getDevice(deviceID)->getWidth();
2656                 unsigned int size = bytes * width * height;
2657                 if(size == RIOut->getSize())
2658                 {
2659                     processPixels(RIOut->getpPixels(), dstBuffer, width, height, bytes, flipRedAndBlue, flipImage);
2660                     success = true;
2661                 }
2662                 else
2663                 {
2664                     DPO->printOut(L"ERROR: GetPixels() - bufferSizes do not match!\n");
2665                 }
2666             }
2667             else
2668             {
2669                 DPO->printOut(L"ERROR: GetPixels() - Unable to grab frame for device %i\n", deviceID);
2670             }
2671         }
2672         else
2673         {
2674             DPO->printOut(L"ERROR: GetPixels() - Not raw data source device %i\n", deviceID);
2675         }
2676     }
2677     else
2678     {
2679         DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2680     }
2681     return success;
2682 }
2683
2684 void videoInput::processPixels(unsigned char * src, unsigned char * dst, unsigned int width,
2685                                 unsigned int height, unsigned int bpp, bool bRGB, bool bFlip)
2686 {
2687     unsigned int widthInBytes = width * bpp;
2688     unsigned int numBytes = widthInBytes * height;
2689     int *dstInt, *srcInt;
2690     if(!bRGB)
2691     {
2692         if(bFlip)
2693         {
2694             for(unsigned int y = 0; y < height; y++)
2695             {
2696                 dstInt = (int *)(dst + (y * widthInBytes));
2697                 srcInt = (int *)(src + ( (height -y -1) * widthInBytes));
2698                 memcpy(dstInt, srcInt, widthInBytes);
2699             }
2700         }
2701         else
2702         {
2703             memcpy(dst, src, numBytes);
2704         }
2705     }
2706     else
2707     {
2708         if(bFlip)
2709         {
2710             unsigned int x = 0;
2711             unsigned int y = (height - 1) * widthInBytes;
2712             src += y;
2713             for(unsigned int i = 0; i < numBytes; i+=3)
2714             {
2715                 if(x >= width)
2716                 {
2717                     x = 0;
2718                     src -= widthInBytes*2;
2719                 }
2720                 *dst = *(src+2);
2721                 dst++;
2722                 *dst = *(src+1);
2723                 dst++;
2724                 *dst = *src;
2725                 dst++;
2726                 src+=3;
2727                 x++;
2728             }
2729         }
2730         else
2731         {
2732             for(unsigned int i = 0; i < numBytes; i+=3)
2733             {
2734                 *dst = *(src+2);
2735                 dst++;
2736                 *dst = *(src+1);
2737                 dst++;
2738                 *dst = *src;
2739                 dst++;
2740                 src+=3;
2741             }
2742         }
2743     }
2744 }
2745 }
2746
2747 /******* Capturing video from camera via Microsoft Media Foundation **********/
2748 class CvCaptureCAM_MSMF : public CvCapture
2749 {
2750 public:
2751     CvCaptureCAM_MSMF();
2752     virtual ~CvCaptureCAM_MSMF();
2753     virtual bool open( int index );
2754     virtual void close();
2755     virtual double getProperty(int);
2756     virtual bool setProperty(int, double);
2757     virtual bool grabFrame();
2758     virtual IplImage* retrieveFrame(int);
2759     virtual int getCaptureDomain() { return CV_CAP_MSMF; } // Return the type of the capture object: CV_CAP_VFW, etc...
2760 protected:
2761     void init();
2762     int index, width, height, fourcc;
2763     IplImage* frame;
2764     videoInput VI;
2765 };
2766
2767 struct SuppressVideoInputMessages
2768 {
2769     SuppressVideoInputMessages() { videoInput::setVerbose(true); }
2770 };
2771
2772 static SuppressVideoInputMessages do_it;
2773
2774 CvCaptureCAM_MSMF::CvCaptureCAM_MSMF():
2775     index(-1),
2776     width(-1),
2777     height(-1),
2778     fourcc(-1),
2779     frame(NULL),
2780     VI(videoInput::getInstance())
2781 {
2782     CoInitialize(0);
2783 }
2784
2785 CvCaptureCAM_MSMF::~CvCaptureCAM_MSMF()
2786 {
2787     close();
2788     CoUninitialize();
2789 }
2790
2791 void CvCaptureCAM_MSMF::close()
2792 {
2793     if( index >= 0 )
2794     {
2795         VI.closeDevice(index);
2796         index = -1;
2797         cvReleaseImage(&frame);
2798     }
2799     width = height = -1;
2800 }
2801
2802 // Initialize camera input
2803 bool CvCaptureCAM_MSMF::open( int _index )
2804 {
2805     int try_index = _index;
2806     int devices = 0;
2807     close();
2808     devices = VI.listDevices(true);
2809     if (devices == 0)
2810         return false;
2811     try_index = try_index < 0 ? 0 : (try_index > devices-1 ? devices-1 : try_index);
2812     VI.setupDevice(try_index);
2813     if( !VI.isFrameNew(try_index) )
2814         return false;
2815     index = try_index;
2816     return true;
2817 }
2818
2819 bool CvCaptureCAM_MSMF::grabFrame()
2820 {
2821     while (VI.isDeviceSetup(index) && !VI.isFrameNew(index))
2822         Sleep(1);
2823     return VI.isDeviceSetup(index);
2824 }
2825
2826 IplImage* CvCaptureCAM_MSMF::retrieveFrame(int)
2827 {
2828     if( !frame || (int)VI.getWidth(index) != frame->width || (int)VI.getHeight(index) != frame->height )
2829     {
2830         if (frame)
2831             cvReleaseImage( &frame );
2832         unsigned int w = VI.getWidth(index), h = VI.getHeight(index);
2833         frame = cvCreateImage( cvSize(w,h), 8, 3 );
2834     }
2835     VI.getPixels( index, (uchar*)frame->imageData, false, true );
2836     return frame;
2837 }
2838
2839 double CvCaptureCAM_MSMF::getProperty( int property_id )
2840 {
2841     // image format proprrties
2842     switch( property_id )
2843     {
2844     case CV_CAP_PROP_FRAME_WIDTH:
2845         return VI.getWidth(index);
2846     case CV_CAP_PROP_FRAME_HEIGHT:
2847         return VI.getHeight(index);
2848     }
2849     return -1;
2850 }
2851 bool CvCaptureCAM_MSMF::setProperty( int property_id, double value )
2852 {
2853     // image capture properties
2854     bool handled = false;
2855     switch( property_id )
2856     {
2857     case CV_CAP_PROP_FRAME_WIDTH:
2858         width = cvRound(value);
2859         handled = true;
2860         break;
2861     case CV_CAP_PROP_FRAME_HEIGHT:
2862         height = cvRound(value);
2863         handled = true;
2864         break;
2865     }
2866
2867     if ( handled ) {
2868         if( width > 0 && height > 0 )
2869         {
2870             if( width != (int)VI.getWidth(index) || height != (int)VI.getHeight(index)  && VI.isDeviceSetup(index))//|| fourcc != VI.getFourcc(index) )
2871             {
2872                 VI.closeDevice(index);
2873                 VI.setupDevice(index, width, height);
2874             }
2875             return VI.isDeviceSetup(index);
2876         }
2877         return true;
2878     }
2879
2880     return false;
2881 }
2882
2883 class CvCaptureFile_MSMF : public CvCapture
2884 {
2885 public:
2886     CvCaptureFile_MSMF();
2887     virtual ~CvCaptureFile_MSMF();
2888
2889     virtual bool open( const char* filename );
2890     virtual void close();
2891
2892     virtual double getProperty(int);
2893     virtual bool setProperty(int, double);
2894     virtual bool grabFrame();
2895     virtual IplImage* retrieveFrame(int);
2896     virtual int getCaptureDomain() { return CV_CAP_MSMF; }
2897 protected:
2898     ImageGrabberThread* grabberThread;
2899     IMFMediaSource* videoFileSource;
2900     std::vector<MediaType> captureFormats;
2901     int captureFormatIndex;
2902     IplImage* frame;
2903     bool isOpened;
2904
2905     HRESULT enumerateCaptureFormats(IMFMediaSource *pSource);
2906     HRESULT getSourceDuration(IMFMediaSource *pSource, MFTIME *pDuration);
2907 };
2908
2909 CvCaptureFile_MSMF::CvCaptureFile_MSMF():
2910     grabberThread(NULL),
2911     videoFileSource(NULL),
2912     captureFormatIndex(0),
2913     frame(NULL),
2914     isOpened(false)
2915 {
2916     MFStartup(MF_VERSION);
2917 }
2918
2919 CvCaptureFile_MSMF::~CvCaptureFile_MSMF()
2920 {
2921     close();
2922     MFShutdown();
2923 }
2924
2925 bool CvCaptureFile_MSMF::open(const char* filename)
2926 {
2927     if (!filename)
2928         return false;
2929
2930     wchar_t* unicodeFileName = new wchar_t[strlen(filename)+1];
2931     MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, strlen(filename)+1);
2932
2933     HRESULT hr = S_OK;
2934
2935     MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
2936
2937     ComPtr<IMFSourceResolver> pSourceResolver = NULL;
2938     IUnknown* pUnkSource = NULL;
2939
2940     hr = MFCreateSourceResolver(pSourceResolver.GetAddressOf());
2941
2942     if (SUCCEEDED(hr))
2943     {
2944         hr = pSourceResolver->CreateObjectFromURL(
2945             unicodeFileName,
2946             MF_RESOLUTION_MEDIASOURCE,
2947             NULL, // Optional property store.
2948             &ObjectType,
2949             &pUnkSource
2950             );
2951     }
2952
2953     // Get the IMFMediaSource from the IUnknown pointer.
2954     if (SUCCEEDED(hr))
2955     {
2956         hr = pUnkSource->QueryInterface(IID_PPV_ARGS(&videoFileSource));
2957     }
2958
2959     SafeRelease(&pUnkSource);
2960
2961     if (SUCCEEDED(hr))
2962     {
2963         hr = enumerateCaptureFormats(videoFileSource);
2964     }
2965
2966     if (SUCCEEDED(hr))
2967     {
2968         hr = ImageGrabberThread::CreateInstance(&grabberThread, videoFileSource, (unsigned int)-2, true);
2969     }
2970
2971     if (SUCCEEDED(hr))
2972     {
2973         grabberThread->start();
2974     }
2975
2976     isOpened = SUCCEEDED(hr);
2977
2978     return isOpened;
2979 }
2980
2981 void CvCaptureFile_MSMF::close()
2982 {
2983     if (grabberThread)
2984     {
2985         isOpened = false;
2986         SetEvent(grabberThread->getImageGrabber()->ig_hFinish);
2987         grabberThread->stop();
2988         delete grabberThread;
2989     }
2990
2991     if (videoFileSource)
2992     {
2993         videoFileSource->Shutdown();
2994     }
2995 }
2996
2997 bool CvCaptureFile_MSMF::setProperty(int property_id, double value)
2998 {
2999     // image capture properties
3000     // FIXME: implement method in VideoInput back end
3001     (void) property_id;
3002     (void) value;
3003     return false;
3004 }
3005
3006 double CvCaptureFile_MSMF::getProperty(int property_id)
3007 {
3008     // image format proprrties
3009     switch( property_id )
3010     {
3011     case CV_CAP_PROP_FRAME_WIDTH:
3012         return captureFormats[captureFormatIndex].width;
3013     case CV_CAP_PROP_FRAME_HEIGHT:
3014         return captureFormats[captureFormatIndex].height;
3015     case CV_CAP_PROP_FRAME_COUNT:
3016         {
3017             MFTIME duration;
3018             getSourceDuration(this->videoFileSource, &duration);
3019             double fps = ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_NUMERATOR) /
3020             ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_DENOMINATOR);
3021             return (double)floor(((double)duration/1e7)*fps+0.5);
3022         }
3023     case CV_CAP_PROP_FOURCC:
3024         return captureFormats[captureFormatIndex].MF_MT_SUBTYPE.Data1;
3025     case CV_CAP_PROP_FPS:
3026         return ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_NUMERATOR) /
3027             ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_DENOMINATOR);
3028     }
3029  
3030     return -1;
3031 }
3032
3033 bool CvCaptureFile_MSMF::grabFrame()
3034 {
3035     DWORD waitResult = (DWORD)-1;
3036     if (isOpened)
3037     {
3038         SetEvent(grabberThread->getImageGrabber()->ig_hFrameGrabbed);
3039         HANDLE tmp[] = {grabberThread->getImageGrabber()->ig_hFrameReady, grabberThread->getImageGrabber()->ig_hFinish, 0};
3040         waitResult = WaitForMultipleObjects(2, tmp, FALSE, INFINITE);
3041     }
3042
3043     return isOpened && grabberThread->getImageGrabber()->getRawImage()->isNew() && (waitResult == WAIT_OBJECT_0);
3044 }
3045
3046 IplImage* CvCaptureFile_MSMF::retrieveFrame(int)
3047 {
3048     unsigned int width = captureFormats[captureFormatIndex].width;
3049     unsigned int height = captureFormats[captureFormatIndex].height;
3050     unsigned int bytes = 3;
3051     if( !frame || (int)width != frame->width || (int)height != frame->height )
3052     {
3053         if (frame)
3054             cvReleaseImage( &frame );
3055         frame = cvCreateImage( cvSize(width,height), 8, 3 );
3056     }
3057
3058     RawImage *RIOut = grabberThread->getImageGrabber()->getRawImage();
3059     unsigned int size = bytes * width * height;
3060
3061     bool verticalFlip = captureFormats[captureFormatIndex].MF_MT_DEFAULT_STRIDE < 0;
3062
3063     if(RIOut && size == RIOut->getSize())
3064     {
3065          videoInput::processPixels(RIOut->getpPixels(), (unsigned char*)frame->imageData, width, 
3066              height, bytes, false, verticalFlip);
3067     }
3068
3069     return frame;
3070 }
3071
3072 HRESULT CvCaptureFile_MSMF::enumerateCaptureFormats(IMFMediaSource *pSource)
3073 {
3074     ComPtr<IMFPresentationDescriptor> pPD = NULL;
3075     ComPtr<IMFStreamDescriptor> pSD = NULL;
3076     ComPtr<IMFMediaTypeHandler> pHandler = NULL;
3077     ComPtr<IMFMediaType> pType = NULL;
3078     HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf());
3079     if (FAILED(hr))
3080     {
3081         goto done;
3082     }
3083
3084     BOOL fSelected;
3085     hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf());
3086     if (FAILED(hr))
3087     {
3088         goto done;
3089     }
3090     hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf());
3091     if (FAILED(hr))
3092     {
3093         goto done;
3094     }
3095     DWORD cTypes = 0;
3096     hr = pHandler->GetMediaTypeCount(&cTypes);
3097     if (FAILED(hr))
3098     {
3099         goto done;
3100     }
3101     for (DWORD i = 0; i < cTypes; i++)
3102     {
3103         hr = pHandler->GetMediaTypeByIndex(i, pType.GetAddressOf());
3104         if (FAILED(hr))
3105         {
3106             goto done;
3107         }
3108         MediaType MT = FormatReader::Read(pType.Get());
3109         captureFormats.push_back(MT);
3110     }
3111
3112 done:
3113     return hr;
3114 }
3115
3116 HRESULT CvCaptureFile_MSMF::getSourceDuration(IMFMediaSource *pSource, MFTIME *pDuration)
3117 {
3118     *pDuration = 0;
3119
3120     IMFPresentationDescriptor *pPD = NULL;
3121
3122     HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
3123     if (SUCCEEDED(hr))
3124     {
3125         hr = pPD->GetUINT64(MF_PD_DURATION, (UINT64*)pDuration);
3126         pPD->Release();
3127     }
3128     return hr;
3129 }
3130
3131 CvCapture* cvCreateCameraCapture_MSMF( int index )
3132 {
3133     CvCaptureCAM_MSMF* capture = new CvCaptureCAM_MSMF;
3134     try
3135     {
3136         if( capture->open( index ))
3137             return capture;
3138     }
3139     catch(...)
3140     {
3141         delete capture;
3142         throw;
3143     }
3144     delete capture;
3145     return 0;
3146 }
3147
3148 CvCapture* cvCreateFileCapture_MSMF (const char* filename)
3149 {
3150     CvCaptureFile_MSMF* capture = new CvCaptureFile_MSMF;
3151     try
3152     {
3153         if( capture->open(filename) )
3154             return capture;
3155         else
3156         {
3157             delete capture;
3158             return NULL;
3159         }
3160     }
3161     catch(...)
3162     {
3163         delete capture;
3164         throw;
3165     }
3166 }
3167
3168 //
3169 //
3170 // Media Foundation-based Video Writer
3171 //
3172 //
3173
3174 class CvVideoWriter_MSMF : public CvVideoWriter
3175 {
3176 public:
3177     CvVideoWriter_MSMF();
3178     virtual ~CvVideoWriter_MSMF();
3179     virtual bool open(const char* filename, int fourcc,
3180                        double fps, CvSize frameSize, bool isColor);
3181     virtual void close();
3182     virtual bool writeFrame(const IplImage* img);
3183
3184 private:
3185     UINT32 videoWidth;
3186     UINT32 videoHeight;
3187     double fps;
3188     UINT32 bitRate;
3189     UINT32 frameSize;
3190     GUID   encodingFormat;
3191     GUID   inputFormat;
3192
3193     DWORD  streamIndex;
3194     ComPtr<IMFSinkWriter> sinkWriter;
3195
3196     bool   initiated;
3197
3198     LONGLONG rtStart;
3199     UINT64 rtDuration;
3200
3201     HRESULT InitializeSinkWriter(const char* filename);
3202     static const GUID FourCC2GUID(int fourcc);
3203     HRESULT WriteFrame(DWORD *videoFrameBuffer, const LONGLONG& rtStart, const LONGLONG& rtDuration);
3204 };
3205
3206 CvVideoWriter_MSMF::CvVideoWriter_MSMF():
3207     initiated(false)
3208 {
3209 }
3210
3211 CvVideoWriter_MSMF::~CvVideoWriter_MSMF()
3212 {
3213     close();
3214 }
3215
3216 const GUID CvVideoWriter_MSMF::FourCC2GUID(int fourcc)
3217 {
3218     switch(fourcc)
3219     {
3220         case CV_FOURCC_MACRO('d', 'v', '2', '5'):
3221             return MFVideoFormat_DV25; break;
3222         case CV_FOURCC_MACRO('d', 'v', '5', '0'):
3223             return MFVideoFormat_DV50; break;
3224         case CV_FOURCC_MACRO('d', 'v', 'c', ' '):
3225             return MFVideoFormat_DVC; break;
3226         case CV_FOURCC_MACRO('d', 'v', 'h', '1'):
3227             return MFVideoFormat_DVH1; break;
3228         case CV_FOURCC_MACRO('d', 'v', 'h', 'd'):
3229             return MFVideoFormat_DVHD; break;
3230         case CV_FOURCC_MACRO('d', 'v', 's', 'd'):
3231             return MFVideoFormat_DVSD; break;
3232         case CV_FOURCC_MACRO('d', 'v', 's', 'l'):
3233                 return MFVideoFormat_DVSL; break;
3234         case CV_FOURCC_MACRO('H', '2', '6', '3'):
3235                 return MFVideoFormat_H263; break;
3236         case CV_FOURCC_MACRO('H', '2', '6', '4'):
3237                 return MFVideoFormat_H264; break;
3238         case CV_FOURCC_MACRO('M', '4', 'S', '2'):
3239                 return MFVideoFormat_M4S2; break;
3240         case CV_FOURCC_MACRO('M', 'J', 'P', 'G'):
3241                 return MFVideoFormat_MJPG; break;
3242         case CV_FOURCC_MACRO('M', 'P', '4', '3'):
3243                 return MFVideoFormat_MP43; break;
3244         case CV_FOURCC_MACRO('M', 'P', '4', 'S'):
3245                 return MFVideoFormat_MP4S; break;
3246         case CV_FOURCC_MACRO('M', 'P', '4', 'V'):
3247                 return MFVideoFormat_MP4V; break;
3248         case CV_FOURCC_MACRO('M', 'P', 'G', '1'):
3249                 return MFVideoFormat_MPG1; break;
3250         case CV_FOURCC_MACRO('M', 'S', 'S', '1'):
3251                 return MFVideoFormat_MSS1; break;
3252         case CV_FOURCC_MACRO('M', 'S', 'S', '2'):
3253                 return MFVideoFormat_MSS2; break;
3254         case CV_FOURCC_MACRO('W', 'M', 'V', '1'):
3255                 return MFVideoFormat_WMV1; break;
3256         case CV_FOURCC_MACRO('W', 'M', 'V', '2'):
3257                 return MFVideoFormat_WMV2; break;
3258         case CV_FOURCC_MACRO('W', 'M', 'V', '3'):
3259                 return MFVideoFormat_WMV3; break;
3260         case CV_FOURCC_MACRO('W', 'V', 'C', '1'):
3261                 return MFVideoFormat_WVC1; break;
3262         default:
3263             return MFVideoFormat_H264;
3264     }
3265 }
3266
3267 bool CvVideoWriter_MSMF::open( const char* filename, int fourcc,
3268                        double _fps, CvSize frameSize, bool /*isColor*/ )
3269 {
3270     videoWidth = frameSize.width;
3271     videoHeight = frameSize.height;
3272     fps = _fps;
3273     bitRate = (UINT32)fps*videoWidth*videoHeight; // 1-bit per pixel
3274     encodingFormat = FourCC2GUID(fourcc);
3275     inputFormat = MFVideoFormat_RGB32;
3276
3277     HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3278     if (SUCCEEDED(hr))
3279     {
3280         hr = MFStartup(MF_VERSION);
3281         if (SUCCEEDED(hr))
3282         {
3283             hr = InitializeSinkWriter(filename);
3284             if (SUCCEEDED(hr))
3285             {
3286                 initiated = true;
3287                 rtStart = 0;
3288                 MFFrameRateToAverageTimePerFrame((UINT32)fps, 1, &rtDuration);
3289             }
3290         }
3291     }
3292
3293     return SUCCEEDED(hr);
3294 }
3295
3296 void CvVideoWriter_MSMF::close()
3297 {
3298     if (!initiated)
3299     {
3300         return;
3301     }
3302
3303     initiated = false;
3304     sinkWriter->Finalize();
3305     MFShutdown();
3306 }
3307
3308 bool CvVideoWriter_MSMF::writeFrame(const IplImage* img)
3309 {
3310     if (!img)
3311         return false;
3312
3313     int length = img->width * img->height * 4;
3314     DWORD* target = new DWORD[length];
3315
3316     for (int rowIdx = 0; rowIdx < img->height; rowIdx++)
3317     {
3318         char* rowStart = img->imageData + rowIdx*img->widthStep;
3319         for (int colIdx = 0; colIdx < img->width; colIdx++)
3320         {
3321             BYTE b = rowStart[colIdx * img->nChannels + 0];
3322             BYTE g = rowStart[colIdx * img->nChannels + 1];
3323             BYTE r = rowStart[colIdx * img->nChannels + 2];
3324
3325             target[rowIdx*img->width+colIdx] = (r << 16) + (g << 8) + b;
3326         }
3327     }
3328
3329     // Send frame to the sink writer.
3330     HRESULT hr = WriteFrame(target, rtStart, rtDuration);
3331     if (FAILED(hr))
3332     {
3333         delete[] target;
3334         return false;
3335     }
3336     rtStart += rtDuration;
3337
3338     delete[] target;
3339
3340     return true;
3341 }
3342
3343 HRESULT CvVideoWriter_MSMF::InitializeSinkWriter(const char* filename)
3344 {
3345     ComPtr<IMFAttributes> spAttr;
3346     ComPtr<IMFMediaType>  mediaTypeOut;
3347     ComPtr<IMFMediaType>  mediaTypeIn;
3348     ComPtr<IMFByteStream> spByteStream;
3349
3350     MFCreateAttributes(&spAttr, 10);
3351     spAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true);
3352
3353     wchar_t* unicodeFileName = new wchar_t[strlen(filename)+1];
3354     MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, strlen(filename)+1);
3355
3356     HRESULT hr = MFCreateSinkWriterFromURL(unicodeFileName, NULL, spAttr.Get(), &sinkWriter);
3357
3358     delete[] unicodeFileName;
3359
3360     // Set the output media type.
3361     if (SUCCEEDED(hr))
3362     {
3363         hr = MFCreateMediaType(&mediaTypeOut);
3364     }
3365     if (SUCCEEDED(hr))
3366     {
3367         hr = mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
3368     }
3369     if (SUCCEEDED(hr))
3370     {
3371         hr = mediaTypeOut->SetGUID(MF_MT_SUBTYPE, encodingFormat);
3372     }
3373     if (SUCCEEDED(hr))
3374     {
3375         hr = mediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, bitRate);
3376     }
3377     if (SUCCEEDED(hr))
3378     {
3379         hr = mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
3380     }
3381     if (SUCCEEDED(hr))
3382     {
3383         hr = MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight);
3384     }
3385     if (SUCCEEDED(hr))
3386     {
3387         hr = MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1);
3388     }
3389     if (SUCCEEDED(hr))
3390     {
3391         hr = MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
3392     }
3393
3394     if (SUCCEEDED(hr))
3395     {
3396         hr = sinkWriter->AddStream(mediaTypeOut.Get(), &streamIndex);
3397     }
3398
3399     // Set the input media type.
3400     if (SUCCEEDED(hr))
3401     {
3402         hr = MFCreateMediaType(&mediaTypeIn);
3403     }
3404     if (SUCCEEDED(hr))
3405     {
3406         hr = mediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
3407     }
3408     if (SUCCEEDED(hr))
3409     {
3410         hr = mediaTypeIn->SetGUID(MF_MT_SUBTYPE, inputFormat);
3411     }
3412     if (SUCCEEDED(hr))
3413     {
3414         hr = mediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
3415     }
3416     if (SUCCEEDED(hr))
3417     {
3418         hr = MFSetAttributeSize(mediaTypeIn.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight);
3419     }
3420     if (SUCCEEDED(hr))
3421     {
3422         hr = MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1);
3423     }
3424     if (SUCCEEDED(hr))
3425     {
3426         hr = MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
3427     }
3428
3429     if (SUCCEEDED(hr))
3430     {
3431         hr = sinkWriter->SetInputMediaType(streamIndex, mediaTypeIn.Get(), NULL);
3432     }
3433
3434     // Tell the sink writer to start accepting data.
3435     if (SUCCEEDED(hr))
3436     {
3437         hr = sinkWriter->BeginWriting();
3438     }
3439
3440     return hr;
3441 }
3442
3443 HRESULT CvVideoWriter_MSMF::WriteFrame(DWORD *videoFrameBuffer, const LONGLONG& Start, const LONGLONG& Duration)
3444 {
3445     ComPtr<IMFSample> sample;
3446     ComPtr<IMFMediaBuffer> buffer;
3447
3448     const LONG cbWidth = 4 * videoWidth;
3449     const DWORD cbBuffer = cbWidth * videoHeight;
3450
3451     BYTE *pData = NULL;
3452
3453     // Create a new memory buffer.
3454     HRESULT hr = MFCreateMemoryBuffer(cbBuffer, &buffer);
3455
3456     // Lock the buffer and copy the video frame to the buffer.
3457     if (SUCCEEDED(hr))
3458     {
3459         hr = buffer->Lock(&pData, NULL, NULL);
3460     }
3461
3462     if (SUCCEEDED(hr))
3463     {
3464 #if defined(_M_ARM)
3465         hr = MFCopyImage(
3466             pData,                      // Destination buffer.
3467             -cbWidth,                   // Destination stride.
3468             (BYTE*)videoFrameBuffer,    // First row in source image.
3469             cbWidth,                    // Source stride.
3470             cbWidth,                    // Image width in bytes.
3471             videoHeight                 // Image height in pixels.
3472             );
3473 #else
3474         hr = MFCopyImage(
3475             pData,                      // Destination buffer.
3476             cbWidth,                    // Destination stride.
3477             (BYTE*)videoFrameBuffer,    // First row in source image.
3478             cbWidth,                    // Source stride.
3479             cbWidth,                    // Image width in bytes.
3480             videoHeight                 // Image height in pixels.
3481             );
3482 #endif
3483     }
3484
3485     if (buffer)
3486     {
3487         buffer->Unlock();
3488     }
3489
3490     // Set the data length of the buffer.
3491     if (SUCCEEDED(hr))
3492     {
3493         hr = buffer->SetCurrentLength(cbBuffer);
3494     }
3495
3496     // Create a media sample and add the buffer to the sample.
3497     if (SUCCEEDED(hr))
3498     {
3499         hr = MFCreateSample(&sample);
3500     }
3501     if (SUCCEEDED(hr))
3502     {
3503         hr = sample->AddBuffer(buffer.Get());
3504     }
3505
3506     // Set the time stamp and the duration.
3507     if (SUCCEEDED(hr))
3508     {
3509         hr = sample->SetSampleTime(Start);
3510     }
3511     if (SUCCEEDED(hr))
3512     {
3513         hr = sample->SetSampleDuration(Duration);
3514     }
3515
3516     // Send the sample to the Sink Writer.
3517     if (SUCCEEDED(hr))
3518     {
3519         hr = sinkWriter->WriteSample(streamIndex, sample.Get());
3520     }
3521
3522     return hr;
3523 }
3524
3525 CvVideoWriter* cvCreateVideoWriter_MSMF( const char* filename, int fourcc,
3526                                         double fps, CvSize frameSize, int isColor )
3527 {
3528     CvVideoWriter_MSMF* writer = new CvVideoWriter_MSMF;
3529     if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))
3530         return writer;
3531     delete writer;
3532     return NULL;
3533 }
3534
3535 #endif