感觉Microsoft Source Reader还是比较坑的,只是由于需要,不得不使用。其实按照Microsoft提供的示例,基本上可以正常的调试出程序来。
下面的例子,简单的给出了Source Reader的代码。同时,HRESULT CreateVideoDeviceSource(IMFMediaSource **ppSource)函数中,使用了指针的指针,能正确的传出ppSource,不是NULL。之前调试时,使用HRESULT CreateVideoDeviceSource(IMFMediaSource *ppSource),出来后,ppSource依旧为NULL。后来直接把代码展开,没有继续深入考虑。感谢前两天@wuruifang 的建议,之后在网上搜了一下,指针的指针可以使得输入参数为NULL时输出正常。因而此处重新写成一个函数(以前不清楚为啥用指针的指针时出错,现在倒是没有)。
主要代码:
1 int _tmain(int argc, _TCHAR* argv[]) 2 { 3 IMFMediaSource *ppSource = NULL; 4 CreateVideoDeviceSource(&ppSource); 5 6 // hr = EnumerateCaptureFormats(ppSource); // This can show the formats the camera support. Notice that output window of visual studio shows the infomation. 7 // if (FAILED(hr)) 8 // abort(); 9 HRESULT hr; 10 IMFSourceReader *pReader; 11 hr = MFCreateSourceReaderFromMediaSource(ppSource, NULL, &pReader); 12 if (FAILED(hr)) 13 abort(); 14 15 hr = SetDeviceFormat(ppSource, 6); //I need to configure the camera to format 6. 16 if (FAILED(hr)) 17 abort(); 18 19 ProcessSamples(pReader); 20 21 SafeRelease(&pReader); 22 SafeRelease(&ppSource); 23 MFShutdown(); 24 CoUninitialize(); 25 } 26 27 HRESULT ProcessSamples(IMFSourceReader *pReader) 28 { 29 HRESULT hr = S_OK; 30 IMFSample *pSample = NULL; 31 size_t cSamples = 0; 32 33 _LARGE_INTEGER time_start; /*begin time */ 34 _LARGE_INTEGER time_over; /*end time*/ 35 double dqFreq; /*timer frequence*/ 36 LARGE_INTEGER f; /*timer frequence*/ 37 QueryPerformanceFrequency(&f); 38 dqFreq = (double)f.QuadPart; 39 40 QueryPerformanceCounter(&time_start); 41 42 43 bool quit = false; 44 while (!quit) 45 { 46 DWORD streamIndex, flags; 47 LONGLONG llTimeStamp; 48 49 hr = pReader->ReadSample( 50 MF_SOURCE_READER_ANY_STREAM, // Stream index. 51 0, // Flags. 52 &streamIndex, // Receives the actual stream index. 53 &flags, // Receives status flags. 54 &llTimeStamp, // Receives the time stamp. 55 &pSample // Receives the sample or NULL. 56 ); 57 58 if (FAILED(hr)) 59 break; 60 61 if (flags & MF_SOURCE_READERF_ENDOFSTREAM) 62 { 63 wprintf(L"\tEnd of stream\n"); 64 quit = true; 65 } 66 67 if (pSample) 68 { 69 BYTE* data; 70 IMFMediaBuffer* buffer; 71 DWORD max, current; 72 73 // printf(" cSamples = %d\n", cSamples); 74 ++cSamples; 75 pSample->GetBufferByIndex(0, &buffer); 76 buffer->Lock(&data, &max, ¤t); 77 78 // saveBMP(data, cSamples, IMGWIDTH, IMGHEIGHT); 79 80 buffer->Unlock(); 81 SafeRelease(&buffer); 82 83 QueryPerformanceCounter(&time_over); //In order to find the frames per second of the camera. 84 double usedtime = ((time_over.QuadPart - time_start.QuadPart) / dqFreq); 85 if (usedtime>1) 86 { 87 printf(" cSamples = %d\n", cSamples); 88 cSamples = 0; 89 QueryPerformanceCounter(&time_start); 90 } 91 } 92 SafeRelease(&pSample); 93 } 94 95 SafeRelease(&pSample); 96 return hr; 97 } 98 99 HRESULT CreateVideoDeviceSource(IMFMediaSource **ppSource) 100 { 101 HRESULT hr; 102 hr = CoInitialize(NULL); 103 if (FAILED(hr)) 104 abort(); 105 hr = MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET); 106 if (FAILED(hr)) 107 abort(); 108 109 *ppSource = NULL; 110 111 IMFMediaSource *pSource = NULL; 112 IMFAttributes *pAttributes = NULL; 113 IMFActivate **ppDevices = NULL; 114 115 // Create an attribute store to specify the enumeration parameters. 116 /*HRESULT*/ hr = MFCreateAttributes(&pAttributes, 1); 117 if (FAILED(hr)) 118 abort(); 119 120 // Source type: video capture devices 121 hr = pAttributes->SetGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, 122 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID ); 123 if (FAILED(hr)) 124 abort(); 125 126 // Enumerate devices. 127 UINT32 count; 128 hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count); 129 if (FAILED(hr)) 130 abort(); 131 if (count == 0) 132 { 133 hr = E_FAIL; 134 return hr; 135 } 136 137 // Create the media source object. 138 hr = ppDevices[0]->ActivateObject(IID_PPV_ARGS(&pSource)); 139 if (FAILED(hr)) 140 abort(); 141 142 *ppSource = pSource; 143 (*ppSource)->AddRef(); 144 145 // release part 146 SafeRelease(&pAttributes); 147 148 for (DWORD i = 0; i < count; i++) 149 { 150 SafeRelease(&ppDevices[i]); 151 } 152 CoTaskMemFree(ppDevices); 153 SafeRelease(&pSource); //此处不确定,是否需要SafeRelease。 154 return hr; 155 }
得到的图片(程序中保存的是BMP图片,由于cnblogs不支持BMP,因而转成jpg):
完整代码(不会插入超链接,抱歉)见:https://github.com/darkknightzh/Microsoft-Source-Reader
参考(其他的记不清了,见谅):
Microsoft :http://msdn.microsoft.com/en-us/library/windows/desktop/dd389281(v=vs.85).aspx
指针的指针(详见4楼,14楼) :http://bbs.csdn.net/topics/210076970