windows下使用vfw方式生成AVI视频的实现

生成视频文件的方式很多,你可以使用libx264这个开源的264编解码库来编码视频,生成视频文件;但是这样很麻烦,还需要另外找一个包装器(比如mp4)来包装这个视频流,否则播放器一般无法识别和播放。

想生成视频文件?何必舍近求远,windows系统本身就内置了一套视频生成框架——VFW,它提供了一组API,可以直接将RGB数据写入到视频文件中,大部分播放器都能够识别并播放这种视频文件。下面我将发布一个我修改过的AVI视频录制类,使用者可以直接使用此类来录制视频。

//
// avifile.h
//
#include <windows.h>
#include <vfw.h>

class CAviFile
{
public:
	CAviFile();
	~CAviFile(void);

	/// <Summary> 
	/// 初始化AVI对象
	/// </Summary>
	HRESULT Open(LPCSTR lpszFileName, DWORD dwCodec, DWORD dwFPS, INT nWidth, INT nHeight, INT nQuality, INT nKeyFrame);

	/// <Summary> 
	/// 销毁AVI对象
	/// </Summary>
	HRESULT Close(void);

	/// </Summary>
	/// Inserts the given bitmap bits into the movie as a new Frame at the end.
	/// The width, height and nBitsPerPixel are the width, height and bits per pixel
	/// of the bitmap pointed to by the input pBits.
	/// </Summary>
	HRESULT	AppendNewFrame(int nWidth, int nHeight, LPVOID pBits, int nBitsPerPixel);

	
private:
	HRESULT	AppendFrame(int, int, LPVOID, int);

private:
	// Keeps track of the current Frame Index
	LONG				m_lSample;
	PAVIFILE            m_pAviFile;
	PAVISTREAM			m_pAviStream;
	PAVISTREAM			m_pAviCompressedStream;

	// RGB缓冲区
	BOOL                m_bStatus;
};



//
// avifile.cpp
//
#include "StdAfx.h"
#include "avifile.h"

#pragma comment( lib, "vfw32.lib" )

CAviFile:: CAviFile()
{
	m_bStatus     = FALSE;
	m_lSample     = 0;
	m_pAviFile    = NULL;
	m_pAviStream  = NULL;
}
CAviFile::~CAviFile(void)
{
	Close();
}

