1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
41 #include "precomp.hpp"
42 #if (defined WIN32 || defined _WIN32) && defined HAVE_MSMF
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
55 #include <mfobjects.h>
57 #include <Mfreadwrite.h>
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")
75 #include <wrl/client.h>
76 using namespace Microsoft::WRL;
80 struct IMFMediaSource;
86 template <class T> void SafeRelease(T **ppT)
95 /// Class for printing info into consol
100 static DebugPrintOut& getInstance();
101 void printOut(const wchar_t *format, ...);
102 void setVerbose(bool state);
108 // Structure for collecting info about types of video, which are supported by current video device
111 unsigned int MF_MT_FRAME_SIZE;
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;
136 wchar_t *pMF_MT_MAJOR_TYPEName;
137 wchar_t *pMF_MT_SUBTYPEName;
143 /// Class for parsing info from IMFMediaType into the local MediaType
147 static MediaType Read(IMFMediaType *pType);
153 DWORD WINAPI MainThreadFunction( LPVOID lpParam );
154 typedef void(*emergensyStopEventCallback)(int, 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();
166 unsigned int getSize();
169 unsigned int ri_size;
170 unsigned char *ri_pixels;
171 RawImage(unsigned int size);
174 // Class for grabbing image from video stream
175 class ImageGrabber : public IMFSampleGrabberSinkCallback
179 HRESULT initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat);
180 HRESULT startGrabbing(void);
181 void pauseGrabbing();
182 void resumeGrabbing();
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);
188 const HANDLE ig_hFrameReady;
189 const HANDLE ig_hFrameGrabbed;
190 const HANDLE ig_hFinish;
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;
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);
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,
224 STDMETHODIMP OnShutdown();
227 /// Class for controlling of thread of the grabbing raw data from video device
228 class ImageGrabberThread
230 friend DWORD WINAPI MainThreadFunction( LPVOID lpParam );
232 ~ImageGrabberThread(void);
233 static HRESULT CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious = false);
236 void setEmergencyStopEvent(void *userData, void(*func)(int, void *));
237 ImageGrabber *getImageGrabber();
241 ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious);
243 DWORD igt_ThreadIdArray;
244 ImageGrabber *igt_pImageGrabber;
245 emergensyStopEventCallback igt_func;
248 unsigned int igt_DeviceID;
251 // Structure for collecting info about one parametr of current video device
263 // Structure for collecting info about 17 parametrs of current video device
272 Parametr ColorEnable;
273 Parametr WhiteBalance;
274 Parametr BacklightCompensation;
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 *);
291 /// Class for controlling of video device
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);
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();
313 IMFMediaSource *getMediaSource();
314 RawImage *getRawImageOut();
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;
329 std::map<UINT64, FrameRateMap> vd_CaptureFormats;
330 std::vector<MediaType> vd_CurrentFormats;
331 IMFMediaSource *vd_pSource;
332 emergensyStopEventCallback vd_func;
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);
340 long checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice);
343 /// Class for managing of list of video devices
348 long initDevices(IMFAttributes *pAttributes);
349 static videoDevices& getInstance();
350 videoDevice *getDevice(unsigned int i);
351 unsigned int getCount();
355 std::vector<videoDevice *> vds_Devices;
359 // Class for creating of Media Foundation context
360 class Media_Foundation
363 virtual ~Media_Foundation(void);
364 static Media_Foundation& getInstance();
365 bool buildListOfDevices();
367 Media_Foundation(void);
370 /// The only visiable class for controlling of video devices in format singelton
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);
421 bool accessToDevices;
423 void updateListOfDevices();
426 DebugPrintOut::DebugPrintOut(void):verbose(true)
430 DebugPrintOut::~DebugPrintOut(void)
434 DebugPrintOut& DebugPrintOut::getInstance()
436 static DebugPrintOut instance;
440 void DebugPrintOut::printOut(const wchar_t *format, ...)
447 va_start(args, format);
448 if(wcscmp(format, L"%i"))
450 i = va_arg (args, int);
452 if(wcscmp(format, L"%s"))
454 p = va_arg (args, wchar_t *);
456 wprintf(format, i,p);
461 void DebugPrintOut::setVerbose(bool state)
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);
471 unsigned int *GetParametr(GUID guid, MediaType &out)
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);
496 HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType &out)
498 WCHAR *pGuidName = NULL;
499 WCHAR *pGuidValName = NULL;
502 PropVariantInit(&var);
503 HRESULT hr = pAttr->GetItemByIndex(index, &guid, &var);
508 hr = GetGUIDNameNew(guid, &pGuidName);
513 hr = SpecialCaseAttributeValueNew(guid, var, out);
524 p = GetParametr(guid, out);
535 if(guid == MF_MT_AM_FORMAT_TYPE)
537 hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
540 out.MF_MT_AM_FORMAT_TYPE = MF_MT_AM_FORMAT_TYPE;
541 out.pMF_MT_AM_FORMAT_TYPEName = pGuidValName;
545 if(guid == MF_MT_MAJOR_TYPE)
547 hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
550 out.MF_MT_MAJOR_TYPE = MF_MT_MAJOR_TYPE;
551 out.pMF_MT_MAJOR_TYPEName = pGuidValName;
555 if(guid == MF_MT_SUBTYPE)
557 hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
560 out.MF_MT_SUBTYPE = MF_MT_SUBTYPE;
561 out.pMF_MT_SUBTYPEName = pGuidValName;
568 case VT_VECTOR | VT_UI1:
577 CoTaskMemFree(pGuidName);
578 CoTaskMemFree(pGuidValName);
579 PropVariantClear(&var);
583 HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz)
587 LPCWSTR pcwsz = GetGUIDNameConstNew(guid);
590 size_t cchLength = 0;
591 hr = StringCchLengthW(pcwsz, STRSAFE_MAX_CCH, &cchLength);
596 pName = (WCHAR*)CoTaskMemAlloc((cchLength + 1) * sizeof(WCHAR));
602 hr = StringCchCopyW(pName, cchLength + 1, pcwsz);
610 hr = StringFromCLSID(guid, &pName);
616 CoTaskMemFree(pName);
625 void LogUINT32AsUINT64New(const PROPVARIANT& var, UINT32 &uHigh, UINT32 &uLow)
627 Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow);
630 float OffsetToFloatNew(const MFOffset& offset)
632 return offset.value + (static_cast<float>(offset.fract) / 65536.0f);
635 HRESULT LogVideoAreaNew(const PROPVARIANT& var)
637 if (var.caub.cElems < sizeof(MFVideoArea))
644 HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, MediaType &out)
646 if (guid == MF_MT_DEFAULT_STRIDE)
648 out.MF_MT_DEFAULT_STRIDE = var.intVal;
650 if (guid == MF_MT_FRAME_SIZE)
652 UINT32 uHigh = 0, uLow = 0;
653 LogUINT32AsUINT64New(var, uHigh, uLow);
656 out.MF_MT_FRAME_SIZE = out.width * out.height;
659 if (guid == MF_MT_FRAME_RATE)
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;
667 if (guid == MF_MT_FRAME_RATE_RANGE_MAX)
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;
675 if (guid == MF_MT_FRAME_RATE_RANGE_MIN)
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;
683 if (guid == MF_MT_PIXEL_ASPECT_RATIO)
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;
697 #ifndef IF_EQUAL_RETURN
698 #define IF_EQUAL_RETURN(param, val) if(val == param) return L#val
701 LPCWSTR GetGUIDNameConstNew(const GUID& guid)
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);
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
846 FormatReader::FormatReader(void)
850 MediaType FormatReader::Read(IMFMediaType *pType)
855 hr = pType->LockStore();
860 hr = pType->GetCount(&count);
865 for (UINT32 i = 0; i < count; i++)
867 hr = LogAttributeValueByIndexNew(pType, i, out);
873 hr = pType->UnlockStore();
881 FormatReader::~FormatReader(void)
885 #define CHECK_HR(x) if (FAILED(x)) { goto done; }
887 ImageGrabber::ImageGrabber(unsigned int deviceID, bool synchronous):
889 ig_DeviceID(deviceID),
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))
901 ImageGrabber::~ImageGrabber(void)
905 ig_pSession->Shutdown();
908 CloseHandle(ig_hFinish);
912 CloseHandle(ig_hFrameReady);
913 CloseHandle(ig_hFrameGrabbed);
916 SafeRelease(&ig_pSession);
917 SafeRelease(&ig_pTopology);
918 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
920 DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroing instance of the ImageGrabber class\n", ig_DeviceID);
923 HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat)
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;
936 ig_pSession->Shutdown();
938 SafeRelease(&ig_pSession);
939 SafeRelease(&ig_pTopology);
940 ig_pSource = pSource;
941 hr = pSource->CreatePresentationDescriptor(&pPD);
947 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD);
951 hr = pSD->GetMediaTypeHandler(&pHandler);
956 hr = pHandler->GetMediaTypeCount(&cTypes);
962 hr = pHandler->GetCurrentMediaType(&pCurrentType);
966 MT = FormatReader::Read(pCurrentType.Get());
969 unsigned int sizeRawImage = 0;
970 if(VideoFormat == MFVideoFormat_RGB24)
972 sizeRawImage = MT.MF_MT_FRAME_SIZE * 3;
974 else if(VideoFormat == MFVideoFormat_RGB32)
976 sizeRawImage = MT.MF_MT_FRAME_SIZE * 4;
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));
1001 ig_pSession->Shutdown();
1003 SafeRelease(&ig_pSession);
1004 SafeRelease(&ig_pTopology);
1010 void ImageGrabber::stopGrabbing()
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);
1018 HRESULT ImageGrabber::startGrabbing(void)
1020 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1021 ComPtr<IMFMediaEvent> pEvent = NULL;
1023 PropVariantInit(&var);
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);
1030 HRESULT hrStatus = S_OK;
1032 if(!ig_pSession) break;
1033 hr = ig_pSession->GetEvent(0, &pEvent);
1039 hr = pEvent->GetStatus(&hrStatus);
1045 hr = pEvent->GetType(&met);
1051 if (met == MESessionEnded)
1053 DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionEnded \n", ig_DeviceID);
1054 ig_pSession->Stop();
1057 if (met == MESessionStopped)
1059 DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionStopped \n", ig_DeviceID);
1062 if (met == MEVideoCaptureDeviceRemoved)
1064 DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved \n", ig_DeviceID);
1067 if ((met == MEError) || (met == MENonFatalError))
1069 pEvent->GetStatus(&hrStatus);
1070 DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: MEError | MENonFatalError: %u\n", ig_DeviceID, hrStatus);
1074 DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Finish startGrabbing \n", ig_DeviceID);
1077 SetEvent(ig_hFinish);
1082 void ImageGrabber::pauseGrabbing()
1086 void ImageGrabber::resumeGrabbing()
1090 HRESULT ImageGrabber::CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo)
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;
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++)
1105 // In this example, we look for audio streams and connect them to the sink.
1106 BOOL fSelected = FALSE;
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)
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));
1120 CHECK_HR(hr = pPD->DeselectStream(i));
1123 *ppTopo = pTopology;
1124 (*ppTopo)->AddRef();
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.
1137 ComPtr<IMFTopologyNode> pNode = NULL;
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();
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.
1158 ComPtr<IMFTopologyNode> pNode = NULL;
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();
1173 HRESULT ImageGrabber::CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, bool synchronious)
1175 *ppIG = new (std::nothrow) ImageGrabber(deviceID, synchronious);
1178 return E_OUTOFMEMORY;
1180 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1181 DPO->printOut(L"IMAGEGRABBER VIDEODEVICE %i: Creating instance of ImageGrabber\n", deviceID);
1185 STDMETHODIMP ImageGrabber::QueryInterface(REFIID riid, void** ppv)
1187 HRESULT hr = E_NOINTERFACE;
1189 if(riid == IID_IUnknown || riid == IID_IMFSampleGrabberSinkCallback)
1191 *ppv = static_cast<IMFSampleGrabberSinkCallback *>(this);
1194 if(riid == IID_IMFClockStateSink)
1196 *ppv = static_cast<IMFClockStateSink *>(this);
1201 reinterpret_cast<IUnknown *>(*ppv)->AddRef();
1206 STDMETHODIMP_(ULONG) ImageGrabber::AddRef()
1208 return InterlockedIncrement(&m_cRef);
1211 STDMETHODIMP_(ULONG) ImageGrabber::Release()
1213 ULONG cRef = InterlockedDecrement(&m_cRef);
1221 STDMETHODIMP ImageGrabber::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset)
1223 (void)hnsSystemTime;
1224 (void)llClockStartOffset;
1228 STDMETHODIMP ImageGrabber::OnClockStop(MFTIME hnsSystemTime)
1230 (void)hnsSystemTime;
1234 STDMETHODIMP ImageGrabber::OnClockPause(MFTIME hnsSystemTime)
1236 (void)hnsSystemTime;
1240 STDMETHODIMP ImageGrabber::OnClockRestart(MFTIME hnsSystemTime)
1242 (void)hnsSystemTime;
1246 STDMETHODIMP ImageGrabber::OnClockSetRate(MFTIME hnsSystemTime, float flRate)
1249 (void)hnsSystemTime;
1253 STDMETHODIMP ImageGrabber::OnSetPresentationClock(IMFPresentationClock* pClock)
1259 STDMETHODIMP ImageGrabber::OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags,
1260 LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer,
1263 (void)guidMajorMediaType;
1265 (void)dwSampleFlags;
1266 (void)llSampleDuration;
1269 HANDLE tmp[] = {ig_hFinish, ig_hFrameGrabbed, NULL};
1271 DWORD status = WaitForMultipleObjects(2, tmp, FALSE, INFINITE);
1272 if (status == WAIT_OBJECT_0)
1274 printf("OnProcessFrame called after ig_hFinish event\n");
1280 ig_RIFirst->fastCopy(pSampleBuffer);
1281 ig_RIOut = ig_RIFirst;
1285 ig_RISecond->fastCopy(pSampleBuffer);
1286 ig_RIOut = ig_RISecond;
1291 SetEvent(ig_hFrameReady);
1301 STDMETHODIMP ImageGrabber::OnShutdown()
1303 SetEvent(ig_hFinish);
1307 RawImage *ImageGrabber::getRawImage()
1312 DWORD WINAPI MainThreadFunction( LPVOID lpParam )
1314 ImageGrabberThread *pIGT = (ImageGrabberThread *)lpParam;
1319 HRESULT ImageGrabberThread::CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious)
1321 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1322 *ppIGT = new (std::nothrow) ImageGrabberThread(pSource, deviceID, synchronious);
1325 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Memory cannot be allocated\n", deviceID);
1326 return E_OUTOFMEMORY;
1329 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Creating of the instance of ImageGrabberThread\n", deviceID);
1333 ImageGrabberThread::ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious):
1338 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1339 HRESULT hr = ImageGrabber::CreateInstance(&igt_pImageGrabber, deviceID, synchronious);
1340 igt_DeviceID = deviceID;
1343 hr = igt_pImageGrabber->initImageGrabber(pSource, MFVideoFormat_RGB24);
1346 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with initialization of the instance of the ImageGrabber class\n", deviceID);
1350 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Initialization of instance of the ImageGrabber class\n", deviceID);
1355 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i There is a problem with creation of the instance of the ImageGrabber class\n", deviceID);
1359 void ImageGrabberThread::setEmergencyStopEvent(void *userData, void(*func)(int, void *))
1364 igt_userData = userData;
1368 ImageGrabberThread::~ImageGrabberThread(void)
1370 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1371 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Destroing ImageGrabberThread\n", igt_DeviceID);
1373 WaitForSingleObject(igt_Handle, INFINITE);
1374 delete igt_pImageGrabber;
1377 void ImageGrabberThread::stop()
1380 if(igt_pImageGrabber)
1382 igt_pImageGrabber->stopGrabbing();
1386 void ImageGrabberThread::start()
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
1397 void ImageGrabberThread::run()
1399 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1400 if(igt_pImageGrabber)
1402 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Thread for grabbing images is started\n", igt_DeviceID);
1403 HRESULT hr = igt_pImageGrabber->startGrabbing();
1406 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with starting the process of grabbing\n", igt_DeviceID);
1411 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i The thread is finished without execution of grabbing\n", igt_DeviceID);
1415 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Emergency Stop thread\n", igt_DeviceID);
1418 igt_func(igt_DeviceID, igt_userData);
1422 DPO->printOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Finish thread\n", igt_DeviceID);
1425 ImageGrabber *ImageGrabberThread::getImageGrabber()
1427 return igt_pImageGrabber;
1430 Media_Foundation::Media_Foundation(void)
1432 HRESULT hr = MFStartup(MF_VERSION);
1435 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1436 DPO->printOut(L"MEDIA FOUNDATION: It cannot be created!!!\n");
1440 Media_Foundation::~Media_Foundation(void)
1442 HRESULT hr = MFShutdown();
1445 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1446 DPO->printOut(L"MEDIA FOUNDATION: Resources cannot be released\n");
1450 bool Media_Foundation::buildListOfDevices()
1453 ComPtr<IMFAttributes> pAttributes = NULL;
1455 hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1);
1458 hr = pAttributes->SetGUID(
1459 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
1460 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
1465 videoDevices *vDs = &videoDevices::getInstance();
1466 hr = vDs->initDevices(pAttributes.Get());
1470 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1471 DPO->printOut(L"MEDIA FOUNDATION: The access to the video cameras denied\n");
1474 return (SUCCEEDED(hr));
1477 Media_Foundation& Media_Foundation::getInstance()
1479 static Media_Foundation instance;
1483 RawImage::RawImage(unsigned int size): ri_new(false), ri_pixels(NULL)
1486 ri_pixels = new unsigned char[size];
1487 memset((void *)ri_pixels,0,ri_size);
1490 bool RawImage::isNew()
1495 unsigned int RawImage::getSize()
1500 RawImage::~RawImage(void)
1506 long RawImage::CreateInstance(RawImage **ppRImage,unsigned int size)
1508 *ppRImage = new (std::nothrow) RawImage(size);
1509 if (ppRImage == NULL)
1511 return E_OUTOFMEMORY;
1516 void RawImage::setCopy(const BYTE * pSampleBuffer)
1518 memcpy(ri_pixels, pSampleBuffer, ri_size);
1522 void RawImage::fastCopy(const BYTE * pSampleBuffer)
1524 memcpy(ri_pixels, pSampleBuffer, ri_size);
1528 unsigned char * RawImage::getpPixels()
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)
1539 void videoDevice::setParametrs(CamParametrs parametrs)
1545 Parametr *pParametr = (Parametr *)(¶metrs);
1546 Parametr *pPrevParametr = (Parametr *)(&vd_PrevParametrs);
1547 IAMVideoProcAmp *pProcAmp = NULL;
1548 HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp));
1551 for(unsigned int i = 0; i < 10; i++)
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);
1556 pProcAmp->Release();
1558 IAMCameraControl *pProcControl = NULL;
1559 hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl));
1562 for(unsigned int i = 0; i < 7; i++)
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);
1567 pProcControl->Release();
1569 vd_PrevParametrs = parametrs;
1574 CamParametrs videoDevice::getParametrs()
1581 Parametr *pParametr = (Parametr *)(&out);
1582 IAMVideoProcAmp *pProcAmp = NULL;
1583 HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp));
1586 for(unsigned int i = 0; i < 10; i++)
1589 hr = pProcAmp->GetRange(VideoProcAmp_Brightness+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag);
1592 temp.CurrentValue = temp.Default;
1593 pParametr[i] = temp;
1596 pProcAmp->Release();
1598 IAMCameraControl *pProcControl = NULL;
1599 hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl));
1602 for(unsigned int i = 0; i < 7; i++)
1605 hr = pProcControl->GetRange(CameraControl_Pan+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag);
1608 temp.CurrentValue = temp.Default;
1609 pParametr[10 + i] = temp;
1612 pProcControl->Release();
1619 long videoDevice::resetDevice(IMFActivate *pActivate)
1622 vd_CurrentFormats.clear();
1623 if(vd_pFriendlyName)
1624 CoTaskMemFree(vd_pFriendlyName);
1625 vd_pFriendlyName = NULL;
1628 IMFMediaSource *pSource = NULL;
1629 hr = pActivate->GetAllocatedString(
1630 MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
1634 hr = pActivate->ActivateObject(
1635 __uuidof(IMFMediaSource),
1638 enumerateCaptureFormats(pSource);
1639 buildLibraryofTypes();
1640 SafeRelease(&pSource);
1643 vd_pFriendlyName = NULL;
1644 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1645 DPO->printOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber);
1651 long videoDevice::readInfoOfDevice(IMFActivate *pActivate, unsigned int Num)
1654 vd_CurrentNumber = Num;
1655 hr = resetDevice(pActivate);
1659 long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice)
1662 IMFActivate **ppDevices = NULL;
1663 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1665 wchar_t *newFriendlyName = NULL;
1666 hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
1671 if(count > vd_CurrentNumber)
1673 hr = ppDevices[vd_CurrentNumber]->GetAllocatedString(
1674 MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
1680 if(wcscmp(newFriendlyName, vd_pFriendlyName) != 0)
1682 DPO->printOut(L"VIDEODEVICE %i: Chosen device cannot be found \n", vd_CurrentNumber);
1688 *pDevice = ppDevices[vd_CurrentNumber];
1689 (*pDevice)->AddRef();
1694 DPO->printOut(L"VIDEODEVICE %i: Name of device cannot be gotten \n", vd_CurrentNumber);
1699 DPO->printOut(L"VIDEODEVICE %i: Number of devices more than corrent number of the device \n", vd_CurrentNumber);
1702 for(UINT32 i = 0; i < count; i++)
1704 SafeRelease(&ppDevices[i]);
1706 SafeRelease(ppDevices);
1713 DPO->printOut(L"VIDEODEVICE %i: List of DeviceSources cannot be enumerated \n", vd_CurrentNumber);
1718 long videoDevice::initDevice()
1721 ComPtr<IMFAttributes> pAttributes = NULL;
1722 IMFActivate *vd_pActivate = NULL;
1723 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1725 hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1);
1728 hr = pAttributes->SetGUID(
1729 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
1730 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
1735 hr = checkDevice(pAttributes.Get(), &vd_pActivate);
1736 if (SUCCEEDED(hr) && vd_pActivate)
1738 SafeRelease(&vd_pSource);
1739 hr = vd_pActivate->ActivateObject(
1740 __uuidof(IMFMediaSource),
1746 SafeRelease(&vd_pActivate);
1750 DPO->printOut(L"VIDEODEVICE %i: Device there is not \n", vd_CurrentNumber);
1755 DPO->printOut(L"VIDEODEVICE %i: The attribute of video cameras cannot be getting \n", vd_CurrentNumber);
1761 MediaType videoDevice::getFormat(unsigned int id)
1763 if(id < vd_CurrentFormats.size())
1765 return vd_CurrentFormats[id];
1767 else return MediaType();
1769 int videoDevice::getCountFormats()
1771 return vd_CurrentFormats.size();
1773 void videoDevice::setEmergencyStopEvent(void *userData, void(*func)(int, void *))
1776 vd_userData = userData;
1778 void videoDevice::closeDevice()
1782 vd_IsSetuped = false;
1784 SafeRelease(&vd_pSource);
1785 if(vd_LockOut == RawDataLock)
1792 vd_LockOut = OpenLock;
1793 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1794 DPO->printOut(L"VIDEODEVICE %i: Device is stopped \n", vd_CurrentNumber);
1797 unsigned int videoDevice::getWidth()
1804 unsigned int videoDevice::getHeight()
1811 IMFMediaSource *videoDevice::getMediaSource()
1813 IMFMediaSource *out = NULL;
1814 if(vd_LockOut == OpenLock)
1816 vd_LockOut = MediaSourceLock;
1821 int videoDevice::findType(unsigned int size, unsigned int frameRate)
1823 if(vd_CaptureFormats.size() == 0)
1825 FrameRateMap FRM = vd_CaptureFormats[size];
1828 UINT64 frameRateMax = 0; SUBTYPEMap STMMax;
1831 std::map<UINT64, SUBTYPEMap>::iterator f = FRM.begin();
1832 for(; f != FRM.end(); f++)
1834 if((*f).first >= frameRateMax)
1836 frameRateMax = (*f).first;
1837 STMMax = (*f).second;
1843 std::map<UINT64, SUBTYPEMap>::iterator f = FRM.begin();
1844 for(; f != FRM.end(); f++)
1846 if((*f).first >= frameRateMax)
1848 if(frameRate > (*f).first)
1850 frameRateMax = (*f).first;
1851 STMMax = (*f).second;
1856 if(STMMax.size() == 0)
1858 std::map<String, vectorNum>::iterator S = STMMax.begin();
1859 vectorNum VN = (*S).second;
1865 void videoDevice::buildLibraryofTypes()
1868 unsigned int framerate;
1869 std::vector<MediaType>::iterator i = vd_CurrentFormats.begin();
1871 for(; i != vd_CurrentFormats.end(); i++)
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);
1881 FRM[framerate] = STM;
1882 vd_CaptureFormats[size] = FRM;
1887 long videoDevice::setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex)
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());
1899 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf());
1904 hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf());
1909 hr = pHandler->GetMediaTypeByIndex((DWORD)dwFormatIndex, pType.GetAddressOf());
1914 hr = pHandler->SetCurrentMediaType(pType.Get());
1920 bool videoDevice::isDeviceSetup()
1922 return vd_IsSetuped;
1925 RawImage * videoDevice::getRawImageOut()
1927 if(!vd_IsSetuped) return NULL;
1929 return vd_pImGrTh->getImageGrabber()->getRawImage();
1932 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1933 DPO->printOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class does not exist \n", vd_CurrentNumber);
1938 bool videoDevice::isFrameNew()
1940 if(!vd_IsSetuped) return false;
1941 if(vd_LockOut == RawDataLock || vd_LockOut == OpenLock)
1943 if(vd_LockOut == OpenLock)
1945 vd_LockOut = RawDataLock;
1946 HRESULT hr = ImageGrabberThread::CreateInstance(&vd_pImGrTh, vd_pSource, vd_CurrentNumber);
1949 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
1950 DPO->printOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class cannot be created.\n", vd_CurrentNumber);
1953 vd_pImGrTh->setEmergencyStopEvent(vd_userData, vd_func);
1954 vd_pImGrTh->start();
1958 return vd_pImGrTh->getImageGrabber()->getRawImage()->isNew();
1963 bool videoDevice::isDeviceMediaSource()
1965 if(vd_LockOut == MediaSourceLock) return true;
1969 bool videoDevice::isDeviceRawDataSource()
1971 if(vd_LockOut == RawDataLock) return true;
1975 bool videoDevice::setupDevice(unsigned int id)
1977 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
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));
1989 DPO->printOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber);
1990 vd_PrevParametrs = getParametrs();
1991 return vd_IsSetuped;
1995 DPO->printOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber);
2001 DPO->printOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber);
2006 bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate)
2008 unsigned int id = findType(w * h, idealFramerate);
2009 return setupDevice(id);
2012 wchar_t *videoDevice::getName()
2014 return vd_pFriendlyName;
2017 videoDevice::~videoDevice(void)
2020 SafeRelease(&vd_pSource);
2021 if(vd_pFriendlyName)
2022 CoTaskMemFree(vd_pFriendlyName);
2025 HRESULT videoDevice::enumerateCaptureFormats(IMFMediaSource *pSource)
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());
2037 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf());
2042 hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf());
2048 hr = pHandler->GetMediaTypeCount(&cTypes);
2053 for (DWORD i = 0; i < cTypes; i++)
2055 hr = pHandler->GetMediaTypeByIndex(i, pType.GetAddressOf());
2060 MediaType MT = FormatReader::Read(pType.Get());
2061 vd_CurrentFormats.push_back(MT);
2068 videoDevices::videoDevices(void): count(0)
2071 void videoDevices::clearDevices()
2073 std::vector<videoDevice *>::iterator i = vds_Devices.begin();
2074 for(; i != vds_Devices.end(); ++i)
2076 vds_Devices.clear();
2079 videoDevices::~videoDevices(void)
2084 videoDevice * videoDevices::getDevice(unsigned int i)
2086 if(i >= vds_Devices.size())
2094 return vds_Devices[i];
2097 long videoDevices::initDevices(IMFAttributes *pAttributes)
2100 IMFActivate **ppDevices = NULL;
2102 hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
2107 for(UINT32 i = 0; i < count; i++)
2109 videoDevice *vd = new videoDevice;
2110 vd->readInfoOfDevice(ppDevices[i], i);
2111 vds_Devices.push_back(vd);
2112 SafeRelease(&ppDevices[i]);
2114 SafeRelease(ppDevices);
2121 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2122 DPO->printOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n");
2127 unsigned int videoDevices::getCount()
2129 return vds_Devices.size();
2132 videoDevices& videoDevices::getInstance()
2134 static videoDevices instance;
2138 Parametr::Parametr()
2148 MediaType::MediaType()
2150 pMF_MT_AM_FORMAT_TYPEName = NULL;
2151 pMF_MT_MAJOR_TYPEName = NULL;
2152 pMF_MT_SUBTYPEName = NULL;
2156 MediaType::~MediaType()
2161 void MediaType::Clear()
2163 MF_MT_FRAME_SIZE = 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));
2189 videoInput::videoInput(void): accessToDevices(false)
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");
2198 void videoInput::updateListOfDevices()
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");
2207 videoInput::~videoInput(void)
2209 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2210 DPO->printOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n");
2213 IMFMediaSource *videoInput::getMediaSource(int deviceID)
2215 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2218 videoDevices *VDS = &videoDevices::getInstance();
2219 videoDevice * VD = VDS->getDevice(deviceID);
2222 IMFMediaSource *out = VD->getMediaSource();
2224 DPO->printOut(L"VideoDevice %i: There is not any suitable IMFMediaSource interface\n", deviceID);
2230 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2235 bool videoInput::setupDevice(int deviceID, unsigned int id)
2237 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2240 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2245 videoDevices *VDS = &videoDevices::getInstance();
2246 videoDevice * VD = VDS->getDevice(deviceID);
2249 bool out = VD->setupDevice(id);
2251 DPO->printOut(L"VIDEODEVICE %i: This device cannot be started\n", deviceID);
2257 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2262 bool videoInput::setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate)
2264 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2267 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2272 videoDevices *VDS = &videoDevices::getInstance();
2273 videoDevice * VD = VDS->getDevice(deviceID);
2276 bool out = VD->setupDevice(w, h, idealFramerate);
2278 DPO->printOut(L"VIDEODEVICE %i: this device cannot be started\n", deviceID);
2284 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n", deviceID);
2289 MediaType videoInput::getFormat(int deviceID, unsigned int id)
2291 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2294 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2299 videoDevices *VDS = &videoDevices::getInstance();
2300 videoDevice * VD = VDS->getDevice(deviceID);
2302 return VD->getFormat(id);
2306 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2311 bool videoInput::isDeviceSetup(int deviceID)
2313 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2316 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2321 videoDevices *VDS = &videoDevices::getInstance();
2322 videoDevice * VD = VDS->getDevice(deviceID);
2324 return VD->isDeviceSetup();
2328 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2333 bool videoInput::isDeviceMediaSource(int deviceID)
2335 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2338 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2343 videoDevices *VDS = &videoDevices::getInstance();
2344 videoDevice * VD = VDS->getDevice(deviceID);
2346 return VD->isDeviceMediaSource();
2350 DPO->printOut(L"Device(s): There is not any suitable video device\n");
2355 bool videoInput::isDeviceRawDataSource(int deviceID)
2357 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2360 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2365 videoDevices *VDS = &videoDevices::getInstance();
2366 videoDevice * VD = VDS->getDevice(deviceID);
2369 bool isRaw = VD->isDeviceRawDataSource();
2375 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2380 bool videoInput::isFrameNew(int deviceID)
2382 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2385 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2390 if(!isDeviceSetup(deviceID))
2392 if(isDeviceMediaSource(deviceID))
2395 videoDevices *VDS = &videoDevices::getInstance();
2396 videoDevice * VD = VDS->getDevice(deviceID);
2399 return VD->isFrameNew();
2404 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2409 unsigned int videoInput::getCountFormats(int deviceID)
2411 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2414 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2419 videoDevices *VDS = &videoDevices::getInstance();
2420 videoDevice * VD = VDS->getDevice(deviceID);
2422 return VD->getCountFormats();
2426 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2431 void videoInput::closeAllDevices()
2433 videoDevices *VDS = &videoDevices::getInstance();
2434 for(unsigned int i = 0; i < VDS->getCount(); i++)
2438 void videoInput::setParametrs(int deviceID, CamParametrs parametrs)
2440 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2443 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2448 videoDevices *VDS = &videoDevices::getInstance();
2449 videoDevice *VD = VDS->getDevice(deviceID);
2451 VD->setParametrs(parametrs);
2455 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2459 CamParametrs videoInput::getParametrs(int deviceID)
2461 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2465 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2470 videoDevices *VDS = &videoDevices::getInstance();
2471 videoDevice *VD = VDS->getDevice(deviceID);
2473 out = VD->getParametrs();
2477 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2482 void videoInput::closeDevice(int deviceID)
2484 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2487 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2492 videoDevices *VDS = &videoDevices::getInstance();
2493 videoDevice *VD = VDS->getDevice(deviceID);
2499 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2503 unsigned int videoInput::getWidth(int deviceID)
2505 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2508 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2513 videoDevices *VDS = &videoDevices::getInstance();
2514 videoDevice * VD = VDS->getDevice(deviceID);
2516 return VD->getWidth();
2520 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2525 unsigned int videoInput::getHeight(int deviceID)
2527 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2530 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2535 videoDevices *VDS = &videoDevices::getInstance();
2536 videoDevice * VD = VDS->getDevice(deviceID);
2538 return VD->getHeight();
2542 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2547 wchar_t *videoInput::getNameVideoDevice(int deviceID)
2549 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2552 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2557 videoDevices *VDS = &videoDevices::getInstance();
2558 videoDevice * VD = VDS->getDevice(deviceID);
2560 return VD->getName();
2564 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2569 unsigned int videoInput::listDevices(bool silent)
2571 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
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++)
2582 if(!silent)DPO->printOut(L"SETUP: %i) %s \n",i, getNameVideoDevice(i));
2584 if(!silent)DPO->printOut(L"SETUP: %i Device(s) found\n\n", out);
2588 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2593 videoInput& videoInput::getInstance()
2595 static videoInput instance;
2599 bool videoInput::isDevicesAcceable()
2601 return accessToDevices;
2604 void videoInput::setVerbose(bool state)
2606 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2607 DPO->setVerbose(state);
2610 void videoInput::setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *))
2612 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2615 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2622 videoDevices *VDS = &videoDevices::getInstance();
2623 videoDevice * VD = VDS->getDevice(deviceID);
2625 VD->setEmergencyStopEvent(userData, func);
2630 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2634 bool videoInput::getPixels(int deviceID, unsigned char * dstBuffer, bool flipRedAndBlue, bool flipImage)
2636 bool success = false;
2637 unsigned int bytes = 3;
2638 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2641 DPO->printOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID);
2646 bool isRaw = isDeviceRawDataSource(deviceID);
2649 videoDevices *VDS = &videoDevices::getInstance();
2650 DebugPrintOut *DPO = &DebugPrintOut::getInstance();
2651 RawImage *RIOut = VDS->getDevice(deviceID)->getRawImageOut();
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())
2659 processPixels(RIOut->getpPixels(), dstBuffer, width, height, bytes, flipRedAndBlue, flipImage);
2664 DPO->printOut(L"ERROR: GetPixels() - bufferSizes do not match!\n");
2669 DPO->printOut(L"ERROR: GetPixels() - Unable to grab frame for device %i\n", deviceID);
2674 DPO->printOut(L"ERROR: GetPixels() - Not raw data source device %i\n", deviceID);
2679 DPO->printOut(L"VIDEODEVICE(s): There is not any suitable video device\n");
2684 void videoInput::processPixels(unsigned char * src, unsigned char * dst, unsigned int width,
2685 unsigned int height, unsigned int bpp, bool bRGB, bool bFlip)
2687 unsigned int widthInBytes = width * bpp;
2688 unsigned int numBytes = widthInBytes * height;
2689 int *dstInt, *srcInt;
2694 for(unsigned int y = 0; y < height; y++)
2696 dstInt = (int *)(dst + (y * widthInBytes));
2697 srcInt = (int *)(src + ( (height -y -1) * widthInBytes));
2698 memcpy(dstInt, srcInt, widthInBytes);
2703 memcpy(dst, src, numBytes);
2711 unsigned int y = (height - 1) * widthInBytes;
2713 for(unsigned int i = 0; i < numBytes; i+=3)
2718 src -= widthInBytes*2;
2732 for(unsigned int i = 0; i < numBytes; i+=3)
2747 /******* Capturing video from camera via Microsoft Media Foundation **********/
2748 class CvCaptureCAM_MSMF : public CvCapture
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...
2762 int index, width, height, fourcc;
2767 struct SuppressVideoInputMessages
2769 SuppressVideoInputMessages() { videoInput::setVerbose(true); }
2772 static SuppressVideoInputMessages do_it;
2774 CvCaptureCAM_MSMF::CvCaptureCAM_MSMF():
2780 VI(videoInput::getInstance())
2785 CvCaptureCAM_MSMF::~CvCaptureCAM_MSMF()
2791 void CvCaptureCAM_MSMF::close()
2795 VI.closeDevice(index);
2797 cvReleaseImage(&frame);
2799 width = height = -1;
2802 // Initialize camera input
2803 bool CvCaptureCAM_MSMF::open( int _index )
2805 int try_index = _index;
2808 devices = VI.listDevices(true);
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) )
2819 bool CvCaptureCAM_MSMF::grabFrame()
2821 while (VI.isDeviceSetup(index) && !VI.isFrameNew(index))
2823 return VI.isDeviceSetup(index);
2826 IplImage* CvCaptureCAM_MSMF::retrieveFrame(int)
2828 if( !frame || (int)VI.getWidth(index) != frame->width || (int)VI.getHeight(index) != frame->height )
2831 cvReleaseImage( &frame );
2832 unsigned int w = VI.getWidth(index), h = VI.getHeight(index);
2833 frame = cvCreateImage( cvSize(w,h), 8, 3 );
2835 VI.getPixels( index, (uchar*)frame->imageData, false, true );
2839 double CvCaptureCAM_MSMF::getProperty( int property_id )
2841 // image format proprrties
2842 switch( property_id )
2844 case CV_CAP_PROP_FRAME_WIDTH:
2845 return VI.getWidth(index);
2846 case CV_CAP_PROP_FRAME_HEIGHT:
2847 return VI.getHeight(index);
2851 bool CvCaptureCAM_MSMF::setProperty( int property_id, double value )
2853 // image capture properties
2854 bool handled = false;
2855 switch( property_id )
2857 case CV_CAP_PROP_FRAME_WIDTH:
2858 width = cvRound(value);
2861 case CV_CAP_PROP_FRAME_HEIGHT:
2862 height = cvRound(value);
2868 if( width > 0 && height > 0 )
2870 if( width != (int)VI.getWidth(index) || height != (int)VI.getHeight(index) && VI.isDeviceSetup(index))//|| fourcc != VI.getFourcc(index) )
2872 VI.closeDevice(index);
2873 VI.setupDevice(index, width, height);
2875 return VI.isDeviceSetup(index);
2883 class CvCaptureFile_MSMF : public CvCapture
2886 CvCaptureFile_MSMF();
2887 virtual ~CvCaptureFile_MSMF();
2889 virtual bool open( const char* filename );
2890 virtual void close();
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; }
2898 ImageGrabberThread* grabberThread;
2899 IMFMediaSource* videoFileSource;
2900 std::vector<MediaType> captureFormats;
2901 int captureFormatIndex;
2905 HRESULT enumerateCaptureFormats(IMFMediaSource *pSource);
2906 HRESULT getSourceDuration(IMFMediaSource *pSource, MFTIME *pDuration);
2909 CvCaptureFile_MSMF::CvCaptureFile_MSMF():
2910 grabberThread(NULL),
2911 videoFileSource(NULL),
2912 captureFormatIndex(0),
2916 MFStartup(MF_VERSION);
2919 CvCaptureFile_MSMF::~CvCaptureFile_MSMF()
2925 bool CvCaptureFile_MSMF::open(const char* filename)
2930 wchar_t* unicodeFileName = new wchar_t[strlen(filename)+1];
2931 MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, strlen(filename)+1);
2935 MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
2937 ComPtr<IMFSourceResolver> pSourceResolver = NULL;
2938 IUnknown* pUnkSource = NULL;
2940 hr = MFCreateSourceResolver(pSourceResolver.GetAddressOf());
2944 hr = pSourceResolver->CreateObjectFromURL(
2946 MF_RESOLUTION_MEDIASOURCE,
2947 NULL, // Optional property store.
2953 // Get the IMFMediaSource from the IUnknown pointer.
2956 hr = pUnkSource->QueryInterface(IID_PPV_ARGS(&videoFileSource));
2959 SafeRelease(&pUnkSource);
2963 hr = enumerateCaptureFormats(videoFileSource);
2968 hr = ImageGrabberThread::CreateInstance(&grabberThread, videoFileSource, (unsigned int)-2, true);
2973 grabberThread->start();
2976 isOpened = SUCCEEDED(hr);
2981 void CvCaptureFile_MSMF::close()
2986 SetEvent(grabberThread->getImageGrabber()->ig_hFinish);
2987 grabberThread->stop();
2988 delete grabberThread;
2991 if (videoFileSource)
2993 videoFileSource->Shutdown();
2997 bool CvCaptureFile_MSMF::setProperty(int property_id, double value)
2999 // image capture properties
3000 // FIXME: implement method in VideoInput back end
3006 double CvCaptureFile_MSMF::getProperty(int property_id)
3008 // image format proprrties
3009 switch( property_id )
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:
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);
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);
3033 bool CvCaptureFile_MSMF::grabFrame()
3035 DWORD waitResult = (DWORD)-1;
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);
3043 return isOpened && grabberThread->getImageGrabber()->getRawImage()->isNew() && (waitResult == WAIT_OBJECT_0);
3046 IplImage* CvCaptureFile_MSMF::retrieveFrame(int)
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 )
3054 cvReleaseImage( &frame );
3055 frame = cvCreateImage( cvSize(width,height), 8, 3 );
3058 RawImage *RIOut = grabberThread->getImageGrabber()->getRawImage();
3059 unsigned int size = bytes * width * height;
3061 bool verticalFlip = captureFormats[captureFormatIndex].MF_MT_DEFAULT_STRIDE < 0;
3063 if(RIOut && size == RIOut->getSize())
3065 videoInput::processPixels(RIOut->getpPixels(), (unsigned char*)frame->imageData, width,
3066 height, bytes, false, verticalFlip);
3072 HRESULT CvCaptureFile_MSMF::enumerateCaptureFormats(IMFMediaSource *pSource)
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());
3085 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf());
3090 hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf());
3096 hr = pHandler->GetMediaTypeCount(&cTypes);
3101 for (DWORD i = 0; i < cTypes; i++)
3103 hr = pHandler->GetMediaTypeByIndex(i, pType.GetAddressOf());
3108 MediaType MT = FormatReader::Read(pType.Get());
3109 captureFormats.push_back(MT);
3116 HRESULT CvCaptureFile_MSMF::getSourceDuration(IMFMediaSource *pSource, MFTIME *pDuration)
3120 IMFPresentationDescriptor *pPD = NULL;
3122 HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
3125 hr = pPD->GetUINT64(MF_PD_DURATION, (UINT64*)pDuration);
3131 CvCapture* cvCreateCameraCapture_MSMF( int index )
3133 CvCaptureCAM_MSMF* capture = new CvCaptureCAM_MSMF;
3136 if( capture->open( index ))
3148 CvCapture* cvCreateFileCapture_MSMF (const char* filename)
3150 CvCaptureFile_MSMF* capture = new CvCaptureFile_MSMF;
3153 if( capture->open(filename) )
3170 // Media Foundation-based Video Writer
3174 class CvVideoWriter_MSMF : public CvVideoWriter
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);
3190 GUID encodingFormat;
3194 ComPtr<IMFSinkWriter> sinkWriter;
3201 HRESULT InitializeSinkWriter(const char* filename);
3202 static const GUID FourCC2GUID(int fourcc);
3203 HRESULT WriteFrame(DWORD *videoFrameBuffer, const LONGLONG& rtStart, const LONGLONG& rtDuration);
3206 CvVideoWriter_MSMF::CvVideoWriter_MSMF():
3211 CvVideoWriter_MSMF::~CvVideoWriter_MSMF()
3216 const GUID CvVideoWriter_MSMF::FourCC2GUID(int fourcc)
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;
3263 return MFVideoFormat_H264;
3267 bool CvVideoWriter_MSMF::open( const char* filename, int fourcc,
3268 double _fps, CvSize frameSize, bool /*isColor*/ )
3270 videoWidth = frameSize.width;
3271 videoHeight = frameSize.height;
3273 bitRate = (UINT32)fps*videoWidth*videoHeight; // 1-bit per pixel
3274 encodingFormat = FourCC2GUID(fourcc);
3275 inputFormat = MFVideoFormat_RGB32;
3277 HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3280 hr = MFStartup(MF_VERSION);
3283 hr = InitializeSinkWriter(filename);
3288 MFFrameRateToAverageTimePerFrame((UINT32)fps, 1, &rtDuration);
3293 return SUCCEEDED(hr);
3296 void CvVideoWriter_MSMF::close()
3304 sinkWriter->Finalize();
3308 bool CvVideoWriter_MSMF::writeFrame(const IplImage* img)
3313 int length = img->width * img->height * 4;
3314 DWORD* target = new DWORD[length];
3316 for (int rowIdx = 0; rowIdx < img->height; rowIdx++)
3318 char* rowStart = img->imageData + rowIdx*img->widthStep;
3319 for (int colIdx = 0; colIdx < img->width; colIdx++)
3321 BYTE b = rowStart[colIdx * img->nChannels + 0];
3322 BYTE g = rowStart[colIdx * img->nChannels + 1];
3323 BYTE r = rowStart[colIdx * img->nChannels + 2];
3325 target[rowIdx*img->width+colIdx] = (r << 16) + (g << 8) + b;
3329 // Send frame to the sink writer.
3330 HRESULT hr = WriteFrame(target, rtStart, rtDuration);
3336 rtStart += rtDuration;
3343 HRESULT CvVideoWriter_MSMF::InitializeSinkWriter(const char* filename)
3345 ComPtr<IMFAttributes> spAttr;
3346 ComPtr<IMFMediaType> mediaTypeOut;
3347 ComPtr<IMFMediaType> mediaTypeIn;
3348 ComPtr<IMFByteStream> spByteStream;
3350 MFCreateAttributes(&spAttr, 10);
3351 spAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true);
3353 wchar_t* unicodeFileName = new wchar_t[strlen(filename)+1];
3354 MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, strlen(filename)+1);
3356 HRESULT hr = MFCreateSinkWriterFromURL(unicodeFileName, NULL, spAttr.Get(), &sinkWriter);
3358 delete[] unicodeFileName;
3360 // Set the output media type.
3363 hr = MFCreateMediaType(&mediaTypeOut);
3367 hr = mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
3371 hr = mediaTypeOut->SetGUID(MF_MT_SUBTYPE, encodingFormat);
3375 hr = mediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, bitRate);
3379 hr = mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
3383 hr = MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight);
3387 hr = MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1);
3391 hr = MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
3396 hr = sinkWriter->AddStream(mediaTypeOut.Get(), &streamIndex);
3399 // Set the input media type.
3402 hr = MFCreateMediaType(&mediaTypeIn);
3406 hr = mediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
3410 hr = mediaTypeIn->SetGUID(MF_MT_SUBTYPE, inputFormat);
3414 hr = mediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
3418 hr = MFSetAttributeSize(mediaTypeIn.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight);
3422 hr = MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1);
3426 hr = MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
3431 hr = sinkWriter->SetInputMediaType(streamIndex, mediaTypeIn.Get(), NULL);
3434 // Tell the sink writer to start accepting data.
3437 hr = sinkWriter->BeginWriting();
3443 HRESULT CvVideoWriter_MSMF::WriteFrame(DWORD *videoFrameBuffer, const LONGLONG& Start, const LONGLONG& Duration)
3445 ComPtr<IMFSample> sample;
3446 ComPtr<IMFMediaBuffer> buffer;
3448 const LONG cbWidth = 4 * videoWidth;
3449 const DWORD cbBuffer = cbWidth * videoHeight;
3453 // Create a new memory buffer.
3454 HRESULT hr = MFCreateMemoryBuffer(cbBuffer, &buffer);
3456 // Lock the buffer and copy the video frame to the buffer.
3459 hr = buffer->Lock(&pData, NULL, NULL);
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.
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.
3490 // Set the data length of the buffer.
3493 hr = buffer->SetCurrentLength(cbBuffer);
3496 // Create a media sample and add the buffer to the sample.
3499 hr = MFCreateSample(&sample);
3503 hr = sample->AddBuffer(buffer.Get());
3506 // Set the time stamp and the duration.
3509 hr = sample->SetSampleTime(Start);
3513 hr = sample->SetSampleDuration(Duration);
3516 // Send the sample to the Sink Writer.
3519 hr = sinkWriter->WriteSample(streamIndex, sample.Get());
3525 CvVideoWriter* cvCreateVideoWriter_MSMF( const char* filename, int fourcc,
3526 double fps, CvSize frameSize, int isColor )
3528 CvVideoWriter_MSMF* writer = new CvVideoWriter_MSMF;
3529 if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))