完整的DirectShow捕获音视频的demo(源码)

DirectShow获取视频和音频数据

完整的DirectShow捕获音视频的demo(源码)_第1张图片      

近段时间由于工作上的需要,大概看了下DirectShow,写了个小的demo,方便理解。以后在深入的学习下DirectShow。贴出代码。

对音频所做的处理如下图:

完整的DirectShow捕获音视频的demo(源码)_第2张图片


1. common.h文件

#ifndef __COMMON_H__
#define __COMMON_H__

#include <DShow.h>
#include "qedit.h"
#include <strsafe.h>
#include <assert.h>
#pragma comment(lib,"Strmiids.lib")

//define release maco
#define ReleaseInterface(x) \
	if ( NULL != x ) \
{ \
	x->Release( ); \
	x = NULL; \
}
// Application-defined message to notify app of filter graph events
#define WM_GRAPHNOTIFY  WM_APP+100

void Msg(HWND hwnd,TCHAR *szFormat, ...);
bool Bstr_Compare(BSTR bstrFilter,BSTR bstrDevice);

#endif// __COMMON_H__

实现:

#include "common.h"

void Msg(HWND hwnd,TCHAR *szFormat, ...)
{
	TCHAR szBuffer[1024];  
	const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
	const int LASTCHAR = NUMCHARS - 1;

	va_list pArgs;
	va_start(pArgs, szFormat);

	(void)StringCchVPrintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
	va_end(pArgs);

	szBuffer[LASTCHAR] = TEXT('\0');

	MessageBox(hwnd, szBuffer, TEXT("Message"), MB_OK | MB_ICONERROR);
}

bool Bstr_Compare(BSTR bstrFilter,BSTR bstrDevice)
{
	bool flag = true;
	int strlenFilter = SysStringLen(bstrFilter);
	int strlenDevice = SysStringLen(bstrDevice);
	char* chrFilter = (char*)malloc(strlenFilter+1);
	char* chrDevice = (char*)malloc(strlenDevice+1);
	int j = 0;

	if (strlenFilter!=strlenDevice)
		flag = false;
	else
	{
		for(; j < strlenFilter;j++)
		{
			chrFilter[j] = (char)bstrFilter[j];
			chrDevice[j] = (char)bstrDevice[j];

		}
		chrFilter[strlenFilter] = '\0';
		chrDevice[strlenDevice] = '\0';

		for(j=0; j < strlenFilter;j++)
		{
			if(chrFilter[j] != chrDevice[j])
				flag = false;
		}

		if(flag == true && j == strlenFilter-1)
			flag = true;
	}
	return flag;
}


2.SampleGrabberCallback.h文件,由于截取视频图片,回调函数的实现

#ifndef __SAMPLEGRABBERCALLBACK_H__
#define __SAMPLEGRABBERCALLBACK_H__
#include "common.h"

class SampleGrabberCallback : public ISampleGrabberCB
{
public:
	ULONG STDMETHODCALLTYPE AddRef();
	ULONG STDMETHODCALLTYPE Release();
	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void** ppvObject);

	HRESULT STDMETHODCALLTYPE SampleCB(double Time, IMediaSample *pSample);
	HRESULT STDMETHODCALLTYPE BufferCB(double Time, BYTE *pBuffer, long BufferLen);
	
	SampleGrabberCallback();
	BOOL SaveBitmap(BYTE * pBuffer, long lBufferSize ); //保存bitmap图片
public:
	BOOL m_bGetPicture;  // is get a picture
	long m_lWidth;       //存储图片的宽度
	long m_lHeight;		 //存储图片的长度
	int  m_iBitCount;    //the number of bits per pixel (bpp)
	TCHAR m_chTempPath[MAX_PATH];
	TCHAR m_chSwapStr[MAX_PATH];
	TCHAR m_chDirName[MAX_PATH];
};

#endif //__SAMPLEGRABBERCALLBACK_H__

实现:

#include "SampleGrabberCallback.h"



SampleGrabberCallback::SampleGrabberCallback()
{
	m_bGetPicture = FALSE;
	//Get template path
	GetTempPath(MAX_PATH,m_chTempPath);
	StringCchCat(m_chTempPath,MAX_PATH,TEXT("NTKOCapturePic"));
	CreateDirectory(m_chTempPath,NULL);
}

ULONG STDMETHODCALLTYPE SampleGrabberCallback::AddRef()
{
	return 1;
}

ULONG STDMETHODCALLTYPE SampleGrabberCallback::Release()
{
	return 2;
}

HRESULT STDMETHODCALLTYPE SampleGrabberCallback::QueryInterface(REFIID riid,void** ppvObject)
{
	if (NULL == ppvObject) return E_POINTER;
	if (riid == __uuidof(IUnknown))
	{
		*ppvObject = static_cast<IUnknown*>(this);
		return S_OK;
	}
	if (riid == IID_ISampleGrabberCB)
	{
		*ppvObject = static_cast<ISampleGrabberCB*>(this);
		return S_OK;
	}
	return E_NOTIMPL;

}

