Hello all,
I have code (found long time ago, ~2001) to make videos from OpenGL rendering in my view class. In my OnDraw() function I call the function SaveAsAvi(). This works as intended until I have 255 frames in the movie I am trying to make. After that, Windows Media Player claims it cannot play the file. VirtualDub claims the avi contains Palette Changes and shows the correct number of frames (>255) but all frames past 255 are the same and equal to the last frame.
Does anyone have an idea what I am doing wrong? Memory overflow? Need to free m_pixels sometime somewhere? Any help would be appreciated.
The code for making the avi's is in the following files:
Avi.h:
Avi.cpp:
I have code (found long time ago, ~2001) to make videos from OpenGL rendering in my view class. In my OnDraw() function I call the function SaveAsAvi(). This works as intended until I have 255 frames in the movie I am trying to make. After that, Windows Media Player claims it cannot play the file. VirtualDub claims the avi contains Palette Changes and shows the correct number of frames (>255) but all frames past 255 are the same and equal to the last frame.
Does anyone have an idea what I am doing wrong? Memory overflow? Need to free m_pixels sometime somewhere? Any help would be appreciated.
Code:
void C***View::SaveAsAvi()
{
C***Doc* pDoc = GetDocument();
if (pDoc->m_avi_status == -1) // initialize AVI stuff
{
KillTimer(1);
// allocate space for the pixel info
m_big=GlobalAlloc(GHND,m_cx*m_cy*4); //m_cx and m_cy members of my view class, these store width and height
m_pixels=GlobalLock(m_big); // m_big is defined as HGLOBAL in the header file of my view class
CreateAVI(pDoc->m_avi_filename,m_cx,m_cy);
glReadPixels(0,0,m_cx,m_cy,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_pixels); // m_pixels is defined as LPVOID in the header file of my view class
int ValidWrite = 0;
while (ValidWrite==0)
{
ValidWrite = WriteAVIFrame(m_pixels,15);
}
if (ValidWrite==1)
{
pDoc->m_avi_status = 1;
GetParentFrame()->PostMessage(WM_COMMAND, MAKELONG(ID_PLAY_FORWARD, 0));
SetTimer(1,50,NULL);
}
}
if (pDoc->m_avi_status == 1) // "normal" writing to avi file
{
glReadPixels(0,0,m_cx,m_cy,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_pixels);
if (WriteAVIFrame(m_pixels,15)==0)
{
KillTimer(1);
AfxGetMainWnd()->MessageBox("Error writing AVI file");
SetTimer(1,50,NULL);
pDoc->m_avi_status = 2; // will close avi file later
}
}
if (pDoc->m_avi_status == 2) // finish and close avi file
{
pDoc->m_avi_status = 0;
CloseAVI();
GlobalUnlock(m_big); // free up memory
GlobalFree(m_big);
GetParentFrame()->PostMessage(WM_COMMAND, MAKELONG(ID_STOP_DRAWING, 0));
}
}Avi.h:
Code:
#define ONETICKTIME 1
bool CreateAVI(LPCTSTR str,int Width,int Height);
int WriteAVIFrame(LPVOID pixels, int fps);
void CloseAVI();Code:
#include "stdafx.h"
#include "avi.h"
//
#include <vfw.h>
BITMAPINFO BI ;
PAVISTREAM psCompressed;
PAVISTREAM ps;
PAVIFILE pfile;
int m_nframe;
int width,height;
//
//
//
bool CreateAVI(LPCTSTR str,int Width,int Height)
{
int iSize = sizeof(BITMAPINFOHEADER);
memset(&BI, 0, iSize);
BI.bmiHeader.biSize=iSize;
BI.bmiHeader.biWidth=Width;
BI.bmiHeader.biHeight=Height;
BI.bmiHeader.biPlanes=1;
BI.bmiHeader.biBitCount=32;
BI.bmiHeader.biCompression=BI_RGB;
m_nframe=0;
width=Width;
height=Height;
HRESULT hr;
AVIFileInit();
hr = AVIFileOpen(&pfile, // returned file pointer
str, // file name
OF_WRITE | OF_CREATE, // mode to open file with
NULL); // use handler determined
// from file extension....
if (hr != AVIERR_OK)
return FALSE;
return TRUE;
// m_timeOneFrame=timeOneFrame;
}
//
//
//
//
int WriteAVIFrame(LPVOID pixels, int fps)
{
HRESULT hr;
if(!m_nframe)
{
AVICOMPRESSOPTIONS opts;
AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
AVISTREAMINFO strhdr;
memset(&strhdr, 0, sizeof(strhdr));
strhdr.fccType = streamtypeVIDEO;// stream type
strhdr.fccHandler = 0;
strhdr.dwScale = 1;
strhdr.dwRate = fps;
strhdr.dwSuggestedBufferSize = width*height*4;
SetRect(&strhdr.rcFrame, 0, 0,width,height); // rectangle for stream
// And create the stream;
hr = AVIFileCreateStream(pfile, // file pointer
&ps, // returned stream pointer
&strhdr); // stream header
if (hr != AVIERR_OK)
return 0;
memset(&opts, 0, sizeof(opts));
if (!AVISaveOptions(NULL, 0, 1, &ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts))
return 2;
hr = AVIMakeCompressedStream(&psCompressed, ps, &opts, NULL);
if (hr != AVIERR_OK)
return 0;
hr=AVIStreamSetFormat(psCompressed,0,&BI,sizeof(BITMAPINFO));
if(hr != AVIERR_OK)
return 0;
}
hr = AVIStreamWrite(psCompressed, // stream pointer
(m_nframe) * ONETICKTIME, // time of this frame
1, // number to write
pixels,
width*height*4,
m_nframe+1, // flags....
// AVIIF_KEYFRAME, // flags....
NULL,
NULL);
if (hr != AVIERR_OK)
return 0;
m_nframe++;
return 1;
}
//
//
//
void CloseAVI()
{
if (ps)
AVIStreamClose(ps);
if (psCompressed)
AVIStreamClose(psCompressed);
if (pfile)
AVIFileClose(pfile);
AVIFileExit();
}