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






4.92/5 (32投票s)
2001 年 10 月 3 日
3分钟阅读

457361

13880
如果您想从 OpenGL 应用程序生成 AVI 视频,那么这个类就是您所需要的。
引言
CAviGenerator
是 Video For Windows (VFW) 库的一个简单封装。它会在后台为您处理大量的初始化工作,并隐藏库函数调用,这样用户就可以用最少的代码行数开始生成电影,而无需对 VFW 有太多的了解。
该类的主要特点是
- 生成您机器上安装的任何编解码器的 AVI 电影
- 无需生成数千个单独的图像,
- 使用简单
CAVIGenerator
类从 MSDN 示例 writeavi.c 中汲取灵感。
CAVIGenerator:一个 AVI 视频封装器
一个简单的类,使 AVI 视频的创建变得容易。
属性
每个对象包含电影的一般特征,例如
- 文件名,
- 帧率(fps)
- 图像描述:
BITMAPINFOHEADER
它还包含用于处理“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
您必须遵循以下步骤
- 设置文件名(可选)、帧率(可选)和位图信息(必需)。如果您想捕获 OpenGL 屏幕,只需将
CView
对象的指针发送到SetBitmapHeader
函数。或者,用户可以自己填充BITMAPINFOHEADER
结构。确保位图尺寸是 4 的倍数。 - 通过调用
InitEngine
初始化 AVI 引擎。将弹出对话框以选择和填写编解码器的参数。 - 对于每一帧:执行绘图操作,用 BRG 顺序填充图像缓冲区,并通过
AddFrame
将其发送到 AVI 引擎。 - 通过调用
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 添加到您的项目中
- 将 AVIGenerator.h 和 AVIGenerator.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。