HRESULT STDMETHODCALLTYPE SampleGrabberCallback::SampleCB(double Time, IMediaSample *pSample)
{
	return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE SampleGrabberCallback::BufferCB(double Time, BYTE *pBuffer, long BufferLen)
{
	if(FALSE == m_bGetPicture)  //判断是否需要截图
		return S_FALSE;
	if(!pBuffer)
		return E_POINTER;

	SaveBitmap(pBuffer,BufferLen);

	m_bGetPicture = FALSE;
	return S_OK;
}

BOOL SampleGrabberCallback::SaveBitmap(BYTE * pBuffer, long lBufferSize )
{
	SYSTEMTIME sysTime;
	GetLocalTime(&sysTime);
	StringCchCopy(m_chSwapStr,MAX_PATH,m_chTempPath);
	StringCchPrintf(m_chDirName,MAX_PATH,TEXT("\\%04i%02i%02i%02i%02i%02i%03ione.bmp"),
					sysTime.wYear,sysTime.wMonth,sysTime.wDay,sysTime.wHour,
					sysTime.wMinute,sysTime.wSecond,sysTime.wMilliseconds);
	StringCchCat(m_chSwapStr,MAX_PATH,m_chDirName);
	//MessageBox(NULL,chTempPath,TEXT("Message"),MB_OK);
	//create picture file
	HANDLE hf = CreateFile(m_chSwapStr,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,
		CREATE_ALWAYS,0,NULL);
	if(hf == INVALID_HANDLE_VALUE)
	{
		return E_FAIL;
	}

	BITMAPFILEHEADER bfh;  //Set bitmap header
	ZeroMemory(&bfh,sizeof(bfh));
	bfh.bfType = 'MB';
	bfh.bfSize = sizeof(bfh) + lBufferSize + sizeof(BITMAPFILEHEADER);
	bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPFILEHEADER);
	// Write the file header.
	DWORD dwWritten = 0;
	WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );    
	// Write the file Format
	BITMAPINFOHEADER bih;
	ZeroMemory(&bih,sizeof(bih));
	bih.biSize = sizeof( bih );
	bih.biWidth = m_lWidth;
	bih.biHeight = m_lHeight;
	bih.biPlanes = 1;
	bih.biBitCount = m_iBitCount;  //Specifies the number of bits per pixel (bpp)
	WriteFile( hf, &bih, sizeof( bih ), &dwWritten, NULL );
	//Write the file Data
	WriteFile( hf, pBuffer, lBufferSize, &dwWritten, NULL );
	CloseHandle( hf );
	return 0;
}

3.CaptureVideo.h 捕获视频,预览和截图文件

#ifndef __CAPTUREVIDEO_H__
#define __CAPTUREVIDEO_H__
#include "SampleGrabberCallback.h"

class CaptureVideo
{
public:
	CaptureVideo();
	~CaptureVideo();
	HRESULT InitializeEnv(); //initialize environment
	HRESULT EnumAllDevices(HWND hCombox);  //Enumeration all devices
	void CloseInterface(); //close all interface
	HRESULT OpenDevice(int deviceID, LONG nLeft, LONG nTop, LONG nWide, LONG nHeight);
	HRESULT BindFilter(int deviceID, IBaseFilter **pBaseFilter);
	HRESULT SetupVideoWindow(LONG nLeft, LONG nTop, LONG nWidth, LONG nHeight);
	void ResizeVideoWindow(LONG nLeft, LONG nTop, LONG nWidth, LONG nHeight);
	void GrabOneFrame(BOOL bGrab); // use ISampleGrabberCallbackCB get a picture
	HRESULT HandleGraphCapturePicture(void); //capture picture  use GetCurrentBuffer

private:
	IGraphBuilder *m_pGraphBuilder;
	ICaptureGraphBuilder2 *m_pCaptureGB;
	IMediaControl *m_pMediaControl;
	IBaseFilter *m_pDevFilter;
	ISampleGrabber *m_pSampGrabber;  
	IMediaEventEx *m_pMediaEvent;
public:
	int m_nCaptureDeviceNumber;      //Device Count
	//vector<string> m_vecCapDeviceName; //the Device name
	TCHAR m_pCapDeviceName[10][MAX_PATH]; //the Device name
	HWND m_App;
	BOOL m_bGetOneShot;
	BOOL m_bConnect;
	IVideoWindow *m_pVideoWindow;
};


#endif  //__CAPTUREVIDEO_H__

实现:

#include "CaptureVideo.h"

SampleGrabberCallback g_sampleGrabberCB;  //CallBack

CaptureVideo::CaptureVideo()
{
	//COM Library Initialize
	if (FAILED(CoInitialize(NULL)))
	{
		Msg(m_App,TEXT("CoInitialize Failed!\r\n"));
		return;
	}
	//initialize member variable
	m_nCaptureDeviceNumber = 0;
	m_pDevFilter = NULL;
	m_pCaptureGB = NULL;
	m_pGraphBuilder = NULL;
	m_pMediaControl = NULL;
	m_pMediaEvent = NULL;
	m_pSampGrabber = NULL;
	m_pVideoWindow = NULL;
	m_App = NULL;
	m_bGetOneShot = FALSE;
	m_bConnect = FALSE;
	InitializeEnv();
}

CaptureVideo::~CaptureVideo()
{
	CloseInterface();
	CoUninitialize();
}

