pcsx2/plugins/zerogs/dx/Win32/aviUtil.h

485 lines
14 KiB
C++

#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame.
#include <string>
using namespace std;
#include <memory.h>
#include <mmsystem.h>
#include <vfw.h>
BOOL AVI_Init()
{
/* first let's make sure we are running on 1.1 */
WORD wVer = HIWORD(VideoForWindowsVersion());
if (wVer < 0x010a){
/* oops, we are too old, blow out of here */
//MessageBeep(MB_ICONHAND);
MessageBox(NULL, "Cant't init AVI File - Video for Windows version is to old", "Error", MB_OK|MB_ICONSTOP);
return FALSE;
}
AVIFileInit();
return TRUE;
}
BOOL AVI_FileOpenWrite(PAVIFILE * pfile, const char *filename)
{
HRESULT hr = AVIFileOpen(pfile, // returned file pointer
filename, // 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;
}
DWORD getFOURCC(const char* value)
{
if(_stricmp(value, "DIB") == 0)
{
return mmioFOURCC(value[0],value[1],value[2],' ');
}
else if((_stricmp(value, "CVID") == 0)
|| (_stricmp(value, "IV32") == 0)
|| (_stricmp(value, "MSVC") == 0)
|| (_stricmp(value, "IV50") == 0))
{
return mmioFOURCC(value[0],value[1],value[2],value[3]);
}
else
{
return NULL;
}
}
// Fill in the header for the video stream....
// The video stream will run in rate ths of a second....
BOOL AVI_CreateStream(PAVIFILE pfile, PAVISTREAM * ps, int rate, // sample/second
unsigned long buffersize, int rectwidth, int rectheight,
const char* _compressor)
{
AVISTREAMINFO strhdr;
memset(&strhdr, 0, sizeof(strhdr));
strhdr.fccType = streamtypeVIDEO;// stream type
strhdr.fccHandler = getFOURCC(_compressor);
//strhdr.fccHandler = 0; // no compression!
//strhdr.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed
//strhdr.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak
//strhdr.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2
//strhdr.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1
//strhdr.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0
//strhdr.dwFlags = AVISTREAMINFO_DISABLED;
//strhdr.dwCaps =
//strhdr.wPriority =
//strhdr.wLanguage =
strhdr.dwScale = 1;
strhdr.dwRate = rate; // rate fps
//strhdr.dwStart =
//strhdr.dwLength =
//strhdr.dwInitialFrames =
strhdr.dwSuggestedBufferSize = buffersize;
strhdr.dwQuality = -1; // use the default
//strhdr.dwSampleSize =
SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream
(int) rectwidth,
(int) rectheight);
//strhdr.dwEditCount =
//strhdr.dwFormatChangeCount =
//strcpy(strhdr.szName, "Full Frames (Uncompressed)");
// And create the stream;
HRESULT hr = AVIFileCreateStream(pfile, // file pointer
ps, // returned stream pointer
&strhdr); // stream header
if (hr != AVIERR_OK) {
return FALSE;
}
return TRUE;
}
string getFOURCCVAsString(DWORD value)
{
string returnValue = "";
if( value == 0 )
return returnValue;
DWORD ch0 = value & 0x000000FF;
returnValue.push_back((char) ch0);
DWORD ch1 = (value & 0x0000FF00)>>8;
returnValue.push_back((char) ch1);
DWORD ch2 = (value & 0x00FF0000)>>16;
returnValue.push_back((char) ch2);
DWORD ch3 = (value & 0xFF000000)>>24;
returnValue.push_back((char) ch3);
return returnValue;
}
string dumpAVICOMPRESSOPTIONS(AVICOMPRESSOPTIONS opts)
{
char tmp[255];
string returnValue = "Dump of AVICOMPRESSOPTIONS\n";
returnValue += "DWORD fccType = streamtype("; returnValue += getFOURCCVAsString(opts.fccType); returnValue += ")\n";
returnValue += "DWORD fccHandler = "; returnValue += getFOURCCVAsString(opts.fccHandler); returnValue += "\n";
_snprintf(tmp, 255, "DWORD dwKeyFrameEvery = %d\n", opts.dwKeyFrameEvery);
returnValue += tmp;
_snprintf(tmp, 255, "DWORD dwQuality = %d\n", opts.dwQuality);
returnValue += tmp;
_snprintf(tmp, 255, "DWORD dwBytesPerSecond = %d\n", opts.dwBytesPerSecond);
returnValue += tmp;
if((opts.dwFlags & AVICOMPRESSF_DATARATE) == AVICOMPRESSF_DATARATE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_DATARATE\n");}
else if((opts.dwFlags & AVICOMPRESSF_INTERLEAVE) == AVICOMPRESSF_INTERLEAVE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_INTERLEAVE\n");}
else if((opts.dwFlags & AVICOMPRESSF_KEYFRAMES) == AVICOMPRESSF_KEYFRAMES){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_KEYFRAMES\n");}
else if((opts.dwFlags & AVICOMPRESSF_VALID) == AVICOMPRESSF_VALID){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_VALID\n");}
else {_snprintf(tmp, 255, "DWORD dwFlags = Unknown(%d)\n", opts.dwFlags);}
returnValue += tmp;
_snprintf(tmp, 255, "LPVOID lpFormat = %d\n", opts.lpFormat);
returnValue += tmp;
_snprintf(tmp, 255, "DWORD cbFormat = %d\n", opts.cbFormat);
returnValue += tmp;
_snprintf(tmp, 255, "LPVOID lpParms = %d\n", opts.lpParms);
returnValue += tmp;
_snprintf(tmp, 255, "DWORD cbParms = %d\n", opts.cbParms);
returnValue += tmp;
_snprintf(tmp, 255, "DWORD dwInterleaveEvery = %d\n", opts.dwInterleaveEvery);
returnValue += tmp;
return returnValue;
}
BOOL AVI_SetOptions(PAVISTREAM * ps, PAVISTREAM * psCompressed, LPBITMAPINFOHEADER lpbi,
const char* _compressor)
{
AVICOMPRESSOPTIONS opts;
AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
memset(&opts, 0, sizeof(opts));
opts.fccType = streamtypeVIDEO;
opts.fccHandler = getFOURCC(_compressor);
//opts.fccHandler = 0;
//opts.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed
//opts.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak
//opts.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2
//opts.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1
//opts.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0
//opts.dwKeyFrameEvery = 5;
//opts.dwQuality
//opts.dwBytesPerSecond
//opts.dwFlags = AVICOMPRESSF_KEYFRAMES;
//opts.lpFormat
//opts.cbFormat
//opts.lpParms
//opts.cbParms
//opts.dwInterleaveEvery
/* display the compression options dialog box if specified compressor is unknown */
if(getFOURCC(_compressor) == NULL)
{
if (!AVISaveOptions(NULL, 0, 1, ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts))
{
return FALSE;
}
//printf("%s", dumpAVICOMPRESSOPTIONS(opts));
//MessageBox(NULL, dumpAVICOMPRESSOPTIONS(opts).c_str(), "AVICOMPRESSOPTIONS", MB_OK);
}
HRESULT hr = AVIMakeCompressedStream(psCompressed, *ps, &opts, NULL);
if (hr != AVIERR_OK) {
return FALSE;
}
hr = AVIStreamSetFormat(*psCompressed, 0,
lpbi, // stream format
lpbi->biSize // format size
+ lpbi->biClrUsed * sizeof(RGBQUAD)
);
if (hr != AVIERR_OK) {
return FALSE;
}
return TRUE;
}
BOOL AVI_SetText(PAVIFILE pfile, PAVISTREAM psText, char *szText, int width, int height, int TextHeight)
{
// Fill in the stream header for the text stream....
AVISTREAMINFO strhdr;
DWORD dwTextFormat;
// The text stream is in 60ths of a second....
memset(&strhdr, 0, sizeof(strhdr));
strhdr.fccType = streamtypeTEXT;
strhdr.fccHandler = mmioFOURCC('D', 'R', 'A', 'W');
strhdr.dwScale = 1;
strhdr.dwRate = 60;
strhdr.dwSuggestedBufferSize = sizeof(szText);
SetRect(&strhdr.rcFrame, 0, (int) height,
(int) width, (int) height + TextHeight); // #define TEXT_HEIGHT 20
// ....and create the stream.
HRESULT hr = AVIFileCreateStream(pfile, &psText, &strhdr);
if (hr != AVIERR_OK) {
return FALSE;
}
dwTextFormat = sizeof(dwTextFormat);
hr = AVIStreamSetFormat(psText, 0, &dwTextFormat, sizeof(dwTextFormat));
if (hr != AVIERR_OK) {
return FALSE;
}
return TRUE;
}
BOOL AVI_AddFrame(PAVISTREAM psCompressed, int time, LPBITMAPINFOHEADER lpbi)
{
int ImageSize = lpbi->biSizeImage;
if (ImageSize == 0)
{
if (lpbi->biBitCount == 24)
{
ImageSize = lpbi->biWidth * lpbi->biHeight * 3;
}
}
HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer
time, // time of this frame
1, // number to write
(LPBYTE) lpbi + // pointer to data
lpbi->biSize +
lpbi->biClrUsed * sizeof(RGBQUAD),
ImageSize, // lpbi->biSizeImage, // size of this frame
AVIIF_KEYFRAME, // flags....
NULL,
NULL);
if (hr != AVIERR_OK)
{
char strMsg[255];
_snprintf(strMsg, 255, "Error: AVIStreamWrite, error %d",hr);
MessageBox(NULL, strMsg, "", MB_OK);
return FALSE;
}
return TRUE;
}
BOOL AVI_AddText(PAVISTREAM psText, int time, char *szText)
{
int iLen = strlen(szText);
HRESULT hr = AVIStreamWrite(psText,
time,
1,
szText,
iLen + 1,
AVIIF_KEYFRAME,
NULL,
NULL);
if (hr != AVIERR_OK)
return FALSE;
return TRUE;
}
BOOL AVI_CloseStream(PAVISTREAM ps, PAVISTREAM psCompressed, PAVISTREAM psText)
{
if (ps)
AVIStreamClose(ps);
if (psCompressed)
AVIStreamClose(psCompressed);
if (psText)
AVIStreamClose(psText);
return TRUE;
}
BOOL AVI_CloseFile(PAVIFILE pfile)
{
if (pfile)
AVIFileClose(pfile);
return TRUE;
}
BOOL AVI_Exit()
{
AVIFileExit();
return TRUE;
}
/* Here are the additional functions we need! */
static PAVIFILE pfile = NULL;
static PAVISTREAM ps = NULL;
static PAVISTREAM psCompressed = NULL;
static int count = 0;
// Initialization...
bool START_AVI(const char* file_name)
{
if(! AVI_Init())
{
//printf("Error - AVI_Init()\n");
return false;
}
if(! AVI_FileOpenWrite(&pfile, file_name))
{
//printf("Error - AVI_FileOpenWrite()\n");
return false;
}
return true;
}
bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int width, int height, int bits, void* pdata)
{
if(count == 0)
{
if(! AVI_CreateStream(pfile, &ps, _frameRate,
width*height/bits,
width,
height, _compressor))
{
//printf("Error - AVI_CreateStream()\n");
return false;
}
BITMAPINFOHEADER bi;
memset(&bi, 0, sizeof(bi));
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = bits;
bi.biCompression = BI_RGB;
bi.biSizeImage = width * height * bits /8;
if(! AVI_SetOptions(&ps, &psCompressed, &bi, _compressor))
{
return false;
}
}
HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer
count, // time of this frame
1, // number to write
pdata,
width*height/8, // lpbi->biSizeImage, // size of this frame
AVIIF_KEYFRAME, // flags....
NULL,
NULL);
if (hr != AVIERR_OK)
{
char strMsg[255];
_snprintf(strMsg, 255, "Error: AVIStreamWrite, error %d",hr);
MessageBox(NULL, strMsg, "", MB_OK);
return FALSE;
}
count++;
return true;
}
//Now we can add frames
// ie. ADD_FRAME_FROM_DIB_TO_AVI(yourDIB, "CVID", 25);
bool ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, const char* _compressor, int _frameRate)
{
LPBITMAPINFOHEADER lpbi;
if(count == 0)
{
lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib);
if(! AVI_CreateStream(pfile, &ps, _frameRate,
(unsigned long) lpbi->biSizeImage,
(int) lpbi->biWidth,
(int) lpbi->biHeight, _compressor))
{
//printf("Error - AVI_CreateStream()\n");
GlobalUnlock(lpbi);
return false;
}
if(! AVI_SetOptions(&ps, &psCompressed, lpbi, _compressor))
{
//printf("Error - AVI_SetOptions()\n");
GlobalUnlock(lpbi);
return false;
}
GlobalUnlock(lpbi);
}
lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib);
if(! AVI_AddFrame(psCompressed, count * 1, lpbi))
{
//printf("Error - AVI_AddFrame()\n");
GlobalUnlock(lpbi);
return false;
}
GlobalUnlock(lpbi);
count++;
return true;
}
// The end...
bool STOP_AVI()
{
if(! AVI_CloseStream(ps, psCompressed, NULL))
{
//printf("Error - AVI_CloseStream()\n");
return false;
}
if(! AVI_CloseFile(pfile))
{
//printf("Error - AVI_CloseFile()\n");
return false;
}
if(! AVI_Exit())
{
//printf("Error - AVI_Exit()\n");
return false;
}
return true;
}