www.pudn.com > 3DEDITOR.rar > AVICAPTURE.CPP
// AVICapture.cpp: implementation of the AVICapture class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "3DEditor.h"
#include "AVICapture.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
AVICapture::AVICapture() :
width(-1),
height(-1),
frameRate(30.0f),
frameCounter(0),
capturing(false),
aviFile(NULL),
aviStream(NULL),
compAviStream(NULL),
image(NULL)
{
AVIFileInit();
}
AVICapture::~AVICapture()
{
cleanup();
AVIFileExit();
}
bool AVICapture::start(CString filename,
int w, int h,
float fps)
{
if (capturing)
return false;
width = w;
height = h;
frameRate = fps;
if (HIWORD(VideoForWindowsVersion()) < 0x010a)
{
// We need to be running on version 1.1 or later
return false;
}
// Compute the width of a row in bytes; pad so that rows are aligned on
// 4 byte boundaries.
int rowBytes = (width * 3 + 3) & ~0x3;
image = new unsigned char[rowBytes * height];
HRESULT hr = AVIFileOpen(&aviFile,
filename,
OF_WRITE | OF_CREATE,
NULL);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"Erroring creating avi file for capture.","ERROR",MB_OK);
return false;
}
AVISTREAMINFO info;
ZeroMemory(&info, sizeof info);
info.fccType = streamtypeVIDEO;
info.fccHandler = 0;
info.dwScale = 1;
info.dwRate = (DWORD) frameRate;
info.dwSuggestedBufferSize = rowBytes * height;
SetRect(&info.rcFrame, 0, 0, width, height);
hr = AVIFileCreateStream(aviFile, &aviStream, &info);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"Error creating AVI stream.","ERROR",MB_OK);
cleanup();
return false;
}
// Display a dialog to allow the user to select compression options
AVICOMPRESSOPTIONS options;
AVICOMPRESSOPTIONS* arrOptions[1] = { &options };
ZeroMemory(&options, sizeof options);
if (!AVISaveOptions(NULL, 0, 1, &aviStream,
(LPAVICOMPRESSOPTIONS*) &arrOptions))
{
// The user either clicked on cancel or there was an error
cleanup();
return false;
}
hr = AVIMakeCompressedStream(&compAviStream, aviStream, &options, NULL);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"Error creating compressed AVI stream.", "ERROR",MB_OK);
cleanup();
return false;
}
BITMAPINFOHEADER bi;
ZeroMemory(&bi, sizeof bi);
bi.biSize = sizeof bi;
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biSizeImage = rowBytes * height;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
hr = AVIStreamSetFormat(compAviStream, 0, &bi, sizeof bi);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"AVIStreamSetFormat failed.","ERROR",MB_OK);
cleanup();
return false;
}
capturing = true;
frameCounter = 0;
return true;
}
bool AVICapture::end()
{
capturing = false;
cleanup();
return true;
}
bool AVICapture::captureFrame()
{
if (!capturing)
return false;
// Get the dimensions of the current viewport
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
int x = viewport[0] + (viewport[2] - width) / 2;
int y = viewport[1] + (viewport[3] - height) / 2;
glReadPixels(x, y, width, height,
GL_BGR_EXT, GL_UNSIGNED_BYTE,
image);
int rowBytes = (width * 3 + 3) & ~0x3;
LONG samplesWritten = 0;
LONG bytesWritten = 0;
HRESULT hr = AVIStreamWrite(compAviStream,
frameCounter,
1,
image,
rowBytes * height,
AVIIF_KEYFRAME,
&samplesWritten,
&bytesWritten);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"AVIStreamWrite failed on frame.", "ERROR",MB_OK);
return false;
}
// printf("Writing frame: %d %d => %d bytes\n",
// frameCounter, rowBytes * height, bytesWritten);
frameCounter++;
return true;
}
void AVICapture::cleanup()
{
if (aviStream != NULL)
{
AVIStreamRelease(aviStream);
aviStream = NULL;
}
if (compAviStream != NULL)
{
AVIStreamRelease(compAviStream);
compAviStream = NULL;
}
if (aviFile != NULL)
{
AVIFileRelease(aviFile);
aviFile = NULL;
}
if (image != NULL)
{
delete[] image;
image = NULL;
}
}
int AVICapture::getWidth() const
{
return width;
}
int AVICapture::getHeight() const
{
return height;
}
float AVICapture::getFrameRate() const
{
return frameRate;
}