HRESULT CaptureVideo::EnumAllDevices(HWND hCombox)
{
	if (!hCombox)
		return S_FALSE;
	ICreateDevEnum *pDevEnum;
	IEnumMoniker   *pEnumMon;
	IMoniker	   *pMoniker;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
			IID_ICreateDevEnum,(LPVOID*)&pDevEnum);
	if (SUCCEEDED(hr))
	{
		hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnumMon, 0);
		if (hr == S_FALSE)
		{
			hr = VFW_E_NOT_FOUND;
			return hr;
		}
		pEnumMon->Reset();
		ULONG cFetched;
		while(hr=pEnumMon->Next(1,&pMoniker,&cFetched),hr == S_OK)
		{
			IPropertyBag *pProBag;
			hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,(LPVOID*)&pProBag);
			if (SUCCEEDED(hr))
			{
				VARIANT varTemp;
				varTemp.vt = VT_BSTR;
				hr = pProBag->Read(L"FriendlyName",&varTemp,NULL);
				if (SUCCEEDED(hr))
				{
					//int nStrSize = WideCharToMultiByte(CP_ACP,0,varTemp.bstrVal,-1,0,0,NULL,FALSE);
					//char *strName = new char[nStrSize];
					//WideCharToMultiByte(CP_ACP,0,varTemp.bstrVal,-1,strName,nStrSize,NULL,FALSE);
					//m_vecCapDeviceName.push_back(string(strName)); //push the device name to vector
					
					StringCchCopy(m_pCapDeviceName[m_nCaptureDeviceNumber],MAX_PATH,varTemp.bstrVal);
					m_nCaptureDeviceNumber++; //Device number add 1
					::SendMessage(hCombox, CB_ADDSTRING, 0,(LPARAM)varTemp.bstrVal);
					SysFreeString(varTemp.bstrVal);
				}
				pProBag->Release();
			}
			pMoniker->Release();
		}
		pEnumMon->Release();
	}
	return hr;
}

HRESULT CaptureVideo::InitializeEnv()
{
	HRESULT hr;

	//Create the filter graph
	hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
						  IID_IGraphBuilder,(LPVOID*)&m_pGraphBuilder);
	if(FAILED(hr))
		return hr;
	
	//Create the capture graph builder
	hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL,CLSCTX_INPROC_SERVER,
						  IID_ICaptureGraphBuilder2,(LPVOID*)&m_pCaptureGB);
	if(FAILED(hr))
		return hr;

	//Obtain interfaces for media control and Video Window
	hr = m_pGraphBuilder->QueryInterface(IID_IMediaControl,(LPVOID*)&m_pMediaControl);
	if(FAILED(hr))
		return hr;

	hr = m_pGraphBuilder->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVideoWindow);
	if(FAILED(hr))
		return hr;

	hr = m_pGraphBuilder->QueryInterface(IID_IMediaEventEx,(LPVOID*)&m_pMediaEvent);
	if(FAILED(hr))
		return hr;

	hr = m_pMediaEvent->SetNotifyWindow((OAHWND)m_App,WM_GRAPHNOTIFY,0);

	if(FAILED(hr))
		return hr;
	m_pCaptureGB->SetFiltergraph(m_pGraphBuilder);
	if(FAILED(hr))
		return hr;
	return hr;
}

void CaptureVideo::CloseInterface()
{
	m_bGetOneShot = FALSE;

	if (m_pMediaControl)
		m_pMediaControl->Stop();
	if(m_pVideoWindow)
	{
		m_pVideoWindow->get_Visible(FALSE);
		m_pVideoWindow->put_Owner(NULL);
	}

	if(m_pMediaEvent)
		m_pMediaEvent->SetNotifyWindow(NULL,WM_GRAPHNOTIFY,0);

	//release interface
	ReleaseInterface(m_pDevFilter);
	ReleaseInterface(m_pCaptureGB);
	ReleaseInterface(m_pGraphBuilder);
	ReleaseInterface(m_pMediaControl);
	ReleaseInterface(m_pMediaEvent);
	ReleaseInterface(m_pSampGrabber);
	ReleaseInterface(m_pVideoWindow);
}

HRESULT CaptureVideo::BindFilter(int deviceID, IBaseFilter **pBaseFilter)
{
	ICreateDevEnum *pDevEnum;
	IEnumMoniker   *pEnumMon;
	IMoniker	   *pMoniker;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
		IID_ICreateDevEnum,(LPVOID*)&pDevEnum);
	if (SUCCEEDED(hr))
	{
		hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnumMon, 0);
		if (hr == S_FALSE)
		{
			hr = VFW_E_NOT_FOUND;
			return hr;
		}
		pEnumMon->Reset();
		ULONG cFetched;
		int index = 0;
		while(hr=pEnumMon->Next(1,&pMoniker,&cFetched),hr == S_OK, index<= deviceID)
		{
			IPropertyBag *pProBag;
			hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,(LPVOID*)&pProBag);
			if (SUCCEEDED(hr))
			{
				if (index == deviceID)
				{
					pMoniker->BindToObject(0,0,IID_IBaseFilter,(LPVOID*)pBaseFilter);
				}
			}
			pMoniker->Release();
			index++;
		}
		pEnumMon->Release();
	}
	return hr;
}

