|
下载:DirectShow获取视频和音频数据
近段时间由于工作上的需要,大概看了下DirectShow,写了个小的demo,方便理解。以后在深入的学习下DirectShow。贴出代码。
对音频所做的处理如下图:
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);
HRESULTDeviceConnect(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);
}
|
|