1/*M/////////////////////////////////////////////////////////////////////////////////////// 2// 3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4// 5// By downloading, copying, installing or using the software you agree to this license. 6// If you do not agree to this license, do not download, install, 7// copy or use the software. 8// 9// 10// Intel License Agreement 11// For Open Source Computer Vision Library 12// 13// Copyright (C) 2000, Intel Corporation, all rights reserved. 14// Third party copyrights are property of their respective owners. 15// 16// Redistribution and use in source and binary forms, with or without modification, 17// are permitted provided that the following conditions are met: 18// 19// * Redistribution's of source code must retain the above copyright notice, 20// this list of conditions and the following disclaimer. 21// 22// * Redistribution's in binary form must reproduce the above copyright notice, 23// this list of conditions and the following disclaimer in the documentation 24// and/or other materials provided with the distribution. 25// 26// * The name of Intel Corporation may not be used to endorse or promote products 27// derived from this software without specific prior written permission. 28// 29// This software is provided by the copyright holders and contributors "as is" and 30// any express or implied warranties, including, but not limited to, the implied 31// warranties of merchantability and fitness for a particular purpose are disclaimed. 32// In no event shall the Intel Corporation or contributors be liable for any direct, 33// indirect, incidental, special, exemplary, or consequential damages 34// (including, but not limited to, procurement of substitute goods or services; 35// loss of use, data, or profits; or business interruption) however caused 36// and on any theory of liability, whether in contract, strict liability, 37// or tort (including negligence or otherwise) arising in any way out of 38// the use of this software, even if advised of the possibility of such damage. 39// 40//M*/ 41#include "precomp.hpp" 42#if (defined WIN32 || defined _WIN32) && defined HAVE_MSMF 43/* 44 Media Foundation-based Video Capturing module is based on 45 videoInput library by Evgeny Pereguda: 46 http://www.codeproject.com/Articles/559437/Capturing-of-video-from-web-camera-on-Windows-7-an 47 Originaly licensed under The Code Project Open License (CPOL) 1.02: 48 http://www.codeproject.com/info/cpol10.aspx 49*/ 50//require Windows 8 for some of the formats defined otherwise could baseline on lower version 51#if WINVER < _WIN32_WINNT_WIN7 52#undef WINVER 53#define WINVER _WIN32_WINNT_WIN7 54#endif 55#if defined _MSC_VER && _MSC_VER >= 1600 56 #define HAVE_CONCURRENCY 57#endif 58#include <windows.h> 59#include <guiddef.h> 60#include <mfidl.h> 61#include <Mfapi.h> 62#include <mfplay.h> 63#include <mfobjects.h> 64#include <tchar.h> 65#include <strsafe.h> 66#include <Mfreadwrite.h> 67#include <new> 68#include <map> 69#include <vector> 70#include <string> 71#include <stdio.h> 72#include <stdarg.h> 73#include <string.h> 74 75#ifdef _MSC_VER 76#pragma warning(disable:4503) 77#pragma comment(lib, "mfplat") 78#pragma comment(lib, "mf") 79#pragma comment(lib, "mfuuid") 80#pragma comment(lib, "Strmiids") 81#pragma comment(lib, "Mfreadwrite") 82#if (WINVER >= 0x0602) // Available since Win 8 83#pragma comment(lib, "MinCore_Downlevel") 84#endif 85#endif 86 87#include <mferror.h> 88 89#ifdef WINRT 90 // for ComPtr usage 91#include <wrl/client.h> 92#ifdef __cplusplus_winrt 93#include <agile.h> 94#include <vccorlib.h> 95#endif 96 97#include <wrl\async.h> 98#include <wrl\implements.h> 99#include <wrl\module.h> 100#include <wrl\wrappers\corewrappers.h> 101#include <windows.media.capture.h> 102#include <windows.devices.enumeration.h> 103#ifdef HAVE_CONCURRENCY 104#include <concrt.h> 105#ifndef __cplusplus_winrt 106__declspec(noreturn) void __stdcall __abi_WinRTraiseException(long); 107 108inline void __abi_ThrowIfFailed(long __hrArg) 109{ 110 if (__hrArg < 0) 111 { 112 __abi_WinRTraiseException(__hrArg); 113 } 114} 115 116struct Guid 117{ 118public: 119 Guid(); 120 Guid(__rcGUID_t); 121 operator ::__rcGUID_t(); 122 bool Equals(Guid __guidArg); 123 bool Equals(__rcGUID_t __guidArg); 124 Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, unsigned __int8 __dArg, 125 unsigned __int8 __eArg, unsigned __int8 __fArg, unsigned __int8 __gArg, unsigned __int8 __hArg, 126 unsigned __int8 __iArg, unsigned __int8 __jArg, unsigned __int8 __kArg); 127 Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, const unsigned __int8* __dArg); 128private: 129 unsigned long __a; 130 unsigned short __b; 131 unsigned short __c; 132 unsigned char __d; 133 unsigned char __e; 134 unsigned char __f; 135 unsigned char __g; 136 unsigned char __h; 137 unsigned char __i; 138 unsigned char __j; 139 unsigned char __k; 140}; 141 142static_assert(sizeof(Guid) == sizeof(::_GUID), "Incorect size for Guid"); 143static_assert(sizeof(__rcGUID_t) == sizeof(::_GUID), "Incorect size for __rcGUID_t"); 144 145//////////////////////////////////////////////////////////////////////////////// 146inline Guid::Guid() : __a(0), __b(0), __c(0), __d(0), __e(0), __f(0), __g(0), __h(0), __i(0), __j(0), __k(0) 147{ 148} 149 150inline Guid::Guid(__rcGUID_t __guid) : 151__a(reinterpret_cast<const __s_GUID&>(__guid).Data1), 152__b(reinterpret_cast<const __s_GUID&>(__guid).Data2), 153__c(reinterpret_cast<const __s_GUID&>(__guid).Data3), 154__d(reinterpret_cast<const __s_GUID&>(__guid).Data4[0]), 155__e(reinterpret_cast<const __s_GUID&>(__guid).Data4[1]), 156__f(reinterpret_cast<const __s_GUID&>(__guid).Data4[2]), 157__g(reinterpret_cast<const __s_GUID&>(__guid).Data4[3]), 158__h(reinterpret_cast<const __s_GUID&>(__guid).Data4[4]), 159__i(reinterpret_cast<const __s_GUID&>(__guid).Data4[5]), 160__j(reinterpret_cast<const __s_GUID&>(__guid).Data4[6]), 161__k(reinterpret_cast<const __s_GUID&>(__guid).Data4[7]) 162{ 163} 164 165inline Guid::operator ::__rcGUID_t() 166{ 167 return reinterpret_cast<__rcGUID_t>(*this); 168} 169 170inline bool Guid::Equals(Guid __guidArg) 171{ 172 return *this == __guidArg; 173} 174 175inline bool Guid::Equals(__rcGUID_t __guidArg) 176{ 177 return *this == static_cast< Guid>(__guidArg); 178} 179 180inline bool operator==(Guid __aArg, Guid __bArg) 181{ 182 auto __a = reinterpret_cast<unsigned long*>(&__aArg); 183 auto __b = reinterpret_cast<unsigned long*>(&__bArg); 184 185 return (__a[0] == __b[0] && __a[1] == __b[1] && __a[2] == __b[2] && __a[3] == __b[3]); 186} 187 188inline bool operator!=(Guid __aArg, Guid __bArg) 189{ 190 return !(__aArg == __bArg); 191} 192 193inline bool operator<(Guid __aArg, Guid __bArg) 194{ 195 auto __a = reinterpret_cast<unsigned long*>(&__aArg); 196 auto __b = reinterpret_cast<unsigned long*>(&__bArg); 197 198 if (__a[0] != __b[0]) 199 { 200 return __a[0] < __b[0]; 201 } 202 203 if (__a[1] != __b[1]) 204 { 205 return __a[1] < __b[1]; 206 } 207 208 if (__a[2] != __b[2]) 209 { 210 return __a[2] < __b[2]; 211 } 212 213 if (__a[3] != __b[3]) 214 { 215 return __a[3] < __b[3]; 216 } 217 218 return false; 219} 220 221inline Guid::Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, unsigned __int8 __dArg, 222 unsigned __int8 __eArg, unsigned __int8 __fArg, unsigned __int8 __gArg, unsigned __int8 __hArg, 223 unsigned __int8 __iArg, unsigned __int8 __jArg, unsigned __int8 __kArg) : 224 __a(__aArg), __b(__bArg), __c(__cArg), __d(__dArg), __e(__eArg), __f(__fArg), __g(__gArg), __h(__hArg), __i(__iArg), __j(__jArg), __k(__kArg) 225{ 226} 227 228inline Guid::Guid(unsigned int __aArg, unsigned short __bArg, unsigned short __cArg, const unsigned __int8 __dArg[8]) : 229__a(__aArg), __b(__bArg), __c(__cArg) 230{ 231 __d = __dArg[0]; 232 __e = __dArg[1]; 233 __f = __dArg[2]; 234 __g = __dArg[3]; 235 __h = __dArg[4]; 236 __i = __dArg[5]; 237 __j = __dArg[6]; 238 __k = __dArg[7]; 239} 240 241__declspec(selectany) Guid __winrt_GUID_NULL(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 242 243// 244//// Don't want to define the real IUnknown from unknown.h here. That would means if the user has 245//// any broken code that uses it, compile errors will take the form of e.g.: 246//// predefined C++ WinRT types (compiler internal)(41) : see declaration of 'IUnknown::QueryInterface' 247//// This is not helpful. If they use IUnknown, we still need to point them to the actual unknown.h so 248//// that they can see the original definition. 249//// 250//// For WinRT, we'll instead have a parallel COM interface hierarchy for basic interfaces starting with _. 251//// The type mismatch is not an issue. COM passes types through GUID / void* combos - the original type 252//// doesn't come into play unless the user static_casts an implementation type to one of these, but 253//// the WinRT implementation types are hidden. 254__interface __declspec(uuid("00000000-0000-0000-C000-000000000046")) __abi_IUnknown 255{ 256public: 257 virtual long __stdcall __abi_QueryInterface(Guid&, void**) = 0; 258 virtual unsigned long __stdcall __abi_AddRef() = 0; 259 virtual unsigned long __stdcall __abi_Release() = 0; 260}; 261#endif 262#include "ppltasks_winrt.h" 263#endif 264#else 265#include <comdef.h> 266#endif 267 268struct IMFMediaType; 269#ifndef WINRT 270struct IMFActivate; 271struct IMFMediaSource; 272#endif 273struct IMFAttributes; 274 275namespace 276{ 277 278template <class T> void SafeRelease(T **ppT) 279{ 280 if (*ppT) 281 { 282 (*ppT)->Release(); 283 *ppT = NULL; 284 } 285} 286 287#ifdef _DEBUG 288/// Class for printing info into console 289class DPO 290{ 291public: 292 ~DPO(void); 293 static DPO& getInstance(); 294 void printOut(const wchar_t *format, ...); 295 void setVerbose(bool state); 296 bool verbose; 297private: 298 DPO(void); 299}; 300#define DebugPrintOut(...) DPO::getInstance().printOut(__VA_ARGS__) 301#else 302#define DebugPrintOut(...) void() 303#endif 304 305#include "cap_msmf.hpp" 306 307// Structure for collecting info about types of video, which are supported by current video device 308struct MediaType 309{ 310 unsigned int MF_MT_FRAME_SIZE; 311 unsigned int height; 312 unsigned int width; 313 unsigned int MF_MT_YUV_MATRIX; 314 unsigned int MF_MT_VIDEO_LIGHTING; 315 int MF_MT_DEFAULT_STRIDE; // stride is negative if image is bottom-up 316 unsigned int MF_MT_VIDEO_CHROMA_SITING; 317 GUID MF_MT_AM_FORMAT_TYPE; 318 wchar_t *pMF_MT_AM_FORMAT_TYPEName; 319 unsigned int MF_MT_FIXED_SIZE_SAMPLES; 320 unsigned int MF_MT_VIDEO_NOMINAL_RANGE; 321 unsigned int MF_MT_FRAME_RATE_NUMERATOR; 322 unsigned int MF_MT_FRAME_RATE_DENOMINATOR; 323 unsigned int MF_MT_PIXEL_ASPECT_RATIO; 324 unsigned int MF_MT_PIXEL_ASPECT_RATIO_low; 325 unsigned int MF_MT_ALL_SAMPLES_INDEPENDENT; 326 unsigned int MF_MT_FRAME_RATE_RANGE_MIN; 327 unsigned int MF_MT_FRAME_RATE_RANGE_MIN_low; 328 unsigned int MF_MT_SAMPLE_SIZE; 329 unsigned int MF_MT_VIDEO_PRIMARIES; 330 unsigned int MF_MT_INTERLACE_MODE; 331 unsigned int MF_MT_FRAME_RATE_RANGE_MAX; 332 unsigned int MF_MT_FRAME_RATE_RANGE_MAX_low; 333 GUID MF_MT_MAJOR_TYPE; 334 GUID MF_MT_SUBTYPE; 335 wchar_t *pMF_MT_MAJOR_TYPEName; 336 wchar_t *pMF_MT_SUBTYPEName; 337 MediaType(); 338 ~MediaType(); 339 void Clear(); 340}; 341 342/// Class for parsing info from IMFMediaType into the local MediaType 343class FormatReader 344{ 345public: 346 static MediaType Read(IMFMediaType *pType); 347 ~FormatReader(void); 348private: 349 FormatReader(void); 350}; 351 352DWORD WINAPI MainThreadFunction( LPVOID lpParam ); 353typedef void(*emergensyStopEventCallback)(int, void *); 354 355class RawImage 356{ 357public: 358 ~RawImage(void); 359 // Function of creation of the instance of the class 360 static long CreateInstance(RawImage **ppRImage,unsigned int size); 361 void setCopy(const BYTE * pSampleBuffer); 362 void fastCopy(const BYTE * pSampleBuffer); 363 unsigned char * getpPixels(); 364 bool isNew(); 365 unsigned int getSize(); 366private: 367 bool ri_new; 368 unsigned int ri_size; 369 unsigned char *ri_pixels; 370 RawImage(unsigned int size); 371}; 372 373class ImageGrabberCallback : public IMFSampleGrabberSinkCallback 374{ 375public: 376 void pauseGrabbing(); 377 void resumeGrabbing(); 378 RawImage *getRawImage(); 379 // IMFClockStateSink methods 380 STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset); 381 STDMETHODIMP OnClockStop(MFTIME hnsSystemTime); 382 STDMETHODIMP OnClockPause(MFTIME hnsSystemTime); 383 STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime); 384 STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate); 385 // IMFSampleGrabberSinkCallback methods 386 STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock); 387 STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, 388 LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, 389 DWORD dwSampleSize); 390 STDMETHODIMP OnShutdown(); 391 392 const HANDLE ig_hFrameReady; 393 const HANDLE ig_hFrameGrabbed; 394 const HANDLE ig_hFinish; 395protected: 396 ImageGrabberCallback(bool synchronous); 397 bool ig_RIE; 398 bool ig_Close; 399 bool ig_Synchronous; 400 long m_cRef; 401 402 RawImage *ig_RIFirst; 403 RawImage *ig_RISecond; 404 RawImage *ig_RIOut; 405private: 406 ImageGrabberCallback& operator=(const ImageGrabberCallback&); // Declared to fix compilation warning. 407 }; 408 409#ifdef WINRT 410extern const __declspec(selectany) WCHAR RuntimeClass_CV_ImageGrabberWinRT[] = L"cv.ImageGrabberWinRT"; 411 412class ImageGrabberWinRT : 413 public Microsoft::WRL::RuntimeClass< 414 Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRtClassicComMix>, 415 IMFSampleGrabberSinkCallback>, public ImageGrabberCallback 416{ 417 InspectableClass(RuntimeClass_CV_ImageGrabberWinRT, BaseTrust) 418public: 419 ImageGrabberWinRT(bool synchronous); 420 ~ImageGrabberWinRT(void); 421 422 HRESULT initImageGrabber(MAKE_WRL_REF(_MediaCapture) pSource, 423 GUID VideoFormat); 424 HRESULT startGrabbing(MAKE_WRL_REF(_AsyncAction)* action); 425 HRESULT stopGrabbing(MAKE_WRL_REF(_AsyncAction)* action); 426 // IMFClockStateSink methods 427 STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) { return ImageGrabberCallback::OnClockStart(hnsSystemTime, llClockStartOffset); } 428 STDMETHODIMP OnClockStop(MFTIME hnsSystemTime) { return ImageGrabberCallback::OnClockStop(hnsSystemTime); } 429 STDMETHODIMP OnClockPause(MFTIME hnsSystemTime) { return ImageGrabberCallback::OnClockPause(hnsSystemTime); } 430 STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime) { return ImageGrabberCallback::OnClockRestart(hnsSystemTime); } 431 STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate) { return ImageGrabberCallback::OnClockSetRate(hnsSystemTime, flRate); } 432 // IMFSampleGrabberSinkCallback methods 433 STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock) { return ImageGrabberCallback::OnSetPresentationClock(pClock); } 434 STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, 435 LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, 436 DWORD dwSampleSize) { return ImageGrabberCallback::OnProcessSample(guidMajorMediaType, dwSampleFlags, llSampleTime, llSampleDuration, pSampleBuffer, dwSampleSize); } 437 STDMETHODIMP OnShutdown() { return ImageGrabberCallback::OnShutdown(); } 438 // Function of creation of the instance of the class 439 static HRESULT CreateInstance(ImageGrabberWinRT **ppIG, bool synchronous = false); 440private: 441 MAKE_WRL_AGILE_REF(_MediaCapture) ig_pMedCapSource; 442 MediaSink* ig_pMediaSink; 443}; 444#endif 445 446// Class for grabbing image from video stream 447class ImageGrabber : public ImageGrabberCallback 448{ 449public: 450 ~ImageGrabber(void); 451 HRESULT initImageGrabber(IMFMediaSource *pSource); 452 HRESULT startGrabbing(void); 453 void stopGrabbing(); 454 // IUnknown methods 455 STDMETHODIMP QueryInterface(REFIID iid, void** ppv); 456 STDMETHODIMP_(ULONG) AddRef(); 457 STDMETHODIMP_(ULONG) Release(); 458 // Function of creation of the instance of the class 459 static HRESULT CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, bool synchronous = false); 460 461private: 462 unsigned int ig_DeviceID; 463 464 IMFMediaSource *ig_pSource; 465 IMFMediaSession *ig_pSession; 466 IMFTopology *ig_pTopology; 467 ImageGrabber(unsigned int deviceID, bool synchronous); 468 HRESULT CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo); 469 HRESULT AddSourceNode(IMFTopology *pTopology, IMFMediaSource *pSource, 470 IMFPresentationDescriptor *pPD, IMFStreamDescriptor *pSD, IMFTopologyNode **ppNode); 471 HRESULT AddOutputNode(IMFTopology *pTopology, IMFActivate *pActivate, DWORD dwId, IMFTopologyNode **ppNode); 472 473 ImageGrabber& operator=(const ImageGrabber&); // Declared to fix comiplation error. 474}; 475 476/// Class for controlling of thread of the grabbing raw data from video device 477class ImageGrabberThread 478{ 479 friend DWORD WINAPI MainThreadFunction( LPVOID lpParam ); 480public: 481 ~ImageGrabberThread(void); 482 static HRESULT CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious = false); 483 void start(); 484 void stop(); 485 void setEmergencyStopEvent(void *userData, void(*func)(int, void *)); 486 ImageGrabber *getImageGrabber(); 487protected: 488 virtual void run(); 489private: 490 ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious); 491 HANDLE igt_Handle; 492 DWORD igt_ThreadIdArray; 493 ImageGrabber *igt_pImageGrabber; 494 emergensyStopEventCallback igt_func; 495 void *igt_userData; 496 bool igt_stop; 497 unsigned int igt_DeviceID; 498}; 499 500// Structure for collecting info about one parametr of current video device 501struct Parametr 502{ 503 long CurrentValue; 504 long Min; 505 long Max; 506 long Step; 507 long Default; 508 long Flag; 509 Parametr(); 510}; 511 512// Structure for collecting info about 17 parametrs of current video device 513struct CamParametrs 514{ 515 Parametr Brightness; 516 Parametr Contrast; 517 Parametr Hue; 518 Parametr Saturation; 519 Parametr Sharpness; 520 Parametr Gamma; 521 Parametr ColorEnable; 522 Parametr WhiteBalance; 523 Parametr BacklightCompensation; 524 Parametr Gain; 525 Parametr Pan; 526 Parametr Tilt; 527 Parametr Roll; 528 Parametr Zoom; 529 Parametr Exposure; 530 Parametr Iris; 531 Parametr Focus; 532}; 533 534typedef std::wstring String; 535typedef std::vector<int> vectorNum; 536typedef std::map<String, vectorNum> SUBTYPEMap; 537typedef std::map<UINT64, SUBTYPEMap> FrameRateMap; 538typedef void(*emergensyStopEventCallback)(int, void *); 539 540/// Class for controlling of video device 541class videoDevice 542{ 543public: 544 videoDevice(void); 545 ~videoDevice(void); 546 void closeDevice(); 547 CamParametrs getParametrs(); 548 void setParametrs(CamParametrs parametrs); 549 void setEmergencyStopEvent(void *userData, void(*func)(int, void *)); 550#ifdef WINRT 551 long readInfoOfDevice(MAKE_WRL_REF(_IDeviceInformation) pDevice, unsigned int Num); 552 void waitForDevice() 553 { 554 if (vd_pAction) { 555#ifdef HAVE_CONCURRENCY 556 CREATE_TASK DEFINE_RET_TYPE(void)(vd_pAction).wait(); 557#endif 558 vd_pAction = nullptr; 559 } 560 } 561#else 562 long readInfoOfDevice(IMFActivate *pActivate, unsigned int Num); 563#endif 564 wchar_t *getName(); 565 int getCountFormats(); 566 unsigned int getWidth(); 567 unsigned int getHeight(); 568 unsigned int getFrameRate() const; 569 MediaType getFormat(unsigned int id); 570 bool setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate = 0); 571 bool setupDevice(unsigned int id); 572 bool isDeviceSetup(); 573 bool isDeviceMediaSource(); 574 bool isDeviceRawDataSource(); 575 bool isFrameNew(); 576 IMFMediaSource *getMediaSource(); 577 RawImage *getRawImageOut(); 578private: 579 enum typeLock 580 { 581 MediaSourceLock, 582 RawDataLock, 583 OpenLock 584 } vd_LockOut; 585 wchar_t *vd_pFriendlyName; 586 ImageGrabberThread *vd_pImGrTh; 587 CamParametrs vd_PrevParametrs; 588 unsigned int vd_Width; 589 unsigned int vd_Height; 590 unsigned int vd_FrameRate; 591 unsigned int vd_CurrentNumber; 592 bool vd_IsSetuped; 593 std::map<UINT64, FrameRateMap> vd_CaptureFormats; 594 std::vector<MediaType> vd_CurrentFormats; 595 IMFMediaSource *vd_pSource; 596#ifdef WINRT 597 MAKE_WRL_AGILE_REF(_MediaCapture) vd_pMedCap; 598 EventRegistrationToken vd_cookie; 599 ImageGrabberWinRT *vd_pImGr; 600 MAKE_WRL_REF(_AsyncAction) vd_pAction; 601#ifdef HAVE_CONCURRENCY 602 Concurrency::critical_section vd_lock; 603#endif 604#endif 605 emergensyStopEventCallback vd_func; 606 void *vd_userData; 607 HRESULT enumerateCaptureFormats(IMFMediaSource *pSource); 608 long setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex); 609 void buildLibraryofTypes(); 610 int findType(unsigned int size, unsigned int frameRate = 0); 611#ifdef WINRT 612 HRESULT enumerateCaptureFormats(MAKE_WRL_REF(_MediaCapture) pSource); 613 long setDeviceFormat(MAKE_WRL_REF(_MediaCapture) pSource, unsigned long dwFormatIndex, MAKE_WRL_REF(_AsyncAction)* pAction); 614 long resetDevice(MAKE_WRL_REF(_IDeviceInformation) pDevice); 615#ifdef HAVE_CONCURRENCY 616 long checkDevice(_DeviceClass devClass, DEFINE_TASK<void>* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice); 617#endif 618#else 619 long resetDevice(IMFActivate *pActivate); 620 long checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice); 621#endif 622 long initDevice(); 623}; 624 625/// Class for managing of list of video devices 626class videoDevices 627{ 628public: 629 ~videoDevices(void); 630#ifdef WINRT 631 long initDevices(_DeviceClass devClass); 632 void waitInit() { 633 if (vds_enumTask) { 634#ifdef HAVE_CONCURRENCY 635 CREATE_TASK DEFINE_RET_TYPE(void)(vds_enumTask).wait(); 636#endif 637 vds_enumTask = nullptr; 638 } 639 } 640#else 641 long initDevices(IMFAttributes *pAttributes); 642#endif 643 static videoDevices& getInstance(); 644 videoDevice *getDevice(unsigned int i); 645 unsigned int getCount(); 646 void clearDevices(); 647private: 648 UINT32 count; 649#ifdef WINRT 650 MAKE_WRL_REF(_AsyncAction) vds_enumTask; 651#endif 652 std::vector<videoDevice *> vds_Devices; 653 videoDevices(void); 654}; 655 656// Class for creating of Media Foundation context 657class Media_Foundation 658{ 659public: 660 virtual ~Media_Foundation(void); 661 static Media_Foundation& getInstance(); 662 bool buildListOfDevices(); 663private: 664 Media_Foundation(void); 665}; 666 667/// The only visiable class for controlling of video devices in format singelton 668class videoInput 669{ 670public: 671 virtual ~videoInput(void); 672 // Getting of static instance of videoInput class 673 static videoInput& getInstance(); 674 // Closing video device with deviceID 675 void closeDevice(int deviceID); 676 // Setting callback function for emergency events(for example: removing video device with deviceID) with userData 677 void setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *)); 678 // Closing all devices 679 void closeAllDevices(); 680 // Getting of parametrs of video device with deviceID 681 CamParametrs getParametrs(int deviceID); 682 // Setting of parametrs of video device with deviceID 683 void setParametrs(int deviceID, CamParametrs parametrs); 684 // Getting numbers of existence videodevices with listing in consol 685 unsigned int listDevices(bool silent = false); 686 // Getting numbers of formats, which are supported by videodevice with deviceID 687 unsigned int getCountFormats(int deviceID) const; 688 // Getting width of image, which is getting from videodevice with deviceID 689 unsigned int getWidth(int deviceID) const; 690 // Getting height of image, which is getting from videodevice with deviceID 691 unsigned int getHeight(int deviceID) const; 692 // Getting frame rate, which is getting from videodevice with deviceID 693 unsigned int getFrameRate(int deviceID) const; 694 // Getting name of videodevice with deviceID 695 wchar_t *getNameVideoDevice(int deviceID); 696 // Getting interface MediaSource for Media Foundation from videodevice with deviceID 697 IMFMediaSource *getMediaSource(int deviceID); 698 // Getting format with id, which is supported by videodevice with deviceID 699 MediaType getFormat(int deviceID, int unsigned id); 700 // Checking of existence of the suitable video devices 701 bool isDevicesAcceable(); 702 // Checking of using the videodevice with deviceID 703 bool isDeviceSetup(int deviceID); 704 // Checking of using MediaSource from videodevice with deviceID 705 bool isDeviceMediaSource(int deviceID); 706 // Checking of using Raw Data of pixels from videodevice with deviceID 707 bool isDeviceRawDataSource(int deviceID); 708#ifdef _DEBUG 709 // Setting of the state of outprinting info in console 710 static void setVerbose(bool state); 711#endif 712 // Initialization of video device with deviceID by media type with id 713 bool setupDevice(int deviceID, unsigned int id = 0); 714 // Initialization of video device with deviceID by wisth w, height h and fps idealFramerate 715 bool setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate = 30); 716 // Checking of recivig of new frame from video device with deviceID 717 bool isFrameNew(int deviceID); 718#ifdef WINRT 719 void waitForDevice(int deviceID); 720#endif 721 // Writing of Raw Data pixels from video device with deviceID with correction of RedAndBlue flipping flipRedAndBlue and vertical flipping flipImage 722 bool getPixels(int deviceID, unsigned char * pixels, bool flipRedAndBlue = false, bool flipImage = false); 723 static void processPixels(unsigned char * src, unsigned char * dst, unsigned int width, unsigned int height, unsigned int bpp, bool bRGB, bool bFlip); 724private: 725 bool accessToDevices; 726 videoInput(void); 727 void updateListOfDevices(); 728}; 729 730#ifdef _DEBUG 731DPO::DPO(void):verbose(true) 732{ 733} 734 735DPO::~DPO(void) 736{ 737} 738 739DPO& DPO::getInstance() 740{ 741 static DPO instance; 742 return instance; 743} 744 745void DPO::printOut(const wchar_t *format, ...) 746{ 747 if(verbose) 748 { 749 int i = 0; 750 wchar_t *p = NULL; 751 va_list args; 752 va_start(args, format); 753 if( ::IsDebuggerPresent() ) 754 { 755 WCHAR szMsg[512]; 756 ::StringCchVPrintfW(szMsg, sizeof(szMsg)/sizeof(szMsg[0]), format, args); 757 ::OutputDebugStringW(szMsg); 758 } 759 else 760 { 761 if(wcscmp(format, L"%i")) 762 { 763 i = va_arg (args, int); 764 } 765 if(wcscmp(format, L"%s")) 766 { 767 p = va_arg (args, wchar_t *); 768 } 769 wprintf(format, i,p); 770 } 771 va_end (args); 772 } 773} 774 775void DPO::setVerbose(bool state) 776{ 777 verbose = state; 778} 779#endif 780 781LPCWSTR GetGUIDNameConstNew(const GUID& guid); 782HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz); 783HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index); 784HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, MediaType &out); 785 786unsigned int *GetParametr(GUID guid, MediaType &out) 787{ 788 if(guid == MF_MT_YUV_MATRIX) 789 return &(out.MF_MT_YUV_MATRIX); 790 if(guid == MF_MT_VIDEO_LIGHTING) 791 return &(out.MF_MT_VIDEO_LIGHTING); 792 if(guid == MF_MT_DEFAULT_STRIDE) 793 return (unsigned int*)&(out.MF_MT_DEFAULT_STRIDE); 794 if(guid == MF_MT_VIDEO_CHROMA_SITING) 795 return &(out.MF_MT_VIDEO_CHROMA_SITING); 796 if(guid == MF_MT_VIDEO_NOMINAL_RANGE) 797 return &(out.MF_MT_VIDEO_NOMINAL_RANGE); 798 if(guid == MF_MT_ALL_SAMPLES_INDEPENDENT) 799 return &(out.MF_MT_ALL_SAMPLES_INDEPENDENT); 800 if(guid == MF_MT_FIXED_SIZE_SAMPLES) 801 return &(out.MF_MT_FIXED_SIZE_SAMPLES); 802 if(guid == MF_MT_SAMPLE_SIZE) 803 return &(out.MF_MT_SAMPLE_SIZE); 804 if(guid == MF_MT_VIDEO_PRIMARIES) 805 return &(out.MF_MT_VIDEO_PRIMARIES); 806 if(guid == MF_MT_INTERLACE_MODE) 807 return &(out.MF_MT_INTERLACE_MODE); 808 return NULL; 809} 810 811HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType &out) 812{ 813 WCHAR *pGuidName = NULL; 814 WCHAR *pGuidValName = NULL; 815 GUID guid = { 0 }; 816 PROPVARIANT var; 817 PropVariantInit(&var); 818 HRESULT hr = pAttr->GetItemByIndex(index, &guid, &var); 819 if (FAILED(hr)) 820 { 821 goto done; 822 } 823 hr = GetGUIDNameNew(guid, &pGuidName); 824 if (FAILED(hr)) 825 { 826 goto done; 827 } 828 hr = SpecialCaseAttributeValueNew(guid, var, out); 829 unsigned int *p; 830 if (FAILED(hr)) 831 { 832 goto done; 833 } 834 if (hr == S_FALSE) 835 { 836 switch (var.vt) 837 { 838 case VT_UI4: 839 p = GetParametr(guid, out); 840 if(p) 841 { 842 *p = var.ulVal; 843 } 844 break; 845 case VT_UI8: 846 break; 847 case VT_R8: 848 break; 849 case VT_CLSID: 850 if(guid == MF_MT_AM_FORMAT_TYPE) 851 { 852 hr = GetGUIDNameNew(*var.puuid, &pGuidValName); 853 if (SUCCEEDED(hr)) 854 { 855 out.MF_MT_AM_FORMAT_TYPE = *var.puuid; 856 out.pMF_MT_AM_FORMAT_TYPEName = pGuidValName; 857 pGuidValName = NULL; 858 } 859 } 860 if(guid == MF_MT_MAJOR_TYPE) 861 { 862 hr = GetGUIDNameNew(*var.puuid, &pGuidValName); 863 if (SUCCEEDED(hr)) 864 { 865 out.MF_MT_MAJOR_TYPE = *var.puuid; 866 out.pMF_MT_MAJOR_TYPEName = pGuidValName; 867 pGuidValName = NULL; 868 } 869 } 870 if(guid == MF_MT_SUBTYPE) 871 { 872 hr = GetGUIDNameNew(*var.puuid, &pGuidValName); 873 if (SUCCEEDED(hr)) 874 { 875 out.MF_MT_SUBTYPE = *var.puuid; 876 out.pMF_MT_SUBTYPEName = pGuidValName; 877 pGuidValName = NULL; 878 } 879 } 880 break; 881 case VT_LPWSTR: 882 break; 883 case VT_VECTOR | VT_UI1: 884 break; 885 case VT_UNKNOWN: 886 break; 887 default: 888 break; 889 } 890 } 891done: 892 CoTaskMemFree(pGuidName); 893 CoTaskMemFree(pGuidValName); 894 PropVariantClear(&var); 895 return hr; 896} 897 898HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz) 899{ 900 HRESULT hr = S_OK; 901 WCHAR *pName = NULL; 902 LPCWSTR pcwsz = GetGUIDNameConstNew(guid); 903 if (pcwsz) 904 { 905 size_t cchLength = 0; 906 hr = StringCchLengthW(pcwsz, STRSAFE_MAX_CCH, &cchLength); 907 if (FAILED(hr)) 908 { 909 goto done; 910 } 911 pName = (WCHAR*)CoTaskMemAlloc((cchLength + 1) * sizeof(WCHAR)); 912 if (pName == NULL) 913 { 914 hr = E_OUTOFMEMORY; 915 goto done; 916 } 917 hr = StringCchCopyW(pName, cchLength + 1, pcwsz); 918 if (FAILED(hr)) 919 { 920 goto done; 921 } 922 } 923 else 924 { 925 hr = StringFromCLSID(guid, &pName); 926 } 927done: 928 if (FAILED(hr)) 929 { 930 *ppwsz = NULL; 931 CoTaskMemFree(pName); 932 } 933 else 934 { 935 *ppwsz = pName; 936 } 937 return hr; 938} 939 940void LogUINT32AsUINT64New(const PROPVARIANT& var, UINT32 &uHigh, UINT32 &uLow) 941{ 942 Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow); 943} 944 945float OffsetToFloatNew(const MFOffset& offset) 946{ 947 return offset.value + (static_cast<float>(offset.fract) / 65536.0f); 948} 949 950HRESULT LogVideoAreaNew(const PROPVARIANT& var) 951{ 952 if (var.caub.cElems < sizeof(MFVideoArea)) 953 { 954 return S_OK; 955 } 956 return S_OK; 957} 958 959HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, MediaType &out) 960{ 961 if (guid == MF_MT_DEFAULT_STRIDE) 962 { 963 out.MF_MT_DEFAULT_STRIDE = var.intVal; 964 } else 965 if (guid == MF_MT_FRAME_SIZE) 966 { 967 UINT32 uHigh = 0, uLow = 0; 968 LogUINT32AsUINT64New(var, uHigh, uLow); 969 out.width = uHigh; 970 out.height = uLow; 971 out.MF_MT_FRAME_SIZE = out.width * out.height; 972 } 973 else 974 if (guid == MF_MT_FRAME_RATE) 975 { 976 UINT32 uHigh = 0, uLow = 0; 977 LogUINT32AsUINT64New(var, uHigh, uLow); 978 out.MF_MT_FRAME_RATE_NUMERATOR = uHigh; 979 out.MF_MT_FRAME_RATE_DENOMINATOR = uLow; 980 } 981 else 982 if (guid == MF_MT_FRAME_RATE_RANGE_MAX) 983 { 984 UINT32 uHigh = 0, uLow = 0; 985 LogUINT32AsUINT64New(var, uHigh, uLow); 986 out.MF_MT_FRAME_RATE_RANGE_MAX = uHigh; 987 out.MF_MT_FRAME_RATE_RANGE_MAX_low = uLow; 988 } 989 else 990 if (guid == MF_MT_FRAME_RATE_RANGE_MIN) 991 { 992 UINT32 uHigh = 0, uLow = 0; 993 LogUINT32AsUINT64New(var, uHigh, uLow); 994 out.MF_MT_FRAME_RATE_RANGE_MIN = uHigh; 995 out.MF_MT_FRAME_RATE_RANGE_MIN_low = uLow; 996 } 997 else 998 if (guid == MF_MT_PIXEL_ASPECT_RATIO) 999 { 1000 UINT32 uHigh = 0, uLow = 0; 1001 LogUINT32AsUINT64New(var, uHigh, uLow); 1002 out.MF_MT_PIXEL_ASPECT_RATIO = uHigh; 1003 out.MF_MT_PIXEL_ASPECT_RATIO_low = uLow; 1004 } 1005 else 1006 { 1007 return S_FALSE; 1008 } 1009 return S_OK; 1010} 1011 1012#ifndef IF_EQUAL_RETURN 1013#define IF_EQUAL_RETURN(param, val) if(val == param) return L#val 1014#endif 1015 1016LPCWSTR GetGUIDNameConstNew(const GUID& guid) 1017{ 1018 IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE); 1019 IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE); 1020 IF_EQUAL_RETURN(guid, MF_MT_SUBTYPE); 1021 IF_EQUAL_RETURN(guid, MF_MT_ALL_SAMPLES_INDEPENDENT); 1022 IF_EQUAL_RETURN(guid, MF_MT_FIXED_SIZE_SAMPLES); 1023 IF_EQUAL_RETURN(guid, MF_MT_COMPRESSED); 1024 IF_EQUAL_RETURN(guid, MF_MT_SAMPLE_SIZE); 1025 IF_EQUAL_RETURN(guid, MF_MT_WRAPPED_TYPE); 1026 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_NUM_CHANNELS); 1027 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_SECOND); 1028 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND); 1029 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_AVG_BYTES_PER_SECOND); 1030 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BLOCK_ALIGNMENT); 1031 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BITS_PER_SAMPLE); 1032 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_VALID_BITS_PER_SAMPLE); 1033 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_BLOCK); 1034 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_CHANNEL_MASK); 1035 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FOLDDOWN_MATRIX); 1036 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKREF); 1037 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKTARGET); 1038 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGREF); 1039 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGTARGET); 1040 IF_EQUAL_RETURN(guid, MF_MT_AUDIO_PREFER_WAVEFORMATEX); 1041 IF_EQUAL_RETURN(guid, MF_MT_AAC_PAYLOAD_TYPE); 1042 IF_EQUAL_RETURN(guid, MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION); 1043 IF_EQUAL_RETURN(guid, MF_MT_FRAME_SIZE); 1044 IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE); 1045 IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MAX); 1046 IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MIN); 1047 IF_EQUAL_RETURN(guid, MF_MT_PIXEL_ASPECT_RATIO); 1048 IF_EQUAL_RETURN(guid, MF_MT_DRM_FLAGS); 1049 IF_EQUAL_RETURN(guid, MF_MT_PAD_CONTROL_FLAGS); 1050 IF_EQUAL_RETURN(guid, MF_MT_SOURCE_CONTENT_HINT); 1051 IF_EQUAL_RETURN(guid, MF_MT_VIDEO_CHROMA_SITING); 1052 IF_EQUAL_RETURN(guid, MF_MT_INTERLACE_MODE); 1053 IF_EQUAL_RETURN(guid, MF_MT_TRANSFER_FUNCTION); 1054 IF_EQUAL_RETURN(guid, MF_MT_VIDEO_PRIMARIES); 1055 IF_EQUAL_RETURN(guid, MF_MT_CUSTOM_VIDEO_PRIMARIES); 1056 IF_EQUAL_RETURN(guid, MF_MT_YUV_MATRIX); 1057 IF_EQUAL_RETURN(guid, MF_MT_VIDEO_LIGHTING); 1058 IF_EQUAL_RETURN(guid, MF_MT_VIDEO_NOMINAL_RANGE); 1059 IF_EQUAL_RETURN(guid, MF_MT_GEOMETRIC_APERTURE); 1060 IF_EQUAL_RETURN(guid, MF_MT_MINIMUM_DISPLAY_APERTURE); 1061 IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_APERTURE); 1062 IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_ENABLED); 1063 IF_EQUAL_RETURN(guid, MF_MT_AVG_BITRATE); 1064 IF_EQUAL_RETURN(guid, MF_MT_AVG_BIT_ERROR_RATE); 1065 IF_EQUAL_RETURN(guid, MF_MT_MAX_KEYFRAME_SPACING); 1066 IF_EQUAL_RETURN(guid, MF_MT_DEFAULT_STRIDE); 1067 IF_EQUAL_RETURN(guid, MF_MT_PALETTE); 1068 IF_EQUAL_RETURN(guid, MF_MT_USER_DATA); 1069 IF_EQUAL_RETURN(guid, MF_MT_AM_FORMAT_TYPE); 1070 IF_EQUAL_RETURN(guid, MF_MT_MPEG_START_TIME_CODE); 1071 IF_EQUAL_RETURN(guid, MF_MT_MPEG2_PROFILE); 1072 IF_EQUAL_RETURN(guid, MF_MT_MPEG2_LEVEL); 1073 IF_EQUAL_RETURN(guid, MF_MT_MPEG2_FLAGS); 1074 IF_EQUAL_RETURN(guid, MF_MT_MPEG_SEQUENCE_HEADER); 1075 IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_0); 1076 IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_0); 1077 IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_1); 1078 IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_1); 1079 IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_SRC_PACK); 1080 IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_CTRL_PACK); 1081 IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_HEADER); 1082 IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_FORMAT); 1083 IF_EQUAL_RETURN(guid, MF_MT_IMAGE_LOSS_TOLERANT); 1084 IF_EQUAL_RETURN(guid, MF_MT_MPEG4_SAMPLE_DESCRIPTION); 1085 IF_EQUAL_RETURN(guid, MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY); 1086 IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_4CC); 1087 IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_WAVE_FORMAT_TAG); 1088 // Media types 1089 IF_EQUAL_RETURN(guid, MFMediaType_Audio); 1090 IF_EQUAL_RETURN(guid, MFMediaType_Video); 1091 IF_EQUAL_RETURN(guid, MFMediaType_Protected); 1092 IF_EQUAL_RETURN(guid, MFMediaType_SAMI); 1093 IF_EQUAL_RETURN(guid, MFMediaType_Script); 1094 IF_EQUAL_RETURN(guid, MFMediaType_Image); 1095 IF_EQUAL_RETURN(guid, MFMediaType_HTML); 1096 IF_EQUAL_RETURN(guid, MFMediaType_Binary); 1097 IF_EQUAL_RETURN(guid, MFMediaType_FileTransfer); 1098 IF_EQUAL_RETURN(guid, MFVideoFormat_AI44); // FCC('AI44') 1099 IF_EQUAL_RETURN(guid, MFVideoFormat_ARGB32); // D3DFMT_A8R8G8B8 1100 IF_EQUAL_RETURN(guid, MFVideoFormat_AYUV); // FCC('AYUV') 1101 IF_EQUAL_RETURN(guid, MFVideoFormat_DV25); // FCC('dv25') 1102 IF_EQUAL_RETURN(guid, MFVideoFormat_DV50); // FCC('dv50') 1103 IF_EQUAL_RETURN(guid, MFVideoFormat_DVH1); // FCC('dvh1') 1104 IF_EQUAL_RETURN(guid, MFVideoFormat_DVSD); // FCC('dvsd') 1105 IF_EQUAL_RETURN(guid, MFVideoFormat_DVSL); // FCC('dvsl') 1106 IF_EQUAL_RETURN(guid, MFVideoFormat_H264); // FCC('H264') 1107 IF_EQUAL_RETURN(guid, MFVideoFormat_I420); // FCC('I420') 1108 IF_EQUAL_RETURN(guid, MFVideoFormat_IYUV); // FCC('IYUV') 1109 IF_EQUAL_RETURN(guid, MFVideoFormat_M4S2); // FCC('M4S2') 1110 IF_EQUAL_RETURN(guid, MFVideoFormat_MJPG); 1111 IF_EQUAL_RETURN(guid, MFVideoFormat_MP43); // FCC('MP43') 1112 IF_EQUAL_RETURN(guid, MFVideoFormat_MP4S); // FCC('MP4S') 1113 IF_EQUAL_RETURN(guid, MFVideoFormat_MP4V); // FCC('MP4V') 1114 IF_EQUAL_RETURN(guid, MFVideoFormat_MPG1); // FCC('MPG1') 1115 IF_EQUAL_RETURN(guid, MFVideoFormat_MSS1); // FCC('MSS1') 1116 IF_EQUAL_RETURN(guid, MFVideoFormat_MSS2); // FCC('MSS2') 1117 IF_EQUAL_RETURN(guid, MFVideoFormat_NV11); // FCC('NV11') 1118 IF_EQUAL_RETURN(guid, MFVideoFormat_NV12); // FCC('NV12') 1119 IF_EQUAL_RETURN(guid, MFVideoFormat_P010); // FCC('P010') 1120 IF_EQUAL_RETURN(guid, MFVideoFormat_P016); // FCC('P016') 1121 IF_EQUAL_RETURN(guid, MFVideoFormat_P210); // FCC('P210') 1122 IF_EQUAL_RETURN(guid, MFVideoFormat_P216); // FCC('P216') 1123 IF_EQUAL_RETURN(guid, MFVideoFormat_RGB24); // D3DFMT_R8G8B8 1124 IF_EQUAL_RETURN(guid, MFVideoFormat_RGB32); // D3DFMT_X8R8G8B8 1125 IF_EQUAL_RETURN(guid, MFVideoFormat_RGB555); // D3DFMT_X1R5G5B5 1126 IF_EQUAL_RETURN(guid, MFVideoFormat_RGB565); // D3DFMT_R5G6B5 1127 IF_EQUAL_RETURN(guid, MFVideoFormat_RGB8); 1128 IF_EQUAL_RETURN(guid, MFVideoFormat_UYVY); // FCC('UYVY') 1129 IF_EQUAL_RETURN(guid, MFVideoFormat_v210); // FCC('v210') 1130 IF_EQUAL_RETURN(guid, MFVideoFormat_v410); // FCC('v410') 1131 IF_EQUAL_RETURN(guid, MFVideoFormat_WMV1); // FCC('WMV1') 1132 IF_EQUAL_RETURN(guid, MFVideoFormat_WMV2); // FCC('WMV2') 1133 IF_EQUAL_RETURN(guid, MFVideoFormat_WMV3); // FCC('WMV3') 1134 IF_EQUAL_RETURN(guid, MFVideoFormat_WVC1); // FCC('WVC1') 1135 IF_EQUAL_RETURN(guid, MFVideoFormat_Y210); // FCC('Y210') 1136 IF_EQUAL_RETURN(guid, MFVideoFormat_Y216); // FCC('Y216') 1137 IF_EQUAL_RETURN(guid, MFVideoFormat_Y410); // FCC('Y410') 1138 IF_EQUAL_RETURN(guid, MFVideoFormat_Y416); // FCC('Y416') 1139 IF_EQUAL_RETURN(guid, MFVideoFormat_Y41P); 1140 IF_EQUAL_RETURN(guid, MFVideoFormat_Y41T); 1141 IF_EQUAL_RETURN(guid, MFVideoFormat_YUY2); // FCC('YUY2') 1142 IF_EQUAL_RETURN(guid, MFVideoFormat_YV12); // FCC('YV12') 1143 IF_EQUAL_RETURN(guid, MFVideoFormat_YVYU); 1144 IF_EQUAL_RETURN(guid, MFAudioFormat_PCM); // WAVE_FORMAT_PCM 1145 IF_EQUAL_RETURN(guid, MFAudioFormat_Float); // WAVE_FORMAT_IEEE_FLOAT 1146 IF_EQUAL_RETURN(guid, MFAudioFormat_DTS); // WAVE_FORMAT_DTS 1147 IF_EQUAL_RETURN(guid, MFAudioFormat_Dolby_AC3_SPDIF); // WAVE_FORMAT_DOLBY_AC3_SPDIF 1148 IF_EQUAL_RETURN(guid, MFAudioFormat_DRM); // WAVE_FORMAT_DRM 1149 IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV8); // WAVE_FORMAT_WMAUDIO2 1150 IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV9); // WAVE_FORMAT_WMAUDIO3 1151 IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS 1152 IF_EQUAL_RETURN(guid, MFAudioFormat_WMASPDIF); // WAVE_FORMAT_WMASPDIF 1153 IF_EQUAL_RETURN(guid, MFAudioFormat_MSP1); // WAVE_FORMAT_WMAVOICE9 1154 IF_EQUAL_RETURN(guid, MFAudioFormat_MP3); // WAVE_FORMAT_MPEGLAYER3 1155 IF_EQUAL_RETURN(guid, MFAudioFormat_MPEG); // WAVE_FORMAT_MPEG 1156 IF_EQUAL_RETURN(guid, MFAudioFormat_AAC); // WAVE_FORMAT_MPEG_HEAAC 1157 IF_EQUAL_RETURN(guid, MFAudioFormat_ADTS); // WAVE_FORMAT_MPEG_ADTS_AAC 1158 return NULL; 1159} 1160 1161FormatReader::FormatReader(void) 1162{ 1163} 1164 1165MediaType FormatReader::Read(IMFMediaType *pType) 1166{ 1167 UINT32 count = 0; 1168 MediaType out; 1169 HRESULT hr = pType->LockStore(); 1170 if (FAILED(hr)) 1171 { 1172 return out; 1173 } 1174 hr = pType->GetCount(&count); 1175 if (FAILED(hr)) 1176 { 1177 return out; 1178 } 1179 for (UINT32 i = 0; i < count; i++) 1180 { 1181 hr = LogAttributeValueByIndexNew(pType, i, out); 1182 if (FAILED(hr)) 1183 { 1184 break; 1185 } 1186 } 1187 hr = pType->UnlockStore(); 1188 if (FAILED(hr)) 1189 { 1190 return out; 1191 } 1192 return out; 1193} 1194 1195FormatReader::~FormatReader(void) 1196{ 1197} 1198 1199#define CHECK_HR(x) if (FAILED(x)) { goto done; } 1200 1201ImageGrabberCallback::ImageGrabberCallback(bool synchronous): 1202 m_cRef(1), 1203 ig_RIE(true), 1204 ig_Close(false), 1205 ig_Synchronous(synchronous), 1206 ig_hFrameReady(synchronous ? CreateEvent(NULL, FALSE, FALSE, NULL): 0), 1207 ig_hFrameGrabbed(synchronous ? CreateEvent(NULL, FALSE, TRUE, NULL): 0), 1208 ig_hFinish(CreateEvent(NULL, TRUE, FALSE, NULL)) 1209{} 1210 1211ImageGrabber::ImageGrabber(unsigned int deviceID, bool synchronous): 1212 ImageGrabberCallback(synchronous), 1213 ig_DeviceID(deviceID), 1214 ig_pSource(NULL), 1215 ig_pSession(NULL), 1216 ig_pTopology(NULL) 1217{} 1218 1219ImageGrabber::~ImageGrabber(void) 1220{ 1221 if (ig_pSession) 1222 { 1223 ig_pSession->Shutdown(); 1224 } 1225 1226 CloseHandle(ig_hFinish); 1227 1228 if (ig_Synchronous) 1229 { 1230 CloseHandle(ig_hFrameReady); 1231 CloseHandle(ig_hFrameGrabbed); 1232 } 1233 1234 SafeRelease(&ig_pSession); 1235 SafeRelease(&ig_pTopology); 1236 1237 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroying instance of the ImageGrabber class\n", ig_DeviceID); 1238} 1239 1240#ifdef WINRT 1241 1242ImageGrabberWinRT::ImageGrabberWinRT(bool synchronous): 1243 ImageGrabberCallback(synchronous), 1244 ig_pMediaSink(NULL) 1245{ 1246 ig_pMedCapSource = nullptr; 1247} 1248 1249ImageGrabberWinRT::~ImageGrabberWinRT(void) 1250{ 1251 //stop must already be performed and complete by object owner 1252 if (ig_pMediaSink != NULL) { 1253 ((IMFMediaSink*)ig_pMediaSink)->Shutdown(); 1254 } 1255 SafeRelease(&ig_pMediaSink); 1256 RELEASE_AGILE_WRL(ig_pMedCapSource) 1257 1258 CloseHandle(ig_hFinish); 1259 1260 if (ig_Synchronous) 1261 { 1262 CloseHandle(ig_hFrameReady); 1263 CloseHandle(ig_hFrameGrabbed); 1264 } 1265 1266 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE: Destroying instance of the ImageGrabberWinRT class\n"); 1267} 1268 1269HRESULT ImageGrabberWinRT::initImageGrabber(MAKE_WRL_REF(_MediaCapture) pSource, 1270 GUID VideoFormat) 1271{ 1272 HRESULT hr; 1273 MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; 1274 WRL_PROP_GET(pSource, VideoDeviceController, pDevCont, hr) 1275 if (FAILED(hr)) return hr; 1276 GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) 1277 if (FAILED(hr)) return hr; 1278 MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; 1279 WRL_METHOD(pMedDevCont, GetMediaStreamProperties, pMedEncProps, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) 1280 if (FAILED(hr)) return hr; 1281 GET_WRL_OBJ_FROM_OBJ(_VideoEncodingProperties, pVidProps, pMedEncProps, hr); 1282 if (FAILED(hr)) return hr; 1283 _ComPtr<IMFMediaType> pType = NULL; 1284 hr = MediaSink::ConvertPropertiesToMediaType(DEREF_AS_NATIVE_WRL_OBJ(ABI::Windows::Media::MediaProperties::IMediaEncodingProperties, pMedEncProps), &pType); 1285 if (FAILED(hr)) return hr; 1286 MediaType MT = FormatReader::Read(pType.Get()); 1287 unsigned int sizeRawImage = 0; 1288 if(VideoFormat == MFVideoFormat_RGB24) 1289 { 1290 sizeRawImage = MT.MF_MT_FRAME_SIZE * 3; 1291 } 1292 else if(VideoFormat == MFVideoFormat_RGB32) 1293 { 1294 sizeRawImage = MT.MF_MT_FRAME_SIZE * 4; 1295 } 1296 sizeRawImage = MT.MF_MT_SAMPLE_SIZE; 1297 CHECK_HR(hr = RawImage::CreateInstance(&ig_RIFirst, sizeRawImage)); 1298 CHECK_HR(hr = RawImage::CreateInstance(&ig_RISecond, sizeRawImage)); 1299 ig_RIOut = ig_RISecond; 1300 ig_pMedCapSource = pSource; 1301done: 1302 return hr; 1303} 1304 1305HRESULT ImageGrabberWinRT::stopGrabbing(MAKE_WRL_REF(_AsyncAction)* action) 1306{ 1307 HRESULT hr = S_OK; 1308 if (ig_pMedCapSource != nullptr) { 1309 GET_WRL_OBJ_FROM_REF(_MediaCaptureVideoPreview, imedPrevCap, DEREF_AGILE_WRL_OBJ(ig_pMedCapSource), hr) 1310 if (FAILED(hr)) return hr; 1311 MAKE_WRL_REF(_AsyncAction) pAction; 1312 WRL_METHOD_BASE(imedPrevCap, StopPreviewAsync, pAction, hr) 1313 if (SUCCEEDED(hr)) { 1314#ifdef HAVE_CONCURRENCY 1315 DEFINE_TASK<void> _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction); 1316 *action = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, _task, this) 1317 HRESULT hr = S_OK; 1318 _task.wait(); 1319 SafeRelease(&ig_pMediaSink); 1320 SetEvent(ig_hFinish); 1321 END_CREATE_ASYNC(hr)); 1322#else 1323 *action = nullptr; 1324#endif 1325 } 1326 } 1327 return hr; 1328} 1329 1330HRESULT ImageGrabberWinRT::startGrabbing(MAKE_WRL_REF(_AsyncAction)* action) 1331{ 1332 HRESULT hr = S_OK; 1333 GET_WRL_OBJ_FROM_REF(_MediaCaptureVideoPreview, imedPrevCap, DEREF_AGILE_WRL_OBJ(ig_pMedCapSource), hr) 1334 if (FAILED(hr)) return hr; 1335 ACTIVATE_OBJ(RuntimeClass_Windows_Foundation_Collections_PropertySet, _PropertySet, pSet, hr) 1336 if (FAILED(hr)) return hr; 1337 GET_WRL_OBJ_FROM_OBJ(_Map, spSetting, pSet, hr) 1338 if (FAILED(hr)) return hr; 1339 ACTIVATE_STATIC_OBJ(RuntimeClass_Windows_Foundation_PropertyValue, MAKE_WRL_OBJ(_PropertyValueStatics), spPropVal, hr) 1340 if (FAILED(hr)) return hr; 1341 _ObjectObj pVal; 1342 boolean bReplaced; 1343 WRL_METHOD(spPropVal, CreateUInt32, pVal, hr, (unsigned int)WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) 1344 if (FAILED(hr)) return hr; 1345 WRL_METHOD(spSetting, Insert, bReplaced, hr, DEREF_WRL_OBJ(_StringReference(MF_PROP_VIDTYPE)), DEREF_WRL_OBJ(pVal)) 1346 if (FAILED(hr)) return hr; 1347 WRL_METHOD(spSetting, Insert, bReplaced, hr, DEREF_WRL_OBJ(_StringReference(MF_PROP_SAMPLEGRABBERCALLBACK)), reinterpret_cast<_Object>(this)) 1348 if (FAILED(hr)) return hr; 1349 MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; 1350 WRL_PROP_GET(ig_pMedCapSource, VideoDeviceController, pDevCont, hr) 1351 if (FAILED(hr)) return hr; 1352 GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) 1353 if (FAILED(hr)) return hr; 1354 MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; 1355 WRL_METHOD(pMedDevCont, GetMediaStreamProperties, pMedEncProps, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) 1356 if (FAILED(hr)) return hr; 1357 GET_WRL_OBJ_FROM_OBJ(_VideoEncodingProperties, pVidProps, pMedEncProps, hr); 1358 if (FAILED(hr)) return hr; 1359 ACTIVATE_OBJ(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile, _MediaEncodingProfile, pEncProps, hr) 1360 if (FAILED(hr)) return hr; 1361 WRL_PROP_PUT(pEncProps, Video, DEREF_WRL_OBJ(pVidProps), hr) 1362 if (FAILED(hr)) return hr; 1363 WRL_METHOD(spSetting, Insert, bReplaced, hr, DEREF_WRL_OBJ(_StringReference(MF_PROP_VIDENCPROPS)), DEREF_WRL_OBJ(pVidProps)) 1364 if (SUCCEEDED(hr)) { 1365 //can start/stop multiple times with same MediaCapture object if using activatable class 1366 WRL_METHOD(imedPrevCap, _StartPreviewToCustomSinkIdAsync, *action, hr, DEREF_WRL_OBJ(pEncProps), DEREF_WRL_OBJ(_StringReference(RuntimeClass_CV_MediaSink)), DEREF_WRL_OBJ(pSet)) 1367 if (FAILED(hr) && hr == REGDB_E_CLASSNOTREG) { 1368 hr = Microsoft::WRL::Make<MediaSink>().CopyTo(&ig_pMediaSink); 1369 if (FAILED(hr)) return hr; 1370 hr = ((ABI::Windows::Media::IMediaExtension*)ig_pMediaSink)->SetProperties(DEREF_AS_NATIVE_WRL_OBJ(ABI::Windows::Foundation::Collections::IPropertySet, pSet)); 1371 if (FAILED(hr)) return hr; 1372 WRL_METHOD(imedPrevCap, StartPreviewToCustomSinkAsync, *action, hr, DEREF_WRL_OBJ(pEncProps), reinterpret_cast<MAKE_WRL_REF(_MediaExtension)>(ig_pMediaSink)) 1373 } 1374 } 1375 return hr; 1376} 1377 1378HRESULT ImageGrabberWinRT::CreateInstance(ImageGrabberWinRT **ppIG, bool synchronous) 1379{ 1380 *ppIG = Microsoft::WRL::Make<ImageGrabberWinRT>(synchronous).Detach(); 1381 if (ppIG == NULL) 1382 { 1383 return E_OUTOFMEMORY; 1384 } 1385 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE: Creating instance of ImageGrabberWinRT\n"); 1386 return S_OK; 1387} 1388#endif 1389 1390HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource) 1391{ 1392 _ComPtr<IMFActivate> pSinkActivate = NULL; 1393 _ComPtr<IMFMediaType> pType = NULL; 1394 _ComPtr<IMFPresentationDescriptor> pPD = NULL; 1395 _ComPtr<IMFStreamDescriptor> pSD = NULL; 1396 _ComPtr<IMFMediaTypeHandler> pHandler = NULL; 1397 _ComPtr<IMFMediaType> pCurrentType = NULL; 1398 MediaType MT; 1399 // Clean up. 1400 if (ig_pSession) 1401 { 1402 ig_pSession->Shutdown(); 1403 } 1404 SafeRelease(&ig_pSession); 1405 SafeRelease(&ig_pTopology); 1406 ig_pSource = pSource; 1407 HRESULT hr = pSource->CreatePresentationDescriptor(&pPD); 1408 if (FAILED(hr)) 1409 { 1410 goto err; 1411 } 1412 BOOL fSelected; 1413 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD); 1414 if (FAILED(hr)) { 1415 goto err; 1416 } 1417 hr = pSD->GetMediaTypeHandler(&pHandler); 1418 if (FAILED(hr)) { 1419 goto err; 1420 } 1421 DWORD cTypes = 0; 1422 hr = pHandler->GetMediaTypeCount(&cTypes); 1423 if (FAILED(hr)) { 1424 goto err; 1425 } 1426 if(cTypes > 0) 1427 { 1428 hr = pHandler->GetCurrentMediaType(&pCurrentType); 1429 if (FAILED(hr)) { 1430 goto err; 1431 } 1432 MT = FormatReader::Read(pCurrentType.Get()); 1433 } 1434err: 1435 CHECK_HR(hr); 1436 CHECK_HR(hr = RawImage::CreateInstance(&ig_RIFirst, MT.MF_MT_SAMPLE_SIZE)); 1437 CHECK_HR(hr = RawImage::CreateInstance(&ig_RISecond, MT.MF_MT_SAMPLE_SIZE)); 1438 ig_RIOut = ig_RISecond; 1439 // Configure the media type that the Sample Grabber will receive. 1440 // Setting the major and subtype is usually enough for the topology loader 1441 // to resolve the topology. 1442 CHECK_HR(hr = MFCreateMediaType(pType.GetAddressOf())); 1443 CHECK_HR(hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MT.MF_MT_MAJOR_TYPE)); 1444 CHECK_HR(hr = pType->SetGUID(MF_MT_SUBTYPE, MT.MF_MT_SUBTYPE)); 1445 // Create the sample grabber sink. 1446 CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pType.Get(), this, pSinkActivate.GetAddressOf())); 1447 // To run as fast as possible, set this attribute (requires Windows 7): 1448 CHECK_HR(hr = pSinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE)); 1449 // Create the Media Session. 1450 CHECK_HR(hr = MFCreateMediaSession(NULL, &ig_pSession)); 1451 // Create the topology. 1452 CHECK_HR(hr = CreateTopology(pSource, pSinkActivate.Get(), &ig_pTopology)); 1453done: 1454 // Clean up. 1455 if (FAILED(hr)) 1456 { 1457 if (ig_pSession) 1458 { 1459 ig_pSession->Shutdown(); 1460 } 1461 SafeRelease(&ig_pSession); 1462 SafeRelease(&ig_pTopology); 1463 } 1464 return hr; 1465} 1466 1467void ImageGrabber::stopGrabbing() 1468{ 1469 if(ig_pSession) 1470 ig_pSession->Stop(); 1471 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Stopping of of grabbing of images\n", ig_DeviceID); 1472} 1473 1474HRESULT ImageGrabber::startGrabbing(void) 1475{ 1476 PROPVARIANT var; 1477 PropVariantInit(&var); 1478 HRESULT hr = ig_pSession->SetTopology(0, ig_pTopology); 1479 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Start Grabbing of the images\n", ig_DeviceID); 1480 hr = ig_pSession->Start(&GUID_NULL, &var); 1481 for(;;) 1482 { 1483 _ComPtr<IMFMediaEvent> pEvent = NULL; 1484 HRESULT hrStatus = S_OK; 1485 MediaEventType met; 1486 if(!ig_pSession) break; 1487 hr = ig_pSession->GetEvent(0, &pEvent); 1488 if(!SUCCEEDED(hr)) 1489 { 1490 hr = S_OK; 1491 goto done; 1492 } 1493 hr = pEvent->GetStatus(&hrStatus); 1494 if(!SUCCEEDED(hr)) 1495 { 1496 hr = S_OK; 1497 goto done; 1498 } 1499 hr = pEvent->GetType(&met); 1500 if(!SUCCEEDED(hr)) 1501 { 1502 hr = S_OK; 1503 goto done; 1504 } 1505 if (met == MESessionEnded) 1506 { 1507 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionEnded\n", ig_DeviceID); 1508 ig_pSession->Stop(); 1509 break; 1510 } 1511 if (met == MESessionStopped) 1512 { 1513 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionStopped \n", ig_DeviceID); 1514 break; 1515 } 1516#if (WINVER >= 0x0602) // Available since Win 8 1517 if (met == MEVideoCaptureDeviceRemoved) 1518 { 1519 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved \n", ig_DeviceID); 1520 break; 1521 } 1522#endif 1523 if ((met == MEError) || (met == MENonFatalError)) 1524 { 1525 pEvent->GetStatus(&hrStatus); 1526 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MEError | MENonFatalError: %u\n", ig_DeviceID, hrStatus); 1527 break; 1528 } 1529 } 1530 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Finish startGrabbing \n", ig_DeviceID); 1531 1532done: 1533 SetEvent(ig_hFinish); 1534 1535 return hr; 1536} 1537 1538void ImageGrabberCallback::pauseGrabbing() 1539{ 1540} 1541 1542void ImageGrabberCallback::resumeGrabbing() 1543{ 1544} 1545 1546HRESULT ImageGrabber::CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo) 1547{ 1548 IMFTopology* pTopology = NULL; 1549 _ComPtr<IMFPresentationDescriptor> pPD = NULL; 1550 _ComPtr<IMFStreamDescriptor> pSD = NULL; 1551 _ComPtr<IMFMediaTypeHandler> pHandler = NULL; 1552 _ComPtr<IMFTopologyNode> pNode1 = NULL; 1553 _ComPtr<IMFTopologyNode> pNode2 = NULL; 1554 HRESULT hr = S_OK; 1555 DWORD cStreams = 0; 1556 CHECK_HR(hr = MFCreateTopology(&pTopology)); 1557 CHECK_HR(hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf())); 1558 CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); 1559 for (DWORD i = 0; i < cStreams; i++) 1560 { 1561 // In this example, we look for audio streams and connect them to the sink. 1562 BOOL fSelected = FALSE; 1563 GUID majorType; 1564 CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD)); 1565 CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); 1566 CHECK_HR(hr = pHandler->GetMajorType(&majorType)); 1567 if (majorType == MFMediaType_Video && fSelected) 1568 { 1569 CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD.Get(), pSD.Get(), pNode1.GetAddressOf())); 1570 CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivate, 0, pNode2.GetAddressOf())); 1571 CHECK_HR(hr = pNode1->ConnectOutput(0, pNode2.Get(), 0)); 1572 break; 1573 } 1574 else 1575 { 1576 CHECK_HR(hr = pPD->DeselectStream(i)); 1577 } 1578 } 1579 *ppTopo = pTopology; 1580 (*ppTopo)->AddRef(); 1581 1582done: 1583 return hr; 1584} 1585 1586HRESULT ImageGrabber::AddSourceNode( 1587 IMFTopology *pTopology, // Topology. 1588 IMFMediaSource *pSource, // Media source. 1589 IMFPresentationDescriptor *pPD, // Presentation descriptor. 1590 IMFStreamDescriptor *pSD, // Stream descriptor. 1591 IMFTopologyNode **ppNode) // Receives the node pointer. 1592{ 1593 _ComPtr<IMFTopologyNode> pNode = NULL; 1594 HRESULT hr = S_OK; 1595 CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, pNode.GetAddressOf())); 1596 CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource)); 1597 CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD)); 1598 CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD)); 1599 CHECK_HR(hr = pTopology->AddNode(pNode.Get())); 1600 // Return the pointer to the caller. 1601 *ppNode = pNode.Get(); 1602 (*ppNode)->AddRef(); 1603 1604done: 1605 return hr; 1606} 1607 1608HRESULT ImageGrabber::AddOutputNode( 1609 IMFTopology *pTopology, // Topology. 1610 IMFActivate *pActivate, // Media sink activation object. 1611 DWORD dwId, // Identifier of the stream sink. 1612 IMFTopologyNode **ppNode) // Receives the node pointer. 1613{ 1614 _ComPtr<IMFTopologyNode> pNode = NULL; 1615 HRESULT hr = S_OK; 1616 CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, pNode.GetAddressOf())); 1617 CHECK_HR(hr = pNode->SetObject(pActivate)); 1618 CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId)); 1619 CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)); 1620 CHECK_HR(hr = pTopology->AddNode(pNode.Get())); 1621 // Return the pointer to the caller. 1622 *ppNode = pNode.Get(); 1623 (*ppNode)->AddRef(); 1624 1625done: 1626 return hr; 1627} 1628 1629HRESULT ImageGrabber::CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, bool synchronious) 1630{ 1631 *ppIG = new (std::nothrow) ImageGrabber(deviceID, synchronious); 1632 if (ppIG == NULL) 1633 { 1634 return E_OUTOFMEMORY; 1635 } 1636 DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Creating instance of ImageGrabber\n", deviceID); 1637 return S_OK; 1638} 1639 1640STDMETHODIMP ImageGrabber::QueryInterface(REFIID riid, void** ppv) 1641{ 1642 HRESULT hr = E_NOINTERFACE; 1643 *ppv = NULL; 1644 if(riid == IID_IUnknown || riid == IID_IMFSampleGrabberSinkCallback) 1645 { 1646 *ppv = static_cast<IMFSampleGrabberSinkCallback *>(this); 1647 hr = S_OK; 1648 } 1649 if(riid == IID_IMFClockStateSink) 1650 { 1651 *ppv = static_cast<IMFClockStateSink *>(this); 1652 hr = S_OK; 1653 } 1654 if(SUCCEEDED(hr)) 1655 { 1656 reinterpret_cast<IUnknown *>(*ppv)->AddRef(); 1657 } 1658 return hr; 1659} 1660 1661STDMETHODIMP_(ULONG) ImageGrabber::AddRef() 1662{ 1663 return InterlockedIncrement(&m_cRef); 1664} 1665 1666STDMETHODIMP_(ULONG) ImageGrabber::Release() 1667{ 1668 ULONG cRef = InterlockedDecrement(&m_cRef); 1669 if (cRef == 0) 1670 { 1671 delete this; 1672 } 1673 return cRef; 1674} 1675 1676STDMETHODIMP ImageGrabberCallback::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) 1677{ 1678 (void)hnsSystemTime; 1679 (void)llClockStartOffset; 1680 return S_OK; 1681} 1682 1683STDMETHODIMP ImageGrabberCallback::OnClockStop(MFTIME hnsSystemTime) 1684{ 1685 (void)hnsSystemTime; 1686 return S_OK; 1687} 1688 1689STDMETHODIMP ImageGrabberCallback::OnClockPause(MFTIME hnsSystemTime) 1690{ 1691 (void)hnsSystemTime; 1692 return S_OK; 1693} 1694 1695STDMETHODIMP ImageGrabberCallback::OnClockRestart(MFTIME hnsSystemTime) 1696{ 1697 (void)hnsSystemTime; 1698 return S_OK; 1699} 1700 1701STDMETHODIMP ImageGrabberCallback::OnClockSetRate(MFTIME hnsSystemTime, float flRate) 1702{ 1703 (void)flRate; 1704 (void)hnsSystemTime; 1705 return S_OK; 1706} 1707 1708STDMETHODIMP ImageGrabberCallback::OnSetPresentationClock(IMFPresentationClock* pClock) 1709{ 1710 (void)pClock; 1711 return S_OK; 1712} 1713 1714STDMETHODIMP ImageGrabberCallback::OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, 1715 LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, 1716 DWORD dwSampleSize) 1717{ 1718 (void)guidMajorMediaType; 1719 (void)llSampleTime; 1720 (void)dwSampleFlags; 1721 (void)llSampleDuration; 1722 (void)dwSampleSize; 1723 1724 HANDLE tmp[] = {ig_hFinish, ig_hFrameGrabbed, NULL}; 1725 1726 DWORD status = WaitForMultipleObjects(2, tmp, FALSE, INFINITE); 1727 if (status == WAIT_OBJECT_0) 1728 { 1729 DebugPrintOut(L"OnProcessFrame called after ig_hFinish event\n"); 1730 return S_OK; 1731 } 1732 1733 if(ig_RIE) 1734 { 1735 ig_RIFirst->fastCopy(pSampleBuffer); 1736 ig_RIOut = ig_RIFirst; 1737 } 1738 else 1739 { 1740 ig_RISecond->fastCopy(pSampleBuffer); 1741 ig_RIOut = ig_RISecond; 1742 } 1743 1744 if (ig_Synchronous) 1745 { 1746 SetEvent(ig_hFrameReady); 1747 } 1748 else 1749 { 1750 ig_RIE = !ig_RIE; 1751 } 1752 1753 return S_OK; 1754} 1755 1756STDMETHODIMP ImageGrabberCallback::OnShutdown() 1757{ 1758 SetEvent(ig_hFinish); 1759 return S_OK; 1760} 1761 1762RawImage *ImageGrabberCallback::getRawImage() 1763{ 1764 return ig_RIOut; 1765} 1766 1767DWORD WINAPI MainThreadFunction( LPVOID lpParam ) 1768{ 1769 ImageGrabberThread *pIGT = (ImageGrabberThread *)lpParam; 1770 pIGT->run(); 1771 return 0; 1772} 1773 1774HRESULT ImageGrabberThread::CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious) 1775{ 1776 *ppIGT = new (std::nothrow) ImageGrabberThread(pSource, deviceID, synchronious); 1777 if (ppIGT == NULL) 1778 { 1779 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Memory cannot be allocated\n", deviceID); 1780 return E_OUTOFMEMORY; 1781 } 1782 else 1783 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Creating of the instance of ImageGrabberThread\n", deviceID); 1784 return S_OK; 1785} 1786 1787ImageGrabberThread::ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious) : 1788 igt_func(NULL), 1789 igt_Handle(NULL), 1790 igt_stop(false) 1791{ 1792 HRESULT hr = ImageGrabber::CreateInstance(&igt_pImageGrabber, deviceID, synchronious); 1793 igt_DeviceID = deviceID; 1794 if(SUCCEEDED(hr)) 1795 { 1796 hr = igt_pImageGrabber->initImageGrabber(pSource); 1797 if(!SUCCEEDED(hr)) 1798 { 1799 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with initialization of the instance of the ImageGrabber class\n", deviceID); 1800 } 1801 else 1802 { 1803 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Initialization of instance of the ImageGrabber class\n", deviceID); 1804 } 1805 } 1806 else 1807 { 1808 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with creation of the instance of the ImageGrabber class\n", deviceID); 1809 } 1810} 1811 1812void ImageGrabberThread::setEmergencyStopEvent(void *userData, void(*func)(int, void *)) 1813{ 1814 if(func) 1815 { 1816 igt_func = func; 1817 igt_userData = userData; 1818 } 1819} 1820 1821ImageGrabberThread::~ImageGrabberThread(void) 1822{ 1823 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Destroing ImageGrabberThread\n", igt_DeviceID); 1824 if (igt_Handle) 1825 WaitForSingleObject(igt_Handle, INFINITE); 1826 delete igt_pImageGrabber; 1827} 1828 1829void ImageGrabberThread::stop() 1830{ 1831 igt_stop = true; 1832 if(igt_pImageGrabber) 1833 { 1834 igt_pImageGrabber->stopGrabbing(); 1835 } 1836} 1837 1838void ImageGrabberThread::start() 1839{ 1840 igt_Handle = CreateThread( 1841 NULL, // default security attributes 1842 0, // use default stack size 1843 MainThreadFunction, // thread function name 1844 this, // argument to thread function 1845 0, // use default creation flags 1846 &igt_ThreadIdArray); // returns the thread identifier 1847} 1848 1849void ImageGrabberThread::run() 1850{ 1851 if(igt_pImageGrabber) 1852 { 1853 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Thread for grabbing images is started\n", igt_DeviceID); 1854 HRESULT hr = igt_pImageGrabber->startGrabbing(); 1855 if(!SUCCEEDED(hr)) 1856 { 1857 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with starting the process of grabbing\n", igt_DeviceID); 1858 } 1859 } 1860 else 1861 { 1862 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i The thread is finished without execution of grabbing\n", igt_DeviceID); 1863 } 1864 if(!igt_stop) 1865 { 1866 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Emergency Stop thread\n", igt_DeviceID); 1867 if(igt_func) 1868 { 1869 igt_func(igt_DeviceID, igt_userData); 1870 } 1871 } 1872 else 1873 DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Finish thread\n", igt_DeviceID); 1874} 1875 1876ImageGrabber *ImageGrabberThread::getImageGrabber() 1877{ 1878 return igt_pImageGrabber; 1879} 1880 1881Media_Foundation::Media_Foundation(void) 1882{ 1883 HRESULT hr = MFStartup(MF_VERSION); 1884 if(!SUCCEEDED(hr)) 1885 { 1886 DebugPrintOut(L"MEDIA FOUNDATION: It cannot be created!!!\n"); 1887 } 1888} 1889 1890Media_Foundation::~Media_Foundation(void) 1891{ 1892 HRESULT hr = MFShutdown(); 1893 if(!SUCCEEDED(hr)) 1894 { 1895 DebugPrintOut(L"MEDIA FOUNDATION: Resources cannot be released\n"); 1896 } 1897} 1898 1899bool Media_Foundation::buildListOfDevices() 1900{ 1901 HRESULT hr = S_OK; 1902#ifdef WINRT 1903 videoDevices *vDs = &videoDevices::getInstance(); 1904 hr = vDs->initDevices(WRL_ENUM_GET(_DeviceClass, DeviceClass, VideoCapture)); 1905#else 1906 _ComPtr<IMFAttributes> pAttributes = NULL; 1907 CoInitialize(NULL); 1908 hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1); 1909 if (SUCCEEDED(hr)) 1910 { 1911 hr = pAttributes->SetGUID( 1912 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, 1913 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID 1914 ); 1915 } 1916 if (SUCCEEDED(hr)) 1917 { 1918 videoDevices *vDs = &videoDevices::getInstance(); 1919 hr = vDs->initDevices(pAttributes.Get()); 1920 } 1921#endif 1922 if (FAILED(hr)) 1923 { 1924 DebugPrintOut(L"MEDIA FOUNDATION: The access to the video cameras denied\n"); 1925 } 1926 1927 return (SUCCEEDED(hr)); 1928} 1929 1930Media_Foundation& Media_Foundation::getInstance() 1931{ 1932 static Media_Foundation instance; 1933 return instance; 1934} 1935 1936RawImage::RawImage(unsigned int size): ri_new(false), ri_pixels(NULL) 1937{ 1938 ri_size = size; 1939 ri_pixels = new unsigned char[size]; 1940 memset((void *)ri_pixels,0,ri_size); 1941} 1942 1943bool RawImage::isNew() 1944{ 1945 return ri_new; 1946} 1947 1948unsigned int RawImage::getSize() 1949{ 1950 return ri_size; 1951} 1952 1953RawImage::~RawImage(void) 1954{ 1955 delete []ri_pixels; 1956 ri_pixels = NULL; 1957} 1958 1959long RawImage::CreateInstance(RawImage **ppRImage,unsigned int size) 1960{ 1961 *ppRImage = new (std::nothrow) RawImage(size); 1962 if (ppRImage == NULL) 1963 { 1964 return E_OUTOFMEMORY; 1965 } 1966 return S_OK; 1967} 1968 1969void RawImage::setCopy(const BYTE * pSampleBuffer) 1970{ 1971 memcpy(ri_pixels, pSampleBuffer, ri_size); 1972 ri_new = true; 1973} 1974 1975void RawImage::fastCopy(const BYTE * pSampleBuffer) 1976{ 1977 memcpy(ri_pixels, pSampleBuffer, ri_size); 1978 ri_new = true; 1979} 1980 1981unsigned char * RawImage::getpPixels() 1982{ 1983 ri_new = false; 1984 return ri_pixels; 1985} 1986 1987videoDevice::videoDevice(void): vd_IsSetuped(false), vd_LockOut(OpenLock), vd_pFriendlyName(NULL), 1988 vd_Width(0), vd_Height(0), vd_FrameRate(0), vd_pSource(NULL), vd_pImGrTh(NULL), vd_func(NULL), vd_userData(NULL) 1989{ 1990#ifdef WINRT 1991 vd_pMedCap = nullptr; 1992 vd_cookie.value = 0; 1993 vd_pImGr = NULL; 1994 vd_pAction = nullptr; 1995#endif 1996} 1997 1998void videoDevice::setParametrs(CamParametrs parametrs) 1999{ 2000 if(vd_IsSetuped) 2001 { 2002 if(vd_pSource) 2003 { 2004 Parametr *pParametr = (Parametr *)(¶metrs); 2005 Parametr *pPrevParametr = (Parametr *)(&vd_PrevParametrs); 2006 IAMVideoProcAmp *pProcAmp = NULL; 2007 HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp)); 2008 if (SUCCEEDED(hr)) 2009 { 2010 for(unsigned int i = 0; i < 10; i++) 2011 { 2012 if(pPrevParametr[i].CurrentValue != pParametr[i].CurrentValue || pPrevParametr[i].Flag != pParametr[i].Flag) 2013 hr = pProcAmp->Set(VideoProcAmp_Brightness + i, pParametr[i].CurrentValue, pParametr[i].Flag); 2014 } 2015 pProcAmp->Release(); 2016 } 2017 IAMCameraControl *pProcControl = NULL; 2018 hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl)); 2019 if (SUCCEEDED(hr)) 2020 { 2021 for(unsigned int i = 0; i < 7; i++) 2022 { 2023 if(pPrevParametr[10 + i].CurrentValue != pParametr[10 + i].CurrentValue || pPrevParametr[10 + i].Flag != pParametr[10 + i].Flag) 2024 hr = pProcControl->Set(CameraControl_Pan+i, pParametr[10 + i].CurrentValue, pParametr[10 + i].Flag); 2025 } 2026 pProcControl->Release(); 2027 } 2028 vd_PrevParametrs = parametrs; 2029 } 2030 } 2031} 2032 2033CamParametrs videoDevice::getParametrs() 2034{ 2035 CamParametrs out; 2036 if(vd_IsSetuped) 2037 { 2038 if(vd_pSource) 2039 { 2040 Parametr *pParametr = (Parametr *)(&out); 2041 IAMVideoProcAmp *pProcAmp = NULL; 2042 HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp)); 2043 if (SUCCEEDED(hr)) 2044 { 2045 for(unsigned int i = 0; i < 10; i++) 2046 { 2047 Parametr temp; 2048 hr = pProcAmp->GetRange(VideoProcAmp_Brightness+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag); 2049 if (SUCCEEDED(hr)) 2050 { 2051 temp.CurrentValue = temp.Default; 2052 pParametr[i] = temp; 2053 } 2054 } 2055 pProcAmp->Release(); 2056 } 2057 IAMCameraControl *pProcControl = NULL; 2058 hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl)); 2059 if (SUCCEEDED(hr)) 2060 { 2061 for(unsigned int i = 0; i < 7; i++) 2062 { 2063 Parametr temp; 2064 hr = pProcControl->GetRange(CameraControl_Pan+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag); 2065 if (SUCCEEDED(hr)) 2066 { 2067 temp.CurrentValue = temp.Default; 2068 pParametr[10 + i] = temp; 2069 } 2070 } 2071 pProcControl->Release(); 2072 } 2073 } 2074 } 2075 return out; 2076} 2077 2078#ifdef WINRT 2079long videoDevice::resetDevice(MAKE_WRL_REF(_IDeviceInformation) pDevice) 2080#else 2081long videoDevice::resetDevice(IMFActivate *pActivate) 2082#endif 2083{ 2084 HRESULT hr = E_FAIL; 2085 vd_CurrentFormats.clear(); 2086 if(vd_pFriendlyName) 2087 CoTaskMemFree(vd_pFriendlyName); 2088 vd_pFriendlyName = NULL; 2089#ifdef WINRT 2090 if (pDevice) 2091 { 2092 ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCapture, _MediaCapture, pIMedCap, hr) 2093 if (FAILED(hr)) return hr; 2094 ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCaptureInitializationSettings, _MediaCaptureInitializationSettings, pCapInitSet, hr) 2095 if (FAILED(hr)) return hr; 2096 _StringObj str; 2097 WRL_PROP_GET(pDevice, Name, *REF_WRL_OBJ(str), hr) 2098 if (FAILED(hr)) return hr; 2099 unsigned int length = 0; 2100 PCWSTR wstr = WindowsGetStringRawBuffer(reinterpret_cast<HSTRING>(DEREF_WRL_OBJ(str)), &length); 2101 vd_pFriendlyName = (wchar_t*)CoTaskMemAlloc((length + 1) * sizeof(wchar_t)); 2102 wcscpy(vd_pFriendlyName, wstr); 2103 WRL_PROP_GET(pDevice, Id, *REF_WRL_OBJ(str), hr) 2104 if (FAILED(hr)) return hr; 2105 WRL_PROP_PUT(pCapInitSet, VideoDeviceId, DEREF_WRL_OBJ(str), hr) 2106 if (FAILED(hr)) return hr; 2107 WRL_PROP_PUT(pCapInitSet, StreamingCaptureMode, WRL_ENUM_GET(_StreamingCaptureMode, StreamingCaptureMode, Video), hr) 2108 if (FAILED(hr)) return hr; 2109 MAKE_WRL_REF(_AsyncAction) pAction; 2110 WRL_METHOD(DEREF_WRL_OBJ(pIMedCap), _InitializeWithSettingsAsync, pAction, hr, DEREF_WRL_OBJ(pCapInitSet)) 2111#ifdef HAVE_CONCURRENCY 2112 DEFINE_TASK<void> _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction); 2113 if (FAILED(hr)) return hr; 2114 MAKE_WRL_AGILE_REF(_MediaCapture) pAgileMedCap; 2115 pAgileMedCap = PREPARE_TRANSFER_WRL_OBJ(pIMedCap); 2116 Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); 2117 MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; 2118 SAVE_CURRENT_CONTEXT(context); 2119 vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, _task, pOldAction, context, &pAgileMedCap, this) 2120 HRESULT hr = S_OK; 2121 if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); 2122 _task.wait(); 2123 if (SUCCEEDED(hr)) { 2124 //all camera capture calls only in original context 2125 BEGIN_CALL_IN_CONTEXT(hr, context, pAgileMedCap, this) 2126 enumerateCaptureFormats(DEREF_AGILE_WRL_OBJ(pAgileMedCap)); 2127 END_CALL_IN_CONTEXT_BASE 2128 } 2129 buildLibraryofTypes(); 2130 RELEASE_AGILE_WRL(pAgileMedCap) 2131 END_CREATE_ASYNC(hr)); 2132#endif 2133 } 2134#else 2135 if(pActivate) 2136 { 2137 IMFMediaSource *pSource = NULL; 2138 hr = pActivate->GetAllocatedString( 2139 MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, 2140 &vd_pFriendlyName, 2141 NULL 2142 ); 2143 hr = pActivate->ActivateObject( 2144 __uuidof(IMFMediaSource), 2145 (void**)&pSource 2146 ); 2147 enumerateCaptureFormats(pSource); 2148 buildLibraryofTypes(); 2149 SafeRelease(&pSource); 2150 if(FAILED(hr)) 2151 { 2152 vd_pFriendlyName = NULL; 2153 DebugPrintOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber); 2154 } 2155 } 2156#endif 2157 return hr; 2158} 2159 2160#ifdef WINRT 2161long videoDevice::readInfoOfDevice(MAKE_WRL_REF(_IDeviceInformation) pDevice, unsigned int Num) 2162{ 2163 HRESULT hr = -1; 2164 vd_CurrentNumber = Num; 2165 hr = resetDevice(pDevice); 2166 return hr; 2167} 2168#else 2169long videoDevice::readInfoOfDevice(IMFActivate *pActivate, unsigned int Num) 2170{ 2171 vd_CurrentNumber = Num; 2172 return resetDevice(pActivate); 2173} 2174#endif 2175 2176#ifdef WINRT 2177#ifdef HAVE_CONCURRENCY 2178long videoDevice::checkDevice(_DeviceClass devClass, DEFINE_TASK<void>* pTask, MAKE_WRL_REF(_IDeviceInformation)* ppDevice) 2179{ 2180 HRESULT hr = S_OK; 2181 ACTIVATE_STATIC_OBJ(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation, MAKE_WRL_OBJ(_DeviceInformationStatics), pDevStat, hr) 2182 if (FAILED(hr)) return hr; 2183 MAKE_WRL_REF(_AsyncOperation<MAKE_WRL_REF(_DeviceInformationCollection)>) pAction; 2184 WRL_METHOD(pDevStat, _FindAllAsyncDeviceClass, pAction, hr, devClass) 2185 if (SUCCEEDED(hr)) { 2186 *pTask = CREATE_TASK DEFINE_RET_TYPE(void)([pAction, &ppDevice, this]() -> DEFINE_RET_FORMAL(void) { 2187 HRESULT hr = S_OK; 2188 MAKE_WRL_OBJ(_VectorView<MAKE_WRL_REF(_DeviceInformation)>) pVector = 2189 CREATE_TASK DEFINE_RET_TYPE(MAKE_WRL_REF(_VectorView<MAKE_WRL_REF(_DeviceInformation)>))(pAction).get(); 2190 UINT32 count = 0; 2191 if (SUCCEEDED(hr)) WRL_PROP_GET(pVector, Size, count, hr) 2192 if (SUCCEEDED(hr) && count > 0) { 2193 for (UINT32 i = 0; i < count; i++) { 2194 MAKE_WRL_OBJ(_IDeviceInformation) pDevice; 2195 WRL_METHOD(pVector, GetAt, pDevice, hr, i) 2196 if (SUCCEEDED(hr)) { 2197 _StringObj str; 2198 unsigned int length = 0; 2199 WRL_PROP_GET(pDevice, Name, *REF_WRL_OBJ(str), hr) 2200 PCWSTR wstr = WindowsGetStringRawBuffer(reinterpret_cast<HSTRING>(DEREF_WRL_OBJ(str)), &length); 2201 if (wcscmp(wstr, vd_pFriendlyName) == 0) { 2202 *ppDevice = PREPARE_TRANSFER_WRL_OBJ(pDevice); 2203 } 2204 } 2205 } 2206 } 2207 RET_VAL_BASE; 2208 }); 2209 } 2210 return hr; 2211} 2212#endif 2213#else 2214long videoDevice::checkDevice(IMFAttributes *pAttributes, IMFActivate **pDevice) 2215{ 2216 IMFActivate **ppDevices = NULL; 2217 UINT32 count; 2218 wchar_t *newFriendlyName = NULL; 2219 HRESULT hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); 2220 if (SUCCEEDED(hr)) 2221 { 2222 if(count > 0) 2223 { 2224 if(count > vd_CurrentNumber) 2225 { 2226 hr = ppDevices[vd_CurrentNumber]->GetAllocatedString( 2227 MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, 2228 &newFriendlyName, 2229 NULL 2230 ); 2231 if (SUCCEEDED(hr)) 2232 { 2233 if(wcscmp(newFriendlyName, vd_pFriendlyName) != 0) 2234 { 2235 DebugPrintOut(L"VIDEODEVICE %i: Chosen device cannot be found \n", vd_CurrentNumber); 2236 hr = E_INVALIDARG; 2237 pDevice = NULL; 2238 } 2239 else 2240 { 2241 *pDevice = ppDevices[vd_CurrentNumber]; 2242 (*pDevice)->AddRef(); 2243 } 2244 } 2245 else 2246 { 2247 DebugPrintOut(L"VIDEODEVICE %i: Name of device cannot be gotten \n", vd_CurrentNumber); 2248 } 2249 } 2250 else 2251 { 2252 DebugPrintOut(L"VIDEODEVICE %i: Number of devices more than corrent number of the device \n", vd_CurrentNumber); 2253 hr = E_INVALIDARG; 2254 } 2255 for(UINT32 i = 0; i < count; i++) 2256 { 2257 SafeRelease(&ppDevices[i]); 2258 } 2259 SafeRelease(ppDevices); 2260 } 2261 else 2262 hr = E_FAIL; 2263 } 2264 else 2265 { 2266 DebugPrintOut(L"VIDEODEVICE %i: List of DeviceSources cannot be enumerated \n", vd_CurrentNumber); 2267 } 2268 return hr; 2269} 2270#endif 2271 2272long videoDevice::initDevice() 2273{ 2274 HRESULT hr = S_OK; 2275 CoInitialize(NULL); 2276#ifdef WINRT 2277#ifdef HAVE_CONCURRENCY 2278 Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); 2279 MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; 2280 SAVE_CURRENT_CONTEXT(context); 2281 vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, pOldAction, context, this) 2282 HRESULT hr; 2283 if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); 2284 DEFINE_TASK<void> pTask; 2285 MAKE_WRL_OBJ(_IDeviceInformation) pDevInfo; 2286 hr = checkDevice(WRL_ENUM_GET(_DeviceClass, DeviceClass, VideoCapture), &pTask, REF_WRL_OBJ(pDevInfo)); 2287 if (SUCCEEDED(hr)) pTask.wait(); 2288 if (SUCCEEDED(hr)) { 2289 DEFINE_TASK<void> _task; 2290 BEGIN_CALL_IN_CONTEXT(hr, context, pDevInfo, &_task, context, this) 2291 HRESULT hr; 2292 ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCapture, _MediaCapture, pIMedCap, hr) 2293 if (SUCCEEDED(hr)) { 2294 RELEASE_WRL(vd_pMedCap); 2295 vd_pMedCap = PREPARE_TRANSFER_WRL_OBJ(pIMedCap); 2296 ACTIVATE_OBJ(RuntimeClass_Windows_Media_Capture_MediaCaptureInitializationSettings, _MediaCaptureInitializationSettings, pCapInitSet, hr) 2297 _StringObj str; 2298 if (SUCCEEDED(hr)) { 2299 WRL_PROP_GET(pDevInfo, Id, *REF_WRL_OBJ(str), hr) 2300 if (SUCCEEDED(hr)) { 2301 WRL_PROP_PUT(pCapInitSet, VideoDeviceId, DEREF_WRL_OBJ(str), hr) 2302 } 2303 } 2304 if (SUCCEEDED(hr)) 2305 WRL_PROP_PUT(pCapInitSet, StreamingCaptureMode, WRL_ENUM_GET(_StreamingCaptureMode, StreamingCaptureMode, Video), hr) 2306 if (SUCCEEDED(hr)) reinterpret_cast<ABI::Windows::Media::Capture::IMediaCapture*>(DEREF_AGILE_WRL_OBJ(vd_pMedCap))->add_Failed(Microsoft::WRL::Callback<ABI::Windows::Media::Capture::IMediaCaptureFailedEventHandler>([this, context](ABI::Windows::Media::Capture::IMediaCapture*, ABI::Windows::Media::Capture::IMediaCaptureFailedEventArgs*) -> HRESULT { 2307 HRESULT hr; 2308 BEGIN_CALL_IN_CONTEXT(hr, context, this) 2309 closeDevice(); 2310 END_CALL_IN_CONTEXT_BASE 2311 return hr; 2312 }).Get(), &vd_cookie); 2313 MAKE_WRL_OBJ(_AsyncAction) pAction; 2314 if (SUCCEEDED(hr)) WRL_METHOD(vd_pMedCap, _InitializeWithSettingsAsync, *REF_WRL_OBJ(pAction), hr, DEREF_WRL_OBJ(pCapInitSet)) 2315 if (SUCCEEDED(hr)) _task = CREATE_TASK DEFINE_RET_TYPE(void)(DEREF_WRL_OBJ(pAction)); 2316 } 2317 END_CALL_IN_CONTEXT(hr) 2318 _task.wait(); 2319 } 2320 END_CREATE_ASYNC(hr)); 2321#endif 2322#else 2323 _ComPtr<IMFAttributes> pAttributes = NULL; 2324 IMFActivate *vd_pActivate = NULL; 2325 hr = MFCreateAttributes(pAttributes.GetAddressOf(), 1); 2326 if (SUCCEEDED(hr)) 2327 { 2328 hr = pAttributes->SetGUID( 2329 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, 2330 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID 2331 ); 2332 } 2333 if (SUCCEEDED(hr)) 2334 { 2335 hr = checkDevice(pAttributes.Get(), &vd_pActivate); 2336 if (SUCCEEDED(hr) && vd_pActivate) 2337 { 2338 SafeRelease(&vd_pSource); 2339 hr = vd_pActivate->ActivateObject( 2340 __uuidof(IMFMediaSource), 2341 (void**)&vd_pSource 2342 ); 2343 if (SUCCEEDED(hr)) 2344 { 2345 } 2346 SafeRelease(&vd_pActivate); 2347 } 2348 else 2349 { 2350 DebugPrintOut(L"VIDEODEVICE %i: Device there is not \n", vd_CurrentNumber); 2351 } 2352 } 2353 else 2354 { 2355 DebugPrintOut(L"VIDEODEVICE %i: The attribute of video cameras cannot be getting \n", vd_CurrentNumber); 2356 } 2357#endif 2358 return hr; 2359} 2360 2361MediaType videoDevice::getFormat(unsigned int id) 2362{ 2363 if(id < vd_CurrentFormats.size()) 2364 { 2365 return vd_CurrentFormats[id]; 2366 } 2367 else return MediaType(); 2368} 2369int videoDevice::getCountFormats() 2370{ 2371 return (int)vd_CurrentFormats.size(); 2372} 2373void videoDevice::setEmergencyStopEvent(void *userData, void(*func)(int, void *)) 2374{ 2375 vd_func = func; 2376 vd_userData = userData; 2377} 2378void videoDevice::closeDevice() 2379{ 2380 if(vd_IsSetuped) 2381 { 2382 vd_IsSetuped = false; 2383 2384#ifdef WINRT 2385#ifdef HAVE_CONCURRENCY 2386 if (DEREF_AGILE_WRL_OBJ(vd_pMedCap)) { 2387 MAKE_WRL_REF(_AsyncAction) action; 2388 Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); 2389 MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; 2390 vd_pImGr->stopGrabbing(&action); 2391 reinterpret_cast<ABI::Windows::Media::Capture::IMediaCapture*>(DEREF_AGILE_WRL_OBJ(vd_pMedCap))->remove_Failed(vd_cookie); 2392 vd_cookie.value = 0; 2393 vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, action, pOldAction, this) 2394 HRESULT hr = S_OK; 2395 if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); 2396 CREATE_TASK DEFINE_RET_TYPE(void)(action).wait(); 2397 RELEASE_WRL(vd_pMedCap) 2398 if(vd_LockOut == RawDataLock) { 2399 delete vd_pImGr; 2400 } 2401 vd_pImGr = NULL; 2402 vd_LockOut = OpenLock; 2403 END_CREATE_ASYNC(hr)); 2404 return; 2405 } 2406#endif 2407#endif 2408 2409 vd_pSource->Shutdown(); 2410 SafeRelease(&vd_pSource); 2411 if(vd_LockOut == RawDataLock) 2412 { 2413 vd_pImGrTh->stop(); 2414 Sleep(500); 2415 delete vd_pImGrTh; 2416 } 2417 vd_pImGrTh = NULL; 2418 vd_LockOut = OpenLock; 2419 DebugPrintOut(L"VIDEODEVICE %i: Device is stopped \n", vd_CurrentNumber); 2420 } 2421} 2422unsigned int videoDevice::getWidth() 2423{ 2424 if(vd_IsSetuped) 2425 return vd_Width; 2426 else 2427 return 0; 2428} 2429unsigned int videoDevice::getHeight() 2430{ 2431 if(vd_IsSetuped) 2432 return vd_Height; 2433 else 2434 return 0; 2435} 2436 2437unsigned int videoDevice::getFrameRate() const 2438{ 2439 if(vd_IsSetuped) 2440 return vd_FrameRate; 2441 else 2442 return 0; 2443} 2444 2445IMFMediaSource *videoDevice::getMediaSource() 2446{ 2447 IMFMediaSource *out = NULL; 2448 if(vd_LockOut == OpenLock) 2449 { 2450 vd_LockOut = MediaSourceLock; 2451 out = vd_pSource; 2452 } 2453 return out; 2454} 2455int videoDevice::findType(unsigned int size, unsigned int frameRate) 2456{ 2457 // For required frame size look for the suitable video format. 2458 // If not found, get the format for the largest available frame size. 2459 FrameRateMap FRM; 2460 std::map<UINT64, FrameRateMap>::const_iterator fmt; 2461 fmt = vd_CaptureFormats.find(size); 2462 if( fmt != vd_CaptureFormats.end() ) 2463 FRM = fmt->second; 2464 else if( !vd_CaptureFormats.empty() ) 2465 FRM = vd_CaptureFormats.rbegin()->second; 2466 2467 if( FRM.empty() ) 2468 return -1; 2469 2470 UINT64 frameRateMax = 0; SUBTYPEMap STMMax; 2471 if(frameRate == 0) 2472 { 2473 std::map<UINT64, SUBTYPEMap>::iterator f = FRM.begin(); 2474 for(; f != FRM.end(); f++) 2475 { 2476 // Looking for highest possible frame rate. 2477 if((*f).first >= frameRateMax) 2478 { 2479 frameRateMax = (*f).first; 2480 STMMax = (*f).second; 2481 } 2482 } 2483 } 2484 else 2485 { 2486 std::map<UINT64, SUBTYPEMap>::iterator f = FRM.begin(); 2487 for(; f != FRM.end(); f++) 2488 { 2489 // Looking for frame rate higher that recently found but not higher then demanded. 2490 if( (*f).first >= frameRateMax && (*f).first <= frameRate ) 2491 { 2492 frameRateMax = (*f).first; 2493 STMMax = (*f).second; 2494 } 2495 } 2496 } 2497 // Get first (default) item from the list if no suitable frame rate found. 2498 if( STMMax.empty() ) 2499 STMMax = FRM.begin()->second; 2500 2501 // Check if there are any format types on the list. 2502 if( STMMax.empty() ) 2503 return -1; 2504 2505 vectorNum VN = STMMax.begin()->second; 2506 if( VN.empty() ) 2507 return -1; 2508 2509 return VN[0]; 2510} 2511 2512void videoDevice::buildLibraryofTypes() 2513{ 2514 unsigned int size; 2515 unsigned int framerate; 2516 std::vector<MediaType>::iterator i = vd_CurrentFormats.begin(); 2517 int count = 0; 2518 for(; i != vd_CurrentFormats.end(); i++) 2519 { 2520 // Count only supported video formats. 2521 if( (*i).MF_MT_SUBTYPE == MFVideoFormat_RGB24 ) 2522 { 2523 size = (*i).MF_MT_FRAME_SIZE; 2524 framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR / (*i).MF_MT_FRAME_RATE_DENOMINATOR; 2525 FrameRateMap FRM = vd_CaptureFormats[size]; 2526 SUBTYPEMap STM = FRM[framerate]; 2527 String subType((*i).pMF_MT_SUBTYPEName); 2528 vectorNum VN = STM[subType]; 2529 VN.push_back(count); 2530 STM[subType] = VN; 2531 FRM[framerate] = STM; 2532 vd_CaptureFormats[size] = FRM; 2533 } 2534 count++; 2535 } 2536} 2537 2538#ifdef WINRT 2539long videoDevice::setDeviceFormat(MAKE_WRL_REF(_MediaCapture) pSource, unsigned long dwFormatIndex, MAKE_WRL_REF(_AsyncAction)* pAction) 2540{ 2541 HRESULT hr; 2542 MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; 2543 WRL_PROP_GET(pSource, VideoDeviceController, pDevCont, hr) 2544 if (FAILED(hr)) return hr; 2545 GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) 2546 if (FAILED(hr)) return hr; 2547 MAKE_WRL_OBJ(_VectorView<MAKE_WRL_REF(_MediaEncodingProperties)>) pVector; 2548 WRL_METHOD(pMedDevCont, GetAvailableMediaStreamProperties, pVector, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) 2549 if (FAILED(hr)) return hr; 2550 MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; 2551 WRL_METHOD(pVector, GetAt, pMedEncProps, hr, dwFormatIndex) 2552 if (FAILED(hr)) return hr; 2553 WRL_METHOD(pMedDevCont, SetMediaStreamPropertiesAsync, *pAction, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview), DEREF_WRL_OBJ(pMedEncProps)) 2554 return hr; 2555} 2556#endif 2557 2558long videoDevice::setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex) 2559{ 2560 _ComPtr<IMFPresentationDescriptor> pPD = NULL; 2561 _ComPtr<IMFStreamDescriptor> pSD = NULL; 2562 _ComPtr<IMFMediaTypeHandler> pHandler = NULL; 2563 _ComPtr<IMFMediaType> pType = NULL; 2564 HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); 2565 if (FAILED(hr)) 2566 { 2567 goto done; 2568 } 2569 BOOL fSelected; 2570 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf()); 2571 if (FAILED(hr)) 2572 { 2573 goto done; 2574 } 2575 hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf()); 2576 if (FAILED(hr)) 2577 { 2578 goto done; 2579 } 2580 hr = pHandler->GetMediaTypeByIndex((DWORD)dwFormatIndex, pType.GetAddressOf()); 2581 if (FAILED(hr)) 2582 { 2583 goto done; 2584 } 2585 hr = pHandler->SetCurrentMediaType(pType.Get()); 2586 2587done: 2588 return hr; 2589} 2590 2591bool videoDevice::isDeviceSetup() 2592{ 2593 return vd_IsSetuped; 2594} 2595 2596RawImage * videoDevice::getRawImageOut() 2597{ 2598 if(!vd_IsSetuped) return NULL; 2599#ifdef WINRT 2600 if(vd_pImGr) return vd_pImGr->getRawImage(); 2601#endif 2602 if(vd_pImGrTh) 2603 return vd_pImGrTh->getImageGrabber()->getRawImage(); 2604 else 2605 { 2606 DebugPrintOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class does not exist \n", vd_CurrentNumber); 2607 } 2608 return NULL; 2609} 2610 2611bool videoDevice::isFrameNew() 2612{ 2613 if(!vd_IsSetuped) return false; 2614 if(vd_LockOut == RawDataLock || vd_LockOut == OpenLock) 2615 { 2616 if(vd_LockOut == OpenLock) 2617 { 2618 vd_LockOut = RawDataLock; 2619 2620 //must already be closed 2621#ifdef WINRT 2622 if (DEREF_AGILE_WRL_OBJ(vd_pMedCap)) { 2623 MAKE_WRL_REF(_AsyncAction) action; 2624 if (FAILED(ImageGrabberWinRT::CreateInstance(&vd_pImGr))) return false; 2625 if (FAILED(vd_pImGr->initImageGrabber(DEREF_AGILE_WRL_OBJ(vd_pMedCap), MFVideoFormat_RGB24)) || FAILED(vd_pImGr->startGrabbing(&action))) { 2626 delete vd_pImGr; 2627 return false; 2628 } 2629#ifdef HAVE_CONCURRENCY 2630 Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); 2631 MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; 2632 DEFINE_TASK<void> _task = CREATE_TASK DEFINE_RET_TYPE(void)(action); 2633 vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, _task, pOldAction, this) 2634 HRESULT hr = S_OK; 2635 if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); 2636 _task.wait(); 2637 END_CREATE_ASYNC(hr)); 2638#endif 2639 return true; 2640 } 2641#endif 2642 HRESULT hr = ImageGrabberThread::CreateInstance(&vd_pImGrTh, vd_pSource, vd_CurrentNumber); 2643 if(FAILED(hr)) 2644 { 2645 DebugPrintOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class cannot be created.\n", vd_CurrentNumber); 2646 return false; 2647 } 2648 vd_pImGrTh->setEmergencyStopEvent(vd_userData, vd_func); 2649 vd_pImGrTh->start(); 2650 return true; 2651 } 2652#ifdef WINRT 2653 if(vd_pImGr) 2654 return vd_pImGr->getRawImage()->isNew(); 2655#endif 2656 if(vd_pImGrTh) 2657 return vd_pImGrTh->getImageGrabber()->getRawImage()->isNew(); 2658 } 2659 return false; 2660} 2661 2662bool videoDevice::isDeviceMediaSource() 2663{ 2664 if(vd_LockOut == MediaSourceLock) return true; 2665 return false; 2666} 2667 2668bool videoDevice::isDeviceRawDataSource() 2669{ 2670 if(vd_LockOut == RawDataLock) return true; 2671 return false; 2672} 2673 2674bool videoDevice::setupDevice(unsigned int id) 2675{ 2676 if(!vd_IsSetuped) 2677 { 2678 HRESULT hr = initDevice(); 2679 if(SUCCEEDED(hr)) 2680 { 2681#ifdef WINRT 2682#ifdef HAVE_CONCURRENCY 2683 Concurrency::critical_section::scoped_lock _LockHolder(vd_lock); 2684 MAKE_WRL_REF(_AsyncAction) pOldAction = vd_pAction; 2685 SAVE_CURRENT_CONTEXT(context); 2686 vd_pAction = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, pOldAction, context, id, this) 2687 HRESULT hr; 2688 if (pOldAction) CREATE_TASK DEFINE_RET_TYPE(void)(pOldAction).wait(); 2689#endif 2690#endif 2691 vd_Width = vd_CurrentFormats[id].width; 2692 vd_Height = vd_CurrentFormats[id].height; 2693 vd_FrameRate = vd_CurrentFormats[id].MF_MT_FRAME_RATE_NUMERATOR / 2694 vd_CurrentFormats[id].MF_MT_FRAME_RATE_DENOMINATOR; 2695#ifdef WINRT 2696#ifdef HAVE_CONCURRENCY 2697 if (DEREF_AGILE_WRL_OBJ(vd_pMedCap)) { 2698 DEFINE_TASK<void> _task; 2699 BEGIN_CALL_IN_CONTEXT(hr, context, id, &_task, this) 2700 MAKE_WRL_REF(_AsyncAction) pAction; 2701 HRESULT hr = setDeviceFormat(DEREF_AGILE_WRL_OBJ(vd_pMedCap), (DWORD) id, &pAction); 2702 if (SUCCEEDED(hr)) _task = CREATE_TASK DEFINE_RET_TYPE(void)(pAction); 2703 END_CALL_IN_CONTEXT(hr) 2704 if (SUCCEEDED(hr)) _task.wait(); 2705 } else 2706#endif 2707#endif 2708 hr = setDeviceFormat(vd_pSource, (DWORD) id); 2709 vd_IsSetuped = (SUCCEEDED(hr)); 2710 if(vd_IsSetuped) 2711 DebugPrintOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber); 2712 vd_PrevParametrs = getParametrs(); 2713#ifdef WINRT 2714#ifdef HAVE_CONCURRENCY 2715 END_CREATE_ASYNC(hr)); 2716#endif 2717 return true; 2718#else 2719 return vd_IsSetuped; 2720#endif 2721 } 2722 else 2723 { 2724 DebugPrintOut(L"VIDEODEVICE %i: Interface IMFMediaSource cannot be got \n", vd_CurrentNumber); 2725 return false; 2726 } 2727 } 2728 else 2729 { 2730 DebugPrintOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber); 2731 return false; 2732 } 2733} 2734 2735bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate) 2736{ 2737 unsigned int id = findType(w * h, idealFramerate); 2738 if( id < 0 ) 2739 return false; 2740 2741 return setupDevice(id); 2742} 2743 2744wchar_t *videoDevice::getName() 2745{ 2746 return vd_pFriendlyName; 2747} 2748 2749videoDevice::~videoDevice(void) 2750{ 2751 closeDevice(); 2752#ifdef WINRT 2753 RELEASE_WRL(vd_pMedCap) 2754#endif 2755 SafeRelease(&vd_pSource); 2756 if(vd_pFriendlyName) 2757 CoTaskMemFree(vd_pFriendlyName); 2758} 2759 2760#ifdef WINRT 2761HRESULT videoDevice::enumerateCaptureFormats(MAKE_WRL_REF(_MediaCapture) pSource) 2762{ 2763 HRESULT hr; 2764 MAKE_WRL_OBJ(_VideoDeviceController) pDevCont; 2765 WRL_PROP_GET(pSource, VideoDeviceController, pDevCont, hr) 2766 if (FAILED(hr)) return hr; 2767 GET_WRL_OBJ_FROM_OBJ(_MediaDeviceController, pMedDevCont, pDevCont, hr) 2768 if (FAILED(hr)) return hr; 2769 MAKE_WRL_OBJ(_VectorView<MAKE_WRL_REF(_MediaEncodingProperties)>) pVector; 2770 WRL_METHOD(pMedDevCont, GetAvailableMediaStreamProperties, pVector, hr, WRL_ENUM_GET(_MediaStreamType, MediaStreamType, VideoPreview)) 2771 if (FAILED(hr)) return hr; 2772 UINT32 count; 2773 WRL_PROP_GET(pVector, Size, count, hr) 2774 if (FAILED(hr)) return hr; 2775 for (UINT32 i = 0; i < count; i++) { 2776 MAKE_WRL_OBJ(_MediaEncodingProperties) pMedEncProps; 2777 WRL_METHOD(pVector, GetAt, pMedEncProps, hr, i) 2778 if (FAILED(hr)) return hr; 2779 _ComPtr<IMFMediaType> pType = NULL; 2780 hr = MediaSink::ConvertPropertiesToMediaType(DEREF_AS_NATIVE_WRL_OBJ(ABI::Windows::Media::MediaProperties::IMediaEncodingProperties, pMedEncProps), &pType); 2781 if (FAILED(hr)) return hr; 2782 MediaType MT = FormatReader::Read(pType.Get()); 2783 vd_CurrentFormats.push_back(MT); 2784 } 2785 return hr; 2786} 2787#endif 2788 2789HRESULT videoDevice::enumerateCaptureFormats(IMFMediaSource *pSource) 2790{ 2791 _ComPtr<IMFPresentationDescriptor> pPD = NULL; 2792 _ComPtr<IMFStreamDescriptor> pSD = NULL; 2793 _ComPtr<IMFMediaTypeHandler> pHandler = NULL; 2794 _ComPtr<IMFMediaType> pType = NULL; 2795 HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); 2796 if (FAILED(hr)) 2797 { 2798 goto done; 2799 } 2800 BOOL fSelected; 2801 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf()); 2802 if (FAILED(hr)) 2803 { 2804 goto done; 2805 } 2806 hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf()); 2807 if (FAILED(hr)) 2808 { 2809 goto done; 2810 } 2811 DWORD cTypes = 0; 2812 hr = pHandler->GetMediaTypeCount(&cTypes); 2813 if (FAILED(hr)) 2814 { 2815 goto done; 2816 } 2817 for (DWORD i = 0; i < cTypes; i++) 2818 { 2819 hr = pHandler->GetMediaTypeByIndex(i, pType.GetAddressOf()); 2820 if (FAILED(hr)) 2821 { 2822 goto done; 2823 } 2824 MediaType MT = FormatReader::Read(pType.Get()); 2825 vd_CurrentFormats.push_back(MT); 2826 } 2827 2828done: 2829 return hr; 2830} 2831 2832videoDevices::videoDevices(void): count(0) 2833{ 2834#ifdef WINRT 2835 vds_enumTask = nullptr; 2836#endif 2837} 2838 2839void videoDevices::clearDevices() 2840{ 2841 std::vector<videoDevice *>::iterator i = vds_Devices.begin(); 2842 for(; i != vds_Devices.end(); ++i) 2843 delete (*i); 2844 vds_Devices.clear(); 2845} 2846 2847videoDevices::~videoDevices(void) 2848{ 2849 clearDevices(); 2850} 2851 2852videoDevice * videoDevices::getDevice(unsigned int i) 2853{ 2854 if(i >= vds_Devices.size()) 2855 { 2856 return NULL; 2857 } 2858 if(i < 0) 2859 { 2860 return NULL; 2861 } 2862 return vds_Devices[i]; 2863} 2864 2865#ifdef WINRT 2866long videoDevices::initDevices(_DeviceClass devClass) 2867{ 2868 HRESULT hr = S_OK; 2869 ACTIVATE_STATIC_OBJ(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation, MAKE_WRL_OBJ(_DeviceInformationStatics), pDevStat, hr) 2870 if (FAILED(hr)) return hr; 2871 MAKE_WRL_REF(_AsyncOperation<MAKE_WRL_REF(_DeviceInformationCollection)>) pAction; 2872 WRL_METHOD(pDevStat, _FindAllAsyncDeviceClass, pAction, hr, devClass) 2873 if (SUCCEEDED(hr)) { 2874#ifdef HAVE_CONCURRENCY 2875 SAVE_CURRENT_CONTEXT(context); 2876 vds_enumTask = reinterpret_cast<MAKE_WRL_REF(_AsyncAction)>(BEGIN_CREATE_ASYNC(void, pAction, context, this) 2877 HRESULT hr = S_OK; 2878 MAKE_WRL_OBJ(_VectorView<MAKE_WRL_REF(_DeviceInformation)>) pVector = 2879 CREATE_TASK DEFINE_RET_TYPE(MAKE_WRL_REF(_VectorView<MAKE_WRL_REF(_DeviceInformation)>))(pAction).get(); 2880 if (SUCCEEDED(hr)) WRL_PROP_GET(pVector, Size, count, hr) 2881 if (SUCCEEDED(hr) && count > 0) { 2882 for (UINT32 i = 0; i < count; i++) { 2883 videoDevice *vd = new videoDevice; 2884 MAKE_WRL_OBJ(_IDeviceInformation) pDevice; 2885 WRL_METHOD(pVector, GetAt, pDevice, hr, i) 2886 if (SUCCEEDED(hr)) { 2887 BEGIN_CALL_IN_CONTEXT(hr, context, vd, pDevice, i) 2888 vd->readInfoOfDevice(DEREF_WRL_OBJ(pDevice), i); 2889 END_CALL_IN_CONTEXT_BASE 2890 vds_Devices.push_back(vd); 2891 } 2892 } 2893 } 2894 END_CREATE_ASYNC(hr)); 2895#endif 2896 } 2897 return hr; 2898} 2899#else 2900long videoDevices::initDevices(IMFAttributes *pAttributes) 2901{ 2902 clearDevices(); 2903 IMFActivate **ppDevices = NULL; 2904 HRESULT hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); 2905 if (SUCCEEDED(hr)) 2906 { 2907 if(count > 0) 2908 { 2909 for(UINT32 i = 0; i < count; i++) 2910 { 2911 videoDevice *vd = new videoDevice; 2912 vd->readInfoOfDevice(ppDevices[i], i); 2913 vds_Devices.push_back(vd); 2914 SafeRelease(&ppDevices[i]); 2915 } 2916 SafeRelease(ppDevices); 2917 } 2918 else 2919 hr = E_INVALIDARG; 2920 } 2921 else 2922 { 2923 DebugPrintOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n"); 2924 } 2925 return hr; 2926} 2927#endif 2928 2929unsigned int videoDevices::getCount() 2930{ 2931 return (unsigned int)vds_Devices.size(); 2932} 2933 2934videoDevices& videoDevices::getInstance() 2935{ 2936 static videoDevices instance; 2937 return instance; 2938} 2939 2940Parametr::Parametr() 2941{ 2942 CurrentValue = 0; 2943 Min = 0; 2944 Max = 0; 2945 Step = 0; 2946 Default = 0; 2947 Flag = 0; 2948} 2949 2950MediaType::MediaType() 2951{ 2952 pMF_MT_AM_FORMAT_TYPEName = NULL; 2953 pMF_MT_MAJOR_TYPEName = NULL; 2954 pMF_MT_SUBTYPEName = NULL; 2955 Clear(); 2956} 2957 2958MediaType::~MediaType() 2959{ 2960 Clear(); 2961} 2962 2963void MediaType::Clear() 2964{ 2965 MF_MT_FRAME_SIZE = 0; 2966 height = 0; 2967 width = 0; 2968 MF_MT_YUV_MATRIX = 0; 2969 MF_MT_VIDEO_LIGHTING = 0; 2970 MF_MT_DEFAULT_STRIDE = 0; 2971 MF_MT_VIDEO_CHROMA_SITING = 0; 2972 MF_MT_FIXED_SIZE_SAMPLES = 0; 2973 MF_MT_VIDEO_NOMINAL_RANGE = 0; 2974 MF_MT_FRAME_RATE_NUMERATOR = 0; 2975 MF_MT_FRAME_RATE_DENOMINATOR = 0; 2976 MF_MT_PIXEL_ASPECT_RATIO = 0; 2977 MF_MT_PIXEL_ASPECT_RATIO_low = 0; 2978 MF_MT_ALL_SAMPLES_INDEPENDENT = 0; 2979 MF_MT_FRAME_RATE_RANGE_MIN = 0; 2980 MF_MT_FRAME_RATE_RANGE_MIN_low = 0; 2981 MF_MT_SAMPLE_SIZE = 0; 2982 MF_MT_VIDEO_PRIMARIES = 0; 2983 MF_MT_INTERLACE_MODE = 0; 2984 MF_MT_FRAME_RATE_RANGE_MAX = 0; 2985 MF_MT_FRAME_RATE_RANGE_MAX_low = 0; 2986 memset(&MF_MT_MAJOR_TYPE, 0, sizeof(GUID)); 2987 memset(&MF_MT_AM_FORMAT_TYPE, 0, sizeof(GUID)); 2988 memset(&MF_MT_SUBTYPE, 0, sizeof(GUID)); 2989} 2990 2991videoInput::videoInput(void): accessToDevices(false) 2992{ 2993 DebugPrintOut(L"\n***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****\n\n"); 2994 updateListOfDevices(); 2995 if(!accessToDevices) 2996 DebugPrintOut(L"INITIALIZATION: There is not any suitable video device\n"); 2997} 2998 2999void videoInput::updateListOfDevices() 3000{ 3001 Media_Foundation *MF = &Media_Foundation::getInstance(); 3002 accessToDevices = MF->buildListOfDevices(); 3003 if(!accessToDevices) 3004 DebugPrintOut(L"UPDATING: There is not any suitable video device\n"); 3005} 3006 3007videoInput::~videoInput(void) 3008{ 3009 DebugPrintOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n"); 3010} 3011 3012IMFMediaSource *videoInput::getMediaSource(int deviceID) 3013{ 3014 if(accessToDevices) 3015 { 3016 videoDevice * VD = videoDevices::getInstance().getDevice(deviceID); 3017 if(VD) 3018 { 3019 IMFMediaSource *out = VD->getMediaSource(); 3020 if(!out) 3021 DebugPrintOut(L"VideoDevice %i: There is not any suitable IMFMediaSource interface\n", deviceID); 3022 return out; 3023 } 3024 } 3025 else 3026 { 3027 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3028 } 3029 return NULL; 3030} 3031 3032bool videoInput::setupDevice(int deviceID, unsigned int id) 3033{ 3034 if (deviceID < 0 ) 3035 { 3036 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3037 return false; 3038 } 3039 if(accessToDevices) 3040 { 3041 videoDevices *VDS = &videoDevices::getInstance(); 3042 videoDevice * VD = VDS->getDevice(deviceID); 3043 if(VD) 3044 { 3045 bool out = VD->setupDevice(id); 3046 if(!out) 3047 DebugPrintOut(L"VIDEODEVICE %i: This device cannot be started\n", deviceID); 3048 return out; 3049 } 3050 } 3051 else 3052 { 3053 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3054 } 3055 return false; 3056} 3057 3058bool videoInput::setupDevice(int deviceID, unsigned int w, unsigned int h, unsigned int idealFramerate) 3059{ 3060 if (deviceID < 0 ) 3061 { 3062 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3063 return false; 3064 } 3065 if(accessToDevices) 3066 { 3067 videoDevices *VDS = &videoDevices::getInstance(); 3068 videoDevice * VD = VDS->getDevice(deviceID); 3069 if(VD) 3070 { 3071 bool out = VD->setupDevice(w, h, idealFramerate); 3072 if(!out) 3073 DebugPrintOut(L"VIDEODEVICE %i: this device cannot be started\n", deviceID); 3074 return out; 3075 } 3076 } 3077 else 3078 { 3079 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n", deviceID); 3080 } 3081 return false; 3082} 3083 3084MediaType videoInput::getFormat(int deviceID, unsigned int id) 3085{ 3086 if (deviceID < 0) 3087 { 3088 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3089 return MediaType(); 3090 } 3091 if(accessToDevices) 3092 { 3093 videoDevices *VDS = &videoDevices::getInstance(); 3094 videoDevice * VD = VDS->getDevice(deviceID); 3095 if(VD) 3096 return VD->getFormat(id); 3097 } 3098 else 3099 { 3100 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3101 } 3102 return MediaType(); 3103} 3104 3105bool videoInput::isDeviceSetup(int deviceID) 3106{ 3107 if (deviceID < 0) 3108 { 3109 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3110 return false; 3111 } 3112 if(accessToDevices) 3113 { 3114 videoDevices *VDS = &videoDevices::getInstance(); 3115 videoDevice * VD = VDS->getDevice(deviceID); 3116 if(VD) 3117 return VD->isDeviceSetup(); 3118 } 3119 else 3120 { 3121 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3122 } 3123 return false; 3124} 3125 3126bool videoInput::isDeviceMediaSource(int deviceID) 3127{ 3128 if (deviceID < 0) 3129 { 3130 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3131 return false; 3132 } 3133 if(accessToDevices) 3134 { 3135 videoDevices *VDS = &videoDevices::getInstance(); 3136 videoDevice * VD = VDS->getDevice(deviceID); 3137 if(VD) 3138 return VD->isDeviceMediaSource(); 3139 } 3140 else 3141 { 3142 DebugPrintOut(L"Device(s): There is not any suitable video device\n"); 3143 } 3144 return false; 3145} 3146 3147bool videoInput::isDeviceRawDataSource(int deviceID) 3148{ 3149 if (deviceID < 0) 3150 { 3151 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3152 return false; 3153 } 3154 if(accessToDevices) 3155 { 3156 videoDevices *VDS = &videoDevices::getInstance(); 3157 videoDevice * VD = VDS->getDevice(deviceID); 3158 if(VD) 3159 { 3160 bool isRaw = VD->isDeviceRawDataSource(); 3161 return isRaw; 3162 } 3163 } 3164 else 3165 { 3166 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3167 } 3168 return false; 3169} 3170 3171bool videoInput::isFrameNew(int deviceID) 3172{ 3173 if (deviceID < 0) 3174 { 3175 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3176 return false; 3177 } 3178 if(accessToDevices) 3179 { 3180 if(!isDeviceSetup(deviceID)) 3181 { 3182 if(isDeviceMediaSource(deviceID)) 3183 return false; 3184 } 3185 videoDevices *VDS = &videoDevices::getInstance(); 3186 videoDevice * VD = VDS->getDevice(deviceID); 3187 if(VD) 3188 { 3189 return VD->isFrameNew(); 3190 } 3191 } 3192 else 3193 { 3194 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3195 } 3196 return false; 3197} 3198 3199#ifdef WINRT 3200void videoInput::waitForDevice(int deviceID) 3201{ 3202 if (deviceID < 0) 3203 { 3204 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3205 return; 3206 } 3207 if(accessToDevices) 3208 { 3209 if(!isDeviceSetup(deviceID)) 3210 { 3211 if(isDeviceMediaSource(deviceID)) 3212 return; 3213 } 3214 videoDevices *VDS = &videoDevices::getInstance(); 3215 videoDevice * VD = VDS->getDevice(deviceID); 3216 if(VD) 3217 { 3218 VD->waitForDevice(); 3219 } 3220 } 3221 else 3222 { 3223 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3224 } 3225 return; 3226} 3227#endif 3228 3229unsigned int videoInput::getCountFormats(int deviceID) const 3230{ 3231 if (deviceID < 0) 3232 { 3233 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3234 return 0; 3235 } 3236 if(accessToDevices) 3237 { 3238 videoDevices *VDS = &videoDevices::getInstance(); 3239 videoDevice * VD = VDS->getDevice(deviceID); 3240 if(VD) 3241 return VD->getCountFormats(); 3242 } 3243 else 3244 { 3245 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3246 } 3247 return 0; 3248} 3249 3250void videoInput::closeAllDevices() 3251{ 3252 videoDevices *VDS = &videoDevices::getInstance(); 3253 for(unsigned int i = 0; i < VDS->getCount(); i++) 3254 closeDevice(i); 3255} 3256 3257void videoInput::setParametrs(int deviceID, CamParametrs parametrs) 3258{ 3259 if (deviceID < 0) 3260 { 3261 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3262 return; 3263 } 3264 if(accessToDevices) 3265 { 3266 videoDevices *VDS = &videoDevices::getInstance(); 3267 videoDevice *VD = VDS->getDevice(deviceID); 3268 if(VD) 3269 VD->setParametrs(parametrs); 3270 } 3271 else 3272 { 3273 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3274 } 3275} 3276 3277CamParametrs videoInput::getParametrs(int deviceID) 3278{ 3279 CamParametrs out; 3280 if (deviceID < 0) 3281 { 3282 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3283 return out; 3284 } 3285 if(accessToDevices) 3286 { 3287 videoDevices *VDS = &videoDevices::getInstance(); 3288 videoDevice *VD = VDS->getDevice(deviceID); 3289 if(VD) 3290 out = VD->getParametrs(); 3291 } 3292 else 3293 { 3294 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3295 } 3296 return out; 3297} 3298 3299void videoInput::closeDevice(int deviceID) 3300{ 3301 if (deviceID < 0) 3302 { 3303 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3304 return; 3305 } 3306 if(accessToDevices) 3307 { 3308 videoDevices *VDS = &videoDevices::getInstance(); 3309 videoDevice *VD = VDS->getDevice(deviceID); 3310 if(VD) 3311 VD->closeDevice(); 3312 } 3313 else 3314 { 3315 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3316 } 3317} 3318 3319unsigned int videoInput::getWidth(int deviceID) const 3320{ 3321 if (deviceID < 0) 3322 { 3323 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3324 return 0; 3325 } 3326 if(accessToDevices) 3327 { 3328 videoDevices *VDS = &videoDevices::getInstance(); 3329 videoDevice * VD = VDS->getDevice(deviceID); 3330 if(VD) 3331 return VD->getWidth(); 3332 } 3333 else 3334 { 3335 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3336 } 3337 return 0; 3338} 3339 3340unsigned int videoInput::getHeight(int deviceID) const 3341{ 3342 if (deviceID < 0) 3343 { 3344 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3345 return 0; 3346 } 3347 if(accessToDevices) 3348 { 3349 videoDevices *VDS = &videoDevices::getInstance(); 3350 videoDevice * VD = VDS->getDevice(deviceID); 3351 if(VD) 3352 return VD->getHeight(); 3353 } 3354 else 3355 { 3356 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3357 } 3358 return 0; 3359} 3360 3361unsigned int videoInput::getFrameRate(int deviceID) const 3362{ 3363 if (deviceID < 0) 3364 { 3365 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3366 return 0; 3367 } 3368 if(accessToDevices) 3369 { 3370 videoDevice * VD = videoDevices::getInstance().getDevice(deviceID); 3371 if(VD) 3372 return VD->getFrameRate(); 3373 } 3374 else 3375 { 3376 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3377 } 3378 return 0; 3379} 3380 3381wchar_t *videoInput::getNameVideoDevice(int deviceID) 3382{ 3383 if (deviceID < 0) 3384 { 3385 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3386 return NULL; 3387 } 3388 if(accessToDevices) 3389 { 3390 videoDevices *VDS = &videoDevices::getInstance(); 3391 videoDevice * VD = VDS->getDevice(deviceID); 3392 if(VD) 3393 return VD->getName(); 3394 } 3395 else 3396 { 3397 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3398 } 3399 return L"Empty"; 3400} 3401 3402unsigned int videoInput::listDevices(bool silent) 3403{ 3404 int out = 0; 3405 if(accessToDevices) 3406 { 3407 videoDevices *VDS = &videoDevices::getInstance(); 3408#ifdef WINRT 3409 VDS->waitInit(); 3410#endif 3411 out = VDS->getCount(); 3412 if(!silent) DebugPrintOut(L"\nVIDEOINPUT SPY MODE!\n\n"); 3413 if(!silent) DebugPrintOut(L"SETUP: Looking For Capture Devices\n"); 3414 for(int i = 0; i < out; i++) 3415 { 3416 if(!silent) DebugPrintOut(L"SETUP: %i) %s \n",i, getNameVideoDevice(i)); 3417 } 3418 if(!silent) DebugPrintOut(L"SETUP: %i Device(s) found\n\n", out); 3419 } 3420 else 3421 { 3422 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3423 } 3424 return out; 3425} 3426 3427videoInput& videoInput::getInstance() 3428{ 3429 static videoInput instance; 3430 return instance; 3431} 3432 3433bool videoInput::isDevicesAcceable() 3434{ 3435 return accessToDevices; 3436} 3437 3438#ifdef _DEBUG 3439void videoInput::setVerbose(bool state) 3440{ 3441 DPO *dpo = &DPO::getInstance(); 3442 dpo->setVerbose(state); 3443} 3444#endif 3445 3446void videoInput::setEmergencyStopEvent(int deviceID, void *userData, void(*func)(int, void *)) 3447{ 3448 if (deviceID < 0) 3449 { 3450 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3451 return; 3452 } 3453 if(accessToDevices) 3454 { 3455 if(func) 3456 { 3457 videoDevices *VDS = &videoDevices::getInstance(); 3458 videoDevice * VD = VDS->getDevice(deviceID); 3459 if(VD) 3460 VD->setEmergencyStopEvent(userData, func); 3461 } 3462 } 3463 else 3464 { 3465 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3466 } 3467} 3468 3469bool videoInput::getPixels(int deviceID, unsigned char * dstBuffer, bool flipRedAndBlue, bool flipImage) 3470{ 3471 bool success = false; 3472 if (deviceID < 0) 3473 { 3474 DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", deviceID); 3475 return success; 3476 } 3477 if(accessToDevices) 3478 { 3479 bool isRaw = isDeviceRawDataSource(deviceID); 3480 if(isRaw) 3481 { 3482 videoDevice *VD = videoDevices::getInstance().getDevice(deviceID); 3483 RawImage *RIOut = VD->getRawImageOut(); 3484 if(RIOut) 3485 { 3486 const unsigned int bytes = 3; 3487 const unsigned int height = VD->getHeight(); 3488 const unsigned int width = VD->getWidth(); 3489 const unsigned int size = bytes * width * height; 3490 if(size == RIOut->getSize()) 3491 { 3492 processPixels(RIOut->getpPixels(), dstBuffer, width, height, bytes, flipRedAndBlue, flipImage); 3493 success = true; 3494 } 3495 else 3496 { 3497 DebugPrintOut(L"ERROR: GetPixels() - bufferSizes do not match!\n"); 3498 } 3499 } 3500 else 3501 { 3502 DebugPrintOut(L"ERROR: GetPixels() - Unable to grab frame for device %i\n", deviceID); 3503 } 3504 } 3505 else 3506 { 3507 DebugPrintOut(L"ERROR: GetPixels() - Not raw data source device %i\n", deviceID); 3508 } 3509 } 3510 else 3511 { 3512 DebugPrintOut(L"VIDEODEVICE(s): There is not any suitable video device\n"); 3513 } 3514 return success; 3515} 3516 3517void videoInput::processPixels(unsigned char * src, unsigned char * dst, unsigned int width, 3518 unsigned int height, unsigned int bpp, bool bRGB, bool bFlip) 3519{ 3520 unsigned int widthInBytes = width * bpp; 3521 unsigned int numBytes = widthInBytes * height; 3522 int *dstInt, *srcInt; 3523 if(!bRGB) 3524 { 3525 if(bFlip) 3526 { 3527 for(unsigned int y = 0; y < height; y++) 3528 { 3529 dstInt = (int *)(dst + (y * widthInBytes)); 3530 srcInt = (int *)(src + ( (height -y -1) * widthInBytes)); 3531 memcpy(dstInt, srcInt, widthInBytes); 3532 } 3533 } 3534 else 3535 { 3536 memcpy(dst, src, numBytes); 3537 } 3538 } 3539 else 3540 { 3541 if(bFlip) 3542 { 3543 unsigned int x = 0; 3544 unsigned int y = (height - 1) * widthInBytes; 3545 src += y; 3546 for(unsigned int i = 0; i < numBytes; i+=3) 3547 { 3548 if(x >= width) 3549 { 3550 x = 0; 3551 src -= widthInBytes*2; 3552 } 3553 *dst = *(src+2); 3554 dst++; 3555 *dst = *(src+1); 3556 dst++; 3557 *dst = *src; 3558 dst++; 3559 src+=3; 3560 x++; 3561 } 3562 } 3563 else 3564 { 3565 for(unsigned int i = 0; i < numBytes; i+=3) 3566 { 3567 *dst = *(src+2); 3568 dst++; 3569 *dst = *(src+1); 3570 dst++; 3571 *dst = *src; 3572 dst++; 3573 src+=3; 3574 } 3575 } 3576 } 3577} 3578} 3579 3580/******* Capturing video from camera via Microsoft Media Foundation **********/ 3581class CvCaptureCAM_MSMF : public CvCapture 3582{ 3583public: 3584 CvCaptureCAM_MSMF(); 3585 virtual ~CvCaptureCAM_MSMF(); 3586 virtual bool open( int index ); 3587 virtual void close(); 3588 virtual double getProperty(int) const; 3589 virtual bool setProperty(int, double); 3590 virtual bool grabFrame(); 3591 virtual IplImage* retrieveFrame(int); 3592 virtual int getCaptureDomain() { return CV_CAP_MSMF; } // Return the type of the capture object: CV_CAP_VFW, etc... 3593protected: 3594 void init(); 3595 int index, width, height, fourcc; 3596 IplImage* frame; 3597 videoInput VI; 3598#ifdef WINRT 3599#ifdef HAVE_CONCURRENCY 3600 DEFINE_TASK<bool> openTask; 3601 Concurrency::critical_section lock; 3602#endif 3603#endif 3604}; 3605 3606#ifdef _DEBUG 3607struct SuppressVideoInputMessages 3608{ 3609 SuppressVideoInputMessages() { videoInput::setVerbose(true); } 3610}; 3611 3612static SuppressVideoInputMessages do_it; 3613#endif 3614 3615CvCaptureCAM_MSMF::CvCaptureCAM_MSMF(): 3616 index(-1), 3617 width(-1), 3618 height(-1), 3619 fourcc(-1), 3620 frame(NULL), 3621 VI(videoInput::getInstance()) 3622{ 3623 CoInitialize(0); 3624} 3625 3626CvCaptureCAM_MSMF::~CvCaptureCAM_MSMF() 3627{ 3628 close(); 3629 CoUninitialize(); 3630} 3631 3632void CvCaptureCAM_MSMF::close() 3633{ 3634 if( index >= 0 ) 3635 { 3636 VI.closeDevice(index); 3637 index = -1; 3638 cvReleaseImage(&frame); 3639 } 3640 width = height = -1; 3641} 3642 3643// Initialize camera input 3644bool CvCaptureCAM_MSMF::open( int _index ) 3645{ 3646#ifdef WINRT 3647#ifdef HAVE_CONCURRENCY 3648 SAVE_CURRENT_CONTEXT(context); 3649 auto func = [_index, context, this](DEFINE_RET_VAL(bool)) -> DEFINE_RET_FORMAL(bool) { 3650#endif 3651#endif 3652 int try_index = _index; 3653 int devices = 0; 3654 close(); 3655 devices = VI.listDevices(true); 3656 if (devices == 0) 3657 return false; 3658 try_index = try_index < 0 ? 0 : (try_index > devices-1 ? devices-1 : try_index); 3659#ifdef WINRT 3660 HRESULT hr; 3661#ifdef HAVE_CONCURRENCY 3662 BEGIN_CALL_IN_CONTEXT(hr, context, this, try_index) 3663#endif 3664#endif 3665 VI.setupDevice(try_index, 0, 0, 0); // With maximum frame size. 3666#ifdef WINRT 3667#ifdef HAVE_CONCURRENCY 3668 END_CALL_IN_CONTEXT_BASE 3669 VI.waitForDevice(try_index); 3670 BEGIN_CALL_IN_CONTEXT(hr, context, this, try_index) 3671 HRESULT hr = S_OK; 3672#endif 3673#endif 3674 if( !VI.isFrameNew(try_index) ) 3675#ifdef WINRT 3676 hr = E_FAIL; 3677#else 3678 return false; 3679#endif 3680 index = try_index; 3681#ifdef WINRT 3682#ifdef HAVE_CONCURRENCY 3683 END_CALL_IN_CONTEXT_BASE 3684 RET_VAL(true) 3685 }; 3686 Concurrency::critical_section::scoped_lock _LockHolder(lock); 3687 CREATE_OR_CONTINUE_TASK(openTask, bool, func) 3688#endif 3689#endif 3690 return true; 3691} 3692 3693bool CvCaptureCAM_MSMF::grabFrame() 3694{ 3695 while (VI.isDeviceSetup(index) && !VI.isFrameNew(index)) 3696 Sleep(1); 3697 return VI.isDeviceSetup(index); 3698} 3699 3700IplImage* CvCaptureCAM_MSMF::retrieveFrame(int) 3701{ 3702 const int w = (int)VI.getWidth(index); 3703 const int h = (int)VI.getHeight(index); 3704 if( !frame || w != frame->width || h != frame->height ) 3705 { 3706 if (frame) 3707 cvReleaseImage( &frame ); 3708 frame = cvCreateImage( cvSize(w,h), 8, 3 ); 3709 } 3710 VI.getPixels( index, (uchar*)frame->imageData, false, true ); 3711 return frame; 3712} 3713 3714double CvCaptureCAM_MSMF::getProperty( int property_id ) const 3715{ 3716 // image format proprrties 3717 switch( property_id ) 3718 { 3719 case CV_CAP_PROP_FRAME_WIDTH: 3720 return VI.getWidth(index); 3721 case CV_CAP_PROP_FRAME_HEIGHT: 3722 return VI.getHeight(index); 3723 case CV_CAP_PROP_FPS: 3724 return VI.getFrameRate(index); 3725 default: 3726 break; 3727 } 3728 return 0; 3729} 3730bool CvCaptureCAM_MSMF::setProperty( int property_id, double value ) 3731{ 3732 // image capture properties 3733 unsigned int fps = 0; 3734 bool handled = false; 3735 switch( property_id ) 3736 { 3737 case CV_CAP_PROP_FRAME_WIDTH: 3738 width = cvRound(value); 3739 fps = VI.getFrameRate(index); 3740 handled = true; 3741 break; 3742 case CV_CAP_PROP_FRAME_HEIGHT: 3743 height = cvRound(value); 3744 fps = VI.getFrameRate(index); 3745 handled = true; 3746 break; 3747 case CV_CAP_PROP_FPS: 3748 width = (int)VI.getHeight(index); 3749 height = (int)VI.getWidth(index); 3750 fps = cvRound(value); 3751 break; 3752 } 3753 3754 if ( handled ) { 3755 if( width > 0 && height > 0 ) 3756 { 3757 if( (width != (int)VI.getWidth(index) || height != (int)VI.getHeight(index) || fps != VI.getFrameRate(index)) 3758 && VI.isDeviceSetup(index))//|| fourcc != VI.getFourcc(index) ) 3759 { 3760 VI.closeDevice(index); 3761 VI.setupDevice(index, width, height, fps); 3762 } 3763 width = height = -1; 3764 return VI.isDeviceSetup(index); 3765 } 3766 return true; 3767 } 3768 3769 return false; 3770} 3771 3772class CvCaptureFile_MSMF : public CvCapture 3773{ 3774public: 3775 CvCaptureFile_MSMF(); 3776 virtual ~CvCaptureFile_MSMF(); 3777 3778 virtual bool open( const char* filename ); 3779 virtual void close(); 3780 3781 virtual double getProperty(int) const; 3782 virtual bool setProperty(int, double); 3783 virtual bool grabFrame(); 3784 virtual IplImage* retrieveFrame(int); 3785 virtual int getCaptureDomain() { return CV_CAP_MSMF; } 3786protected: 3787 ImageGrabberThread* grabberThread; 3788 IMFMediaSource* videoFileSource; 3789 std::vector<MediaType> captureFormats; 3790 int captureFormatIndex; 3791 IplImage* frame; 3792 bool isOpened; 3793 3794 HRESULT enumerateCaptureFormats(IMFMediaSource *pSource); 3795 HRESULT getSourceDuration(IMFMediaSource *pSource, MFTIME *pDuration) const; 3796}; 3797 3798CvCaptureFile_MSMF::CvCaptureFile_MSMF(): 3799 grabberThread(NULL), 3800 videoFileSource(NULL), 3801 captureFormatIndex(0), 3802 frame(NULL), 3803 isOpened(false) 3804{ 3805 MFStartup(MF_VERSION); 3806} 3807 3808CvCaptureFile_MSMF::~CvCaptureFile_MSMF() 3809{ 3810 close(); 3811 MFShutdown(); 3812} 3813 3814bool CvCaptureFile_MSMF::open(const char* filename) 3815{ 3816 if (!filename) 3817 return false; 3818 3819 wchar_t* unicodeFileName = new wchar_t[strlen(filename)+1]; 3820 MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, (int)strlen(filename)+1); 3821 3822 MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID; 3823 3824 _ComPtr<IMFSourceResolver> pSourceResolver = NULL; 3825 IUnknown* pUnkSource = NULL; 3826 3827 HRESULT hr = MFCreateSourceResolver(pSourceResolver.GetAddressOf()); 3828 3829 if (SUCCEEDED(hr)) 3830 { 3831 hr = pSourceResolver->CreateObjectFromURL( 3832 unicodeFileName, 3833 MF_RESOLUTION_MEDIASOURCE, 3834 NULL, // Optional property store. 3835 &ObjectType, 3836 &pUnkSource 3837 ); 3838 } 3839 3840 // Get the IMFMediaSource from the IUnknown pointer. 3841 if (SUCCEEDED(hr)) 3842 { 3843 hr = pUnkSource->QueryInterface(IID_PPV_ARGS(&videoFileSource)); 3844 } 3845 3846 SafeRelease(&pUnkSource); 3847 3848 if (SUCCEEDED(hr)) 3849 { 3850 hr = enumerateCaptureFormats(videoFileSource); 3851 } 3852 3853 if( captureFormats.empty() ) 3854 { 3855 isOpened = false; 3856 } 3857 else 3858 { 3859 if (SUCCEEDED(hr)) 3860 { 3861 hr = ImageGrabberThread::CreateInstance(&grabberThread, videoFileSource, (unsigned int)-2, true); 3862 } 3863 3864 isOpened = SUCCEEDED(hr); 3865 } 3866 3867 if (isOpened) 3868 { 3869 grabberThread->start(); 3870 } 3871 3872 return isOpened; 3873} 3874 3875void CvCaptureFile_MSMF::close() 3876{ 3877 if (grabberThread) 3878 { 3879 isOpened = false; 3880 SetEvent(grabberThread->getImageGrabber()->ig_hFinish); 3881 grabberThread->stop(); 3882 delete grabberThread; 3883 } 3884 3885 if (videoFileSource) 3886 { 3887 videoFileSource->Shutdown(); 3888 } 3889} 3890 3891bool CvCaptureFile_MSMF::setProperty(int property_id, double value) 3892{ 3893 // image capture properties 3894 // FIXME: implement method in VideoInput back end 3895 (void) property_id; 3896 (void) value; 3897 return false; 3898} 3899 3900double CvCaptureFile_MSMF::getProperty(int property_id) const 3901{ 3902 // image format proprrties 3903 switch( property_id ) 3904 { 3905 case CV_CAP_PROP_FRAME_WIDTH: 3906 return captureFormats[captureFormatIndex].width; 3907 case CV_CAP_PROP_FRAME_HEIGHT: 3908 return captureFormats[captureFormatIndex].height; 3909 case CV_CAP_PROP_FRAME_COUNT: 3910 { 3911 MFTIME duration; 3912 getSourceDuration(this->videoFileSource, &duration); 3913 double fps = ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_NUMERATOR) / 3914 ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_DENOMINATOR); 3915 return (double)floor(((double)duration/1e7)*fps+0.5); 3916 } 3917 case CV_CAP_PROP_FOURCC: 3918 return captureFormats[captureFormatIndex].MF_MT_SUBTYPE.Data1; 3919 case CV_CAP_PROP_FPS: 3920 return ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_NUMERATOR) / 3921 ((double)captureFormats[captureFormatIndex].MF_MT_FRAME_RATE_DENOMINATOR); 3922 } 3923 3924 return -1; 3925} 3926 3927bool CvCaptureFile_MSMF::grabFrame() 3928{ 3929 DWORD waitResult = (DWORD)-1; 3930 if (isOpened) 3931 { 3932 SetEvent(grabberThread->getImageGrabber()->ig_hFrameGrabbed); 3933 HANDLE tmp[] = {grabberThread->getImageGrabber()->ig_hFrameReady, grabberThread->getImageGrabber()->ig_hFinish, 0}; 3934 waitResult = WaitForMultipleObjects(2, tmp, FALSE, INFINITE); 3935 } 3936 3937 return isOpened && grabberThread->getImageGrabber()->getRawImage()->isNew() && (waitResult == WAIT_OBJECT_0); 3938} 3939 3940IplImage* CvCaptureFile_MSMF::retrieveFrame(int) 3941{ 3942 unsigned int width = captureFormats[captureFormatIndex].width; 3943 unsigned int height = captureFormats[captureFormatIndex].height; 3944 unsigned int bytes = 3; 3945 if( !frame || (int)width != frame->width || (int)height != frame->height ) 3946 { 3947 if (frame) 3948 cvReleaseImage( &frame ); 3949 frame = cvCreateImage( cvSize(width,height), 8, 3 ); 3950 } 3951 3952 RawImage *RIOut = grabberThread->getImageGrabber()->getRawImage(); 3953 unsigned int size = bytes * width * height; 3954 3955 bool verticalFlip = captureFormats[captureFormatIndex].MF_MT_DEFAULT_STRIDE < 0; 3956 3957 if(RIOut && size == RIOut->getSize()) 3958 { 3959 videoInput::processPixels(RIOut->getpPixels(), (unsigned char*)frame->imageData, width, 3960 height, bytes, false, verticalFlip); 3961 } 3962 3963 return frame; 3964} 3965 3966HRESULT CvCaptureFile_MSMF::enumerateCaptureFormats(IMFMediaSource *pSource) 3967{ 3968 _ComPtr<IMFPresentationDescriptor> pPD = NULL; 3969 _ComPtr<IMFStreamDescriptor> pSD = NULL; 3970 _ComPtr<IMFMediaTypeHandler> pHandler = NULL; 3971 _ComPtr<IMFMediaType> pType = NULL; 3972 HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); 3973 if (FAILED(hr)) 3974 { 3975 goto done; 3976 } 3977 3978 BOOL fSelected; 3979 hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf()); 3980 if (FAILED(hr)) 3981 { 3982 goto done; 3983 } 3984 hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf()); 3985 if (FAILED(hr)) 3986 { 3987 goto done; 3988 } 3989 DWORD cTypes = 0; 3990 hr = pHandler->GetMediaTypeCount(&cTypes); 3991 if (FAILED(hr)) 3992 { 3993 goto done; 3994 } 3995 for (DWORD i = 0; i < cTypes; i++) 3996 { 3997 hr = pHandler->GetMediaTypeByIndex(i, pType.GetAddressOf()); 3998 if (FAILED(hr)) 3999 { 4000 goto done; 4001 } 4002 MediaType MT = FormatReader::Read(pType.Get()); 4003 // We can capture only RGB video. 4004 if( MT.MF_MT_SUBTYPE == MFVideoFormat_RGB24 ) 4005 captureFormats.push_back(MT); 4006 } 4007 4008done: 4009 return hr; 4010} 4011 4012HRESULT CvCaptureFile_MSMF::getSourceDuration(IMFMediaSource *pSource, MFTIME *pDuration) const 4013{ 4014 *pDuration = 0; 4015 4016 IMFPresentationDescriptor *pPD = NULL; 4017 4018 HRESULT hr = pSource->CreatePresentationDescriptor(&pPD); 4019 if (SUCCEEDED(hr)) 4020 { 4021 hr = pPD->GetUINT64(MF_PD_DURATION, (UINT64*)pDuration); 4022 pPD->Release(); 4023 } 4024 return hr; 4025} 4026 4027CvCapture* cvCreateCameraCapture_MSMF( int index ) 4028{ 4029 CvCaptureCAM_MSMF* capture = new CvCaptureCAM_MSMF; 4030 try 4031 { 4032 if( capture->open( index )) 4033 return capture; 4034 } 4035 catch(...) 4036 { 4037 delete capture; 4038 throw; 4039 } 4040 delete capture; 4041 return 0; 4042} 4043 4044CvCapture* cvCreateFileCapture_MSMF (const char* filename) 4045{ 4046 CvCaptureFile_MSMF* capture = new CvCaptureFile_MSMF; 4047 try 4048 { 4049 if( capture->open(filename) ) 4050 return capture; 4051 else 4052 { 4053 delete capture; 4054 return NULL; 4055 } 4056 } 4057 catch(...) 4058 { 4059 delete capture; 4060 throw; 4061 } 4062} 4063 4064// 4065// 4066// Media Foundation-based Video Writer 4067// 4068// 4069 4070class CvVideoWriter_MSMF : public CvVideoWriter 4071{ 4072public: 4073 CvVideoWriter_MSMF(); 4074 virtual ~CvVideoWriter_MSMF(); 4075 virtual bool open(const char* filename, int fourcc, 4076 double fps, CvSize frameSize, bool isColor); 4077 virtual void close(); 4078 virtual bool writeFrame(const IplImage* img); 4079 4080private: 4081 UINT32 videoWidth; 4082 UINT32 videoHeight; 4083 double fps; 4084 UINT32 bitRate; 4085 UINT32 frameSize; 4086 GUID encodingFormat; 4087 GUID inputFormat; 4088 4089 DWORD streamIndex; 4090 _ComPtr<IMFSinkWriter> sinkWriter; 4091 4092 bool initiated; 4093 4094 LONGLONG rtStart; 4095 UINT64 rtDuration; 4096 4097 HRESULT InitializeSinkWriter(const char* filename); 4098 static const GUID FourCC2GUID(int fourcc); 4099 HRESULT WriteFrame(DWORD *videoFrameBuffer, const LONGLONG& rtStart, const LONGLONG& rtDuration); 4100}; 4101 4102CvVideoWriter_MSMF::CvVideoWriter_MSMF(): 4103 initiated(false) 4104{ 4105} 4106 4107CvVideoWriter_MSMF::~CvVideoWriter_MSMF() 4108{ 4109 close(); 4110} 4111 4112const GUID CvVideoWriter_MSMF::FourCC2GUID(int fourcc) 4113{ 4114 switch(fourcc) 4115 { 4116 case CV_FOURCC_MACRO('d', 'v', '2', '5'): 4117 return MFVideoFormat_DV25; break; 4118 case CV_FOURCC_MACRO('d', 'v', '5', '0'): 4119 return MFVideoFormat_DV50; break; 4120 case CV_FOURCC_MACRO('d', 'v', 'c', ' '): 4121 return MFVideoFormat_DVC; break; 4122 case CV_FOURCC_MACRO('d', 'v', 'h', '1'): 4123 return MFVideoFormat_DVH1; break; 4124 case CV_FOURCC_MACRO('d', 'v', 'h', 'd'): 4125 return MFVideoFormat_DVHD; break; 4126 case CV_FOURCC_MACRO('d', 'v', 's', 'd'): 4127 return MFVideoFormat_DVSD; break; 4128 case CV_FOURCC_MACRO('d', 'v', 's', 'l'): 4129 return MFVideoFormat_DVSL; break; 4130#if (WINVER >= 0x0602) 4131 case CV_FOURCC_MACRO('H', '2', '6', '3'): // Available only for Win 8 target. 4132 return MFVideoFormat_H263; break; 4133#endif 4134 case CV_FOURCC_MACRO('H', '2', '6', '4'): 4135 return MFVideoFormat_H264; break; 4136 case CV_FOURCC_MACRO('M', '4', 'S', '2'): 4137 return MFVideoFormat_M4S2; break; 4138 case CV_FOURCC_MACRO('M', 'J', 'P', 'G'): 4139 return MFVideoFormat_MJPG; break; 4140 case CV_FOURCC_MACRO('M', 'P', '4', '3'): 4141 return MFVideoFormat_MP43; break; 4142 case CV_FOURCC_MACRO('M', 'P', '4', 'S'): 4143 return MFVideoFormat_MP4S; break; 4144 case CV_FOURCC_MACRO('M', 'P', '4', 'V'): 4145 return MFVideoFormat_MP4V; break; 4146 case CV_FOURCC_MACRO('M', 'P', 'G', '1'): 4147 return MFVideoFormat_MPG1; break; 4148 case CV_FOURCC_MACRO('M', 'S', 'S', '1'): 4149 return MFVideoFormat_MSS1; break; 4150 case CV_FOURCC_MACRO('M', 'S', 'S', '2'): 4151 return MFVideoFormat_MSS2; break; 4152 case CV_FOURCC_MACRO('W', 'M', 'V', '1'): 4153 return MFVideoFormat_WMV1; break; 4154 case CV_FOURCC_MACRO('W', 'M', 'V', '2'): 4155 return MFVideoFormat_WMV2; break; 4156 case CV_FOURCC_MACRO('W', 'M', 'V', '3'): 4157 return MFVideoFormat_WMV3; break; 4158 case CV_FOURCC_MACRO('W', 'V', 'C', '1'): 4159 return MFVideoFormat_WVC1; break; 4160 default: 4161 return MFVideoFormat_H264; 4162 } 4163} 4164 4165bool CvVideoWriter_MSMF::open( const char* filename, int fourcc, 4166 double _fps, CvSize frameSize, bool /*isColor*/ ) 4167{ 4168 videoWidth = frameSize.width; 4169 videoHeight = frameSize.height; 4170 fps = _fps; 4171 bitRate = (UINT32)fps*videoWidth*videoHeight; // 1-bit per pixel 4172 encodingFormat = FourCC2GUID(fourcc); 4173 inputFormat = MFVideoFormat_RGB32; 4174 4175 HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 4176 if (SUCCEEDED(hr)) 4177 { 4178 hr = MFStartup(MF_VERSION); 4179 if (SUCCEEDED(hr)) 4180 { 4181 hr = InitializeSinkWriter(filename); 4182 if (SUCCEEDED(hr)) 4183 { 4184 initiated = true; 4185 rtStart = 0; 4186 MFFrameRateToAverageTimePerFrame((UINT32)fps, 1, &rtDuration); 4187 } 4188 } 4189 } 4190 4191 return SUCCEEDED(hr); 4192} 4193 4194void CvVideoWriter_MSMF::close() 4195{ 4196 if (!initiated) 4197 { 4198 return; 4199 } 4200 4201 initiated = false; 4202 sinkWriter->Finalize(); 4203 MFShutdown(); 4204} 4205 4206bool CvVideoWriter_MSMF::writeFrame(const IplImage* img) 4207{ 4208 if (!img) 4209 return false; 4210 4211 int length = img->width * img->height * 4; 4212 DWORD* target = new DWORD[length]; 4213 4214 for (int rowIdx = 0; rowIdx < img->height; rowIdx++) 4215 { 4216 char* rowStart = img->imageData + rowIdx*img->widthStep; 4217 for (int colIdx = 0; colIdx < img->width; colIdx++) 4218 { 4219 BYTE b = rowStart[colIdx * img->nChannels + 0]; 4220 BYTE g = rowStart[colIdx * img->nChannels + 1]; 4221 BYTE r = rowStart[colIdx * img->nChannels + 2]; 4222 4223 target[rowIdx*img->width+colIdx] = (r << 16) + (g << 8) + b; 4224 } 4225 } 4226 4227 // Send frame to the sink writer. 4228 HRESULT hr = WriteFrame(target, rtStart, rtDuration); 4229 if (FAILED(hr)) 4230 { 4231 delete[] target; 4232 return false; 4233 } 4234 rtStart += rtDuration; 4235 4236 delete[] target; 4237 4238 return true; 4239} 4240 4241HRESULT CvVideoWriter_MSMF::InitializeSinkWriter(const char* filename) 4242{ 4243 _ComPtr<IMFAttributes> spAttr; 4244 _ComPtr<IMFMediaType> mediaTypeOut; 4245 _ComPtr<IMFMediaType> mediaTypeIn; 4246 _ComPtr<IMFByteStream> spByteStream; 4247 4248 MFCreateAttributes(&spAttr, 10); 4249 spAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true); 4250 4251 wchar_t* unicodeFileName = new wchar_t[strlen(filename)+1]; 4252 MultiByteToWideChar(CP_ACP, 0, filename, -1, unicodeFileName, (int)strlen(filename)+1); 4253 4254 HRESULT hr = MFCreateSinkWriterFromURL(unicodeFileName, NULL, spAttr.Get(), &sinkWriter); 4255 4256 delete[] unicodeFileName; 4257 4258 // Set the output media type. 4259 if (SUCCEEDED(hr)) 4260 { 4261 hr = MFCreateMediaType(&mediaTypeOut); 4262 } 4263 if (SUCCEEDED(hr)) 4264 { 4265 hr = mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); 4266 } 4267 if (SUCCEEDED(hr)) 4268 { 4269 hr = mediaTypeOut->SetGUID(MF_MT_SUBTYPE, encodingFormat); 4270 } 4271 if (SUCCEEDED(hr)) 4272 { 4273 hr = mediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, bitRate); 4274 } 4275 if (SUCCEEDED(hr)) 4276 { 4277 hr = mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); 4278 } 4279 if (SUCCEEDED(hr)) 4280 { 4281 hr = MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight); 4282 } 4283 if (SUCCEEDED(hr)) 4284 { 4285 hr = MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1); 4286 } 4287 if (SUCCEEDED(hr)) 4288 { 4289 hr = MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1); 4290 } 4291 4292 if (SUCCEEDED(hr)) 4293 { 4294 hr = sinkWriter->AddStream(mediaTypeOut.Get(), &streamIndex); 4295 } 4296 4297 // Set the input media type. 4298 if (SUCCEEDED(hr)) 4299 { 4300 hr = MFCreateMediaType(&mediaTypeIn); 4301 } 4302 if (SUCCEEDED(hr)) 4303 { 4304 hr = mediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); 4305 } 4306 if (SUCCEEDED(hr)) 4307 { 4308 hr = mediaTypeIn->SetGUID(MF_MT_SUBTYPE, inputFormat); 4309 } 4310 if (SUCCEEDED(hr)) 4311 { 4312 hr = mediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); 4313 } 4314 if (SUCCEEDED(hr)) 4315 { 4316 hr = MFSetAttributeSize(mediaTypeIn.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight); 4317 } 4318 if (SUCCEEDED(hr)) 4319 { 4320 hr = MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1); 4321 } 4322 if (SUCCEEDED(hr)) 4323 { 4324 hr = MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1); 4325 } 4326 4327 if (SUCCEEDED(hr)) 4328 { 4329 hr = sinkWriter->SetInputMediaType(streamIndex, mediaTypeIn.Get(), NULL); 4330 } 4331 4332 // Tell the sink writer to start accepting data. 4333 if (SUCCEEDED(hr)) 4334 { 4335 hr = sinkWriter->BeginWriting(); 4336 } 4337 4338 return hr; 4339} 4340 4341HRESULT CvVideoWriter_MSMF::WriteFrame(DWORD *videoFrameBuffer, const LONGLONG& Start, const LONGLONG& Duration) 4342{ 4343 _ComPtr<IMFSample> sample; 4344 _ComPtr<IMFMediaBuffer> buffer; 4345 4346 const LONG cbWidth = 4 * videoWidth; 4347 const DWORD cbBuffer = cbWidth * videoHeight; 4348 4349 BYTE *pData = NULL; 4350 4351 // Create a new memory buffer. 4352 HRESULT hr = MFCreateMemoryBuffer(cbBuffer, &buffer); 4353 4354 // Lock the buffer and copy the video frame to the buffer. 4355 if (SUCCEEDED(hr)) 4356 { 4357 hr = buffer->Lock(&pData, NULL, NULL); 4358 } 4359 4360 if (SUCCEEDED(hr)) 4361 { 4362#if defined(_M_ARM) 4363 hr = MFCopyImage( 4364 pData, // Destination buffer. 4365 -cbWidth, // Destination stride. 4366 (BYTE*)videoFrameBuffer, // First row in source image. 4367 cbWidth, // Source stride. 4368 cbWidth, // Image width in bytes. 4369 videoHeight // Image height in pixels. 4370 ); 4371#else 4372 hr = MFCopyImage( 4373 pData, // Destination buffer. 4374 cbWidth, // Destination stride. 4375 (BYTE*)videoFrameBuffer, // First row in source image. 4376 cbWidth, // Source stride. 4377 cbWidth, // Image width in bytes. 4378 videoHeight // Image height in pixels. 4379 ); 4380#endif 4381 } 4382 4383 if (buffer) 4384 { 4385 buffer->Unlock(); 4386 } 4387 4388 // Set the data length of the buffer. 4389 if (SUCCEEDED(hr)) 4390 { 4391 hr = buffer->SetCurrentLength(cbBuffer); 4392 } 4393 4394 // Create a media sample and add the buffer to the sample. 4395 if (SUCCEEDED(hr)) 4396 { 4397 hr = MFCreateSample(&sample); 4398 } 4399 if (SUCCEEDED(hr)) 4400 { 4401 hr = sample->AddBuffer(buffer.Get()); 4402 } 4403 4404 // Set the time stamp and the duration. 4405 if (SUCCEEDED(hr)) 4406 { 4407 hr = sample->SetSampleTime(Start); 4408 } 4409 if (SUCCEEDED(hr)) 4410 { 4411 hr = sample->SetSampleDuration(Duration); 4412 } 4413 4414 // Send the sample to the Sink Writer. 4415 if (SUCCEEDED(hr)) 4416 { 4417 hr = sinkWriter->WriteSample(streamIndex, sample.Get()); 4418 } 4419 4420 return hr; 4421} 4422 4423CvVideoWriter* cvCreateVideoWriter_MSMF( const char* filename, int fourcc, 4424 double fps, CvSize frameSize, int isColor ) 4425{ 4426 CvVideoWriter_MSMF* writer = new CvVideoWriter_MSMF; 4427 if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 )) 4428 return writer; 4429 delete writer; 4430 return NULL; 4431} 4432 4433#endif 4434