分享
 
 
 

directshow的中文资料之设备列举和捕捉接口

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

这篇解释和示例如何通过DirectShow的接口去初始化和访问系统的硬件设备。代表性的,DirectShow应用程序使用下面类型的硬件。

音/视频捕捉卡

音频或视频回放卡

音频或视频压缩或解压卡(象MPEG解码器)

下面将以AV设备作参考。

如何列举设备

包括在DirectShow SDK中的接口,类,和例子提供了音/视频捕捉和回放的功能。因为文件源过滤器和filter graph manager处理了内在的工作,所有,添加捕捉功能到一个应用程序中,只需添加很少的代码。你可以通过列举系统硬件设备和得到设备列表完成特别的任务(例如:所有的视频捕捉卡的列表)。DirectShow自动为win32和Video for Windows 设备实例化过滤器。

要AV设备工作,首先,你必须检测当前系统存在的设备。ICreateDevEnum接口建立指定类型的列表。提供你需要的检测和设置硬件的功能。访问一个指定的设备有三步,详细的说明和代码如下:

建立系统硬件设备的列表

首先,申明一个列表指针,然后通过 CoCreateInstance 建立。CLSID_SystemDeviceEnum是我们想建立对象的类型,IID_ICreateDevEnum是接口的GUID。

ICreateDevEnum *pCreateDevEnum ;

CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,

IID_ICreateDevEnum, (void**)&pCreateDevEnum) ;

其次,建立一个特别类型的硬件设备的列表(例如视频捕捉卡)

申明一个IEnumMoniker接口,并把他传给ICreateDevEnum::CreateClassEnumerator 方法。你就可以使用他访问新得到的列表了。

IEnumMoniker *pEnumMon ;

pCreateDevEnum->CreateClassEnumerator(

[specify device GUID here]

&pEnumMon, 0);

最后,列举列表直到你得到你想要的设备为止。

如果先前的CreateClassEnumerator调用成功了,你可以用IEnumMoniker::Next得到设备。调用IMoniker::BindToObject建立一个和选择的device联合的filter,并且装载filter的属性(CLSID,FriendlyName, and DevicePath)。不需要为if语句的(1 == cFetched) 困惑,在测试合法性之前,pEnumMon->Next(1, &pMon, &cFetched)方法会设置他为返回对象的数字(如果成功了为1)。

ULONG cFetched = 0;

IMoniker *pMon ;

if (S_OK == (pEnumMon->Next(1, &pMon, &cFetched)) && (1 == cFetched))

{

pMon->BindToObject(0, 0, IID_IBaseFilter, (void **)&[desired interface here]) ;

好,现在你有了一个IMoniker指针,你可以添加设备的filter到filter graph。一旦你添加了filter,你就不需要IMoniker指针,设备列表,或系统设备列表。

pGraph->AddFilter([desired interface here], L"[filter name here]") ;

pMon->Release() ; // Release moniker

}

pEnumMon->Release() ; // Release the class enumerator

}

pCreateDevEnum->Release();

实例:AMCap中的设备列表代码

AMCap例子中,把所有的接口指针和一些成员变量保存在一个全局结构gcap中了。

定义如下:

struct _capstuff {

char szCaptureFile[_MAX_PATH];

WORD wCapFileSize; // size in Meg

ICaptureGraphBuilder *pBuilder;

IVideoWindow *pVW;

IMediaEventEx *pME;

IAMDroppedFrames *pDF;

IAMVideoCompression *pVC;

IAMVfwCaptureDialogs *pDlg;

IAMStreamConfig *pASC; // for audio cap

IAMStreamConfig *pVSC; // for video cap

IBaseFilter *pRender;

IBaseFilter *pVCap, *pACap;

IGraphBuilder *pFg;

IFileSinkFilter *pSink;

IConfigAviMux *pConfigAviMux;

int iMasterStream;

BOOL fCaptureGraphBuilt;

BOOL fPreviewGraphBuilt;

BOOL fCapturing;

BOOL fPreviewing;

BOOL fCapAudio;

int iVideoDevice;

int iAudioDevice;

double FrameRate;

BOOL fWantPreview;

long lCapStartTime;

long lCapStopTime;

char achFriendlyName[120];

BOOL fUseTimeLimit;

DWORD dwTimeLimit;

} gcap;

例子用uIndex变量循环列举系统的硬件设备。

BOOL InitCapFilters()

{

HRESULT hr;

BOOL f;

UINT uIndex = 0;

MakeBuilder函数建立了一个filter graph builder(参考建立一个捕捉程序)。

f = MakeBuilder();

建立设备列表对象,得到ICreateDevEnum接口

ICreateDevEnum *pCreateDevEnum;

hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,

IID_ICreateDevEnum, (void**)&pCreateDevEnum);

