首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

directshow采集摄像头的图像,该如何解决

2012-04-24 
directshow采集摄像头的图像/**函数介绍: 初始化DSHOW接口,并预览视频*入口参数: hVideoWnd : 显示视频的

directshow采集摄像头的图像
/*
*函数介绍: 初始化DSHOW接口,并预览视频
*入口参数: hVideoWnd : 显示视频的窗口句柄
strFileName :录像文件名
*出口参数:(无)
*返回值:TRUE:成功;FALSE:失败
*/
BOOL CCamera::PreviewCamera(HWND hVideoWnd /*视频显示窗口*/
,LPCTSTR strFileName /*录像文件名*/)
{
HRESULT hResult = S_FALSE;
LONGLONG dwStart = 0, dwEnd = 0;
WORD wStartCookie = 1, wEndCookie = 2;
CRect rectVideo; //视频窗口尺寸
CComVariant varCamName; //定义摄像头设备名称
WCHAR wzDeviceName[ MAX_PATH + 1 ]; //摄像头设备名称
CPropertyBag PropBag; //摄像头属性页

//--定义录像用到的编码、写文件等FILTER
CComPtr<IBaseFilter> pVideoEncoder;
CComPtr<IBaseFilter> pASFMultiplexer;
CComPtr<IFileSinkFilter> pFileSinkFilter;
CComPtr<IDMOWrapperFilter> pWrapperFilter;

//默认先释放DSHOW接口
FreeDShow();

//1,创建ICaptureGraphBuilder2接口,用于管理媒体捕捉对象
CHK(m_pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder));

//2,创建IGraphBuilder接口
CHK(m_pGraphBuilder.CoCreateInstance(CLSID_FilterGraph));

//3,
CHK(m_pCaptureGraphBuilder->SetFiltergraph(m_pGraphBuilder ));

//4,得到IMediaControl接口,用于控制流播放
CHK(m_pGraphBuilder.QueryInterface(&m_pMediaControl)); 


//5,得到IMediaSeeking接口,用于设置播放位置
CHK(m_pGraphBuilder.QueryInterface(&m_pMediaSeeking)); 

//6,得到m_pMediaEvent接口,用于获取媒体事件
CHK(m_pGraphBuilder.QueryInterface(&m_pMediaEvent)); 

//7,创建视频捕捉Filter
CHK(m_pVideoCaptureFilter.CoCreateInstance(CLSID_VideoCapture));

//8,得到视频捕捉属性页接口
CHK(m_pVideoCaptureFilter->QueryInterface(&m_pPropertyBag ));

//9,选择视频捕捉设备
//得到第1个视频捕捉设备名。
if (!GetFirstCameraDriver( wzDeviceName ))
{
goto Cleanup;
}
varCamName = wzDeviceName;
if(( varCamName.vt == VT_BSTR ) == NULL ) {
return FALSE;
}
//设置视频捕捉为第1个捕捉设备
PropBag.Write( L"VCapName", &varCamName );  
CHK(m_pPropertyBag->Load( &PropBag, NULL ));

//10,将视频捕捉FILTER添加到FILTER图中。
CHK(m_pGraphBuilder->AddFilter( m_pVideoCaptureFilter, L"Video capture source" ));

//11,创建IDMOWrapperFilter接口
CHK(pVideoEncoder.CoCreateInstance( CLSID_DMOWrapperFilter ));
CHK(pVideoEncoder.QueryInterface( &pWrapperFilter ));
//12,加载WMV9 DMO
CHK(pWrapperFilter->Init( CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER ));

// 13,将编码器FILTER加入到过滤器图中
CHK(m_pGraphBuilder->AddFilter( pVideoEncoder, L"WMV9 DMO Encoder" ));

//14,创建ASF多路(复用)器,并加入到过滤器图中
CHK(m_pCaptureGraphBuilder->SetOutputFileName( &MEDIASUBTYPE_Asf,strFileName, &pASFMultiplexer, &pFileSinkFilter ));


//15,渲染预览视频PIN
CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video, m_pVideoCaptureFilter,
NULL, NULL ));

//16,设置视频预览窗口
CHK(m_pGraphBuilder.QueryInterface(&m_pVideoWindow));

////设置视频播放的WINDOWS窗口
m_pVideoWindow->put_Owner((OAHWND)hVideoWnd);
m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);

//设置视频尺寸
GetClientRect(hVideoWnd,&rectVideo);
m_pVideoWindow->SetWindowPosition(0,0,rectVideo.Width(),rectVideo.Height());
m_pVideoWindow->put_Visible(OATRUE);

//17,渲染捕捉PIN, 用于录像
CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pVideoEncoder, pASFMultiplexer ));

//18,创建Still Pin,用于抓图
CHK(m_pImageSinkFilter.CoCreateInstance(CLSID_IMGSinkFilter));
CHK(m_pGraphBuilder->AddFilter(m_pImageSinkFilter, L"Still image filter" ));
CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_STILL, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, m_pImageSinkFilter ));

//19,设置捕捉流暂停


CHK(m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, 0, 0 ,0,0 ));

//20,预览视频
CHK(m_pMediaControl->Run());
Sleep(1000);

Cleanup:
//释放接口
if (pVideoEncoder != NULL)
{
pVideoEncoder.Release();
pVideoEncoder = NULL;
}

if (pASFMultiplexer != NULL)
{
pASFMultiplexer.Release();
pASFMultiplexer = NULL;
}

if (pFileSinkFilter != NULL)
{
pFileSinkFilter.Release();
pFileSinkFilter = NULL;
}

if (pWrapperFilter != NULL)
{
pWrapperFilter.Release();
pWrapperFilter = NULL;
}

if( FAILED( hResult ))
{
return FALSE;
}
else
{
return TRUE;
}

}

这个代码再帮解释一下,如何把图像流读到一个内存中?

想问下。因为需要把数据发送到其他PC上。

[解决办法]
SDK手册上有没有说摄像头采集的数据格式是什么?如果是字符型的就声明一个全局变量 char *g_image=NULL;
然后在采集前初始化时动态分配内存,g_image=malloc(size*sizeof(unsigned char));还可以用memset将内存区初始化为0什么的,不需要时记得删除指针,防止内存泄露

热点排行