博客
关于我
DirectShow 进行视频预览和录制
阅读量:436 次
发布时间:2019-03-06

本文共 3831 字,大约阅读时间需要 12 分钟。

这一篇讲怎么采集摄像头图像并预览,以及录制视频到本地。

程序实现流程

这里通过使用 CaptureGraphBuilder 来简化 Graph 的创建流程。

具体流程如下:

  1. 初始化 COM 库
  2. 创建各 Filter
  3. 找到视频采集设备,也就是通过 USB 连接的摄像头
  4. 渲染并预览视频
  5. 销毁先前创建的 Filter
  6. 释放COM

视频采集类

先看一下视频采集类的头文件,而源文件就不一次性全部贴出了,而是只介绍几个重要的成员函数。captrue.h 的内容如下:

#pragma once#include 
#include
// 用于确保安全释放的宏#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }class CCapture{public: CCapture(); ~CCapture(); HRESULT Init(HWND hwnd); // 初始化 HRESULT FindCaptureDevice(); // 寻找视频采集设备 HRESULT Render(); // 渲染并预览视频 void DestroyGraph(); // 销毁先前创建的filter void ResizeWindow(); // 重设窗口private: // 窗口句柄 HWND m_hwnd; // 视频采集预览相关 IGraphBuilder *m_pGraph; // filter granph(manager) ICaptureGraphBuilder2 *m_pCapture; // capture granph IMediaControl *m_pMediaC; // 媒体控制接口 IMediaEventEx *m_pMediaE; // 媒体事件接口 IVideoWindow *m_pVideoW; // 视频窗口接口 IBaseFilter *m_pFilter; // 基类filter};

1.初始化

// 初始化HRESULT CCapture::Init(HWND hwnd){	HRESULT hr;	// 创建filter graph manager	hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGraph);	if (FAILED(hr))		return hr;	// 创建capture granph	hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **)&m_pCapture);	if (FAILED(hr))		return hr;	// 查询graph中各IID参数标识的接口指针	hr = m_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pMediaC);	if (FAILED(hr))		return hr;	hr = m_pGraph->QueryInterface(IID_IMediaEventEx, (LPVOID *)&m_pMediaE);	if (FAILED(hr))		return hr;	hr = m_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVideoW);	if (FAILED(hr))		return hr;	// 为capture graph指定要使用的filter graph	hr = m_pCapture->SetFiltergraph(m_pGraph);	if (FAILED(hr))		return hr;	// 将Win32窗口句柄赋给m_hwnd	m_hwnd = hwnd;	return hr;}

进行初始化操作。

2.寻找视频采集设备

// 寻找视频采集设备HRESULT CCapture::FindCaptureDevice(){	HRESULT hr = S_OK;	ICreateDevEnum *pDevEnum = NULL;	IEnumMoniker *pClassEnum = NULL; // 用于视频采集设备的枚举	IMoniker* pMoniker = NULL; // 设备Moniker号	// 创建系统设备枚举	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,IID_ICreateDevEnum, (void **)&pDevEnum);	if (FAILED(hr))		return hr;	// 创建一个指定视频采集设备的枚举	hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClassEnum, 0);	if (FAILED(hr) || pClassEnum == NULL)	{		SAFE_RELEASE(pDevEnum);		return hr;	}	// 使用第一个找到的视频采集设备(只适用于单摄像头的情况)	hr = pClassEnum->Next(1, &pMoniker, NULL);	if (hr == S_FALSE)	{		SAFE_RELEASE(pDevEnum);		SAFE_RELEASE(pClassEnum);		return hr;	}	// 绑定找到摄像头的moniker到filter graph	hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pFilter);	if (FAILED(hr))	{		SAFE_RELEASE(pDevEnum);		SAFE_RELEASE(pClassEnum);		SAFE_RELEASE(pMoniker);		return hr;	}	// 增加filter graph的引用计数	m_pFilter->AddRef(); 	return hr;}

初始化之后,就要找到视频采集设备,即通过 USB 连接的摄像头。这里没有去循环枚举查找多个视频采集设备,固定选择了找到的第一个视频采集设备。

3.渲染并预览视频

// 渲染并预览视频HRESULT CCapture::Render(){	HRESULT hr;        // 将base filter添加到filter graph中    hr = m_pGraph->AddFilter(m_pFilter, L"Video capture");		if (FAILED(hr))	{		m_pFilter->Release();		return hr;	}	// 用ICaptureGraphBuilder2接口构建预览的filter链路	hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pFilter, NULL, NULL);	if (FAILED(hr))	{		m_pFilter->Release();		return hr;	}	// 同时构建一个写文件的filter链路	IBaseFilter *pMux;	hr = m_pCapture->SetOutputFileName(&MEDIASUBTYPE_Avi, L"D:\\example.avi", &pMux, NULL); // 设置输出视频文件位置	hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pFilter, NULL, pMux); // 将m_pFilter的输出pin连接到pMux		// 使用完就可以释放base filter了	pMux->Release();	m_pFilter->Release();	// 显示窗口 , 预览采集图形	hr = m_pVideoW->put_Owner((OAHWND)m_hwnd);	if (FAILED(hr))		return hr;	hr = m_pVideoW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);	if (FAILED(hr))		return hr;	ResizeWindow(); // 重设窗口	hr = m_pVideoW->put_Visible(OATRUE);	if (FAILED(hr))		return hr;	hr = m_pMediaC->Run();		return hr;}

实现效果

代码下载

参考:

转载地址:http://pgsyz.baihongyu.com/

你可能感兴趣的文章
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>
Mysql Innodb 锁机制
查看>>
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>
Mysql InnoDB存储引擎中的checkpoint技术
查看>>
Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
查看>>
MySQL InnoDB引擎的锁机制详解
查看>>
Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
查看>>
mysql InnoDB数据存储引擎 的B+树索引原理
查看>>
mysql innodb通过使用mvcc来实现可重复读
查看>>
mysql interval显示条件值_MySQL INTERVAL关键字可以使用哪些不同的单位值?
查看>>
Mysql join原理
查看>>
mysql order by多个字段排序
查看>>
MySQL Order By实现原理分析和Filesort优化
查看>>
mysql problems
查看>>
mysql replace first,MySQL中处理各种重复的一些方法
查看>>
MySQL replace函数替换字符串语句的用法(mysql字符串替换)
查看>>
Mysql Row_Format 参数讲解
查看>>