建立一个特别类型的硬件设备的列表,类的ID是CLSID_VideoInputDeviceCategory。现在有了一个IEnumMoniker指针,可以访问捕捉设备的列表了。

IEnumMoniker *pEm;

hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);

pCreateDevEnum->Release(); // We don't need the device enumerator anymore

pEm->Reset(); // Go to the start of the

enumerated list

现在需要实际的设备了,调用IEnumMoniker::Next ,然后用得到的指针pM调用IMoniker::BindToObject,绑定filter到设备。如果你不想建立联合的filter,使用IMoniker::BindToStorage 代替IMoniker::BindToObject。

ULONG cFetched;

IMoniker *pM; // This will access the actual devices

gcap.pVCap = NULL;

while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)

{

if ((int)uIndex == gcap.iVideoDevice) { // This is the one we want. Instantiate it.

hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&gcap.pVCap);

pM->Release(); // We don't need the moniker pointer anymore

break;

}

pM->Release();

uIndex++;

}

pEm->Release(); // We've got the device; don't need the

enumerator anymore

当有了设备后,通过接口指针去测量帧数,得到driver的名字,得到捕捉的尺寸(size)。在例子中,把每个指针都存储才gcap全局结构中了。

, and get the capture size. AMCap stores each pointer in the gcap global structure.

// We use this interface to get the number of captured and dropped frames

gcap.pBuilder->FindCaptureInterface(gcap.pVCap,

IID_IAMDroppedFrames, (void **)&gcap.pDF);

// We use this interface to get the name of the driver

gcap.pBuilder->FindCaptureInterface(gcap.pVCap,

IID_IAMVideoCompression, (void **)&gcap.pVC);

// We use this interface to set the frame rate and get the capture size

gcap.pBuilder->FindCaptureInterface(gcap.pVCap,

IID_IAMVideoStreamConfig, (void **)&gcap.pVSC);

然后得到媒体的类型和显示窗口的大小去匹配视频格式的尺寸。

AM_MEDIA_TYPE *pmt;

gcap.pVSC->GetFormat(&pmt); // Current capture format

ResizeWindow(HEADER(pmt->pbFormat)->biWidth,

HEADER(pmt->pbFormat)->biHeight);

DeleteMediaType(pmt);

现在,已经有了视频设备和他的相关信息,重复这个过程,得到音频设和他的信息并存储到全局机构中去。注意,这次是用参数CLSID_AudioInputDeviceCategory 调用ICreateDevEnum::CreateClassEnumerator 。

hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,

IID_ICreateDevEnum, (void**)&pCreateDevEnum);

uIndex = 0;

hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory,

&pEm, 0);

pCreateDevEnum->Release();

pEm->Reset();

gcap.pACap = NULL;

while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)

{

if ((int)uIndex == gcap.iAudioDevice) { // this is the one we want

hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&gcap.pACap);

pM->Release();

break;

}

pM->Release();

uIndex++;

}

pEm->Release();

AMCap also repeats the process of retrieving the format interface, this time for the audio device.

hr = gcap.pBuilder->FindCaptureInterface(gcap.pACap,

IID_IAMAudioStreamConfig, (void **)&gcap.pASC);

}

如何保持DirectShow Filter (Properties) 道具

IPropertyBag 和 IPersistPropertyBag 接口存储和返回Properties的"bags"组。通过这些接口存储的Properties是可以持久保持的。同一个对象在不同的实例之间,他们保持一致。Filter可以存储他们的Properties(CLSID, FriendlyName, and DevicePath)。当一个filter存储完他的Properties之后,实例一个filter时,DirectShow会自动得到他们。添加功能到你的filter中,执行IPersistPropertyBag接口和他的方法。你可以用IPropertyBag::Read 方法装载filter Properties 到Win32 VARIANT 变量中,然后初始化输入输出pin。

下面的代码演示DirectShow的VfWCapture filter如何执行IPersistPropertyBag::Load方法的。记住:在执行期间,你的filter必须提供一个有效的IPropertyBag指针。

STDMETHODIMP CVfwCapture::Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog)

{

HRESULT hr;

CAutoLock cObjectLock(m_pLock); // Locks the object; automatically unlocks it in the destructor.

if (m_pStream) // If the filter already exists for this stream

return E_UNEXPECTED;

VARIANT var; // VARIANT from Platform SDK

var.vt = VT_I4; // four-byte integer (long)

hr = pPropBag->Read(L"VFWIndex", &var, 0); // VFWIndex is the private name used by the Vidcap Class Manager to refer to the VFW Capture filter

if(SUCCEEDED(hr)) // If it read the properties successfully

{

hr = S_OK; // Defaults return value to S_OK

m_iVideoId = var.lVal; // Stores the specified hardware device number

CreatePins(&hr); // Inits the pins, replacing the return value if necessary

}

return hr; // Returns S_OK or an error value, if CreatePins failed

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有