//
// (C) 2004 Mike Brent aka Tursi aka HarmlessLion.com
// This software is provided AS-IS. No warranty
// express or implied is provided.
//
// This notice defines the entire license for this code.
// All rights not explicity granted here are reserved by the
// author.
//
// You may redistribute this software provided the original
// archive is UNCHANGED and a link back to my web page,
// http://harmlesslion.com, is provided as the author's site.
// It is acceptable to link directly to a subpage at harmlesslion.com
// provided that page offers a URL for that purpose
//
// Source code, if available, is provided for educational purposes
// only. You are welcome to read it, learn from it, mock
// it, and hack it up - for your own use only.
//
// Please contact me before distributing derived works or
// ports so that we may work out terms. I don't mind people
// using my code but it's been outright stolen before. In all
// cases the code must maintain credit to the original author(s).
//
// -COMMERCIAL USE- Contact me first. I didn't make
// any money off it - why should you? ;) If you just learned
// something from this, then go ahead. If you just pinched
// a routine or two, let me know, I'll probably just ask
// for credit. If you want to derive a commercial tool
// or use large portions, we need to talk. ;)
//
// If this, itself, is a derived work from someone else's code,
// then their original copyrights and licenses are left intact
// and in full force.
//
// http://harmlesslion.com - visit the web page for contact info
//
// avitest.cpp : Defines the entry point for the application.
//

#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0400

#include <windows.h>
#include <vfw.h>
#include <stdio.h>
#include <stdlib.h>

PAVIFILE myAvi;																// pointer to AVI handle
PAVISTREAM myStream;														// pointer to AVI Stream
AVISTREAMINFO si;															// info about the stream
BITMAPINFOHEADER bi, *biout;												// format of a frame
COMPVARS myComp;
long frame;																	// frame to write
extern unsigned short *framedata;											// data to write (in words, each is 1 pixel)
extern unsigned __int8 Recording;

extern HWND myWnd;

extern int InitAvi();
extern void WriteFrame();
extern void CloseAVI();
extern void debug_write(char*, ...);
extern void ConfigAVI();

extern char AVIFileName[];

int InitAvi();
void WriteFrame();
void CloseAVI();

int InitAvi()
{
	int ret;																	// return code from functions
	DWORD dwFormatSize;
	void *h;

	AVIFileInit();																// init AVI library
	
	debug_write("AVI: %s", AVIFileName);

	ret=AVIFileOpen(&myAvi, AVIFileName, OF_CREATE | OF_WRITE, NULL);			// open and create the file
	
	if (0 != ret)
	{
		debug_write("Can't open AVI file");
	
		AVIFileExit();															// exit AVI library
		return 1;
	}

	si.fccType=streamtypeVIDEO;													// video stream
	si.fccHandler = mmioFOURCC('M', 'S', 'V', 'C');								// (MSVC) 4 character code of compressor
	si.dwFlags=NULL;
	si.dwCaps=NULL;
	si.wPriority=0;
	si.wLanguage=NULL;
	si.dwScale=1;
	si.dwRate=15;																// 15 fps
	si.dwStart=0;
	si.dwLength=0;																// how long?
	si.dwInitialFrames=0;
	si.dwSuggestedBufferSize=0;
	si.dwQuality=1000;															// default quality, else 0-10000
	si.dwSampleSize=0;															// video streams vary in sample size
	si.dwEditCount=0;
	si.dwFormatChangeCount=0;
	strcpy(si.szName,"Classic99Movie");											// description

	ret=AVIFileCreateStream(myAvi, &myStream, &si);								// create the video stream
	
	if (0 != ret)
	{
		debug_write("Can't create stream");

		AVIFileRelease(myAvi);													// release the file
		AVIFileExit();															// exit AVI library

		return 1;
	}
	
	bi.biSize=sizeof(bi);
	bi.biWidth=256+16;
	bi.biHeight=192+16;
	bi.biPlanes=1;
	bi.biBitCount=16;															// 0x0RRRGGGBBB
	bi.biCompression=BI_RGB;
	bi.biSizeImage=0;
	bi.biXPelsPerMeter=0;
	bi.biYPelsPerMeter=0;
	bi.biClrUsed=0;
	bi.biClrImportant=0;

	ZeroMemory(&myComp, sizeof(COMPVARS));
	myComp.cbSize=sizeof(COMPVARS);

	if (!ICCompressorChoose(myWnd, ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME, &bi, NULL, &myComp, NULL))
	{
		debug_write("Cancelled");

		ICCompressorFree(&myComp);
		AVIStreamRelease(myStream);													// release the stream
		AVIFileRelease(myAvi);														// release the file
		AVIFileExit();																// exit AVI library

		return 1;
	}

	dwFormatSize = ICCompressGetFormatSize(myComp.hic, &bi); 
	h = GlobalAlloc(GHND, dwFormatSize); 
	biout = (LPBITMAPINFOHEADER)GlobalLock(h); 
	ICCompressGetFormat(myComp.hic, &bi, biout); 

	ret=AVIStreamSetFormat(myStream, 0, biout, sizeof(BITMAPINFOHEADER));
	if (0 != ret)
	{
		debug_write("Can't set format");

		ICCompressorFree(&myComp);
		AVIStreamRelease(myStream);													// release the stream
		AVIFileRelease(myAvi);														// release the file
		AVIFileExit();																// exit AVI library
		
		return 1;
	}

 
	if (!ICSeqCompressFrameStart(&myComp, (BITMAPINFO*)&bi))
	{
		debug_write("Failed to start compression");

		ICCompressorFree(&myComp);
		AVIStreamRelease(myStream);													// release the stream
		AVIFileRelease(myAvi);														// release the file
		AVIFileExit();																// exit AVI library

		return 1;
	}

	frame=0;

	if (NULL == framedata)
	{
		ICSeqCompressFrameEnd(&myComp);
		ICCompressorFree(&myComp);
		AVIStreamRelease(myStream);													// release the stream
		AVIFileRelease(myAvi);														// release the file
		AVIFileExit();																// exit AVI library

		return 1;
	}
	
	return 0;
}

void WriteFrame()
{
	BOOL key;
	void *data;
	long len;

	if ((myStream) && (framedata))
	{
		len=98304;
		data=ICSeqCompressFrame(&myComp, 0, framedata, &key, &len);				// compress the frame
		if (NULL != data)
			AVIStreamWrite(myStream, frame++, 1, data, len, NULL, NULL, NULL);	// write 1 frame
	}
	else
	{
		debug_write("Can't write frame");
		CloseAVI();
		Recording=0;
	}
}

void CloseAVI()
{
	ICSeqCompressFrameEnd(&myComp);
	ICCompressorFree(&myComp);

	AVIStreamRelease(myStream);													// release the stream

	AVIFileRelease(myAvi);														// release the file

	AVIFileExit();																// exit AVI library
}