HRESULT CaptureVideo::SetupVideoWindow(LONG nLeft, LONG nTop, LONG nWidth, LONG nHeight)
{
	HRESULT hr;
	hr = m_pVideoWindow->put_Owner((OAHWND)m_App);
	if (FAILED(hr))
		return hr;

	hr = m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
	if(FAILED(hr))
		return hr;

	ResizeVideoWindow(nLeft,nTop,nWidth,nHeight);

	hr = m_pVideoWindow->put_Visible(OATRUE);
	if(FAILED(hr))
		return hr;

	return hr;
}

void CaptureVideo::ResizeVideoWindow(LONG nLeft, LONG nTop, LONG nWidth, LONG nHeight)
{
	if(m_pVideoWindow)
	{
		m_pVideoWindow->SetWindowPosition(nLeft,nTop,nWidth,nHeight);
	}
}

HRESULT CaptureVideo::OpenDevice(int deviceID, LONG nLeft, LONG nTop, LONG nWide, LONG nHeight)
{
	HRESULT hr;
	IBaseFilter *pSampleGrabberFilter;
	if (m_bConnect)
	{
		CloseInterface();
		InitializeEnv();
	}

	hr = CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,
						  IID_IBaseFilter, (LPVOID*)&pSampleGrabberFilter);
	if(FAILED(hr))
		return hr;
	//bind device filter
	hr = BindFilter(deviceID,&m_pDevFilter);
	if (FAILED(hr))
		return hr;
	hr = m_pGraphBuilder->AddFilter(m_pDevFilter,L"Video Filter");
	if (FAILED(hr))
		return hr;

	hr = m_pGraphBuilder->AddFilter(pSampleGrabberFilter,L"Sample Grabber");
	if (FAILED(hr))
		return hr;

	hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber,(LPVOID*)&m_pSampGrabber);
	if(FAILED(hr))
		return hr;

	//set media type
	AM_MEDIA_TYPE mediaType;
	ZeroMemory(&mediaType,sizeof(AM_MEDIA_TYPE));
	//Find the current bit depth
	HDC hdc=GetDC(NULL);
	int iBitDepth=GetDeviceCaps(hdc, BITSPIXEL);
	g_sampleGrabberCB.m_iBitCount = iBitDepth;
	ReleaseDC(NULL,hdc);
	//Set the media type
	mediaType.majortype = MEDIATYPE_Video;
	switch(iBitDepth)
	{
	case  8:
		mediaType.subtype=MEDIASUBTYPE_RGB8;
		break;
	case 16:
		mediaType.subtype=MEDIASUBTYPE_RGB555;
		break;
	case 24:
		mediaType.subtype=MEDIASUBTYPE_RGB24;
		break;
	case 32:
		mediaType.subtype=MEDIASUBTYPE_RGB32;
		break;
	default:
		return E_FAIL;
	}
	mediaType.formattype = FORMAT_VideoInfo;
	hr = m_pSampGrabber->SetMediaType(&mediaType);

	hr = m_pCaptureGB->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,
		m_pDevFilter,pSampleGrabberFilter,NULL);
	if(FAILED(hr))
		return hr;

	hr = m_pSampGrabber->GetConnectedMediaType(&mediaType);
	if(FAILED(hr))
		return hr;

	VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mediaType.pbFormat;
	g_sampleGrabberCB.m_lWidth = vih->bmiHeader.biWidth;
	g_sampleGrabberCB.m_lHeight = vih->bmiHeader.biHeight;
	// Configure the Sample Grabber
	hr = m_pSampGrabber->SetOneShot(FALSE);
	if (FAILED(hr))
		return hr;
	hr = m_pSampGrabber->SetBufferSamples(TRUE);
	if (FAILED(hr))
		return hr;
	// 1 = Use the BufferCB callback method.
	hr = m_pSampGrabber->SetCallback(&g_sampleGrabberCB,1);

	//set capture video Window
	SetupVideoWindow(nLeft,nTop,nWide,nHeight);
	hr = m_pMediaControl->Run();
	if(FAILED(hr))
		return hr;

	if (mediaType.cbFormat != 0)
	{
		CoTaskMemFree((PVOID)mediaType.pbFormat);
		mediaType.cbFormat = 0;
		mediaType.pbFormat = NULL;
	}
	if (mediaType.pUnk != NULL)
	{
		mediaType.pUnk->Release();
		mediaType.pUnk = NULL;
	}
	m_bConnect = TRUE;
	return hr;

}

void CaptureVideo::GrabOneFrame(BOOL bGrab)
{
	m_bGetOneShot = bGrab;
	g_sampleGrabberCB.m_bGetPicture = bGrab;
}

HRESULT CaptureVideo::HandleGraphCapturePicture(void)
{
	//////////////////////////////////////////////////////////////////////////
	HRESULT hr;
	long evCode = 0;
	long lBufferSize = 0;
	BYTE *p;
	hr = m_pMediaEvent->WaitForCompletion(INFINITE, &evCode); //
	if (SUCCEEDED(hr))
	{
		switch(evCode)
		{
		case EC_COMPLETE:
			m_pSampGrabber->GetCurrentBuffer(&lBufferSize, NULL);
			p = new BYTE[lBufferSize];
			m_pSampGrabber->GetCurrentBuffer(&lBufferSize, (LONG*)p);// get Current buffer
			g_sampleGrabberCB.SaveBitmap(p,lBufferSize); //save bitmap
			break;
		default:
			break;
		}
	}
	//////////////////////////////////////////////////////////////////////////
	return hr;
}

