1 windows下用dshow可以捕获摄像头和麦克风数据,参照上一篇获取设备信息后可以进一步写出获取数据的代码,继续抛砖
class CDeviceCapture : public ISampleGrabberCB
{
public:
STDMETHODIMP_(ULONG) AddRef() { return 2; }
STDMETHODIMP_(ULONG) Release() { return 1; }
virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ){ return S_OK; };
virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen );
virtual STDMETHODIMP QueryInterface( REFIID riid, void ** ppv )
{
if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){
*ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
return NOERROR;
}
return E_NOINTERFACE;
};
public:
CDeviceCapture(int iType,wstring wszFriendlyName,AM_MEDIA_TYPE* pAmType)
{
m_iType = iType;
m_pAmType = NULL;
setAmType(pAmType);
m_wszFriendlyName = wszFriendlyName;
buildDshowCapGraph(wszFriendlyName);
}
~CDeviceCapture()
{
}
AM_MEDIA_TYPE* getAmType()
{
return m_pAmType;
}
void startCap()
{
m_pControl->Run();
}
void stopCap()
{
m_pControl->Stop();
}
void pauseCap()
{
m_pControl->Pause();
}
private:
void setAmType(AM_MEDIA_TYPE* amType)
{
m_iType==DEVICE_CAP_VIDEO_TYPE?printAmInfo(amType):printAmInfo(amType,false);
if(m_pAmType)
{
DeleteMediaType(m_pAmType);
m_pAmType = NULL;
}
m_pAmType = CreateMediaType(amType);
//FreeMediaType(*m_pAmType);
//CopyMediaType(m_pAmType,amType);
}
bool createDeciceCap(wstring wszFridlyName,IBaseFilter*& device);
bool buildDshowCapGraph(wstring wszFridlyName);
private:
int m_iType;
CComPtr<ICaptureGraphBuilder2> m_pCapGraph2;
CComPtr<IMediaControl> m_pControl;
AM_MEDIA_TYPE* m_pAmType;
wstring m_wszFriendlyName;
CComPtr<ISampleGrabber> m_pSampleGrab;
};
bool CDeviceCapture::createDeciceCap(wstring wszFridlyName,IBaseFilter*& device)
{
bool audio = m_iType== DEVICE_CAP_AUDIO_TYPE?true:false;
CComPtr<ICreateDevEnum> de;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&de);
if (hr != NOERROR) {
__LOGOUT("Can't create CLSID_SystemDeviceEnum object");
return false;
}
CComPtr<IEnumMoniker> em;
if (audio) {
hr = de->CreateClassEnumerator(CLSID_AudioInputDeviceCategory,&em, 0);
} else {
hr = de->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&em, 0);
}
if (hr != NOERROR) {
__LOGOUT("Can't create CLSID_***InputDeviceCategory object");
return false;
}
ULONG got;
IMoniker *m;
em->Reset();
while(hr = em->Next(1, &m, &got), hr==S_OK)
{
IPropertyBag *pb;
hr = m->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pb);
if(!SUCCEEDED(hr)) continue ;
CDShowCapInfo* pCapInfo = new CDShowCapInfo();
VARIANT var;
var.vt = VT_BSTR;
hr = pb->Read(L"FriendlyName", &var, NULL);
if (hr == S_OK) {
wstring szName;
szName.append((wchar_t*)var.bstrVal);
pCapInfo->setFriendlyName(szName);
SysFreeString(var.bstrVal);
if(szName == wszFridlyName)
{
IBaseFilter* dev=NULL;
hr = m->BindToObject(NULL,NULL,IID_IBaseFilter,(void**)&device);
if (hr != S_OK)
{ __LOGOUT("Create Device faild, BindToObjcet error"); }
//device = dev;
return true;
}
}
}
return false;
}
bool CDeviceCapture::buildDshowCapGraph(wstring wszFridlyName)
{
bool audio = m_iType== DEVICE_CAP_AUDIO_TYPE?true:false;
CComPtr<ICaptureGraphBuilder2> graphBuilder;
CComPtr<IGraphBuilder> graph;
CComPtr<IBaseFilter> device ;
HRESULT hr;
IBaseFilter** dev = NULL;
//创建设备filter
if (!createDeciceCap(wszFridlyName, (IBaseFilter*&)device)) {
ThrowStdExp("Can't create AV device filter");
}
assert(device);
//创建filtergraph, capturegraphbuilder2对象
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&graph);
if (FAILED(hr)) {
ThrowStdExp("Can't create CLSID_FilterGraph, Direct X hasn't installed?");
}
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&graphBuilder);
if (FAILED(hr)) {
ThrowStdExp("Can't create CLSID_CaptureGraphBuilder2, Direct X hasn't installed?");
}
hr = graphBuilder->SetFiltergraph(graph);
if (FAILED(hr)) {
ThrowStdExp("SetFiltergraph failed");
}
//隐藏窗口
CComQIPtr<IMediaControl> control = graph;
CComQIPtr<IVideoWindow> window = graph;
window->put_Visible(OAFALSE);
//加入source filter
hr = graph->AddFilter(device, NULL);
if (FAILED(hr)) {
ThrowStdExp("source AddFilter failed");
}
CComPtr<IBaseFilter> nullRender;
hr = CoCreateInstance(CLSID_NullRenderer,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**)&nullRender);
if(FAILED(hr)){
ThrowStdExp("Create Interface error");
}
hr = graph->AddFilter(nullRender, NULL);
if (FAILED(hr)) {
ThrowStdExp("source AddFilter failed");
}
CComPtr<ISampleGrabber> sampleGrabber;
hr = CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,IID_ISampleGrabber,(void**)&sampleGrabber);
if(FAILED(hr)){
ThrowStdExp("Create Interface error");
}
CComPtr<IBaseFilter> filterGrab;
filterGrab = sampleGrabber;
hr = graph->AddFilter(filterGrab, NULL);
if (FAILED(hr)) {
ThrowStdExp("source AddFilter failed");
}
const GUID gType = audio?MEDIATYPE_Audio:MEDIATYPE_Video;
CComPtr<IAMStreamConfig> config;
hr = graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
&gType,
device, IID_IAMStreamConfig, (void **)&config);
if(FAILED(hr)){
ThrowStdExp("Create Interface error");
}
hr = config->SetFormat(m_pAmType); //设置input pin的media type ,传null重置pin为默认type
if (FAILED(hr)) {
int iErr = ::GetLastError();
ThrowStdExp("Can't Pause for grabber");
}
hr =sampleGrabber->SetMediaType(m_pAmType); //设置后,运行时会检查output pin 如果类型不符合会拒绝连接,可不调用
hr = graphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,&gType,device,filterGrab,nullRender);
if(FAILED(hr)){
ThrowStdExp("Create Interface error");
}
AM_MEDIA_TYPE iAmType;
hr = sampleGrabber->GetConnectedMediaType(&iAmType);
if (FAILED(hr)) {
ThrowStdExp("Can't GetConnectedMediaType for grabber");
}
this->setAmType(&iAmType);
FreeMediaType(iAmType);
sampleGrabber->SetCallback(this,1);
hr = control->Pause();
if (FAILED(hr)) {
int iErr = ::GetLastError();
ThrowStdExp("Can't Pause for grabber");
}
m_pCapGraph2 = graphBuilder;
m_pControl = control;
m_pSampleGrab = sampleGrabber;
return true;
}
STDMETHODIMP CDeviceCapture::BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen )
{
printf("time: %f, buffer size: %ld ",SampleTime,BufferLen);
if(m_iType == DEVICE_CAP_VIDEO_TYPE){
printAmInfo(m_pAmType);
AM_MEDIA_TYPE amType ;
m_pSampleGrab->GetConnectedMediaType(&amType);
printAmInfo(&amType);
}
else
{
printAmInfo(m_pAmType,false);
}
printf("\r\n");
return S_OK;
}
int _tmain(int argc, _TCHAR* argv[])
{
try{
::CoInitialize(NULL);
CDshowCapInfoMgr* mgr = new CDshowCapInfoMgr();
mgr->enumAllCapInfo();
mgr->printCapDetail();
//CDShowCapInfo* pInfo = mgr->getVideoInfo(0);
//CDeviceCapture* device = new CDeviceCapture(DEVICE_CAP_VIDEO_TYPE,pInfo->getFriendlyName(),pInfo->getMediaOption(8));
CDShowCapInfo* pInfo = mgr->getAudioInfo(0);
CDeviceCapture* device = new CDeviceCapture(DEVICE_CAP_AUDIO_TYPE,pInfo->getFriendlyName(),pInfo->getMediaOption(0));
device->startCap();
while (true)
{
Sleep(1000);
}
}catch(std::exception e)
{
printf(e.what());
}
return 0;
}