65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 OpenGL 和 Video for Windows 轻松生成 AVI 视频的类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (32投票s)

2001 年 10 月 3 日

3分钟阅读

viewsIcon

457361

downloadIcon

13880

如果您想从 OpenGL 应用程序生成 AVI 视频,那么这个类就是您所需要的。

Sample Image - AviGenerator.jpg

引言

CAviGenerator 是 Video For Windows (VFW) 库的一个简单封装。它会在后台为您处理大量的初始化工作,并隐藏库函数调用,这样用户就可以用最少的代码行数开始生成电影,而无需对 VFW 有太多的了解。

该类的主要特点是

  • 生成您机器上安装的任何编解码器的 AVI 电影
  • 无需生成数千个单独的图像,
  • 使用简单

CAVIGenerator 类从 MSDN 示例 writeavi.c 中汲取灵感。

CAVIGenerator:一个 AVI 视频封装器

一个简单的类,使 AVI 视频的创建变得容易。

属性

每个对象包含电影的一般特征,例如

  • 文件名,
  • 帧率(fps)
  • 图像描述:BITMAPINFOHEADER
这些成员被声明为 protected,可以通过 Set 方法访问。

它还包含用于处理“Video for Windows”AVI 引擎的私有成员。

构造函数

CAVIGenerator();

默认构造函数,默认文件名是“Untitled.avi”,帧率是 30 fps。

CAVIGenerator(LPCTSTR sFileName, CView* pView, DWORD dwRate);

带 CView 的原地构造函数。请参见 SetBitmapHeader(CView* pView)

CAVIGenerator(LPCTSTR sFileName, LPBITMAPINFOHEADER lpbih, DWORD dwRate);

BITMAPINFOHEADER 的原地构造函数。请参见 SetBitmapHeader(LPBITMAPINFOHEADER lpbih)

设置器和获取器

void SetFileName(const CString& _sFileName)

SetFileName 设置输出文件的名称。文件名扩展名应为 .avi,否则 AVI 创建将无法工作。对 .avi 扩展名的检查留给用户。

void SetRate(DWORD dwRate)

SetRate 设置帧率(fps)。

void SetBitmapHeader(CView* pView);

SetBitmapHeader 使用视图 pView 的宽度、高度、24 位/颜色和 BRG 信息填充 m_bih 中的位图信息。它确保宽度和高度都是 4 的倍数。

void SetBitmapHeader(LPBITMAPINFOHEADER lpbih);

SetBitmapHeader 设置位图信息,如 lpbih 中的所示。它假定用户知道自己在做什么。

LPBITMAPINFOHEADER GetBitmapHeader()

GetBitmapHeader 返回指向位图信息头结构的指针。

AVI 创建函数

HRESULT InitEngine();

InitEngine 初始化 VFW 引擎并选择一个编解码器。必须在开始捕获帧之前调用此函数。进行了一些断言以检查位图信息是否已正确初始化。它返回最后一个 HRESULT。如果发生错误,可以使用 GetLastErrorMessage() 检索错误消息。

CAviGenerator avi;
HRESULT hr;

hr=avi.InitEngine();
if (FAILED(hr))
{
    AfxMessageBox(avi.GetLastErrorMessage());
    ...
}
HRESULT AddFrame(BYTE* bmBits);

AddFrame 将一帧添加到电影中。bmBits 指向的数据应与 SetBitmapHeader 所做的位图描述兼容。通常对于 OpenGL,bmBits 是使用 glReadPixels 读取的缓冲区。与 InitEnginge 一样,它返回 HRESULT。

void ReleaseEngine();

ReleaseEngine 释放为电影分配的资源并关闭文件。

使用 CAVIGenerator

您必须遵循以下步骤

  1. 设置文件名(可选)、帧率(可选)和位图信息(必需)。如果您想捕获 OpenGL 屏幕,只需将 CView 对象的指针发送到 SetBitmapHeader 函数。或者,用户可以自己填充 BITMAPINFOHEADER 结构。确保位图尺寸是 4 的倍数。
  2. 通过调用 InitEngine 初始化 AVI 引擎。将弹出对话框以选择和填写编解码器的参数。
  3. 对于每一帧:执行绘图操作,用 BRG 顺序填充图像缓冲区,并通过 AddFrame 将其发送到 AVI 引擎。
  4. 通过调用 ReleaseEngine 释放资源并关闭文件。

您就完成了!以下是一些演示伪代码

CAVIGenerator AviGen;	// generator
BYTE* bmBits;	// image buffer
HRESULT hr;

AviGen.SetRate(20);	// set 20fps
AviGen.SetBitmapHeader(GetActiveView());	// get bitmap info out of the view
hr=AviGen.InitEngine()	// start engine
if (FAILED(hr))
{
    AfxMessageBox(avi.GetLastErrorMessage());
    goto Cleaning;
}

LPBITMAPINFOHEADER lpbih=AviGen.GetBitmapInfo(); // getting bitmap info

// allocating memory for bmBits
bmBits=new BYTE[3 /* BRG*/ * lpbih->biWidth* lpbih->biHeight];	
for (int i=0;i<100;i++)	// make 100 frames
{
	// TODO pust your draw code here.	
	 /* Draw code where bmBits is filled. 
	 For example, to read OpenGL buffer, put 
	 glReadPixels(0,0,lpbih->biWidth,lpbih->biHeight, 
                       GL_BGR_EXT,GL_UNSIGNED_BYTE,bmBits); */ 

	// adding frame and continue if OK
	hr=AviGen.AddFrame(bmBits);
	if (FAILED(hr))
	{
	    AfxMessageBox(avi.GetLastErrorMessage());
	    goto Cleaning;
	}
}
	
// cleaning memory	
Cleaning:
AviGen.ReleaseEngine(); // releasing ressources
delete[] bmBits;	// release ressources

将 CAVIGenerator 添加到您的项目中

  1. AVIGenerator.hAVIGenerator.cpp 添加到您的项目中。

非 MFC 应用程序

如果您想在没有 MFC 的情况下使用 CAviGenerator,请在 AviGenerator.h 中取消定义 _AVIGENERATOR_MFC。这将禁用 MFC 函数调用。

演示项目

一个简单的 MFC SDI 应用程序,使用 OpenGL 显示旋转的立方体和三角形。当选择菜单项 Avi Generation->Generate... 时,您将开始创建 100 帧的 AVI 电影。

OpenGL 绘图代码是从 NeHe Productions 的第 5 课复制粘贴的。

更新历史

  • 2002 年 10 月 21 日 移植到非 MFC 应用程序,添加了 HRESULT 处理
  • 2001 年 8 月 11 日 修复了其他错误。感谢 Dick W Augustsson。
  • 2001 年 2 月 11 日 修复了设置位图头 biSizeImage 字段的错误。感谢 David。
  • 2001 年 8 月 10 日 修复了 ~CAviGenerator 中的错误以及以上示例中的错误(未初始化 LPBITMAPINFOHEADER lpbih)。
  • 2001 年 5 月 10 日 修复了 CAVIGenerator::SetBitmapHeader(LPBITMAPINFOHEADER lpbih) 函数中的错误。感谢 Lori Gardi。
© . All rights reserved.