directshow学习笔记三-----视频预览(还未播放到指定窗口或控件,个人学习所用,仅供参考)

一、首先获取视频采集设备列表

//获取视频采集设备列表
void CTestPreviewDlg::GetDeviceList()
{
// Create the System Device Enumerator.

HRESULT hr = CoInitialize(NULL);
ICreateDevEnum *pSysDevEnum = NULL;

// 初始化COM  
    //hr = CoInitialize(); 

hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum,(void**)&pSysDevEnum);
if(FAILED(hr))
{
//return NULL;
}
// Obtain a class enumerator for the video compressor category.
//创建一个枚举器,枚举视频设备
IEnumMoniker *pEnumCat = NULL;
hr=pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEnumCat, 0);
if (hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
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))
{
// Display the name in your UI somehow.

m_combo.AddString(CString(varName.bstrVal));
}
VariantClear(&varName);
// To create an instance of the filter, do the following:
IBaseFilter *pFilter;
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
(void**)&pFilter); //生成一个filter绑定到设备上。
// Now add the filter to the graph.
//Remember to release pFilter later.
pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
}
pSysDevEnum->Release();
}

二、指定视频采集设备的友好名字,为它创建一个Filter

//指定视频采集设备的友好名字,为它创建一个Filter
IBaseFilter * CTestPreviewDlg::CreateVideoDevice(const char * inFriendlyName)
{
return CreateHardwareFilter(CLSID_VideoInputDeviceCategory,inFriendlyName);
}


//根据设备的友好名字,创建一个代表该设备的Filter
IBaseFilter * CTestPreviewDlg::CreateHardwareFilter(GUID inCategory,const char *  inFriendlyName)
{
//创建一个系统枚举组件对象
ICreateDevEnum * enumHardware = NULL;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_ALL,
IID_ICreateDevEnum,(void**)&enumHardware);
if(FAILED(hr))
{
return NULL;
}

IBaseFilter * hardwareFilter = NULL;
IEnumMoniker * enumMoniker = NULL;
//为指定的目录创建枚举器
hr = enumHardware->CreateClassEnumerator(inCategory,&enumMoniker,0);
if(enumMoniker)
{
enumMoniker->Reset();

ULONG fetched = 0;
IMoniker * moniker = NULL;
char friendlyName[256];

//枚举得到该目录下所有的设备,逐个进行名字匹配
while(!hardwareFilter && SUCCEEDED(enumMoniker->Next(1,&moniker,
&fetched)) && fetched)
{
if(moniker)
{
IPropertyBag * propertyBag = NULL;
VARIANT name;
friendlyName[0] = 0;
hr = moniker->BindToStorage(0,0,IID_IPropertyBag,(void**)&propertyBag);
//读取设备的友好名字
if(SUCCEEDED(hr))
{
name.vt = VT_BSTR;
hr = propertyBag->Read(L"Friendlyname",&name,NULL);
}
if(SUCCEEDED(hr))
{
WideCharToMultiByte(CP_ACP,0,name.bstrVal,-1,
friendlyName,256,NULL,NULL);
//如果当前设备的友好名字与用户指定的设备名字相同,
//则将当前设备标识绑定为Filter形式
if(strcmp(friendlyName,inFriendlyName) == 0)
{
moniker->BindToObject(0,0,IID_IBaseFilter,
(void**)&hardwareFilter);
}
}

//释放使用过的接口
if(propertyBag)
{
propertyBag->Release();
propertyBag = NULL;
}
moniker->Release();
}
}
enumMoniker->Release();
}
enumHardware->Release();

return hardwareFilter;
}

三、查找引脚

//查找引脚

IPin* CTestPreviewDlg::FindPin(IBaseFilter *pFilter, PIN_DIRECTION dir)
{
IEnumPins* pEnumPins;
IPin* pOutpin;
PIN_DIRECTION pDir;
pFilter->EnumPins(&pEnumPins);
while (pEnumPins->Next(1,&pOutpin,NULL)==S_OK)
{
pOutpin->QueryDirection(&pDir);
if (pDir==dir)
{
return pOutpin;
}
}
return 0;
}