4.CaptureAudio.h 预览音频和保存捕获到的音频到文件

#ifndef __CAPTUREAUDIO_H__
#define __CAPTUREAUDIO_H__
#include "common.h"

class CaptureAudio
{
public:
	CaptureAudio();
	~CaptureAudio();
	HRESULT InitializeEnv(); //initialize environment
	HRESULT EnumAllDevices(HWND hCombox);  //Enumeration all devices
	void CloseInterface(); //close all interface
	HRESULT OpenDevice(BSTR bstrDeviceName);
	HRESULT BindDeviceFilter(BSTR deviceName,GUID DEVICE_CLSID,IBaseFilter **pBaseFilter);
	HRESULT	DeviceConnect(IBaseFilter* pInputDevice,IBaseFilter* pOutputDevice, BSTR bstrInputPin, BSTR bstrOutputDevice);

private:
	IGraphBuilder *m_pGraphBuilder;
	ICaptureGraphBuilder2 *m_pCaptureGB;
	IBaseFilter *m_pDevFilter;
	IMediaControl *m_pMediaContrl;
public:
	int m_nCaptureDeviceNumber;      //Device Count
	//vector<string> m_vecCapDeviceName; //the Device name
	TCHAR m_pCapDeviceName[10][MAX_PATH]; //the Device name
	TCHAR m_pRendererDeviceName[10][MAX_PATH]; // Render Device name	
	HWND m_App;
};

#endif  //__CAPTUREAUDIO_H__

实现:

#include "CaptureAudio.h"


CaptureAudio::CaptureAudio()
{
	//COM Library Initialize
	if (FAILED(CoInitialize(NULL)))
	{
		Msg(m_App,TEXT("CoInitialize Failed!\r\n"));
		return;
	}
	//initialize member variable
	m_nCaptureDeviceNumber = 0;
	m_pDevFilter = NULL;
	m_pCaptureGB = NULL;
	m_pGraphBuilder = NULL;
	m_pMediaContrl = NULL;
	m_App = NULL;
	InitializeEnv();
}

CaptureAudio::~CaptureAudio()
{
	CloseInterface();
	CoUninitialize();
}

HRESULT CaptureAudio::EnumAllDevices(HWND hCombox)
{
	if (!hCombox)
		return S_FALSE;
	ICreateDevEnum *pDevEnum;
	IEnumMoniker   *pEnumMon;
	IMoniker	   *pMoniker;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
		IID_ICreateDevEnum,(LPVOID*)&pDevEnum);
	if (SUCCEEDED(hr))
	{
		// get all Audio input Device Friendly Name
		hr = pDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory,&pEnumMon, 0);
		if (hr == S_FALSE)
		{
			hr = VFW_E_NOT_FOUND;
			return hr;
		}
		pEnumMon->Reset();
		ULONG cFetched;
		while(hr=pEnumMon->Next(1,&pMoniker,&cFetched),hr == S_OK)
		{
			IPropertyBag *pProBag;
			hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,(LPVOID*)&pProBag);
			if (SUCCEEDED(hr))
			{
				VARIANT varTemp;
				varTemp.vt = VT_BSTR;
				hr = pProBag->Read(L"FriendlyName",&varTemp,NULL);
				if (SUCCEEDED(hr))
				{
					//int nStrSize = WideCharToMultiByte(CP_ACP,0,varTemp.bstrVal,-1,0,0,NULL,FALSE);
					//char *strName = new char[nStrSize];
					//WideCharToMultiByte(CP_ACP,0,varTemp.bstrVal,-1,strName,nStrSize,NULL,FALSE);
					//m_vecCapDeviceName.push_back(string(strName)); //push the device name to vector

					StringCchCopy(m_pCapDeviceName[m_nCaptureDeviceNumber],MAX_PATH,varTemp.bstrVal);
					m_nCaptureDeviceNumber++; //Device number add 1
					::SendMessage(hCombox, CB_ADDSTRING, 0,(LPARAM)varTemp.bstrVal);
					SysFreeString(varTemp.bstrVal);
				}
				pProBag->Release();
			}
			pMoniker->Release();
		}
		pEnumMon->Release();

		//get All Audio Renderer Device Friendly Name
		hr = pDevEnum->CreateClassEnumerator(CLSID_AudioRendererCategory,&pEnumMon, 0);
		if (hr == S_FALSE)
		{
			hr = VFW_E_NOT_FOUND;
			return hr;
		}
		pEnumMon->Reset();
		int index = 0;
		while(hr=pEnumMon->Next(1,&pMoniker,&cFetched),hr == S_OK)
		{
			IPropertyBag *pProBag;
			hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,(LPVOID*)&pProBag);
			if (SUCCEEDED(hr))
			{
				VARIANT varTemp;
				varTemp.vt = VT_BSTR;
				hr = pProBag->Read(L"FriendlyName",&varTemp,NULL);
				if (SUCCEEDED(hr))
				{
					StringCchCopy(m_pRendererDeviceName[index],MAX_PATH,varTemp.bstrVal);
					index++; //Device number add 1
					SysFreeString(varTemp.bstrVal);
				}
				pProBag->Release();
			}
			pMoniker->Release();
		}
		pEnumMon->Release();
	}
	return hr;
}

