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什么的,不需要时记得删除指针,防止内存泄露