网上很多讲解directshow的资料,讲的都很好,但是就想说各位老大们···上份简单的代码吧,快速开发中 不一定有时间仔细阅读那么多页的文档,对着文档一段段的copy函数也很烦躁,今天我自己传一份directshow获取本地话筒录音的代码。用的时候记得插话筒。
- #include "stdafx.h"
- #include <dshow.h>
- #include <atlconv.h>
- #define OUTPUT_PIN 1
- #define OUTPUT_MEDIATYPE 1
- char* GuidToString(const GUID &guid)
- {
- int buf_len=64;
- char *buf =(char *)malloc(buf_len);
- _snprintf(
- buf,
- buf_len,
- "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
- guid.Data1, guid.Data2, guid.Data3,
- guid.Data4[0], guid.Data4[1],
- guid.Data4[2], guid.Data4[3],
- guid.Data4[4], guid.Data4[5],
- guid.Data4[6], guid.Data4[7]);
- //printf("%s\n",buf);
- return buf;
- }
- HRESULT AddFilterByCLSID(
- IGraphBuilder *pGraph, // Pointer to the Filter Graph Manager.
- const GUID& clsid, // CLSID of the filter to create.
- LPCWSTR wszName, // A name for the filter.
- IBaseFilter **ppF) // Receives a pointer to the filter.
- {
- if (!pGraph || ! ppF) return E_POINTER;
- *ppF = 0;
- IBaseFilter *pF = 0;
- HRESULT hr = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter, reinterpret_cast<void**>(&pF));
- if (SUCCEEDED(hr))
- {
- hr = pGraph->AddFilter(pF, wszName);
- if (SUCCEEDED(hr))
- *ppF = pF;
- else
- pF->Release();
- }
- return hr;
- }
- //
- //HRESULT GetUnconnectedPin(
- // IBaseFilter *pFilter, // Pointer to the filter.
- // PIN_DIRECTION PinDir, // Direction of the pin to find.
- // IPin **ppPin) // Receives a pointer to the pin.
- //{
- // *ppPin = 0;
- // IEnumPins *pEnum = 0;
- // IPin *pPin = 0;
- // HRESULT hr = pFilter->EnumPins(&pEnum);
- // if (FAILED(hr))
- // {
- // return hr;
- // }
- // while (pEnum->Next(1, &pPin, NULL) == S_OK)
- // {
- // PIN_DIRECTION ThisPinDir;
- // pPin->QueryDirection(&ThisPinDir);
- // if (ThisPinDir == PinDir)
- // {
- // IPin *pTmp = 0;
- // hr = pPin->ConnectedTo(&pTmp);
- // if (SUCCEEDED(hr)) // Already connected, not the pin we want.
- // {
- // pTmp->Release();
- // }
- // else // Unconnected, 这就是我们想要的pin,空闲的pin
- // {
- // pEnum->Release();
- // *ppPin = pPin;
- // return S_OK;
- // }
- // }
- // pPin->Release();
- // }
- // pEnum->Release();
- // // Did not find a matching pin.
- // return E_FAIL;
- //}
- //
- // Find an unconnected pin on a filter.
- // This too is stolen from the DX9 SDK.
- HRESULT GetUnconnectedPin(IBaseFilter *pFilter, // Pointer to the filter.
- PIN_DIRECTION PinDir, // Direction of the pin to find.
- IPin **ppPin) // Receives a pointer to the pin.
- {
- *ppPin = 0;
- IEnumPins *pEnum = 0;
- IPin *pPin = 0;
- HRESULT hr = pFilter->EnumPins(&pEnum);
- if (FAILED(hr))
- {
- return hr;
- }
- while (pEnum->Next(1, &pPin, NULL) == S_OK)
- {
- PIN_DIRECTION ThisPinDir;
- pPin->QueryDirection(&ThisPinDir);
- if (ThisPinDir == PinDir)
- {
- IPin *pTmp = 0;
- hr = pPin->ConnectedTo(&pTmp);
- if (SUCCEEDED(hr)) // Already connected--not the pin we want
- {
- pTmp->Release();
- }
- else // Unconnected--this is the pin we want
- {
- pEnum->Release();
- *ppPin = pPin;
- return S_OK;
- }
- }
- pPin->Release();
- }
- pEnum->Release();
- // Did not find a matching pin.
- return E_FAIL;
- }
- HRESULT ConnectFilters(
- IGraphBuilder *pGraph, // Filter Graph Manager.
- IPin *pOut, // Output pin on the upstream filter.
- IBaseFilter *pDest) // Downstream filter.
- {
- if ((pGraph == NULL) || (pOut == NULL) || (pDest == NULL))
- {
- return E_POINTER;
- }
- #ifdef debug
- PIN_DIRECTION PinDir;
- pOut->QueryDirection(&PinDir);
- _ASSERTE(PinDir == PINDIR_OUTPUT);
- #endif
- //找一个空闲的输入pin
- IPin *pIn = 0;
- HRESULT hr = GetUnconnectedPin(pDest, PINDIR_INPUT, &pIn);
- if (FAILED(hr))
- {
- return hr;
- }
- // Try to connect them.
- hr = pGraph->Connect(pOut, pIn);
- pIn->Release();
- return hr;
- }
- static const GUID CLSID_WavDest =
- { 0x3c78b8e2, 0x6c4d, 0x11d1, { 0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 } };
- // Enumerate all of the audio input devices
- // Return the _first_ of these to the caller
- // That should be the one chosen in the control panel.
- HRESULT EnumerateAudioInputFilters(void** gottaFilter)
- {
- // Once again, code stolen from the DX9 SDK.
- // Create the System Device Enumerator.
- ICreateDevEnum *pSysDevEnum = NULL;
- HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
- CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
- (void **)&pSysDevEnum);
- if (FAILED(hr))
- {
- return hr;
- }
- // Obtain a class enumerator for the audio input category.
- IEnumMoniker *pEnumCat = NULL;
- hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory,
- &pEnumCat, 0);
- if (hr == S_OK)
- {
- // Enumerate the monikers.
- IMoniker *pMoniker = NULL;
- ULONG cFetched;
- if (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
- {
- // Bind the first moniker to an object.
- IPropertyBag *pPropBag;
- hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
- (void **)&pPropBag);
- if (SUCCEEDED(hr))
- {
- // To retrieve the filter's friendly name,
- // do the following:
- VARIANT varName;
- VariantInit(&varName);
- hr = pPropBag->Read(L"FriendlyName", &varName, 0);
- if (SUCCEEDED(hr))
- {
- wprintf(L"Selecting Audio Input Device: %s\n",
- varName.bstrVal);
- }
- VariantClear(&varName);
- // To create an instance of the filter,
- // do the following:
- // Remember to release gottaFilter later.
- hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,gottaFilter);
- pPropBag->Release();
- }
- pMoniker->Release();
- }
- pEnumCat->Release();
- }
- pSysDevEnum->Release();
- return hr;
- }
- // Code adopted from example in the DX9 SDK.
- // This code allows us to find the input pins an audio input filter.
- // We'll print out a list of them, indicating the enabled one.
- HRESULT EnumerateAudioInputPins(IBaseFilter *pFilter)
- {
- IEnumPins *pEnum = NULL;
- IPin *pPin = NULL;
- PIN_DIRECTION PinDirThis;
- PIN_INFO pInfo;
- IAMAudioInputMixer *pAMAIM = NULL;
- BOOL pfEnable = FALSE;
- // Begin by enumerating all the pins on a filter.
- HRESULT hr = pFilter->EnumPins(&pEnum);
- if (FAILED(hr))
- {
- return NULL;
- }
- // Now, look for a pin that matches the direction characteristic.
- // When we've found it, we'll examine it.
- while(pEnum->Next(1, &pPin, 0) == S_OK)
- {
- // Get the pin direction.
- pPin->QueryDirection(&PinDirThis);
- if (PinDirThis == PINDIR_INPUT) {
- // OK, we've found an input pin on the filter.
- // Now let's get the information on that pin
- // so we can print the name of the pin to the console.
- hr = pPin->QueryPinInfo(&pInfo);
- if (SUCCEEDED(hr)) {
- wprintf(L"Input pin: %s\n", pInfo.achName);
- // Now let's get the correct interface.
- hr = pPin->QueryInterface(IID_IAMAudioInputMixer,
- (void**) &pAMAIM);
- if (SUCCEEDED(hr)) {
- // Find out whether the pin is enabled.
- // Is it the active input pin on the filter?
- hr = pAMAIM->get_Enable(&pfEnable);
- if (SUCCEEDED(hr)) {
- if (pfEnable) {
- wprintf(L"\tENABLED\n");
- }
- }
- pAMAIM->Release();
- }
- pInfo.pFilter->Release(); // from QueryPinInfo
- }
- }
- pPin->Release();
- }
- pEnum->Release();
- return hr;
- }
- // Connect two filters together with the Filter Graph Manager,
- // Stolen from the DX9 SDK.
- // This is the base version.
- //HRESULT ConnectFilters(IGraphBuilder *pGraph, // Filter Graph Manager.
- // IPin *pOut, // Output pin on the upstream filter.
- // IBaseFilter *pDest) // Downstream filter.
- //{
- // if ((pGraph == NULL) || (pOut == NULL) || (pDest == NULL))
- // {
- // return E_POINTER;
- // }
- // // Find an input pin on the downstream filter.
- // IPin *pIn = 0;
- // HRESULT hr = GetUnconnectedPin(pDest, PINDIR_INPUT, &pIn);
- // if (FAILED(hr))
- // {
- // return hr;
- // }
- // // Try to connect them.
- // hr = pGraph->Connect(pOut, pIn);
- // pIn->Release();
- // return hr;
- //}
- // Enumerate all of the audio compressors.
- // Return the one with the matching name to the caller.
- HRESULT EnumerateAudioCompressorFilters(void** gottaCompressor,
- wchar_t* matchName)
- {
- // Once again, code stolen from the DX9 SDK.
- // Create the System Device Enumerator.
- ICreateDevEnum *pSysDevEnum = NULL;
- HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
- CLSCTX_INPROC_SERVER,
- IID_ICreateDevEnum,
- (void **)&pSysDevEnum);
- if (FAILED(hr))
- {
- return hr;
- }
- // Obtain a class enumerator for the audio input category.
- IEnumMoniker *pEnumCat = NULL;
- hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioCompressorCategory,
- &pEnumCat, 0);
- if (hr == S_OK)
- {
- // Enumerate the monikers.
- IMoniker *pMoniker = NULL;
- ULONG cFetched;
- BOOL done = false;
- while ((pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) && (!done))
- {
- // Bind the first moniker to an object.
- IPropertyBag *pPropBag;
- hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
- (void **)&pPropBag);
- if (SUCCEEDED(hr))
- {
- // Retrieve the filter's friendly name.
- VARIANT varName;
- VariantInit(&varName);
- hr = pPropBag->Read(L"FriendlyName", &varName, 0);
- if (SUCCEEDED(hr))
- {
- wprintf(L"Testing Audio Compressor: %s\n",
- varName.bstrVal);
- // Is it the right one?
- if (wcsncmp(varName.bstrVal, matchName,
- wcslen(matchName)) == 0)
- {
- // We found it; send it back to the caller
- hr = pMoniker->BindToObject(NULL, NULL,
- IID_IBaseFilter,
- gottaCompressor);
- done = true;
- }
- }
- VariantClear(&varName);
- pPropBag->Release();
- }
- pMoniker->Release();
- }
- pEnumCat->Release();
- }
- pSysDevEnum->Release();
- return hr;
- }
- // Connect two filters together with the Filter Graph Manager.
- // Again, stolen from the DX9 SDK.
- // This is an overloaded version.
- HRESULT ConnectFilters(IGraphBuilder *pGraph,
- IBaseFilter *pSrc,
- IBaseFilter *pDest)
- {
- if ((pGraph == NULL) || (pSrc == NULL) || (pDest == NULL))
- {
- return E_POINTER;
- }
- // Find an output pin on the first filter.
- IPin *pOut = 0;
- HRESULT hr = GetUnconnectedPin(pSrc, PINDIR_OUTPUT, &pOut);
- if (FAILED(hr))
- {
- return hr;
- }
- hr = ConnectFilters(pGraph, pOut, pDest);
- pOut->Release();
- return hr;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- IGraphBuilder *pGraph = NULL; // Filter graph builder object
- IMediaControl *pControl = NULL; // Media control object
- IFileSinkFilter *pSink = NULL; // Interface on file writer
- IBaseFilter *pAudioInputFilter = NULL; // Audio capture filter
- IBaseFilter *pFileWriter = NULL; // File writer filter
- // Initialize the COM library.
- HRESULT hr = CoInitialize(NULL);
- if (FAILED(hr))
- {
- // We'll send our error messages to the console.
- printf("ERROR - Could not initialize COM library");
- return hr;
- }
- // Create the Filter Graph Manager and query for interfaces.
- hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
- IID_IGraphBuilder, (void **)&pGraph);
- if (FAILED(hr)) // FAILED is a macro that tests the return value
- {
- printf("ERROR - Could not create the Filter Graph Manager.");
- return hr;
- }
- // Using QueryInterface on the graph builder object,
- // get the IMediaControl object.
- hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
- if (FAILED(hr))
- {
- printf("ERROR - Could not create the Media Control object.");
- pGraph->Release(); // Clean up after ourselves
- CoUninitialize(); // And uninitalize COM
- return hr;
- }
- // OK, so now we want to build the filter graph
- // using an AudioCapture filter.
- // But there are several to choose from,
- // so we need to enumerate them and then pick one.
- hr = EnumerateAudioInputFilters((void**) &pAudioInputFilter);
- hr = EnumerateAudioInputPins(pAudioInputFilter);
- // Add the audio capture filter to the filter graph.
- hr = pGraph->AddFilter(pAudioInputFilter, L"Capture");
- // Next add the AVIMux. (You'll see why.)
- IBaseFilter *pAVIMux = NULL;
- hr = AddFilterByCLSID(pGraph, CLSID_AviDest, L"AVI Mux", &pAVIMux);
- // Connect the filters.
- hr = ConnectFilters(pGraph, pAudioInputFilter, pAVIMux);
- // And now we instance a file writer filter.
- hr = AddFilterByCLSID(pGraph, CLSID_FileWriter,
- L"File Writer", &pFileWriter);
- // Set the file name.
- hr = pFileWriter->QueryInterface(IID_IFileSinkFilter, (void**)&pSink);
- pSink->SetFileName(L"C:\\MyWAVFile.AVI", NULL);
- // Connect the filters.
- hr = ConnectFilters(pGraph, pAVIMux, pFileWriter);
- if (SUCCEEDED(hr))
- {
- // Run the graph.
- hr = pControl->Run();
- if (SUCCEEDED(hr))
- {
- // Wait patiently for completion of the recording.
- wprintf(L"Started recording...press Enter to stop recording.\n");
- // Wait for completion.
- char ch;
- ch = getchar(); // We wait for keyboard input
- }
- // And stop the filter graph.
- hr = pControl->Stop();
- wprintf(L"Stopped recording.\n"); // To the console
- // Before we finish, save the filter graph to a file.
- // SaveGraphFile(pGraph, L"C:\\MyGraph.GRF");
- }
- // Now release everything and clean up.
- pSink->Release();
- pAVIMux->Release();
- pFileWriter->Release();
- pAudioInputFilter->Release();
- pControl->Release();
- pGraph->Release();
- CoUninitialize();
- return 0;
- }