HRESULT CaptureAudio::InitializeEnv()
{
	HRESULT hr;

	//Create the filter graph
	hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,
		IID_IGraphBuilder,(LPVOID*)&m_pGraphBuilder);
	if(FAILED(hr))
		return hr;

	//Create the capture graph builder
	hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL,CLSCTX_INPROC_SERVER,
		IID_ICaptureGraphBuilder2,(LPVOID*)&m_pCaptureGB);
	if(FAILED(hr))
		return hr;

	hr = m_pGraphBuilder->QueryInterface(IID_IMediaControl,(LPVOID*)&m_pMediaContrl);
	if(FAILED(hr))
		return hr;
	m_pCaptureGB->SetFiltergraph(m_pGraphBuilder);
	if(FAILED(hr))
		return hr;
	return hr;
}

void CaptureAudio::CloseInterface()
{
	if (m_pMediaContrl)
		m_pMediaContrl->Stop();
	//release interface
	ReleaseInterface(m_pDevFilter);
	ReleaseInterface(m_pCaptureGB);
	ReleaseInterface(m_pGraphBuilder);
	ReleaseInterface(m_pMediaContrl);
}

HRESULT CaptureAudio::OpenDevice(BSTR bstrDeviceName)
{
	HRESULT hr;
	IBaseFilter  *pWaveDest = NULL, *pWriter = NULL, *pOutputDev = NULL;
	IFileSinkFilter *pSink= NULL;
	BSTR bstrTempDeviceName;
	BSTR bstrOutPin,bstrInPin;
	IBaseFilter *pPinTeeFilter = NULL;
	
	hr = BindDeviceFilter(bstrDeviceName,CLSID_AudioInputDeviceCategory, &m_pDevFilter);
	if (FAILED(hr))
		return hr;
	// Add the audio capture filter to the filter graph. 
	hr = m_pGraphBuilder->AddFilter(m_pDevFilter, L"Capture");
	if (FAILED(hr))
		return hr;
	/************************************************************************/
	/* Audio Prieview                                           */
	/************************************************************************/
	bstrTempDeviceName = SysAllocString(L"Infinite Pin Tee Filter");
	hr = BindDeviceFilter(bstrTempDeviceName,CLSID_LegacyAmFilterCategory,&pPinTeeFilter);
	if (FAILED(hr))
		return hr;
	hr = m_pGraphBuilder->AddFilter(pPinTeeFilter,bstrTempDeviceName);
	bstrInPin = SysAllocString(L"Capture");
	bstrOutPin = SysAllocString(L"Input");
	
	hr = DeviceConnect(m_pDevFilter,pPinTeeFilter,bstrInPin,bstrOutPin);
	if(FAILED(hr))
		return hr;
	//////////////////////////////////////////////////////////////////////////
	// output the Rendered Device
	SysReAllocString(&bstrTempDeviceName,m_pRendererDeviceName[0]); //Rendered Device Name;
	hr = BindDeviceFilter(bstrTempDeviceName,CLSID_AudioRendererCategory,&pOutputDev);
	if(FAILED(hr))
		return hr;
	hr = m_pGraphBuilder->AddFilter(pOutputDev,bstrTempDeviceName);
	if(FAILED(hr))
		return hr;
	SysReAllocString(&bstrInPin,L"Output1");
	SysReAllocString(&bstrOutPin,L"Audio Input pin (rendered)");
	hr = DeviceConnect(pPinTeeFilter,pOutputDev,bstrInPin,bstrOutPin);
	if(FAILED(hr))
		return hr;
	//////////////////////////////////////////////////////////////////////////


	//Add AudioRecorder WAV Dest
	SysReAllocString(&bstrTempDeviceName,TEXT("AudioRecorder WAV Dest"));
	hr = BindDeviceFilter(bstrTempDeviceName,CLSID_LegacyAmFilterCategory, &pWaveDest);
	if (FAILED(hr))
		return hr;
	hr = m_pGraphBuilder->AddFilter(pWaveDest,bstrTempDeviceName);
	if (FAILED(hr))
		return hr;
	//Connect the AudioRecorder WAV Dest
	SysReAllocString(&bstrInPin,L"Output2");
	SysReAllocString(&bstrOutPin,L"In");
	hr = DeviceConnect(pPinTeeFilter,pWaveDest,bstrInPin,bstrOutPin);
	if (FAILED(hr))
		return hr;
	
	// output Filter Wirter
	SysReAllocString(&bstrTempDeviceName,L"File writer");
	hr = BindDeviceFilter(bstrTempDeviceName,CLSID_LegacyAmFilterCategory,&pWriter);	
	if (FAILED(hr))
		return hr;

	IFileSinkFilter *pFileSink= NULL;
	SysReAllocString(&bstrTempDeviceName,L"test.wav");
	hr = pWriter->QueryInterface(IID_IFileSinkFilter, (void**)&pFileSink);
	if(FAILED(hr))
		return hr;
	hr = pFileSink->SetFileName((LPCOLESTR)bstrTempDeviceName,NULL);
	if(FAILED(hr))
		return hr;
	hr = m_pGraphBuilder->AddFilter(pWriter,bstrTempDeviceName);
	if(FAILED(hr))
		return hr;

	SysReAllocString(&bstrInPin,L"Out");
	SysReAllocString(&bstrOutPin,L"in");

	hr = DeviceConnect(pWaveDest,pWriter,bstrInPin,bstrOutPin);
	if(FAILED(hr))
		return hr;
	SysFreeString(bstrInPin);
	SysFreeString(bstrOutPin);
	SysFreeString(bstrTempDeviceName);

	hr = m_pMediaContrl->Run();
	if(FAILED(hr))
		return hr;
	return hr;

}

