
#include "stdafx.h"
#include "CAviFile.h"
#include "../Glew/WGlew.h"
#include "../GLDef.h"

static int g_LogCiatac=0;

CAviFile::CAviFile()
{
	_logFile.Create( W_GetString("logAviFile%d.txt", g_LogCiatac).c_str() );
	g_LogCiatac++;
}	

CAviFile::~CAviFile()
{
	CloseAVI();
}

void CAviFile::_flipIt(void* buffer)// Prohodí červenou a modrou složku pixelů v obrázku
{
	void* b = buffer;// Ukazatel na buffer
	__asm // ASM kód
	{
		mov ecx, 256*256 // Řídící "proměnná" cyklu
		mov ebx, b // Ebx ukazuje na data
		label: // Návěští pro cyklus
		mov al, [ebx+0] // Přesune B složku do al
		mov ah, [ebx+2] // Přesune R složku do ah
		mov [ebx+2], al // Vloží B na správnou pozici
		mov [ebx+0], ah // Vloží R na správnou pozici
		add ebx, 3 // Přesun na další tři byty
		dec ecx // Dekrementuje čítač
		jnz label // Pokud se čítač nerovná nule skok na návěští
	}
}

bool CAviFile::LoadFile(std::string nameFile, int w, int h, int qualit)
{
	_logFile.ExWrite( "Start loading : " );
	_logFile.ExWriteln( nameFile.c_str() );

	glW = w;
	glH = h;
	_hdc = CreateCompatibleDC(0);
	if(!_hdc) MessageBox (HWND_DESKTOP, "HDC failed", "Error", MB_OK | MB_ICONEXCLAMATION);
	_data = 0;
	_hdd = DrawDibOpen();

	AVIFileInit();	
	// Opens The AVI Stream
	_logFile.ExWriteln("Loading stream AVI file");
	if (AVIStreamOpenFromFile(&_pavi, nameFile.c_str(), streamtypeVIDEO, 0, OF_READ, NULL) !=0)
	{
		// Error
		MessageBox (HWND_DESKTOP, "Failed To Open The AVI Stream", "Error", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}

	AVIStreamInfo(_pavi, &_stream, sizeof(_stream));						// Reads Information About The Stream Into psi
	_width=_stream.rcFrame.right-_stream.rcFrame.left;					// Width Is Right Side Of Frame Minus Left
	_height=_stream.rcFrame.bottom-_stream.rcFrame.top;					// Height Is Bottom Of Frame Minus Top

	_lastframe=AVIStreamLength(_pavi);							// The Last Frame Of The Stream

	_mpf=AVIStreamSampleToTime(_pavi, _lastframe)/_lastframe;		// Calculate Rough Milliseconds Per Frame

	_bmih.biSize = sizeof (BITMAPINFOHEADER);					// Size Of The BitmapInfoHeader
	_bmih.biPlanes = 1;											// Bitplanes	
	_bmih.biBitCount = 24;										// Bits Format We Want (24 Bit, 3 Bytes)
	_bmih.biWidth = glW;											// Width We Want (256 Pixels)
	_bmih.biHeight = glH;										// Height We Want (256 Pixels)
	_bmih.biCompression = BI_RGB;								// Requested Mode = RGB

	_hBitmap = CreateDIBSection (_hdc, (BITMAPINFO*)(&_bmih), DIB_RGB_COLORS, (void**)(&_data), NULL, NULL);
	SelectObject (_hdc, _hBitmap);								// Select hBitmap Into Our Device Context (hdc)

	_pgf = AVIStreamGetFrameOpen(_pavi, NULL);						// Create The PGETFRAME	Using Our Request Mode
	if (_pgf==NULL )
	{
		// An Error Occurred Opening The Frame
		//MessageBox (HWND_DESKTOP, "Failed To Open The AVI Frame", "Error", MB_OK | MB_ICONEXCLAMATION);
		cError.ErrorMsg(0, false, true, "Error", "Failed To Open The AVI Frame");
		return FALSE;
	}

	_logFile.ExWriteln("Width : ", _width);
	_logFile.ExWriteln("Height : ", _height);
	_logFile.ExWriteln("Num frames : ", _lastframe);
	// loging
	// Create The Texture
	//glDeleteTextures(1, &texture_id);
	glGenTextures(1, &_texture_id);// Generuje texturu
	glBindTexture(GL_TEXTURE_2D, _texture_id);// Typické vytváření textury z bitmapy
	if(qualit == 0)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);	
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	}else
	if(qualit == 1)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);	
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	}
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glW, glH, 0, GL_RGB, GL_UNSIGNED_BYTE, _data);
	return TRUE;
}

void CAviFile::_GrabAVIFrame()									// Grabs A Frame From The Stream
{
	static int minFrame=0;
	if(minFrame == _frame) return;
	minFrame = _frame;
	LPBITMAPINFOHEADER lpbi;									// Holds The Bitmap Header Information
	lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(_pgf, _frame);	// Grab Data From The AVI Stream
	_pdata=(char *)lpbi+lpbi->biSize+lpbi->biClrUsed * sizeof(RGBQUAD);	// Pointer To Data Returned By AVIStreamGetFrame

	DrawDibDraw (_hdd, _hdc, 0, 0, glW, glH, lpbi, _pdata, 0, 0, _width, _height, 0);

	glBindTexture(GL_TEXTURE_2D, _texture_id);// Typické vytváření textury z bitmapy
	//_flipIt(_data);	

	// Update The Texture
	glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, glW, glH, GL_BGR_EXT, GL_UNSIGNED_BYTE, _data);
}

void CAviFile::CloseAVI()												// Properly Closes The Avi File
{
	if(_hBitmap) DeleteObject(_hBitmap);										// Delete The Device Dependant Bitmap Object
	if(_hdd)     DrawDibClose(_hdd);											// Closes The DrawDib Device Context
	if(_pgf) AVIStreamGetFrameClose(_pgf);								// Deallocates The GetFrame Resources
	if(_pavi) AVIStreamRelease(_pavi);										// Release The Stream
	AVIFileExit();												// Release The File
}

void CAviFile::Render()
{
	if( !_pgf ) return;
	glEnable(GL_TEXTURE_2D);
	_GrabAVIFrame();
	glBindTexture(GL_TEXTURE_2D, _texture_id);
	glBegin(GL_QUADS);									
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 11.0f,  8.3f, -20.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-11.0f,  8.3f, -20.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-11.0f, -8.3f, -20.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 11.0f, -8.3f, -20.0f);
	glEnd();
	Update();
}

void CAviFile::Update()
{
	if( !_pgf ) return;
	// Update
	static DWORD tickCount, tickOld=0;
	tickCount = GetTickCount ();				
	DWORD roz = 0;
	if(tickOld != 0) roz = tickCount-tickOld;
	DWORD milliseconds = roz;	
	tickOld = tickCount;

	static int next;	
	next += milliseconds;		// Zvětšení next o uplynulý čas
	_frame = next / _mpf;			// Výpočet aktuálního snímku
	if (_frame >= _lastframe)		// Přetečení snímků?
	{
		_frame = 0;				// Přetočí video na začátek
		next = 0;				// Nulování času
	}
}

void CAviFile::BindTexture()
{
	if( !_pgf ) return;
	glEnable(GL_TEXTURE_2D);
	_GrabAVIFrame();
	glBindTexture(GL_TEXTURE_2D, _texture_id);
}