プログラミングメモ →目次

AVIファイル作成(例:スクリーン録画)

AVIFile Functions 関数と構造体を利用して、AVIファイルを作成することができます。

例として、モニターの画面を録画して、"c:\screen.avi"に保存するプログラムを作りました。

下の関数は、Windows画面の左上の{0, 0, 400, 300}の領域を、20フレーム/秒で、10秒間録画するものです。

#include <vfw.h>
#pragma comment (lib, "vfw32.lib")
void RecordScreen()
{
	AVISTREAMINFO aviStreamInfo;
	ZeroMemory(&aviStreamInfo, sizeof(AVISTREAMINFO));
	aviStreamInfo.fccType = streamtypeVIDEO;
	aviStreamInfo.fccHandler = comptypeDIB;
	aviStreamInfo.dwScale = 1;
	aviStreamInfo.dwRate = 20;
	aviStreamInfo.dwLength = 200;
	aviStreamInfo.dwQuality = (DWORD)-1;
	SetRect(&aviStreamInfo.rcFrame, 0, 0, 400, 300);
	
	::AVIFileInit();

	PAVIFILE paviFile;
	if (AVIERR_OK != ::AVIFileOpen(&paviFile, L"c:\\screen.avi", OF_CREATE | OF_WRITE, NULL)) 
	{
		::AVIFileExit();
		return;
	}

	PAVISTREAM paviStream;
	if (AVIERR_OK != ::AVIFileCreateStream(paviFile, &paviStream, &aviStreamInfo)) 
	{
		::AVIFileRelease(paviFile);
		::AVIFileExit();
		return;
	}

	BITMAPINFO	bitmapInfo;
	ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
	bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitmapInfo.bmiHeader.biWidth = aviStreamInfo.rcFrame.right;
	bitmapInfo.bmiHeader.biHeight = aviStreamInfo.rcFrame.bottom;
	bitmapInfo.bmiHeader.biPlanes = 1;
	bitmapInfo.bmiHeader.biBitCount = 24;
	bitmapInfo.bmiHeader.biCompression = BI_RGB;
	bitmapInfo.bmiHeader.biSizeImage   = bitmapInfo.bmiHeader.biHeight * ((3 * bitmapInfo.bmiHeader.biWidth + 3) / 4) * 4;

	::AVIStreamSetFormat(paviStream, 0, &bitmapInfo, sizeof(BITMAPINFO));

	HDC hMemDC = ::CreateCompatibleDC(NULL);
	LPVOID pvBits;
	HBITMAP hMemBitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pvBits, NULL, 0);
	HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hMemBitmap);

	HDC dcScreen = ::CreateDC(L"DISPLAY", L"DISPLAY", L"DISPLAY", NULL);
	for (DWORD dwFrameNo = 0; dwFrameNo < aviStreamInfo.dwLength; dwFrameNo ++) 
	{
		::BitBlt(hMemDC, 0, 0, bitmapInfo.bmiHeader.biWidth, bitmapInfo.bmiHeader.biHeight, 
				 dcScreen, 0, 0, SRCCOPY);
	
		::AVIStreamWrite(paviStream, dwFrameNo, 1, pvBits, bitmapInfo.bmiHeader.biSizeImage, AVIIF_KEYFRAME, NULL, NULL);
		::Sleep(50);
	}
	
	::SelectObject(hMemDC, hOldBitmap);
	::DeleteObject(hMemBitmap);
	::DeleteDC(hMemDC);
	::DeleteDC(dcScreen);
	::AVIStreamRelease(paviStream);
	::AVIFileRelease(paviFile);
	::AVIFileExit();
}
モノクロのAVIを作る場合は、色情報が必要なので、newでBITMAPINFOを収納するメモリを所得して、色情報をセットします。
	BITMAPINFO*	pBitmapInfo;
	int iSizeOfBitmapInfo = sizeof(BITMAPINFO) + sizeof(RGBQUAD)*(256-1);

	char* lpszBuff = new char[iSizeOfBitmapInfo]; 
	ZeroMemory(lpszBuff, iSizeOfBitmapInfo);
	pBitmapInfo = (BITMAPINFO*)lpszBuff;

	pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	pBitmapInfo->bmiHeader.biWidth = lpsi->rcFrame.right;
	pBitmapInfo->bmiHeader.biHeight = lpsi->rcFrame.bottom;
	pBitmapInfo->bmiHeader.biPlanes = 1;
	pBitmapInfo->bmiHeader.biBitCount = 8;
	pBitmapInfo->bmiHeader.biClrUsed = 256;
	pBitmapInfo->bmiHeader.biCompression = BI_RGB;
	pBitmapInfo->bmiHeader.biSizeImage = pBitmapInfo->bmiHeader.biHeight * 
	                                                ((pBitmapInfo->bmiHeader.biWidth + 3) / 4) * 4;
	for (int i = 0; i < 256; i ++)
	{
		pBitmapInfo->bmiColors[i].rgbRed = i;
		pBitmapInfo->bmiColors[i].rgbGreen = i;
		pBitmapInfo->bmiColors[i].rgbBlue = i;
	}

	// データをAVIストリームにセットする処理等。

	delete [] lpszBuff;