HRESULT CaptureAudio::DeviceConnect(IBaseFilter* pInputDevice,IBaseFilter* pOutputDevice, BSTR bstrInputPin, BSTR bstrOutputDevice)
{
	HRESULT hr;
	IEnumPins *pInputPins = NULL, *pOutputPins = NULL;
	IPin *pIn = NULL, *pOut = NULL;

	hr = pInputDevice->EnumPins(&pInputPins);
	if (SUCCEEDED(hr))
	{
		hr = pInputDevice->FindPin(bstrInputPin,&pIn);
		if(FAILED(hr))
			return hr;
	}else
		return hr;

	hr = pOutputDevice->EnumPins(&pOutputPins);
	if (SUCCEEDED(hr))
	{
		hr = pOutputDevice->FindPin(bstrOutputDevice,&pOut);
		if(FAILED(hr))
			return hr;
	}

	hr = pIn->Connect(pOut, NULL);
	if (FAILED(hr))
		return hr;
	return hr;
}

HRESULT CaptureAudio::BindDeviceFilter(BSTR deviceName,GUID DEVICE_CLSID,IBaseFilter **pBaseFilter)
{
	ICreateDevEnum *pDevEnum;
	IEnumMoniker   *pEnumMon;
	IMoniker	   *pMoniker;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
		IID_ICreateDevEnum,(LPVOID*)&pDevEnum);
	if (SUCCEEDED(hr))
	{
		hr = pDevEnum->CreateClassEnumerator(DEVICE_CLSID,&pEnumMon, 0);
		if (hr == S_FALSE)
		{
			hr = VFW_E_NOT_FOUND;
			return hr;
		}
		pEnumMon->Reset();
		ULONG cFetched;
		while(hr=pEnumMon->Next(1,&pMoniker,&cFetched),hr == S_OK)
		{
			IPropertyBag *pProBag;
			hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,(LPVOID*)&pProBag);
			if (SUCCEEDED(hr))
			{
				VARIANT varTemp;
				varTemp.vt = VT_BSTR;
				hr = pProBag->Read(L"FriendlyName",&varTemp,NULL);
				if (SUCCEEDED(hr))
				{
					if (Bstr_Compare(varTemp.bstrVal,deviceName) == true)
					{
						hr = pMoniker->BindToObject(NULL,NULL,IID_IBaseFilter,(LPVOID*)pBaseFilter);
						if (SUCCEEDED(hr))
							return hr;
					}
					SysFreeString(varTemp.bstrVal);
				}
				pProBag->Release();
			}
			pMoniker->Release();
		}
		pEnumMon->Release();
	}
	return hr;
}

5.测试:Main.cpp

#include "CaptureVideo.h"
#include "CaptureAudio.h"
#include "resource.h"
#define ID_COMBOBOX  10000
#define ID_COMBOBOX2 10001
#define ID_TIMER     10002

CaptureVideo g_CaptureVideo;

CaptureAudio g_CaptureAudio;
HWND hwndCombo1;
HWND hwndCombo2;
BSTR bstrDeviceName;

HICON g_hIconLarge;
HICON g_hIconSmall;

int g_nTimerCount = 0;

BOOL CALLBACK WndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
VOID CALLBACK TimerGetPicture(HWND hDlg, UINT message, UINT iTimerID, DWORD dwTimer);
VOID SetWindowPosCenter(HWND hDlg);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{


	g_hIconLarge = static_cast<HICON>(LoadImage(hInstance, TEXT("IDI_ICON1"), IMAGE_ICON,  //set large ico
		GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CXICON), 0));
	g_hIconSmall = static_cast<HICON>(LoadImage(hInstance, TEXT("IDI_ICON1"), IMAGE_ICON,   //set small ico
		GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CXSMICON), 0));

    MSG msg;
	HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,WndProc);
	    
	ShowWindow(hDlg,iCmdShow);
	UpdateWindow(hDlg);


    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }

	CoUninitialize();
	// Exit
	DestroyIcon(g_hIconLarge);
	DestroyIcon(g_hIconSmall);	
    return msg.wParam;
}

