Added DXVA hardware acceleration to MSMF-based VideoCapture
[platform/upstream/opencv.git] / modules / videoio / 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 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    Originally licensed under The Code Project Open License (CPOL) 1.02:
48    http://www.codeproject.com/info/cpol10.aspx
49 */
50 //require Windows 8 for some of the formats defined otherwise could baseline on lower version
51 #if WINVER < _WIN32_WINNT_WIN8
52 #undef WINVER
53 #define WINVER _WIN32_WINNT_WIN8
54 #endif
55 #include <windows.h>
56 #include <guiddef.h>
57 #include <mfidl.h>
58 #include <Mfapi.h>
59 #include <mfplay.h>
60 #include <mfobjects.h>
61 #include <tchar.h>
62 #include <strsafe.h>
63 #include <Mfreadwrite.h>
64 #ifdef HAVE_DXVA
65 #include <D3D11.h>
66 #include <D3d11_4.h>
67 #endif
68 #include <new>
69 #include <map>
70 #include <vector>
71 #include <string>
72 #include <algorithm>
73 #include <stdio.h>
74 #include <stdarg.h>
75 #include <string.h>
76
77 #ifdef _MSC_VER
78 #pragma warning(disable:4503)
79 #pragma comment(lib, "mfplat")
80 #pragma comment(lib, "mf")
81 #pragma comment(lib, "mfuuid")
82 #pragma comment(lib, "Strmiids")
83 #pragma comment(lib, "Mfreadwrite")
84 #ifdef HAVE_DXVA
85 #pragma comment(lib, "d3d11")
86 #endif
87 #if (WINVER >= 0x0602) // Available since Win 8
88 #pragma comment(lib, "MinCore_Downlevel")
89 #endif
90 #endif
91
92 #include <mferror.h>
93
94 #include <comdef.h>
95
96 struct IMFMediaType;
97 struct IMFActivate;
98 struct IMFMediaSource;
99 struct IMFAttributes;
100
101 namespace
102 {
103
104 #ifdef _DEBUG
105 void DPOprintOut(const wchar_t *format, ...)
106 {
107     int i = 0;
108     wchar_t *p = NULL;
109     va_list args;
110     va_start(args, format);
111     if (::IsDebuggerPresent())
112     {
113         WCHAR szMsg[512];
114         ::StringCchVPrintfW(szMsg, sizeof(szMsg) / sizeof(szMsg[0]), format, args);
115         ::OutputDebugStringW(szMsg);
116     }
117     else
118     {
119         if (wcscmp(format, L"%i"))
120         {
121             i = va_arg(args, int);
122         }
123         if (wcscmp(format, L"%s"))
124         {
125             p = va_arg(args, wchar_t *);
126         }
127         wprintf(format, i, p);
128     }
129     va_end(args);
130 }
131 #define DebugPrintOut(...) DPOprintOut(__VA_ARGS__)
132 #else
133 #define DebugPrintOut(...) void()
134 #endif
135
136 template <class T>
137 class ComPtr
138 {
139 public:
140     ComPtr() throw()
141     {
142     }
143     ComPtr(T* lp) throw()
144     {
145         p = lp;
146     }
147     ComPtr(_In_ const ComPtr<T>& lp) throw()
148     {
149         p = lp.p;
150     }
151     virtual ~ComPtr()
152     {
153     }
154
155     T** operator&() throw()
156     {
157         assert(p == NULL);
158         return p.operator&();
159     }
160     T* operator->() const throw()
161     {
162         assert(p != NULL);
163         return p.operator->();
164     }
165     bool operator!() const throw()
166     {
167         return p.operator==(NULL);
168     }
169     bool operator==(_In_opt_ T* pT) const throw()
170     {
171         return p.operator==(pT);
172     }
173     bool operator!=(_In_opt_ T* pT) const throw()
174     {
175         return p.operator!=(pT);
176     }
177     operator bool()
178     {
179         return p.operator!=(NULL);
180     }
181
182     T* const* GetAddressOf() const throw()
183     {
184         return &p;
185     }
186
187     T** GetAddressOf() throw()
188     {
189         return &p;
190     }
191
192     T** ReleaseAndGetAddressOf() throw()
193     {
194         p.Release();
195         return &p;
196     }
197
198     T* Get() const throw()
199     {
200         return p;
201     }
202
203     // Attach to an existing interface (does not AddRef)
204     void Attach(_In_opt_ T* p2) throw()
205     {
206         p.Attach(p2);
207     }
208     // Detach the interface (does not Release)
209     T* Detach() throw()
210     {
211         return p.Detach();
212     }
213     _Check_return_ HRESULT CopyTo(_Deref_out_opt_ T** ppT) throw()
214     {
215         assert(ppT != NULL);
216         if (ppT == NULL)
217             return E_POINTER;
218         *ppT = p;
219         if (p != NULL)
220             p->AddRef();
221         return S_OK;
222     }
223
224     void Reset()
225     {
226         p.Release();
227     }
228
229     // query for U interface
230     template<typename U>
231     HRESULT As(_Inout_ U** lp) const throw()
232     {
233         return p->QueryInterface(__uuidof(U), reinterpret_cast<void**>(lp));
234     }
235     // query for U interface
236     template<typename U>
237     HRESULT As(_Out_ ComPtr<U>* lp) const throw()
238     {
239         return p->QueryInterface(__uuidof(U), reinterpret_cast<void**>(lp->ReleaseAndGetAddressOf()));
240     }
241 private:
242     _COM_SMARTPTR_TYPEDEF(T, __uuidof(T));
243     TPtr p;
244 };
245
246 #define _ComPtr ComPtr
247
248 // Structure for collecting info about types of video, which are supported by current video device
249 struct MediaType
250 {
251     unsigned int MF_MT_FRAME_SIZE;
252     UINT32 height;
253     UINT32 width;
254     unsigned int MF_MT_YUV_MATRIX;
255     unsigned int MF_MT_VIDEO_LIGHTING;
256     int MF_MT_DEFAULT_STRIDE; // stride is negative if image is bottom-up
257     unsigned int MF_MT_VIDEO_CHROMA_SITING;
258     GUID MF_MT_AM_FORMAT_TYPE;
259     unsigned int MF_MT_FIXED_SIZE_SAMPLES;
260     unsigned int MF_MT_VIDEO_NOMINAL_RANGE;
261     UINT32 MF_MT_FRAME_RATE_NUMERATOR;
262     UINT32 MF_MT_FRAME_RATE_DENOMINATOR;
263     UINT32 MF_MT_PIXEL_ASPECT_RATIO_NUMERATOR;
264     UINT32 MF_MT_PIXEL_ASPECT_RATIO_DENOMINATOR;
265     unsigned int MF_MT_ALL_SAMPLES_INDEPENDENT;
266     UINT32 MF_MT_FRAME_RATE_RANGE_MIN_NUMERATOR;
267     UINT32 MF_MT_FRAME_RATE_RANGE_MIN_DENOMINATOR;
268     unsigned int MF_MT_SAMPLE_SIZE;
269     unsigned int MF_MT_VIDEO_PRIMARIES;
270     unsigned int MF_MT_INTERLACE_MODE;
271     UINT32 MF_MT_FRAME_RATE_RANGE_MAX_NUMERATOR;
272     UINT32 MF_MT_FRAME_RATE_RANGE_MAX_DENOMINATOR;
273     GUID MF_MT_MAJOR_TYPE;
274     GUID MF_MT_SUBTYPE;
275     LPCWSTR pMF_MT_MAJOR_TYPEName;
276     LPCWSTR pMF_MT_SUBTYPEName;
277     MediaType();
278     MediaType(IMFMediaType *pType);
279     ~MediaType();
280     void Clear();
281 };
282
283 // Class for creating of Media Foundation context
284 class Media_Foundation
285 {
286 public:
287     ~Media_Foundation(void) { /*CV_Assert(SUCCEEDED(MFShutdown()));*/ CoUninitialize(); }
288     static Media_Foundation& getInstance()
289     {
290         static Media_Foundation instance;
291         return instance;
292     }
293 private:
294     Media_Foundation(void) { CoInitialize(0); CV_Assert(SUCCEEDED(MFStartup(MF_VERSION))); }
295 };
296
297 #ifndef IF_GUID_EQUAL_RETURN
298 #define IF_GUID_EQUAL_RETURN(val) if(val == guid) return L#val
299 #endif
300 LPCWSTR GetGUIDNameConstNew(const GUID& guid)
301 {
302     IF_GUID_EQUAL_RETURN(MF_MT_MAJOR_TYPE);
303     IF_GUID_EQUAL_RETURN(MF_MT_SUBTYPE);
304     IF_GUID_EQUAL_RETURN(MF_MT_ALL_SAMPLES_INDEPENDENT);
305     IF_GUID_EQUAL_RETURN(MF_MT_FIXED_SIZE_SAMPLES);
306     IF_GUID_EQUAL_RETURN(MF_MT_COMPRESSED);
307     IF_GUID_EQUAL_RETURN(MF_MT_SAMPLE_SIZE);
308     IF_GUID_EQUAL_RETURN(MF_MT_WRAPPED_TYPE);
309     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_NUM_CHANNELS);
310     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_SAMPLES_PER_SECOND);
311     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND);
312     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_AVG_BYTES_PER_SECOND);
313     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_BLOCK_ALIGNMENT);
314     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_BITS_PER_SAMPLE);
315     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE);
316     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_SAMPLES_PER_BLOCK);
317     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_CHANNEL_MASK);
318     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_FOLDDOWN_MATRIX);
319     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_PEAKREF);
320     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_PEAKTARGET);
321     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_AVGREF);
322     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_AVGTARGET);
323     IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_PREFER_WAVEFORMATEX);
324     IF_GUID_EQUAL_RETURN(MF_MT_AAC_PAYLOAD_TYPE);
325     IF_GUID_EQUAL_RETURN(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION);
326     IF_GUID_EQUAL_RETURN(MF_MT_FRAME_SIZE);
327     IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE);
328     IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE_RANGE_MAX);
329     IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE_RANGE_MIN);
330     IF_GUID_EQUAL_RETURN(MF_MT_PIXEL_ASPECT_RATIO);
331     IF_GUID_EQUAL_RETURN(MF_MT_DRM_FLAGS);
332     IF_GUID_EQUAL_RETURN(MF_MT_PAD_CONTROL_FLAGS);
333     IF_GUID_EQUAL_RETURN(MF_MT_SOURCE_CONTENT_HINT);
334     IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_CHROMA_SITING);
335     IF_GUID_EQUAL_RETURN(MF_MT_INTERLACE_MODE);
336     IF_GUID_EQUAL_RETURN(MF_MT_TRANSFER_FUNCTION);
337     IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_PRIMARIES);
338     IF_GUID_EQUAL_RETURN(MF_MT_CUSTOM_VIDEO_PRIMARIES);
339     IF_GUID_EQUAL_RETURN(MF_MT_YUV_MATRIX);
340     IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_LIGHTING);
341     IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_NOMINAL_RANGE);
342     IF_GUID_EQUAL_RETURN(MF_MT_GEOMETRIC_APERTURE);
343     IF_GUID_EQUAL_RETURN(MF_MT_MINIMUM_DISPLAY_APERTURE);
344     IF_GUID_EQUAL_RETURN(MF_MT_PAN_SCAN_APERTURE);
345     IF_GUID_EQUAL_RETURN(MF_MT_PAN_SCAN_ENABLED);
346     IF_GUID_EQUAL_RETURN(MF_MT_AVG_BITRATE);
347     IF_GUID_EQUAL_RETURN(MF_MT_AVG_BIT_ERROR_RATE);
348     IF_GUID_EQUAL_RETURN(MF_MT_MAX_KEYFRAME_SPACING);
349     IF_GUID_EQUAL_RETURN(MF_MT_DEFAULT_STRIDE);
350     IF_GUID_EQUAL_RETURN(MF_MT_PALETTE);
351     IF_GUID_EQUAL_RETURN(MF_MT_USER_DATA);
352     IF_GUID_EQUAL_RETURN(MF_MT_AM_FORMAT_TYPE);
353     IF_GUID_EQUAL_RETURN(MF_MT_MPEG_START_TIME_CODE);
354     IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_PROFILE);
355     IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_LEVEL);
356     IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_FLAGS);
357     IF_GUID_EQUAL_RETURN(MF_MT_MPEG_SEQUENCE_HEADER);
358     IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_SRC_PACK_0);
359     IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_CTRL_PACK_0);
360     IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_SRC_PACK_1);
361     IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_CTRL_PACK_1);
362     IF_GUID_EQUAL_RETURN(MF_MT_DV_VAUX_SRC_PACK);
363     IF_GUID_EQUAL_RETURN(MF_MT_DV_VAUX_CTRL_PACK);
364     IF_GUID_EQUAL_RETURN(MF_MT_ARBITRARY_HEADER);
365     IF_GUID_EQUAL_RETURN(MF_MT_ARBITRARY_FORMAT);
366     IF_GUID_EQUAL_RETURN(MF_MT_IMAGE_LOSS_TOLERANT);
367     IF_GUID_EQUAL_RETURN(MF_MT_MPEG4_SAMPLE_DESCRIPTION);
368     IF_GUID_EQUAL_RETURN(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY);
369     IF_GUID_EQUAL_RETURN(MF_MT_ORIGINAL_4CC);
370     IF_GUID_EQUAL_RETURN(MF_MT_ORIGINAL_WAVE_FORMAT_TAG);
371     // Media types
372     IF_GUID_EQUAL_RETURN(MFMediaType_Audio);
373     IF_GUID_EQUAL_RETURN(MFMediaType_Video);
374     IF_GUID_EQUAL_RETURN(MFMediaType_Protected);
375 #ifdef MFMediaType_Perception
376     IF_GUID_EQUAL_RETURN(MFMediaType_Perception);
377 #endif
378     IF_GUID_EQUAL_RETURN(MFMediaType_Stream);
379     IF_GUID_EQUAL_RETURN(MFMediaType_SAMI);
380     IF_GUID_EQUAL_RETURN(MFMediaType_Script);
381     IF_GUID_EQUAL_RETURN(MFMediaType_Image);
382     IF_GUID_EQUAL_RETURN(MFMediaType_HTML);
383     IF_GUID_EQUAL_RETURN(MFMediaType_Binary);
384     IF_GUID_EQUAL_RETURN(MFMediaType_FileTransfer);
385     IF_GUID_EQUAL_RETURN(MFVideoFormat_AI44); //     FCC('AI44')
386     IF_GUID_EQUAL_RETURN(MFVideoFormat_ARGB32); //   D3DFMT_A8R8G8B8
387     IF_GUID_EQUAL_RETURN(MFVideoFormat_AYUV); //     FCC('AYUV')
388     IF_GUID_EQUAL_RETURN(MFVideoFormat_DV25); //     FCC('dv25')
389     IF_GUID_EQUAL_RETURN(MFVideoFormat_DV50); //     FCC('dv50')
390     IF_GUID_EQUAL_RETURN(MFVideoFormat_DVH1); //     FCC('dvh1')
391     IF_GUID_EQUAL_RETURN(MFVideoFormat_DVC);
392     IF_GUID_EQUAL_RETURN(MFVideoFormat_DVHD);
393     IF_GUID_EQUAL_RETURN(MFVideoFormat_DVSD); //     FCC('dvsd')
394     IF_GUID_EQUAL_RETURN(MFVideoFormat_DVSL); //     FCC('dvsl')
395     IF_GUID_EQUAL_RETURN(MFVideoFormat_H264); //     FCC('H264')
396     IF_GUID_EQUAL_RETURN(MFVideoFormat_I420); //     FCC('I420')
397     IF_GUID_EQUAL_RETURN(MFVideoFormat_IYUV); //     FCC('IYUV')
398     IF_GUID_EQUAL_RETURN(MFVideoFormat_M4S2); //     FCC('M4S2')
399     IF_GUID_EQUAL_RETURN(MFVideoFormat_MJPG);
400     IF_GUID_EQUAL_RETURN(MFVideoFormat_MP43); //     FCC('MP43')
401     IF_GUID_EQUAL_RETURN(MFVideoFormat_MP4S); //     FCC('MP4S')
402     IF_GUID_EQUAL_RETURN(MFVideoFormat_MP4V); //     FCC('MP4V')
403     IF_GUID_EQUAL_RETURN(MFVideoFormat_MPG1); //     FCC('MPG1')
404     IF_GUID_EQUAL_RETURN(MFVideoFormat_MSS1); //     FCC('MSS1')
405     IF_GUID_EQUAL_RETURN(MFVideoFormat_MSS2); //     FCC('MSS2')
406     IF_GUID_EQUAL_RETURN(MFVideoFormat_NV11); //     FCC('NV11')
407     IF_GUID_EQUAL_RETURN(MFVideoFormat_NV12); //     FCC('NV12')
408     IF_GUID_EQUAL_RETURN(MFVideoFormat_P010); //     FCC('P010')
409     IF_GUID_EQUAL_RETURN(MFVideoFormat_P016); //     FCC('P016')
410     IF_GUID_EQUAL_RETURN(MFVideoFormat_P210); //     FCC('P210')
411     IF_GUID_EQUAL_RETURN(MFVideoFormat_P216); //     FCC('P216')
412     IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB24); //    D3DFMT_R8G8B8
413     IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB32); //    D3DFMT_X8R8G8B8
414     IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB555); //   D3DFMT_X1R5G5B5
415     IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB565); //   D3DFMT_R5G6B5
416     IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB8);
417     IF_GUID_EQUAL_RETURN(MFVideoFormat_UYVY); //     FCC('UYVY')
418     IF_GUID_EQUAL_RETURN(MFVideoFormat_v210); //     FCC('v210')
419     IF_GUID_EQUAL_RETURN(MFVideoFormat_v410); //     FCC('v410')
420     IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV1); //     FCC('WMV1')
421     IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV2); //     FCC('WMV2')
422     IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV3); //     FCC('WMV3')
423     IF_GUID_EQUAL_RETURN(MFVideoFormat_WVC1); //     FCC('WVC1')
424     IF_GUID_EQUAL_RETURN(MFVideoFormat_Y210); //     FCC('Y210')
425     IF_GUID_EQUAL_RETURN(MFVideoFormat_Y216); //     FCC('Y216')
426     IF_GUID_EQUAL_RETURN(MFVideoFormat_Y410); //     FCC('Y410')
427     IF_GUID_EQUAL_RETURN(MFVideoFormat_Y416); //     FCC('Y416')
428     IF_GUID_EQUAL_RETURN(MFVideoFormat_Y41P);
429     IF_GUID_EQUAL_RETURN(MFVideoFormat_Y41T);
430     IF_GUID_EQUAL_RETURN(MFVideoFormat_YUY2); //     FCC('YUY2')
431     IF_GUID_EQUAL_RETURN(MFVideoFormat_YV12); //     FCC('YV12')
432     IF_GUID_EQUAL_RETURN(MFVideoFormat_YVYU);
433 #ifdef MFVideoFormat_H263
434     IF_GUID_EQUAL_RETURN(MFVideoFormat_H263);
435 #endif
436 #ifdef MFVideoFormat_H265
437     IF_GUID_EQUAL_RETURN(MFVideoFormat_H265);
438 #endif
439 #ifdef MFVideoFormat_H264_ES
440     IF_GUID_EQUAL_RETURN(MFVideoFormat_H264_ES);
441 #endif
442 #ifdef MFVideoFormat_HEVC
443     IF_GUID_EQUAL_RETURN(MFVideoFormat_HEVC);
444 #endif
445 #ifdef MFVideoFormat_HEVC_ES
446     IF_GUID_EQUAL_RETURN(MFVideoFormat_HEVC_ES);
447 #endif
448 #ifdef MFVideoFormat_MPEG2
449     IF_GUID_EQUAL_RETURN(MFVideoFormat_MPEG2);
450 #endif
451 #ifdef MFVideoFormat_VP80
452     IF_GUID_EQUAL_RETURN(MFVideoFormat_VP80);
453 #endif
454 #ifdef MFVideoFormat_VP90
455     IF_GUID_EQUAL_RETURN(MFVideoFormat_VP90);
456 #endif
457 #ifdef MFVideoFormat_420O
458     IF_GUID_EQUAL_RETURN(MFVideoFormat_420O);
459 #endif
460 #ifdef MFVideoFormat_Y42T
461     IF_GUID_EQUAL_RETURN(MFVideoFormat_Y42T);
462 #endif
463 #ifdef MFVideoFormat_YVU9
464     IF_GUID_EQUAL_RETURN(MFVideoFormat_YVU9);
465 #endif
466 #ifdef MFVideoFormat_v216
467     IF_GUID_EQUAL_RETURN(MFVideoFormat_v216);
468 #endif
469 #ifdef MFVideoFormat_L8
470     IF_GUID_EQUAL_RETURN(MFVideoFormat_L8);
471 #endif
472 #ifdef MFVideoFormat_L16
473     IF_GUID_EQUAL_RETURN(MFVideoFormat_L16);
474 #endif
475 #ifdef MFVideoFormat_D16
476     IF_GUID_EQUAL_RETURN(MFVideoFormat_D16);
477 #endif
478 #ifdef D3DFMT_X8R8G8B8
479     IF_GUID_EQUAL_RETURN(D3DFMT_X8R8G8B8);
480 #endif
481 #ifdef D3DFMT_A8R8G8B8
482     IF_GUID_EQUAL_RETURN(D3DFMT_A8R8G8B8);
483 #endif
484 #ifdef D3DFMT_R8G8B8
485     IF_GUID_EQUAL_RETURN(D3DFMT_R8G8B8);
486 #endif
487 #ifdef D3DFMT_X1R5G5B5
488     IF_GUID_EQUAL_RETURN(D3DFMT_X1R5G5B5);
489 #endif
490 #ifdef D3DFMT_A4R4G4B4
491     IF_GUID_EQUAL_RETURN(D3DFMT_A4R4G4B4);
492 #endif
493 #ifdef D3DFMT_R5G6B5
494     IF_GUID_EQUAL_RETURN(D3DFMT_R5G6B5);
495 #endif
496 #ifdef D3DFMT_P8
497     IF_GUID_EQUAL_RETURN(D3DFMT_P8);
498 #endif
499 #ifdef D3DFMT_A2R10G10B10
500     IF_GUID_EQUAL_RETURN(D3DFMT_A2R10G10B10);
501 #endif
502 #ifdef D3DFMT_A2B10G10R10
503     IF_GUID_EQUAL_RETURN(D3DFMT_A2B10G10R10);
504 #endif
505 #ifdef D3DFMT_L8
506     IF_GUID_EQUAL_RETURN(D3DFMT_L8);
507 #endif
508 #ifdef D3DFMT_L16
509     IF_GUID_EQUAL_RETURN(D3DFMT_L16);
510 #endif
511 #ifdef D3DFMT_D16
512     IF_GUID_EQUAL_RETURN(D3DFMT_D16);
513 #endif
514 #ifdef MFVideoFormat_A2R10G10B10
515     IF_GUID_EQUAL_RETURN(MFVideoFormat_A2R10G10B10);
516 #endif
517 #ifdef MFVideoFormat_A16B16G16R16F
518     IF_GUID_EQUAL_RETURN(MFVideoFormat_A16B16G16R16F);
519 #endif
520     IF_GUID_EQUAL_RETURN(MFAudioFormat_PCM); //              WAVE_FORMAT_PCM
521     IF_GUID_EQUAL_RETURN(MFAudioFormat_Float); //            WAVE_FORMAT_IEEE_FLOAT
522     IF_GUID_EQUAL_RETURN(MFAudioFormat_DTS); //              WAVE_FORMAT_DTS
523     IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_AC3_SPDIF); //  WAVE_FORMAT_DOLBY_AC3_SPDIF
524     IF_GUID_EQUAL_RETURN(MFAudioFormat_DRM); //              WAVE_FORMAT_DRM
525     IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudioV8); //        WAVE_FORMAT_WMAUDIO2
526     IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudioV9); //        WAVE_FORMAT_WMAUDIO3
527     IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS
528     IF_GUID_EQUAL_RETURN(MFAudioFormat_WMASPDIF); //         WAVE_FORMAT_WMASPDIF
529     IF_GUID_EQUAL_RETURN(MFAudioFormat_MSP1); //             WAVE_FORMAT_WMAVOICE9
530     IF_GUID_EQUAL_RETURN(MFAudioFormat_MP3); //              WAVE_FORMAT_MPEGLAYER3
531     IF_GUID_EQUAL_RETURN(MFAudioFormat_MPEG); //             WAVE_FORMAT_MPEG
532     IF_GUID_EQUAL_RETURN(MFAudioFormat_AAC); //              WAVE_FORMAT_MPEG_HEAAC
533     IF_GUID_EQUAL_RETURN(MFAudioFormat_ADTS); //             WAVE_FORMAT_MPEG_ADTS_AAC
534 #ifdef MFAudioFormat_ALAC
535     IF_GUID_EQUAL_RETURN(MFAudioFormat_ALAC);
536 #endif
537 #ifdef MFAudioFormat_AMR_NB
538     IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_NB);
539 #endif
540 #ifdef MFAudioFormat_AMR_WB
541     IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_WB);
542 #endif
543 #ifdef MFAudioFormat_AMR_WP
544     IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_WP);
545 #endif
546 #ifdef MFAudioFormat_Dolby_AC3
547     IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_AC3);
548 #endif
549 #ifdef MFAudioFormat_Dolby_DDPlus
550     IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_DDPlus);
551 #endif
552 #ifdef MFAudioFormat_FLAC
553     IF_GUID_EQUAL_RETURN(MFAudioFormat_FLAC);
554 #endif
555 #ifdef MFAudioFormat_Opus
556     IF_GUID_EQUAL_RETURN(MFAudioFormat_Opus);
557 #endif
558 #ifdef MEDIASUBTYPE_RAW_AAC1
559     IF_GUID_EQUAL_RETURN(MEDIASUBTYPE_RAW_AAC1);
560 #endif
561 #ifdef MFAudioFormat_Float_SpatialObjects
562     IF_GUID_EQUAL_RETURN(MFAudioFormat_Float_SpatialObjects);
563 #endif
564 #ifdef MFAudioFormat_QCELP
565     IF_GUID_EQUAL_RETURN(MFAudioFormat_QCELP);
566 #endif
567
568     return NULL;
569 }
570
571 bool LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType &out)
572 {
573     PROPVARIANT var;
574     PropVariantInit(&var);
575     GUID guid = { 0 };
576     if (SUCCEEDED(pAttr->GetItemByIndex(index, &guid, &var)))
577     {
578         if (guid == MF_MT_DEFAULT_STRIDE && var.vt == VT_INT)
579             out.MF_MT_DEFAULT_STRIDE = var.intVal;
580         else if (guid == MF_MT_FRAME_RATE && var.vt == VT_UI8)
581             Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_NUMERATOR, &out.MF_MT_FRAME_RATE_DENOMINATOR);
582         else if (guid == MF_MT_FRAME_RATE_RANGE_MAX && var.vt == VT_UI8)
583             Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_RANGE_MAX_NUMERATOR, &out.MF_MT_FRAME_RATE_RANGE_MAX_DENOMINATOR);
584         else if (guid == MF_MT_FRAME_RATE_RANGE_MIN && var.vt == VT_UI8)
585             Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_RANGE_MIN_NUMERATOR, &out.MF_MT_FRAME_RATE_RANGE_MIN_DENOMINATOR);
586         else if (guid == MF_MT_PIXEL_ASPECT_RATIO && var.vt == VT_UI8)
587             Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_PIXEL_ASPECT_RATIO_NUMERATOR, &out.MF_MT_PIXEL_ASPECT_RATIO_DENOMINATOR);
588         else if (guid == MF_MT_YUV_MATRIX && var.vt == VT_UI4)
589             out.MF_MT_YUV_MATRIX = var.ulVal;
590         else if (guid == MF_MT_VIDEO_LIGHTING && var.vt == VT_UI4)
591             out.MF_MT_VIDEO_LIGHTING = var.ulVal;
592         else if (guid == MF_MT_DEFAULT_STRIDE && var.vt == VT_UI4)
593             out.MF_MT_DEFAULT_STRIDE = (int)var.ulVal;
594         else if (guid == MF_MT_VIDEO_CHROMA_SITING && var.vt == VT_UI4)
595             out.MF_MT_VIDEO_CHROMA_SITING = var.ulVal;
596         else if (guid == MF_MT_VIDEO_NOMINAL_RANGE && var.vt == VT_UI4)
597             out.MF_MT_VIDEO_NOMINAL_RANGE = var.ulVal;
598         else if (guid == MF_MT_ALL_SAMPLES_INDEPENDENT && var.vt == VT_UI4)
599             out.MF_MT_ALL_SAMPLES_INDEPENDENT = var.ulVal;
600         else if (guid == MF_MT_FIXED_SIZE_SAMPLES && var.vt == VT_UI4)
601             out.MF_MT_FIXED_SIZE_SAMPLES = var.ulVal;
602         else if (guid == MF_MT_SAMPLE_SIZE && var.vt == VT_UI4)
603             out.MF_MT_SAMPLE_SIZE = var.ulVal;
604         else if (guid == MF_MT_VIDEO_PRIMARIES && var.vt == VT_UI4)
605             out.MF_MT_VIDEO_PRIMARIES = var.ulVal;
606         else if (guid == MF_MT_INTERLACE_MODE && var.vt == VT_UI4)
607             out.MF_MT_INTERLACE_MODE = var.ulVal;
608         else if (guid == MF_MT_AM_FORMAT_TYPE && var.vt == VT_CLSID)
609             out.MF_MT_AM_FORMAT_TYPE = *var.puuid;
610         else if (guid == MF_MT_MAJOR_TYPE && var.vt == VT_CLSID)
611             out.pMF_MT_MAJOR_TYPEName = GetGUIDNameConstNew(out.MF_MT_MAJOR_TYPE = *var.puuid);
612         else if (guid == MF_MT_SUBTYPE && var.vt == VT_CLSID)
613             out.pMF_MT_SUBTYPEName = GetGUIDNameConstNew(out.MF_MT_SUBTYPE = *var.puuid);
614         else if (guid == MF_MT_FRAME_SIZE && var.vt == VT_UI8)
615         {
616             Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.width, &out.height);
617             out.MF_MT_FRAME_SIZE = out.width * out.height;
618         }
619         PropVariantClear(&var);
620         return true;
621     }
622     return false;
623 }
624
625 MediaType::MediaType()
626 {
627     pMF_MT_MAJOR_TYPEName = NULL;
628     pMF_MT_SUBTYPEName = NULL;
629     Clear();
630 }
631
632 MediaType::MediaType(IMFMediaType *pType)
633 {
634     pMF_MT_MAJOR_TYPEName = NULL;
635     pMF_MT_SUBTYPEName = NULL;
636     Clear();
637     UINT32 count = 0;
638     if (SUCCEEDED(pType->GetCount(&count)) &&
639         SUCCEEDED(pType->LockStore()))
640     {
641         for (UINT32 i = 0; i < count; i++)
642             if (!LogAttributeValueByIndexNew(pType, i, *this))
643                 break;
644         pType->UnlockStore();
645     }
646 }
647
648 MediaType::~MediaType()
649 {
650     Clear();
651 }
652
653 void MediaType::Clear()
654 {
655     MF_MT_FRAME_SIZE = 0;
656     height = 0;
657     width = 0;
658     MF_MT_YUV_MATRIX = 0;
659     MF_MT_VIDEO_LIGHTING = 0;
660     MF_MT_DEFAULT_STRIDE = 0;
661     MF_MT_VIDEO_CHROMA_SITING = 0;
662     MF_MT_FIXED_SIZE_SAMPLES = 0;
663     MF_MT_VIDEO_NOMINAL_RANGE = 0;
664     MF_MT_FRAME_RATE_NUMERATOR = 0;
665     MF_MT_FRAME_RATE_DENOMINATOR = 0;
666     MF_MT_PIXEL_ASPECT_RATIO_NUMERATOR = 0;
667     MF_MT_PIXEL_ASPECT_RATIO_DENOMINATOR = 0;
668     MF_MT_ALL_SAMPLES_INDEPENDENT = 0;
669     MF_MT_FRAME_RATE_RANGE_MIN_NUMERATOR = 0;
670     MF_MT_FRAME_RATE_RANGE_MIN_DENOMINATOR = 0;
671     MF_MT_SAMPLE_SIZE = 0;
672     MF_MT_VIDEO_PRIMARIES = 0;
673     MF_MT_INTERLACE_MODE = 0;
674     MF_MT_FRAME_RATE_RANGE_MAX_NUMERATOR = 0;
675     MF_MT_FRAME_RATE_RANGE_MAX_DENOMINATOR = 0;
676     memset(&MF_MT_MAJOR_TYPE, 0, sizeof(GUID));
677     memset(&MF_MT_AM_FORMAT_TYPE, 0, sizeof(GUID));
678     memset(&MF_MT_SUBTYPE, 0, sizeof(GUID));
679 }
680
681 }
682
683 /******* Capturing video from camera or file via Microsoft Media Foundation **********/
684 class CvCapture_MSMF : public CvCapture
685 {
686 public:
687     typedef enum {
688         MODE_SW = 0,
689         MODE_HW = 1
690     } MSMFCapture_Mode;
691     CvCapture_MSMF();
692     virtual ~CvCapture_MSMF();
693     virtual bool open(int index);
694     virtual bool open(const char* filename);
695     virtual void close();
696     virtual double getProperty(int) const CV_OVERRIDE;
697     virtual bool setProperty(int, double) CV_OVERRIDE;
698     virtual bool grabFrame() CV_OVERRIDE;
699     virtual IplImage* retrieveFrame(int) CV_OVERRIDE;
700     virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_MSMF; } // Return the type of the capture object: CV_CAP_VFW, etc...
701 protected:
702     double getFramerate(MediaType MT) const;
703     bool configureOutput(UINT32 width, UINT32 height, double prefFramerate, UINT32 aspectRatioN, UINT32 aspectRatioD, int outFormat, bool convertToFormat);
704     bool setTime(double time, bool rough);
705     bool configureHW(bool enable);
706
707     Media_Foundation& MF;
708     cv::String filename;
709     int camid;
710     MSMFCapture_Mode captureMode;
711 #ifdef HAVE_DXVA
712     _ComPtr<ID3D11Device> D3DDev;
713     _ComPtr<IMFDXGIDeviceManager> D3DMgr;
714 #endif
715     _ComPtr<IMFSourceReader> videoFileSource;
716     DWORD dwStreamIndex;
717     MediaType nativeFormat;
718     MediaType captureFormat;
719     int outputFormat;
720     bool convertFormat;
721     UINT32 aspectN, aspectD;
722     MFTIME duration;
723     _ComPtr<IMFSample> videoSample;
724     LONGLONG sampleTime;
725     IplImage* frame;
726     bool isOpened;
727 };
728
729 CvCapture_MSMF::CvCapture_MSMF():
730     MF(Media_Foundation::getInstance()),
731     filename(""),
732     camid(-1),
733     captureMode(MODE_SW),
734 #ifdef HAVE_DXVA
735     D3DDev(NULL),
736     D3DMgr(NULL),
737 #endif
738     videoFileSource(NULL),
739     videoSample(NULL),
740     outputFormat(CV_CAP_MODE_BGR),
741     convertFormat(true),
742     aspectN(1),
743     aspectD(1),
744     sampleTime(0),
745     frame(NULL),
746     isOpened(false)
747 {
748 }
749
750 CvCapture_MSMF::~CvCapture_MSMF()
751 {
752     close();
753 }
754
755 void CvCapture_MSMF::close()
756 {
757     if (isOpened)
758     {
759         isOpened = false;
760         if (videoSample)
761             videoSample.Reset();
762         if (videoFileSource)
763             videoFileSource.Reset();
764         if (frame)
765             cvReleaseImage(&frame);
766         camid = -1;
767         filename = "";
768     }
769 }
770
771 bool CvCapture_MSMF::configureHW(bool enable)
772 {
773 #ifdef HAVE_DXVA
774     if ((enable && D3DMgr && D3DDev) || (!enable && !D3DMgr && !D3DDev))
775         return true;
776
777     bool reopen = isOpened;
778     int prevcam = camid;
779     cv::String prevfile = filename;
780     close();
781     if (enable)
782     {
783         D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
784             D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0,
785             D3D_FEATURE_LEVEL_9_3,  D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 };
786         if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
787             levels, sizeof(levels) / sizeof(*levels), D3D11_SDK_VERSION, D3DDev.GetAddressOf(), NULL, NULL)))
788         {
789             // NOTE: Getting ready for multi-threaded operation
790             _ComPtr<ID3D11Multithread> D3DDevMT;
791             UINT mgrRToken;
792             if (SUCCEEDED(D3DDev->QueryInterface(IID_PPV_ARGS(&D3DDevMT))))
793             {
794                 D3DDevMT->SetMultithreadProtected(TRUE);
795                 D3DDevMT.Reset();
796                 if (SUCCEEDED(MFCreateDXGIDeviceManager(&mgrRToken, D3DMgr.GetAddressOf())))
797                 {
798                     if (SUCCEEDED(D3DMgr->ResetDevice(D3DDev.Get(), mgrRToken)))
799                     {
800                         captureMode = MODE_HW;
801                         return reopen ? camid >= 0 ? open(prevcam) : open(prevfile.c_str()) : true;
802                     }
803                     D3DMgr.Reset();
804                 }
805             }
806             D3DDev.Reset();
807         }
808         return false;
809     }
810     else
811     {
812         if (D3DMgr)
813             D3DMgr.Reset();
814         if (D3DDev)
815             D3DDev.Reset();
816         captureMode = MODE_SW;
817         return reopen ? camid >= 0 ? open(prevcam) : open(prevfile.c_str()) : true;
818     }
819 #else
820     return !enable;
821 #endif
822 }
823
824 bool CvCapture_MSMF::configureOutput(UINT32 width, UINT32 height, double prefFramerate, UINT32 aspectRatioN, UINT32 aspectRatioD, int outFormat, bool convertToFormat)
825 {
826     if (width != 0 && height != 0 &&
827         width == captureFormat.width && height == captureFormat.height && prefFramerate == getFramerate(nativeFormat) &&
828         aspectRatioN == aspectN && aspectRatioD == aspectD && outFormat == outputFormat && convertToFormat == convertFormat)
829         return true;
830
831     HRESULT hr = S_OK;
832     int dwStreamFallback = -1;
833     MediaType MTFallback;
834     int dwStreamBest = -1;
835     MediaType MTBest;
836
837     DWORD dwMediaTypeTest = 0;
838     DWORD dwStreamTest = 0;
839     while (SUCCEEDED(hr))
840     {
841         _ComPtr<IMFMediaType> pType;
842         hr = videoFileSource->GetNativeMediaType(dwStreamTest, dwMediaTypeTest, &pType);
843         if (hr == MF_E_NO_MORE_TYPES)
844         {
845             hr = S_OK;
846             ++dwStreamTest;
847             dwMediaTypeTest = 0;
848         }
849         else if (SUCCEEDED(hr))
850         {
851             MediaType MT(pType.Get());
852             if (MT.MF_MT_MAJOR_TYPE == MFMediaType_Video)
853             {
854                 if (dwStreamFallback < 0 ||
855                     ((MT.width * MT.height) > (MTFallback.width * MTFallback.height)) ||
856                     (((MT.width * MT.height) == (MTFallback.width * MTFallback.height)) && getFramerate(MT) > getFramerate(MTFallback) && (prefFramerate == 0 || getFramerate(MT) <= prefFramerate)))
857                 {
858                     dwStreamFallback = (int)dwStreamTest;
859                     MTFallback = MT;
860                 }
861                 if (MT.width == width && MT.height == height)
862                 {
863                     if (dwStreamBest < 0 ||
864                         (getFramerate(MT) > getFramerate(MTBest) && (prefFramerate == 0 || getFramerate(MT) <= prefFramerate)))
865                     {
866                         dwStreamBest = (int)dwStreamTest;
867                         MTBest = MT;
868                     }
869                 }
870             }
871             ++dwMediaTypeTest;
872         }
873     }
874     if (dwStreamBest >= 0 || dwStreamFallback >= 0)
875     {
876         // Retrieved stream media type
877         DWORD tryStream = (DWORD)(dwStreamBest >= 0 ? dwStreamBest : dwStreamFallback);
878         MediaType tryMT = dwStreamBest >= 0 ? MTBest : MTFallback;
879         GUID outSubtype = GUID_NULL;
880         UINT32 outStride = 0;
881         UINT32 outSize = 0;
882         if(convertToFormat)
883             switch (outFormat)
884             {
885             case CV_CAP_MODE_BGR:
886             case CV_CAP_MODE_RGB:
887                 outSubtype = captureMode == MODE_HW ? MFVideoFormat_RGB32 : MFVideoFormat_RGB24; // HW accelerated mode support only RGB32
888                 outStride = (captureMode == MODE_HW ? 4 : 3) * tryMT.width;
889                 outSize = outStride * tryMT.height;
890                 break;
891             case CV_CAP_MODE_GRAY:
892                 outSubtype = MFVideoFormat_NV12;
893                 outStride = tryMT.width;
894                 outSize = outStride * tryMT.height * 3 / 2;
895                 break;
896             case CV_CAP_MODE_YUYV:
897                 outSubtype = MFVideoFormat_YUY2;
898                 outStride = 2 * tryMT.width;
899                 outSize = outStride * tryMT.height;
900                 break;
901             default:
902                 return false;
903             }
904         _ComPtr<IMFMediaType>  mediaTypeOut;
905         if (// Set the output media type.
906             SUCCEEDED(MFCreateMediaType(&mediaTypeOut)) &&
907             SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)) &&
908             SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_SUBTYPE, convertToFormat ? outSubtype : tryMT.MF_MT_SUBTYPE)) &&
909             SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, convertToFormat ? MFVideoInterlace_Progressive : tryMT.MF_MT_INTERLACE_MODE)) &&
910             SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, aspectRatioN, aspectRatioD)) &&
911             SUCCEEDED(MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, tryMT.width, tryMT.height)) &&
912             SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, convertToFormat ? 1 : tryMT.MF_MT_FIXED_SIZE_SAMPLES)) &&
913             SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_SAMPLE_SIZE, convertToFormat ? outSize : tryMT.MF_MT_SAMPLE_SIZE)) &&
914             SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_DEFAULT_STRIDE, convertToFormat ? outStride : tryMT.MF_MT_DEFAULT_STRIDE)))//Assume BGR24 input
915         {
916             if (SUCCEEDED(videoFileSource->SetStreamSelection((DWORD)MF_SOURCE_READER_ALL_STREAMS, false)) &&
917                 SUCCEEDED(videoFileSource->SetStreamSelection(tryStream, true)) &&
918                 SUCCEEDED(videoFileSource->SetCurrentMediaType(tryStream, NULL, mediaTypeOut.Get()))
919                 )
920             {
921                 dwStreamIndex = tryStream;
922                 nativeFormat = tryMT;
923                 aspectN = aspectRatioN;
924                 aspectD = aspectRatioD;
925                 outputFormat = outFormat;
926                 convertFormat = convertToFormat;
927                 captureFormat = MediaType(mediaTypeOut.Get());
928                 return true;
929             }
930             close();
931         }
932     }
933     return false;
934 }
935
936 // Initialize camera input
937 bool CvCapture_MSMF::open(int _index)
938 {
939     close();
940
941     _ComPtr<IMFAttributes> msAttr = NULL;
942     if (SUCCEEDED(MFCreateAttributes(msAttr.GetAddressOf(), 1)) &&
943         SUCCEEDED(msAttr->SetGUID(
944             MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
945             MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
946         )))
947     {
948         IMFActivate **ppDevices = NULL;
949         UINT32 count;
950         if (SUCCEEDED(MFEnumDeviceSources(msAttr.Get(), &ppDevices, &count)))
951         {
952             if (count > 0)
953             {
954                 _index = std::min(std::max(0, _index), (int)count - 1);
955                 for (int ind = 0; ind < (int)count; ind++)
956                 {
957                     if (ind == _index && ppDevices[ind])
958                     {
959                         // Set source reader parameters
960                         _ComPtr<IMFMediaSource> mSrc;
961                         _ComPtr<IMFAttributes> srAttr;
962                         if (SUCCEEDED(ppDevices[ind]->ActivateObject(__uuidof(IMFMediaSource), (void**)&mSrc)) && mSrc &&
963                             SUCCEEDED(MFCreateAttributes(&srAttr, 10)) &&
964                             SUCCEEDED(srAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)) &&
965                             SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, false)) &&
966                             SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, false)) &&
967                             SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, true)))
968                         {
969 #ifdef HAVE_DXVA
970                             if (D3DMgr)
971                                 srAttr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, D3DMgr.Get());
972 #endif
973                             if (SUCCEEDED(MFCreateSourceReaderFromMediaSource(mSrc.Get(), srAttr.Get(), &videoFileSource)))
974                             {
975                                 isOpened = true;
976                                 duration = 0;
977                                 if (configureOutput(0, 0, 0, aspectN, aspectD, outputFormat, convertFormat))
978                                     camid = _index;
979                             }
980                         }
981                     }
982                     if (ppDevices[ind])
983                         ppDevices[ind]->Release();
984                 }
985             }
986         }
987         CoTaskMemFree(ppDevices);
988     }
989
990     return isOpened;
991 }
992
993 bool CvCapture_MSMF::open(const char* _filename)
994 {
995     close();
996     if (!_filename)
997         return false;
998
999     // Set source reader parameters
1000     _ComPtr<IMFAttributes> srAttr;
1001     if (SUCCEEDED(MFCreateAttributes(&srAttr, 10)) &&
1002         SUCCEEDED(srAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)) &&
1003         SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, false)) &&
1004         SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, false)) &&
1005         SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, true))
1006         )
1007     {
1008 #ifdef HAVE_DXVA
1009         if(D3DMgr)
1010             srAttr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, D3DMgr.Get());
1011 #endif
1012         cv::AutoBuffer<wchar_t> unicodeFileName(strlen(_filename) + 1);
1013         MultiByteToWideChar(CP_ACP, 0, _filename, -1, unicodeFileName, (int)strlen(_filename) + 1);
1014         if (SUCCEEDED(MFCreateSourceReaderFromURL(unicodeFileName, srAttr.Get(), &videoFileSource)))
1015         {
1016             isOpened = true;
1017             sampleTime = 0;
1018             if (configureOutput(0, 0, 0, aspectN, aspectD, outputFormat, convertFormat))
1019             {
1020                 filename = _filename;
1021                 PROPVARIANT var;
1022                 HRESULT hr;
1023                 if (SUCCEEDED(hr = videoFileSource->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &var)) &&
1024                     var.vt == VT_UI8)
1025                 {
1026                     duration = var.uhVal.QuadPart;
1027                     PropVariantClear(&var);
1028                 }
1029                 else
1030                     duration = 0;
1031             }
1032         }
1033     }
1034
1035     return isOpened;
1036 }
1037
1038 bool CvCapture_MSMF::grabFrame()
1039 {
1040     if (isOpened)
1041     {
1042         DWORD streamIndex, flags;
1043         if (videoSample)
1044             videoSample.Reset();
1045         HRESULT hr;
1046         while(SUCCEEDED(hr = videoFileSource->ReadSample(
1047                                                             dwStreamIndex, // Stream index.
1048                                                             0,             // Flags.
1049                                                             &streamIndex,  // Receives the actual stream index.
1050                                                             &flags,        // Receives status flags.
1051                                                             &sampleTime,  // Receives the time stamp.
1052                                                             &videoSample   // Receives the sample or NULL.
1053                                                         )) &&
1054               streamIndex == dwStreamIndex && !(flags & (MF_SOURCE_READERF_ERROR|MF_SOURCE_READERF_ALLEFFECTSREMOVED|MF_SOURCE_READERF_ENDOFSTREAM)) &&
1055               !videoSample
1056              )
1057         {
1058             if (flags & MF_SOURCE_READERF_STREAMTICK)
1059             {
1060                 DebugPrintOut(L"\tStream tick detected. Retrying to grab the frame\n");
1061             }
1062         }
1063
1064         if (SUCCEEDED(hr))
1065         {
1066             if (streamIndex != dwStreamIndex)
1067             {
1068                 DebugPrintOut(L"\tWrong stream readed. Abort capturing\n");
1069                 close();
1070             }
1071             else if (flags & MF_SOURCE_READERF_ERROR)
1072             {
1073                 DebugPrintOut(L"\tStream reading error. Abort capturing\n");
1074                 close();
1075             }
1076             else if (flags & MF_SOURCE_READERF_ALLEFFECTSREMOVED)
1077             {
1078                 DebugPrintOut(L"\tStream decoding error. Abort capturing\n");
1079                 close();
1080             }
1081             else if (flags & MF_SOURCE_READERF_ENDOFSTREAM)
1082             {
1083                 DebugPrintOut(L"\tEnd of stream detected\n");
1084             }
1085             else
1086             {
1087                 if (flags & MF_SOURCE_READERF_NEWSTREAM)
1088                 {
1089                     DebugPrintOut(L"\tNew stream detected\n");
1090                 }
1091                 if (flags & MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED)
1092                 {
1093                     DebugPrintOut(L"\tStream native media type changed\n");
1094                 }
1095                 if (flags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)
1096                 {
1097                     DebugPrintOut(L"\tStream current media type changed\n");
1098                 }
1099                 return true;
1100             }
1101         }
1102     }
1103     return false;
1104 }
1105
1106 IplImage* CvCapture_MSMF::retrieveFrame(int)
1107 {
1108     DWORD bcnt;
1109     if (videoSample && SUCCEEDED(videoSample->GetBufferCount(&bcnt)) && bcnt > 0)
1110     {
1111         _ComPtr<IMFMediaBuffer> buf = NULL;
1112         if (SUCCEEDED(videoSample->GetBufferByIndex(0, &buf)))
1113         {
1114             DWORD maxsize, cursize;
1115             BYTE* ptr = NULL;
1116             if (SUCCEEDED(buf->Lock(&ptr, &maxsize, &cursize)))
1117             {
1118                 if (convertFormat)
1119                 {
1120                     if ((unsigned int)cursize == captureFormat.MF_MT_SAMPLE_SIZE)
1121                     {
1122                         if (!frame || (int)captureFormat.width != frame->width || (int)captureFormat.height != frame->height)
1123                         {
1124                             cvReleaseImage(&frame);
1125                             unsigned int bytes = outputFormat == CV_CAP_MODE_GRAY || !convertFormat ? 1 : outputFormat == CV_CAP_MODE_YUYV ? 2 : 3;
1126                             frame = cvCreateImage(cvSize(captureFormat.width, captureFormat.height), 8, bytes);
1127                         }
1128                         switch (outputFormat)
1129                         {
1130                         case CV_CAP_MODE_YUYV:
1131                             memcpy(frame->imageData, ptr, cursize);
1132                             break;
1133                         case CV_CAP_MODE_BGR:
1134                             if (captureMode == MODE_HW)
1135                                 cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC4, ptr), cv::cvarrToMat(frame), cv::COLOR_BGRA2BGR);
1136                             else
1137                                 memcpy(frame->imageData, ptr, cursize);
1138                             break;
1139                         case CV_CAP_MODE_RGB:
1140                             if (captureMode == MODE_HW)
1141                                 cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC4, ptr), cv::cvarrToMat(frame), cv::COLOR_BGRA2BGR);
1142                             else
1143                                 cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC3, ptr), cv::cvarrToMat(frame), cv::COLOR_BGR2RGB);
1144                             break;
1145                         case CV_CAP_MODE_GRAY:
1146                             memcpy(frame->imageData, ptr, captureFormat.height*captureFormat.width);
1147                             break;
1148                         default:
1149                             cvReleaseImage(&frame);
1150                             break;
1151                         }
1152                     }
1153                     else
1154                         cvReleaseImage(&frame);
1155                 }
1156                 else
1157                 {
1158                     if (!frame || frame->width != (int)cursize || frame->height != 1)
1159                     {
1160                         cvReleaseImage(&frame);
1161                         frame = cvCreateImage(cvSize(cursize, 1), 8, 1);
1162                     }
1163                     memcpy(frame->imageData, ptr, cursize);
1164                 }
1165                 buf->Unlock();
1166                 return frame;
1167             }
1168         }
1169     }
1170
1171     return NULL;
1172 }
1173
1174 double CvCapture_MSMF::getFramerate(MediaType MT) const
1175 {
1176     if (MT.MF_MT_SUBTYPE == MFVideoFormat_MP43) //Unable to estimate FPS for MP43
1177         return 0;
1178     return MT.MF_MT_FRAME_RATE_DENOMINATOR != 0 ? ((double)MT.MF_MT_FRAME_RATE_NUMERATOR) / ((double)MT.MF_MT_FRAME_RATE_DENOMINATOR) : 0;
1179 }
1180
1181 bool CvCapture_MSMF::setTime(double time, bool rough)
1182 {
1183     PROPVARIANT var;
1184     if (SUCCEEDED(videoFileSource->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS, &var)) &&
1185         var.vt == VT_UI4 && (var.ulVal & MFMEDIASOURCE_CAN_SEEK && (rough || var.ulVal & MFMEDIASOURCE_HAS_SLOW_SEEK)))
1186     {
1187         PropVariantClear(&var);
1188         sampleTime = (LONGLONG)floor(time + 0.5);
1189         var.vt = VT_I8;
1190         var.hVal.QuadPart = sampleTime;
1191         HRESULT hr = videoFileSource->SetCurrentPosition(GUID_NULL, var);
1192         if (videoSample)
1193             videoSample.Reset();
1194         PropVariantClear(&var);
1195         return SUCCEEDED(hr);
1196     }
1197     return false;
1198 }
1199
1200 double CvCapture_MSMF::getProperty( int property_id ) const
1201 {
1202     IAMVideoProcAmp *pProcAmp = NULL;
1203     IAMCameraControl *pProcControl = NULL;
1204     // image format properties
1205     if (property_id == CV_CAP_PROP_FORMAT)
1206         return outputFormat;
1207     else if (property_id == CV_CAP_PROP_MODE)
1208         return captureMode;
1209     else if (property_id == CV_CAP_PROP_CONVERT_RGB)
1210         return convertFormat ? 1 : 0;
1211     else if (property_id == CV_CAP_PROP_SAR_NUM)
1212         return aspectN;
1213     else if (property_id == CV_CAP_PROP_SAR_DEN)
1214         return aspectD;
1215     else if (isOpened)
1216         switch (property_id)
1217         {
1218         case CV_CAP_PROP_FRAME_WIDTH:
1219             return captureFormat.width;
1220         case CV_CAP_PROP_FRAME_HEIGHT:
1221             return captureFormat.height;
1222         case CV_CAP_PROP_FOURCC:
1223             return nativeFormat.MF_MT_SUBTYPE.Data1;
1224         case CV_CAP_PROP_FPS:
1225             return getFramerate(nativeFormat);
1226         case CV_CAP_PROP_FRAME_COUNT:
1227             if (duration != 0)
1228                 return floor(((double)duration / 1e7)*getFramerate(nativeFormat) + 0.5);
1229             else
1230                 break;
1231         case CV_CAP_PROP_POS_FRAMES:
1232             return floor(((double)sampleTime / 1e7)*getFramerate(nativeFormat) + 0.5);
1233         case CV_CAP_PROP_POS_MSEC:
1234             return (double)sampleTime / 1e4;
1235         case CV_CAP_PROP_POS_AVI_RATIO:
1236             if (duration != 0)
1237                 return (double)sampleTime / duration;
1238             else
1239                 break;
1240         case CV_CAP_PROP_BRIGHTNESS:
1241             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1242             {
1243                 long paramVal, paramFlag;
1244                 HRESULT hr = pProcAmp->Get(VideoProcAmp_Brightness, &paramVal, &paramFlag);
1245                 long minVal, maxVal, stepVal;
1246                 if(FAILED(hr))
1247                     hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1248                 pProcAmp->Release();
1249                 if (SUCCEEDED(hr))
1250                     return paramVal;
1251             }
1252             break;
1253         case CV_CAP_PROP_CONTRAST:
1254             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1255             {
1256                 long paramVal, paramFlag;
1257                 HRESULT hr = pProcAmp->Get(VideoProcAmp_Contrast, &paramVal, &paramFlag);
1258                 long minVal, maxVal, stepVal;
1259                 if (FAILED(hr))
1260                     hr = pProcAmp->GetRange(VideoProcAmp_Contrast, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1261                 pProcAmp->Release();
1262                 if (SUCCEEDED(hr))
1263                     return paramVal;
1264             }
1265             break;
1266         case CV_CAP_PROP_SATURATION:
1267             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1268             {
1269                 long paramVal, paramFlag;
1270                 HRESULT hr = pProcAmp->Get(VideoProcAmp_Saturation, &paramVal, &paramFlag);
1271                 long minVal, maxVal, stepVal;
1272                 if (FAILED(hr))
1273                     hr = pProcAmp->GetRange(VideoProcAmp_Saturation, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1274                 pProcAmp->Release();
1275                 if (SUCCEEDED(hr))
1276                     return paramVal;
1277             }
1278             break;
1279         case CV_CAP_PROP_HUE:
1280             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1281             {
1282                 long paramVal, paramFlag;
1283                 HRESULT hr = pProcAmp->Get(VideoProcAmp_Hue, &paramVal, &paramFlag);
1284                 long minVal, maxVal, stepVal;
1285                 if (FAILED(hr))
1286                     hr = pProcAmp->GetRange(VideoProcAmp_Hue, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1287                 pProcAmp->Release();
1288                 if (SUCCEEDED(hr))
1289                     return paramVal;
1290             }
1291             break;
1292         case CV_CAP_PROP_GAIN:
1293             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1294             {
1295                 long paramVal, paramFlag;
1296                 HRESULT hr = pProcAmp->Get(VideoProcAmp_Gain, &paramVal, &paramFlag);
1297                 long minVal, maxVal, stepVal;
1298                 if (FAILED(hr))
1299                     hr = pProcAmp->GetRange(VideoProcAmp_Gain, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1300                 pProcAmp->Release();
1301                 if (SUCCEEDED(hr))
1302                     return paramVal;
1303             }
1304             break;
1305         case CV_CAP_PROP_SHARPNESS:
1306             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1307             {
1308                 long paramVal, paramFlag;
1309                 HRESULT hr = pProcAmp->Get(VideoProcAmp_Sharpness, &paramVal, &paramFlag);
1310                 long minVal, maxVal, stepVal;
1311                 if (FAILED(hr))
1312                     hr = pProcAmp->GetRange(VideoProcAmp_Sharpness, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1313                 pProcAmp->Release();
1314                 if (SUCCEEDED(hr))
1315                     return paramVal;
1316             }
1317             break;
1318         case CV_CAP_PROP_GAMMA:
1319             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1320             {
1321                 long paramVal, paramFlag;
1322                 HRESULT hr = pProcAmp->Get(VideoProcAmp_Gamma, &paramVal, &paramFlag);
1323                 long minVal, maxVal, stepVal;
1324                 if (FAILED(hr))
1325                     hr = pProcAmp->GetRange(VideoProcAmp_Gamma, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1326                 pProcAmp->Release();
1327                 if (SUCCEEDED(hr))
1328                     return paramVal;
1329             }
1330             break;
1331         case CV_CAP_PROP_BACKLIGHT:
1332             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1333             {
1334                 long paramVal, paramFlag;
1335                 HRESULT hr = pProcAmp->Get(VideoProcAmp_BacklightCompensation, &paramVal, &paramFlag);
1336                 long minVal, maxVal, stepVal;
1337                 if (FAILED(hr))
1338                     hr = pProcAmp->GetRange(VideoProcAmp_BacklightCompensation, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1339                 pProcAmp->Release();
1340                 if (SUCCEEDED(hr))
1341                     return paramVal;
1342             }
1343             break;
1344         case CV_CAP_PROP_MONOCHROME:
1345             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1346             {
1347                 long paramVal, paramFlag;
1348                 HRESULT hr = pProcAmp->Get(VideoProcAmp_ColorEnable, &paramVal, &paramFlag);
1349                 long minVal, maxVal, stepVal;
1350                 if (FAILED(hr))
1351                     hr = pProcAmp->GetRange(VideoProcAmp_ColorEnable, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1352                 pProcAmp->Release();
1353                 if (SUCCEEDED(hr))
1354                     return paramVal == 0 ? 1 : 0;
1355             }
1356             break;
1357         case CV_CAP_PROP_TEMPERATURE:
1358             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1359             {
1360                 long paramVal, paramFlag;
1361                 HRESULT hr = pProcAmp->Get(VideoProcAmp_WhiteBalance, &paramVal, &paramFlag);
1362                 long minVal, maxVal, stepVal;
1363                 if (FAILED(hr))
1364                     hr = pProcAmp->GetRange(VideoProcAmp_WhiteBalance, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1365                 pProcAmp->Release();
1366                 if (SUCCEEDED(hr))
1367                     return paramVal;
1368             }
1369         case CV_CAP_PROP_WHITE_BALANCE_BLUE_U:
1370         case CV_CAP_PROP_WHITE_BALANCE_RED_V:
1371             break;
1372         case CV_CAP_PROP_PAN:
1373             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1374             {
1375                 long paramVal, paramFlag;
1376                 HRESULT hr = pProcControl->Get(CameraControl_Pan, &paramVal, &paramFlag);
1377                 long minVal, maxVal, stepVal;
1378                 if (FAILED(hr))
1379                     hr = pProcControl->GetRange(CameraControl_Pan, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1380                 pProcControl->Release();
1381                 if (SUCCEEDED(hr))
1382                     return paramVal;
1383             }
1384             break;
1385         case CV_CAP_PROP_TILT:
1386             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1387             {
1388                 long paramVal, paramFlag;
1389                 HRESULT hr = pProcControl->Get(CameraControl_Tilt, &paramVal, &paramFlag);
1390                 long minVal, maxVal, stepVal;
1391                 if (FAILED(hr))
1392                     hr = pProcControl->GetRange(CameraControl_Tilt, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1393                 pProcControl->Release();
1394                 if (SUCCEEDED(hr))
1395                     return paramVal;
1396             }
1397             break;
1398         case CV_CAP_PROP_ROLL:
1399             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1400             {
1401                 long paramVal, paramFlag;
1402                 HRESULT hr = pProcControl->Get(CameraControl_Roll, &paramVal, &paramFlag);
1403                 long minVal, maxVal, stepVal;
1404                 if (FAILED(hr))
1405                     hr = pProcControl->GetRange(CameraControl_Roll, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1406                 pProcControl->Release();
1407                 if (SUCCEEDED(hr))
1408                     return paramVal;
1409             }
1410             break;
1411         case CV_CAP_PROP_IRIS:
1412             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1413             {
1414                 long paramVal, paramFlag;
1415                 HRESULT hr = pProcControl->Get(CameraControl_Iris, &paramVal, &paramFlag);
1416                 long minVal, maxVal, stepVal;
1417                 if (FAILED(hr))
1418                     hr = pProcControl->GetRange(CameraControl_Iris, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1419                 pProcControl->Release();
1420                 if (SUCCEEDED(hr))
1421                     return paramVal;
1422             }
1423             break;
1424         case CV_CAP_PROP_EXPOSURE:
1425             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1426             {
1427                 long paramVal, paramFlag;
1428                 HRESULT hr = pProcControl->Get(CameraControl_Exposure, &paramVal, &paramFlag);
1429                 long minVal, maxVal, stepVal;
1430                 if (FAILED(hr))
1431                     hr = pProcControl->GetRange(CameraControl_Exposure, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1432                 pProcControl->Release();
1433                 if (SUCCEEDED(hr))
1434                     return paramVal;
1435             }
1436         case CV_CAP_PROP_AUTO_EXPOSURE:
1437             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1438             {
1439                 long paramVal, paramFlag;
1440                 HRESULT hr = pProcControl->Get(CameraControl_Exposure, &paramVal, &paramFlag);
1441                 long minVal, maxVal, stepVal;
1442                 if (FAILED(hr))
1443                     hr = pProcControl->GetRange(CameraControl_Exposure, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1444                 pProcControl->Release();
1445                 if (SUCCEEDED(hr))
1446                     return paramFlag == VideoProcAmp_Flags_Auto;
1447             }
1448             break;
1449         case CV_CAP_PROP_ZOOM:
1450             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1451             {
1452                 long paramVal, paramFlag;
1453                 HRESULT hr = pProcControl->Get(CameraControl_Zoom, &paramVal, &paramFlag);
1454                 long minVal, maxVal, stepVal;
1455                 if (FAILED(hr))
1456                     hr = pProcControl->GetRange(CameraControl_Zoom, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1457                 pProcControl->Release();
1458                 if (SUCCEEDED(hr))
1459                     return paramVal;
1460             }
1461             break;
1462         case CV_CAP_PROP_FOCUS:
1463             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1464             {
1465                 long paramVal, paramFlag;
1466                 HRESULT hr = pProcControl->Get(CameraControl_Focus, &paramVal, &paramFlag);
1467                 long minVal, maxVal, stepVal;
1468                 if (FAILED(hr))
1469                     hr = pProcControl->GetRange(CameraControl_Focus, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1470                 pProcControl->Release();
1471                 if (SUCCEEDED(hr))
1472                     return paramVal;
1473             }
1474         case CV_CAP_PROP_AUTOFOCUS:
1475             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1476             {
1477                 long paramVal, paramFlag;
1478                 HRESULT hr = pProcControl->Get(CameraControl_Focus, &paramVal, &paramFlag);
1479                 long minVal, maxVal, stepVal;
1480                 if (FAILED(hr))
1481                     hr = pProcControl->GetRange(CameraControl_Focus, &minVal, &maxVal, &stepVal, &paramVal, &paramFlag);//Unable to get the property, trying to return default value
1482                 pProcControl->Release();
1483                 if (SUCCEEDED(hr))
1484                     return paramFlag == VideoProcAmp_Flags_Auto;
1485             }
1486             break;
1487
1488         case CV_CAP_PROP_RECTIFICATION:
1489         case CV_CAP_PROP_TRIGGER:
1490         case CV_CAP_PROP_TRIGGER_DELAY:
1491         case CV_CAP_PROP_GUID:
1492         case CV_CAP_PROP_ISO_SPEED:
1493         case CV_CAP_PROP_SETTINGS:
1494         case CV_CAP_PROP_BUFFERSIZE:
1495         default:
1496             break;
1497         }
1498
1499     return -1;
1500 }
1501
1502 bool CvCapture_MSMF::setProperty( int property_id, double value )
1503 {
1504     IAMVideoProcAmp *pProcAmp = NULL;
1505     IAMCameraControl *pProcControl = NULL;
1506     // image capture properties
1507     if (property_id == CV_CAP_PROP_FORMAT)
1508     {
1509         if (isOpened)
1510             return configureOutput(captureFormat.width, captureFormat.height, getFramerate(nativeFormat), aspectN, aspectD, (int)cvRound(value), convertFormat);
1511         else
1512             outputFormat = (int)cvRound(value);
1513         return true;
1514     }
1515     else if (property_id == CV_CAP_PROP_MODE)
1516     {
1517         switch ((MSMFCapture_Mode)((int)value))
1518         {
1519         case MODE_SW:
1520             return configureHW(false);
1521         case MODE_HW:
1522             return configureHW(true);
1523         default:
1524             return false;
1525         }
1526     }
1527     else if (property_id == CV_CAP_PROP_CONVERT_RGB)
1528     {
1529         if (isOpened)
1530             return configureOutput(captureFormat.width, captureFormat.height, getFramerate(nativeFormat), aspectN, aspectD, outputFormat, value != 0);
1531         else
1532             convertFormat = value != 0;
1533         return true;
1534     }
1535     else if (property_id == CV_CAP_PROP_SAR_NUM && value > 0)
1536     {
1537         if (isOpened)
1538             return configureOutput(captureFormat.width, captureFormat.height, getFramerate(nativeFormat), (UINT32)cvRound(value), aspectD, outputFormat, convertFormat);
1539         else
1540             aspectN = (UINT32)cvRound(value);
1541         return true;
1542     }
1543     else if (property_id == CV_CAP_PROP_SAR_DEN && value > 0)
1544     {
1545         if (isOpened)
1546             return configureOutput(captureFormat.width, captureFormat.height, getFramerate(nativeFormat), aspectN, (UINT32)cvRound(value), outputFormat, convertFormat);
1547         else
1548             aspectD = (UINT32)cvRound(value);
1549         return true;
1550     }
1551     else if (isOpened)
1552         switch (property_id)
1553         {
1554         case CV_CAP_PROP_FRAME_WIDTH:
1555             if (value > 0)
1556                 return configureOutput((UINT32)cvRound(value), captureFormat.height, getFramerate(nativeFormat), aspectN, aspectD, outputFormat, convertFormat);
1557             break;
1558         case CV_CAP_PROP_FRAME_HEIGHT:
1559             if (value > 0)
1560                 return configureOutput(captureFormat.width, (UINT32)cvRound(value), getFramerate(nativeFormat), aspectN, aspectD, outputFormat, convertFormat);
1561             break;
1562         case CV_CAP_PROP_FPS:
1563             if (value >= 0)
1564                 return configureOutput(captureFormat.width, captureFormat.height, value, aspectN, aspectD, outputFormat, convertFormat);
1565             break;
1566         case CV_CAP_PROP_FOURCC:
1567             break;
1568         case CV_CAP_PROP_FRAME_COUNT:
1569             break;
1570         case CV_CAP_PROP_POS_AVI_RATIO:
1571             if (duration != 0)
1572                 return setTime(duration * value, true);
1573             break;
1574         case CV_CAP_PROP_POS_FRAMES:
1575             if (getFramerate(nativeFormat) != 0)
1576                 return setTime(value  * 1e7 / getFramerate(nativeFormat), false);
1577             break;
1578         case CV_CAP_PROP_POS_MSEC:
1579                 return setTime(value  * 1e4, true);
1580         case CV_CAP_PROP_BRIGHTNESS:
1581             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1582             {
1583                 long paramVal = (long)value;
1584                 HRESULT hr = pProcAmp->Set(VideoProcAmp_Brightness, paramVal, VideoProcAmp_Flags_Manual);
1585                 pProcAmp->Release();
1586                 return SUCCEEDED(hr);
1587             }
1588             break;
1589         case CV_CAP_PROP_CONTRAST:
1590             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1591             {
1592                 long paramVal = (long)value;
1593                 HRESULT hr = pProcAmp->Set(VideoProcAmp_Contrast, paramVal, VideoProcAmp_Flags_Manual);
1594                 pProcAmp->Release();
1595                 return SUCCEEDED(hr);
1596             }
1597             break;
1598         case CV_CAP_PROP_SATURATION:
1599             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1600             {
1601                 long paramVal = (long)value;
1602                 HRESULT hr = pProcAmp->Set(VideoProcAmp_Saturation, paramVal, VideoProcAmp_Flags_Manual);
1603                 pProcAmp->Release();
1604                 return SUCCEEDED(hr);
1605             }
1606             break;
1607         case CV_CAP_PROP_HUE:
1608             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1609             {
1610                 long paramVal = (long)value;
1611                 HRESULT hr = pProcAmp->Set(VideoProcAmp_Hue, paramVal, VideoProcAmp_Flags_Manual);
1612                 pProcAmp->Release();
1613                 return SUCCEEDED(hr);
1614             }
1615             break;
1616         case CV_CAP_PROP_GAIN:
1617             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1618             {
1619                 long paramVal = (long)value;
1620                 HRESULT hr = pProcAmp->Set(VideoProcAmp_Gain, paramVal, VideoProcAmp_Flags_Manual);
1621                 pProcAmp->Release();
1622                 return SUCCEEDED(hr);
1623             }
1624             break;
1625         case CV_CAP_PROP_SHARPNESS:
1626             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1627             {
1628                 long paramVal = (long)value;
1629                 HRESULT hr = pProcAmp->Set(VideoProcAmp_Sharpness, paramVal, VideoProcAmp_Flags_Manual);
1630                 pProcAmp->Release();
1631                 return SUCCEEDED(hr);
1632             }
1633             break;
1634         case CV_CAP_PROP_GAMMA:
1635             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1636             {
1637                 long paramVal = (long)value;
1638                 HRESULT hr = pProcAmp->Set(VideoProcAmp_Gamma, paramVal, VideoProcAmp_Flags_Manual);
1639                 pProcAmp->Release();
1640                 return SUCCEEDED(hr);
1641             }
1642             break;
1643         case CV_CAP_PROP_BACKLIGHT:
1644             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1645             {
1646                 long paramVal = (long)value;
1647                 HRESULT hr = pProcAmp->Set(VideoProcAmp_BacklightCompensation, paramVal, VideoProcAmp_Flags_Manual);
1648                 pProcAmp->Release();
1649                 return SUCCEEDED(hr);
1650             }
1651             break;
1652         case CV_CAP_PROP_MONOCHROME:
1653             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1654             {
1655                 long paramVal = value != 0 ? 0 : 1;
1656                 HRESULT hr = pProcAmp->Set(VideoProcAmp_ColorEnable, paramVal, VideoProcAmp_Flags_Manual);
1657                 pProcAmp->Release();
1658                 return SUCCEEDED(hr);
1659             }
1660             break;
1661         case CV_CAP_PROP_TEMPERATURE:
1662             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
1663             {
1664                 long paramVal = (long)value;
1665                 HRESULT hr = pProcAmp->Set(VideoProcAmp_WhiteBalance, paramVal, VideoProcAmp_Flags_Manual);
1666                 pProcAmp->Release();
1667                 return SUCCEEDED(hr);
1668             }
1669         case CV_CAP_PROP_WHITE_BALANCE_BLUE_U:
1670         case CV_CAP_PROP_WHITE_BALANCE_RED_V:
1671             break;
1672         case CV_CAP_PROP_PAN:
1673             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1674             {
1675                 long paramVal = (long)value;
1676                 HRESULT hr = pProcControl->Set(CameraControl_Pan, paramVal, VideoProcAmp_Flags_Manual);
1677                 pProcControl->Release();
1678                 return SUCCEEDED(hr);
1679             }
1680             break;
1681         case CV_CAP_PROP_TILT:
1682             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1683             {
1684                 long paramVal = (long)value;
1685                 HRESULT hr = pProcControl->Set(CameraControl_Tilt, paramVal, VideoProcAmp_Flags_Manual);
1686                 pProcControl->Release();
1687                 return SUCCEEDED(hr);
1688             }
1689             break;
1690         case CV_CAP_PROP_ROLL:
1691             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1692             {
1693                 long paramVal = (long)value;
1694                 HRESULT hr = pProcControl->Set(CameraControl_Roll, paramVal, VideoProcAmp_Flags_Manual);
1695                 pProcControl->Release();
1696                 return SUCCEEDED(hr);
1697             }
1698             break;
1699         case CV_CAP_PROP_IRIS:
1700             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1701             {
1702                 long paramVal = (long)value;
1703                 HRESULT hr = pProcControl->Set(CameraControl_Iris, paramVal, VideoProcAmp_Flags_Manual);
1704                 pProcControl->Release();
1705                 return SUCCEEDED(hr);
1706             }
1707             break;
1708         case CV_CAP_PROP_EXPOSURE:
1709             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1710             {
1711                 long paramVal = (long)value;
1712                 HRESULT hr = pProcControl->Set(CameraControl_Exposure, paramVal, VideoProcAmp_Flags_Manual);
1713                 pProcControl->Release();
1714                 return SUCCEEDED(hr);
1715             }
1716         case CV_CAP_PROP_AUTO_EXPOSURE:
1717             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1718             {
1719                 long paramVal = 0;
1720                 HRESULT hr = pProcControl->Set(CameraControl_Exposure, paramVal, value != 0 ? VideoProcAmp_Flags_Auto : VideoProcAmp_Flags_Manual);
1721                 pProcControl->Release();
1722                 return SUCCEEDED(hr);
1723             }
1724             break;
1725         case CV_CAP_PROP_ZOOM:
1726             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1727             {
1728                 long paramVal = (long)value;
1729                 HRESULT hr = pProcControl->Set(CameraControl_Zoom, paramVal, VideoProcAmp_Flags_Manual);
1730                 pProcControl->Release();
1731                 return SUCCEEDED(hr);
1732             }
1733             break;
1734         case CV_CAP_PROP_FOCUS:
1735             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1736             {
1737                 long paramVal = (long)value;
1738                 HRESULT hr = pProcControl->Set(CameraControl_Focus, paramVal, VideoProcAmp_Flags_Manual);
1739                 pProcControl->Release();
1740                 return SUCCEEDED(hr);
1741             }
1742         case CV_CAP_PROP_AUTOFOCUS:
1743             if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
1744             {
1745                 long paramVal = 0;
1746                 HRESULT hr = pProcControl->Set(CameraControl_Focus, paramVal, value != 0 ? VideoProcAmp_Flags_Auto : VideoProcAmp_Flags_Manual);
1747                 pProcControl->Release();
1748                 return SUCCEEDED(hr);
1749             }
1750             break;
1751
1752         case CV_CAP_PROP_RECTIFICATION:
1753         case CV_CAP_PROP_TRIGGER:
1754         case CV_CAP_PROP_TRIGGER_DELAY:
1755         case CV_CAP_PROP_GUID:
1756         case CV_CAP_PROP_ISO_SPEED:
1757         case CV_CAP_PROP_SETTINGS:
1758         case CV_CAP_PROP_BUFFERSIZE:
1759         default:
1760             break;
1761         }
1762
1763     return false;
1764 }
1765
1766 CvCapture* cvCreateCameraCapture_MSMF( int index )
1767 {
1768     CvCapture_MSMF* capture = new CvCapture_MSMF;
1769     try
1770     {
1771         if( capture->open( index ))
1772             return capture;
1773     }
1774     catch(...)
1775     {
1776         delete capture;
1777         throw;
1778     }
1779     delete capture;
1780     return 0;
1781 }
1782
1783 CvCapture* cvCreateFileCapture_MSMF (const char* filename)
1784 {
1785     CvCapture_MSMF* capture = new CvCapture_MSMF;
1786     try
1787     {
1788         if( capture->open(filename) )
1789             return capture;
1790         else
1791         {
1792             delete capture;
1793             return NULL;
1794         }
1795     }
1796     catch(...)
1797     {
1798         delete capture;
1799         throw;
1800     }
1801 }
1802
1803 //
1804 //
1805 // Media Foundation-based Video Writer
1806 //
1807 //
1808
1809 class CvVideoWriter_MSMF : public CvVideoWriter
1810 {
1811 public:
1812     CvVideoWriter_MSMF();
1813     virtual ~CvVideoWriter_MSMF();
1814     virtual bool open(const char* filename, int fourcc,
1815                        double fps, CvSize frameSize, bool isColor);
1816     virtual void close();
1817     virtual bool writeFrame(const IplImage* img);
1818
1819 private:
1820     Media_Foundation& MF;
1821     UINT32 videoWidth;
1822     UINT32 videoHeight;
1823     double fps;
1824     UINT32 bitRate;
1825     UINT32 frameSize;
1826     GUID   encodingFormat;
1827     GUID   inputFormat;
1828
1829     DWORD  streamIndex;
1830     _ComPtr<IMFSinkWriter> sinkWriter;
1831
1832     bool   initiated;
1833
1834     LONGLONG rtStart;
1835     UINT64 rtDuration;
1836
1837     static const GUID FourCC2GUID(int fourcc);
1838 };
1839
1840 CvVideoWriter_MSMF::CvVideoWriter_MSMF():
1841     MF(Media_Foundation::getInstance()),
1842     initiated(false)
1843 {
1844 }
1845
1846 CvVideoWriter_MSMF::~CvVideoWriter_MSMF()
1847 {
1848     close();
1849 }
1850
1851 const GUID CvVideoWriter_MSMF::FourCC2GUID(int fourcc)
1852 {
1853     switch(fourcc)
1854     {
1855         case CV_FOURCC_MACRO('d', 'v', '2', '5'):
1856             return MFVideoFormat_DV25; break;
1857         case CV_FOURCC_MACRO('d', 'v', '5', '0'):
1858             return MFVideoFormat_DV50; break;
1859         case CV_FOURCC_MACRO('d', 'v', 'c', ' '):
1860             return MFVideoFormat_DVC; break;
1861         case CV_FOURCC_MACRO('d', 'v', 'h', '1'):
1862             return MFVideoFormat_DVH1; break;
1863         case CV_FOURCC_MACRO('d', 'v', 'h', 'd'):
1864             return MFVideoFormat_DVHD; break;
1865         case CV_FOURCC_MACRO('d', 'v', 's', 'd'):
1866             return MFVideoFormat_DVSD; break;
1867         case CV_FOURCC_MACRO('d', 'v', 's', 'l'):
1868                 return MFVideoFormat_DVSL; break;
1869 #if (WINVER >= 0x0602)
1870         case CV_FOURCC_MACRO('H', '2', '6', '3'):   // Available only for Win 8 target.
1871                 return MFVideoFormat_H263; break;
1872 #endif
1873         case CV_FOURCC_MACRO('H', '2', '6', '4'):
1874                 return MFVideoFormat_H264; break;
1875         case CV_FOURCC_MACRO('M', '4', 'S', '2'):
1876                 return MFVideoFormat_M4S2; break;
1877         case CV_FOURCC_MACRO('M', 'J', 'P', 'G'):
1878                 return MFVideoFormat_MJPG; break;
1879         case CV_FOURCC_MACRO('M', 'P', '4', '3'):
1880                 return MFVideoFormat_MP43; break;
1881         case CV_FOURCC_MACRO('M', 'P', '4', 'S'):
1882                 return MFVideoFormat_MP4S; break;
1883         case CV_FOURCC_MACRO('M', 'P', '4', 'V'):
1884                 return MFVideoFormat_MP4V; break;
1885         case CV_FOURCC_MACRO('M', 'P', 'G', '1'):
1886                 return MFVideoFormat_MPG1; break;
1887         case CV_FOURCC_MACRO('M', 'S', 'S', '1'):
1888                 return MFVideoFormat_MSS1; break;
1889         case CV_FOURCC_MACRO('M', 'S', 'S', '2'):
1890                 return MFVideoFormat_MSS2; break;
1891         case CV_FOURCC_MACRO('W', 'M', 'V', '1'):
1892                 return MFVideoFormat_WMV1; break;
1893         case CV_FOURCC_MACRO('W', 'M', 'V', '2'):
1894                 return MFVideoFormat_WMV2; break;
1895         case CV_FOURCC_MACRO('W', 'M', 'V', '3'):
1896                 return MFVideoFormat_WMV3; break;
1897         case CV_FOURCC_MACRO('W', 'V', 'C', '1'):
1898                 return MFVideoFormat_WVC1; break;
1899         default:
1900             return MFVideoFormat_H264;
1901     }
1902 }
1903
1904 bool CvVideoWriter_MSMF::open( const char* filename, int fourcc,
1905                        double _fps, CvSize _frameSize, bool /*isColor*/ )
1906 {
1907     if (initiated)
1908         close();
1909     videoWidth = _frameSize.width;
1910     videoHeight = _frameSize.height;
1911     fps = _fps;
1912     bitRate = (UINT32)fps*videoWidth*videoHeight; // 1-bit per pixel
1913     encodingFormat = FourCC2GUID(fourcc);
1914     inputFormat = MFVideoFormat_RGB32;
1915
1916     _ComPtr<IMFMediaType>  mediaTypeOut;
1917     _ComPtr<IMFMediaType>  mediaTypeIn;
1918     _ComPtr<IMFAttributes> spAttr;
1919     if (// Set the output media type.
1920         SUCCEEDED(MFCreateMediaType(&mediaTypeOut)) &&
1921         SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)) &&
1922         SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_SUBTYPE, encodingFormat)) &&
1923         SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, bitRate)) &&
1924         SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) &&
1925         SUCCEEDED(MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight)) &&
1926         SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1)) &&
1927         SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1)) &&
1928         // Set the input media type.
1929         SUCCEEDED(MFCreateMediaType(&mediaTypeIn)) &&
1930         SUCCEEDED(mediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)) &&
1931         SUCCEEDED(mediaTypeIn->SetGUID(MF_MT_SUBTYPE, inputFormat)) &&
1932         SUCCEEDED(mediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) &&
1933         SUCCEEDED(mediaTypeIn->SetUINT32(MF_MT_DEFAULT_STRIDE, 4 * videoWidth)) && //Assume BGR32 input
1934         SUCCEEDED(MFSetAttributeSize(mediaTypeIn.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight)) &&
1935         SUCCEEDED(MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1)) &&
1936         SUCCEEDED(MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1)) &&
1937         // Set sink writer parameters
1938         SUCCEEDED(MFCreateAttributes(&spAttr, 10)) &&
1939         SUCCEEDED(spAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)) &&
1940         SUCCEEDED(spAttr->SetUINT32(MF_SINK_WRITER_DISABLE_THROTTLING, true))
1941         )
1942     {
1943         // Create the sink writer
1944         cv::AutoBuffer<wchar_t> unicodeFileName(strlen(filename) + 1);
1945         MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, (int)strlen(filename) + 1);
1946         HRESULT hr = MFCreateSinkWriterFromURL(unicodeFileName, NULL, spAttr.Get(), &sinkWriter);
1947         if (SUCCEEDED(hr))
1948         {
1949             // Configure the sink writer and tell it start to start accepting data
1950             if (SUCCEEDED(sinkWriter->AddStream(mediaTypeOut.Get(), &streamIndex)) &&
1951                 SUCCEEDED(sinkWriter->SetInputMediaType(streamIndex, mediaTypeIn.Get(), NULL)) &&
1952                 SUCCEEDED(sinkWriter->BeginWriting()))
1953             {
1954                 initiated = true;
1955                 rtStart = 0;
1956                 MFFrameRateToAverageTimePerFrame((UINT32)fps, 1, &rtDuration);
1957                 return true;
1958             }
1959         }
1960     }
1961
1962     return false;
1963 }
1964
1965 void CvVideoWriter_MSMF::close()
1966 {
1967     if (initiated)
1968     {
1969         initiated = false;
1970         sinkWriter->Finalize();
1971         sinkWriter.Reset();
1972     }
1973 }
1974
1975 bool CvVideoWriter_MSMF::writeFrame(const IplImage* img)
1976 {
1977     if (!img ||
1978         (img->nChannels != 1 && img->nChannels != 3 && img->nChannels != 4) ||
1979         (UINT32)img->width != videoWidth || (UINT32)img->height != videoHeight)
1980         return false;
1981
1982     const LONG cbWidth = 4 * videoWidth;
1983     const DWORD cbBuffer = cbWidth * videoHeight;
1984     _ComPtr<IMFSample> sample;
1985     _ComPtr<IMFMediaBuffer> buffer;
1986     BYTE *pData = NULL;
1987     // Prepare a media sample.
1988     if (SUCCEEDED(MFCreateSample(&sample)) &&
1989         // Set sample time stamp and duration.
1990         SUCCEEDED(sample->SetSampleTime(rtStart)) &&
1991         SUCCEEDED(sample->SetSampleDuration(rtDuration)) &&
1992         // Create a memory buffer.
1993         SUCCEEDED(MFCreateMemoryBuffer(cbBuffer, &buffer)) &&
1994         // Set the data length of the buffer.
1995         SUCCEEDED(buffer->SetCurrentLength(cbBuffer)) &&
1996         // Add the buffer to the sample.
1997         SUCCEEDED(sample->AddBuffer(buffer.Get())) &&
1998         // Lock the buffer.
1999         SUCCEEDED(buffer->Lock(&pData, NULL, NULL)))
2000     {
2001         // Copy the video frame to the buffer.
2002         cv::cvtColor(cv::cvarrToMat(img), cv::Mat(videoHeight, videoWidth, CV_8UC4, pData, cbWidth), img->nChannels > 1 ? cv::COLOR_BGR2BGRA : cv::COLOR_GRAY2BGRA);
2003         buffer->Unlock();
2004         // Send media sample to the Sink Writer.
2005         if (SUCCEEDED(sinkWriter->WriteSample(streamIndex, sample.Get())))
2006         {
2007             rtStart += rtDuration;
2008             return true;
2009         }
2010     }
2011
2012     return false;
2013 }
2014
2015 CvVideoWriter* cvCreateVideoWriter_MSMF( const char* filename, int fourcc,
2016                                         double fps, CvSize frameSize, int isColor )
2017 {
2018     CvVideoWriter_MSMF* writer = new CvVideoWriter_MSMF;
2019     if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))
2020         return writer;
2021     delete writer;
2022     return NULL;
2023 }
2024
2025 #endif