directshow 获取本地音频

网上很多讲解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;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值