四、视频预览按钮

void CTestPreviewDlg::OnButton1() 
{
// TODO: Add your control notification handler code here
//在对话框初始化时枚举视频捕捉设备,设计过滤图表。
ICaptureGraphBuilder2 * pBuilder = NULL;
pGraph = NULL;
pMediaControl = NULL;

CoCreateInstance(CLSID_CaptureGraphBuilder2,0,
CLSCTX_INPROC_SERVER,IID_ICaptureGraphBuilder2,(void**)&pBuilder);
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
IID_IGraphBuilder, (void **)&pGraph);
pBuilder->SetFiltergraph(pGraph);
pGraph->QueryInterface(IID_IMediaControl,(void**)&pMediaControl);//查询接口


//自动选择第三个为当前工作的视频采集设备
if(m_combo.GetCount() > 0)
{
m_combo.SetCurSel(2);
CString deviceName;
m_combo.GetLBText(2,deviceName);

pSrc = CreateVideoDevice(deviceName);
}


pGraph->AddFilter(pSrc,L"avi");
pPreview = NULL;


CoCreateInstance(CLSID_VideoRenderer,0,CLSCTX_ALL,

IID_IBaseFilter,(void**)&pPreview);


if (pPreview != NULL)
{
pGraph->AddFilter(pPreview,L"preview");
//连接引脚
IPin * pSourceOut;
pSourceOut = FindPin(pSrc,PINDIR_OUTPUT);
IPin*  pPreIn = FindPin(pPreview,PINDIR_INPUT);

pGraph->ConnectDirect(pSourceOut,pPreIn,NULL);


pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, 
pSourceOut, NULL, NULL); 
//获取预览窗口
IVideoWindow * pViewWnd= NULL;
pPreview->QueryInterface(IID_IVideoWindow,(void**)&pViewWnd);
if (pViewWnd)
{

HWND hwnd;
//hwnd = GetSafeHwnd();
GetDlgItem(IDC_STATIC,&hwnd);
//申明此视频窗口的所有者  
//视频窗口的所有者是hWnd窗口,即此窗口将显示在hWnd窗口之上  
pViewWnd->put_Owner((OAHWND)hwnd);  
//设置视频窗口的样式  
pViewWnd->put_WindowStyle(WS_CHILD);  
//捕获视频窗口的宽度和高度  
//pViewWnd->get_Width(&pWidth);  
//pViewWnd->get_Height(&pHeight);  
//设置视频窗口的位置,大小  
pViewWnd->SetWindowPosition(0,0,100, 100); 
//设置预览窗口的拥有者
//HWND hwnd = GetSafeHwnd(); //所以现在我想把当前活动窗口作为播放窗口,也碰到了同样的问题。    
//HRESULT hr = NULL;
//hr = pViewWnd->put_Owner((OAHWND)hwnd);
//pViewWnd->put_WindowStyle(WS_CHILD);
//pViewWnd->put_Visible(OATRUE);
//pViewWnd->SetWindowPosition(100,100,100,100);
//hr = pViewWnd->put_Owner((OAHWND)hwnd);
//pViewWnd->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);

/*
pViewWnd->put_Left(1);
pViewWnd->put_Top(1);
//获取预览窗口风格
long style;
pViewWnd->get_WindowStyle(&style);
style = style & ~WS_CAPTION;
style = style & ~WS_DLGFRAME;
style = style & WS_CHILD;
pViewWnd->put_WindowStyle(style);
//设置预览窗口宽度和高度
CRect rc;
GetClientRect(rc);
pViewWnd->put_Height(rc.Height()-60);
pViewWnd->put_Width(rc.Width()-2);
*/
}
pMediaControl->Run();
}

}

疑问???????

视频预览窗口不能预览到指定窗口或picture空间中,正在学习中。。。望大神指教

另附源代码地址http://download.csdn.net/detail/afu1972715000/8339661

vc++6.0

猜你喜欢

转载自blog.csdn.net/afu1972715000/article/details/42521155