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