HRESULT CAviFile::Open(LPCSTR lpszFileName, DWORD dwCodec, DWORD dwFPS, INT nWidth, INT nHeight, INT nQuality, INT nKeyFrame)
{
	if (m_bStatus)
	{
		return S_OK;
	}

	AVIFileInit();
	if(FAILED(AVIFileOpen(&m_pAviFile, lpszFileName, OF_CREATE | OF_WRITE, NULL)))
	{
		return E_FAIL;
	}

	// 默认质量
	AVISTREAMINFO AviStreamInfo;
	ZeroMemory(&AviStreamInfo, sizeof(AVISTREAMINFO));
	AviStreamInfo.fccType		          = streamtypeVIDEO;
	AviStreamInfo.fccHandler	          = dwCodec;
	AviStreamInfo.dwScale		          = 1;
	AviStreamInfo.dwRate		          = dwFPS;
	//AviStreamInfo.dwQuality	          = m_nQuality;
	AviStreamInfo.dwSuggestedBufferSize = nWidth * nHeight * 3;
    SetRect(&AviStreamInfo.rcFrame, 0, 0, nWidth, nHeight);
	lstrcpy(AviStreamInfo.szName, "VideoStream");
	if(FAILED(AVIFileCreateStream(m_pAviFile, &m_pAviStream, &AviStreamInfo)))
	{
		return E_FAIL;
	}

	AVICOMPRESSOPTIONS	AviCompressOptions;
	ZeroMemory(&AviCompressOptions, sizeof(AVICOMPRESSOPTIONS));
	AviCompressOptions.fccType          = streamtypeVIDEO;
	AviCompressOptions.fccHandler       = AviStreamInfo.fccHandler;
	AviCompressOptions.dwFlags          = AVICOMPRESSF_KEYFRAMES | AVICOMPRESSF_VALID;//|AVICOMPRESSF_DATARATE;
	AviCompressOptions.dwKeyFrameEvery  = nKeyFrame;
	//AviCompressOptions.dwBytesPerSecond = 0;
	AviCompressOptions.dwQuality        = nQuality;
	if(FAILED(AVIMakeCompressedStream(&m_pAviCompressedStream, m_pAviStream, &AviCompressOptions, NULL)))
	{
		// One reason this error might occur is if you are using a Codec that is not 
		// available on your system. Check the mmioFOURCC() code you are using and make
		// sure you have that codec installed properly on your machine.
		return E_FAIL;
	}

	BITMAPINFO bmpInfo;
	ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
	bmpInfo.bmiHeader.biPlanes		= 1;
	bmpInfo.bmiHeader.biWidth		= nWidth;
	bmpInfo.bmiHeader.biHeight		= nHeight;
	bmpInfo.bmiHeader.biCompression	= BI_RGB;
	bmpInfo.bmiHeader.biBitCount	= 24;
	bmpInfo.bmiHeader.biSize		= sizeof(BITMAPINFOHEADER);
	bmpInfo.bmiHeader.biSizeImage	= bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biHeight * bmpInfo.bmiHeader.biBitCount / 8;
	if(FAILED(AVIStreamSetFormat(m_pAviCompressedStream, 0, (LPVOID)&bmpInfo, bmpInfo.bmiHeader.biSize)))
	{
		// One reason this error might occur is if your bitmap does not meet the Codec requirements.
		// For example, 
		//   your bitmap is 32bpp while the Codec supports only 16 or 24 bpp; Or
		//   your bitmap is 274 * 258 size, while the Codec supports only sizes that are powers of 2; etc...
		// Possible solution to avoid this is: make your bitmap suit the codec requirements,
		// or Choose a codec that is suitable for your bitmap.
		return E_FAIL;
	}

	m_bStatus = TRUE;

	return S_OK;
}
HRESULT CAviFile::Close(void)
{
	if (!m_bStatus)
	{
		return S_OK;
	}

	m_bStatus = FALSE;
	m_lSample = 0;

	if(m_pAviCompressedStream)
	{
		AVIStreamRelease(m_pAviCompressedStream);
		m_pAviCompressedStream = NULL;
	}

	if(m_pAviStream)
	{
		AVIStreamRelease(m_pAviStream);
		m_pAviStream = NULL;
	}
	if(m_pAviFile)
	{
		AVIFileRelease(m_pAviFile);
		m_pAviFile = NULL;
	}

	AVIFileExit();
	return S_OK;
}
HRESULT	CAviFile::AppendNewFrame(int nWidth, int nHeight, LPVOID pBits,int nBitsPerPixel)
{
	return AppendFrame(nWidth, nHeight, pBits, nBitsPerPixel);
}

HRESULT	CAviFile::AppendFrame(int nWidth, int nHeight, LPVOID pBits,int nBitsPerPixel)
{
	if (!m_bStatus)
	{
		return E_FAIL;
	}
	return AVIStreamWrite(m_pAviCompressedStream, m_lSample++, 1, pBits, (nWidth * nHeight * nBitsPerPixel), 0, NULL, NULL);
}

调用用如下方法:

CAviFile m_videoRecord; //定义对象

// 创建avi文件
CString strFile =  _T("C:\\1.avi");
if (FAILED(m_videoRecord.Open(strFile, /*mmioFOURCC('I', '4', '2', '0')*/mmioFOURCC('X', '2', '6', '4'), 5, m_rectWnd.Width(), m_rectWnd.Height(), 100 * 100, 30)))
{
	return FALSE;
}

// 写入视频帧
m_videoRecord.AppendNewFrame(nWidth, nHeight, pBit, 3);

写到这里也就完成了99%了,如果你就这样拿去调试的话,

m_videoRecord.Open

会返回失败,因为找不到响应的编码器,你需要下载x264vfw编码器库, 点这里下载

然后安装,完了在调试就没问题了。

这里只是生成了视频文件,如果还需要音频文件的话,那就相对比较麻烦了,

需要单独在录制一个wav的音频文件,然后在使用AVISaveVW这个API想音视频流合并起来才可以。

各种麻烦就不说了,而且音视频还不同步;如果需要录制带音频的视频文件,就推荐用这种方法了,

建议直接用x264编码视频,用libfaac编码音频,然后用libmp4来包装即可。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值