BOOL CALLBACK WndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int nGetComboxCount = 0;
	int iGetCurSel = 0;
	DWORD dwBaseUnits;
	switch(message)
	{
	case WM_INITDIALOG:
        {
			SendMessage(hDlg,WM_SETICON,FALSE,reinterpret_cast<LPARAM>(g_hIconSmall));
			SendMessage(hDlg,WM_SETICON,TRUE,reinterpret_cast<LPARAM>(g_hIconLarge));
			//////////////////////////////////////////////////////////////////////////
			SetWindowPosCenter(hDlg); //set Dialog at window center
			//////////////////////////////////////////////////////////////////////////
			g_CaptureVideo.m_App = hDlg;
			g_CaptureAudio.m_App = hDlg;
			dwBaseUnits = GetDialogBaseUnits(); 
			hwndCombo1 = CreateWindow(TEXT("COMBOBOX"), TEXT(""), 
				CBS_DROPDOWN | WS_CHILD | WS_VISIBLE, 
				(6 * LOWORD(dwBaseUnits)) / 4, 
				(2 * HIWORD(dwBaseUnits)) / 8, 
				(100 * LOWORD(dwBaseUnits)) / 4, 
				(50 * HIWORD(dwBaseUnits)) / 8, 
				hDlg, (HMENU)ID_COMBOBOX, NULL, NULL);   

			hwndCombo2 = CreateWindow(TEXT("COMBOBOX"), TEXT(""), 
				CBS_DROPDOWN | WS_CHILD | WS_VISIBLE, 
				(110 * LOWORD(dwBaseUnits)) / 4, 
				(2 * HIWORD(dwBaseUnits)) / 8, 
				(100 * LOWORD(dwBaseUnits)) / 4, 
				(50 * HIWORD(dwBaseUnits)) / 8, 
				hDlg, (HMENU)ID_COMBOBOX2, NULL, NULL);   

			//Video
			g_CaptureVideo.EnumAllDevices(hwndCombo1); //Enum All Camera
			nGetComboxCount = ComboBox_GetCount(hwndCombo1);
			if (nGetComboxCount == 0)
				ComboBox_Enable(hwndCombo1,FALSE);
			else
				ComboBox_SetCurSel(hwndCombo1,0);

			if(g_CaptureVideo.m_nCaptureDeviceNumber == 0)
			{
				Msg(hDlg,TEXT("没有摄像头设备"));
				EnableWindow(GetDlgItem(hDlg,IDC_PREVIWE),FALSE);
			}
			EnableWindow(GetDlgItem(hDlg,IDONESHOT),FALSE);

			// Audio
			g_CaptureAudio.EnumAllDevices(hwndCombo2);
			nGetComboxCount = ComboBox_GetCount(hwndCombo2);
			if (nGetComboxCount == 0)
				ComboBox_Enable(hwndCombo2,FALSE);
			else
				ComboBox_SetCurSel(hwndCombo2,0);
			if(g_CaptureAudio.m_nCaptureDeviceNumber == 0)
			{
				Msg(hDlg,TEXT("没有音频设备"));
				EnableWindow(GetDlgItem(hDlg,IDC_PREVIWE),FALSE);
			}
        }
		return TRUE;
	case WM_DESTROY:
        {
			g_CaptureVideo.CloseInterface();
			PostQuitMessage(0);
        }
		break;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDCANCEL:
            {
                PostQuitMessage(0);
            }
           break;
		case IDONESHOT:
            {
                //g_CaptureVideo.GrabOneFrame(TRUE);
				SetTimer(hDlg,ID_TIMER,150,TimerGetPicture);
            }
			break;
		
		case IDC_PREVIWE:
			{
				//Video
				iGetCurSel = ComboBox_GetCurSel(hwndCombo1);
				g_CaptureVideo.OpenDevice(iGetCurSel,20,30,430,400);
				EnableWindow(GetDlgItem(hDlg,IDONESHOT),TRUE);

				//Audio
				iGetCurSel = ComboBox_GetCurSel(hwndCombo2);
				bstrDeviceName = SysAllocString(g_CaptureAudio.m_pCapDeviceName[iGetCurSel]);
				g_CaptureAudio.OpenDevice(bstrDeviceName);
			}
			break;
		default: break;
		}
	case WM_MOVE:
		g_CaptureVideo.m_pVideoWindow->NotifyOwnerMessage((OAHWND)hDlg, message, wParam, lParam);
		break;
	}
	return (FALSE);
}

VOID CALLBACK TimerGetPicture(HWND hDlg, UINT message, UINT iTimerID, DWORD dwTimer)
{
	if(g_nTimerCount < 25)
	{
		g_CaptureVideo.GrabOneFrame(TRUE);
		g_nTimerCount++;
	}else
	{
		KillTimer(hDlg,ID_TIMER);
		g_nTimerCount = 0;
	}
}

VOID SetWindowPosCenter(HWND hDlg)
{
	int cxWindow,cyWindow;  //window Screen width and height
	RECT hDlgRect;          //Dialog Rect
	int cxDialog,cyDialog;  //Dialog Screen width and height
	int cxSetPos,cySetPos;

	GetWindowRect(hDlg,&hDlgRect);
	//
	cxDialog = hDlgRect.right - hDlgRect.left;
	cyDialog = hDlgRect.bottom - hDlgRect.top;
	//
	cxWindow = GetSystemMetrics(SM_CXSCREEN);
	cyWindow = GetSystemMetrics(SM_CYSCREEN);
	//
	cxSetPos = (cxWindow-cxDialog)/2;
	cySetPos = (cyWindow-cyDialog)/2;

	SetWindowPos(hDlg,NULL,cxSetPos,cySetPos,0,0,SWP_NOSIZE);


}


你可能感兴趣的:(完整的DirectShow捕获音视频的demo(源码))