Sign in to follow this  
fishleg003

background avi problems

Recommended Posts

Ive been trying to get a animated background for a side scrolling shooter im making, so i thought the easiest way to do this would be to have an avi playing for the far background with a tile grid in front. Heres my problem though i dont really understand the avi loading process that well ive got it loading in the avi fine and it even displays on the background quad but the problem is that it produces a slight stutter everytime the frame changes which as you can imagine side scroller with a stutter is not that much fun to play with enemies teleporting around each time the avi moves forward a frame. The strange thing is though if i slow the movie down from 25fps to 10fps the stutter is very easy to spot but if i update the movie at 25fps you can barely notice it but its still there. Its not just the movie that stutters the whole game pauses very briefly then because of this gap in time all the player and enemies positions teleport forward. Its got me baffled i stripped nehe's code down to the bare essentials so i could understand it better. Below is what im left with,
#ifndef _Avi_c_
#define _Avi_c_

#include <windows.h>							 
#include <GL/glut.h>
#include <vfw.h>							 #include "Avi.h"				

#pragma comment( lib, "vfw32.lib" )// Search For VFW32.lib While Linking


extern GLuint texture[20];
extern int n_textures;
extern int Video_TexID;

// User Defined Variables
int		next;							// Used For Animation
int		frame=0;						// Frame Counter

AVISTREAMINFO		psi;						// Pointer To A Structure Containing Stream Info
PAVISTREAM		pavi;						// Handle To An Open Stream
PGETFRAME		pgf;						// Pointer To A GetFrame Object
BITMAPINFOHEADER	bmih;						// Header Information For DrawDibDraw Decoding
long			lastframe;					// Last Frame Of The Stream
int			width;						// Video Width
int			height;						// Video Height
char			*pdata;						// Pointer To Texture Data
int			mpf;						// Will Hold Rough Milliseconds Per Frame

HDRAWDIB hdd;								// Handle For Our Dib
HBITMAP hBitmap;							// Handle To A Device Dependant Bitmap
HDC hdc = CreateCompatibleDC(0);					// Creates A Compatible Device Context
unsigned char* data = 0;						// Pointer To Our Resized Image

void flipIt(void* buffer)						// Flips The Red And Blue Bytes (256x256)
{
	void* b = buffer;						// Pointer To The Buffer
	__asm								// Assembler Code To Follow
	{
		mov ecx, 256*512					// Set Up A Counter (Dimensions Of Memory Block)
		mov ebx, b						// Points ebx To Our Data (b)
		label:							// Label Used For Looping
			mov al,[ebx+0]					// Loads Value At ebx Into al
			mov ah,[ebx+2]					// Loads Value At ebx+2 Into ah
			mov [ebx+2],al					// Stores Value In al At ebx+2
			mov [ebx+0],ah					// Stores Value In ah At ebx
			
			add ebx,3					// Moves Through The Data By 3 Bytes
			dec ecx						// Decreases Our Loop Counter
			jnz label					// If Not Zero Jump Back To Label
	}
}

void OpenAVI(LPCSTR szFile)
{
	AVIFileInit();							// Opens The AVIFile Library

	// Opens The AVI Stream
	if (AVIStreamOpenFromFile(&pavi, szFile, streamtypeVIDEO, 0, OF_READ, NULL) !=0)
	{
		// An Error Occurred Opening The Stream
		MessageBox (HWND_DESKTOP, "Failed To Open The AVI Stream", "Error", MB_OK | MB_ICONEXCLAMATION);
	}

	AVIStreamInfo(pavi, &psi, sizeof(psi));				// Reads Information About The Stream Into psi
	width=psi.rcFrame.right-psi.rcFrame.left;			// Width Is Right Side Of Frame Minus Left
	height=psi.rcFrame.bottom-psi.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		= 256;					// Width We Want (256 Pixels)
	bmih.biHeight		= 512;					// 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);					
	pgf=AVIStreamGetFrameOpen(pavi, NULL);
	if (pgf==NULL)
	{
		// An Error Occurred Opening The Frame
		MessageBox (HWND_DESKTOP, "Failed To Open The AVI Frame", "Error", MB_OK | MB_ICONEXCLAMATION);
	}
}

void GrabAVIFrame(const int frame2)// Grabs A Frame From The Stream
{
	LPBITMAPINFOHEADER lpbi;					// Holds The Bitmap Header Information
	lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pgf, frame2);	// Grab Data From The AVI Stream
	pdata=(char *)lpbi+lpbi->biSize+lpbi->biClrUsed * sizeof(RGBQUAD);

	// Convert Data To Requested Bitmap Format
	DrawDibDraw (hdd, hdc, 0, 0, 256, 512, lpbi, pdata, 0, 0, width, height, 0);

	flipIt(data);							
	glBindTexture(GL_TEXTURE_2D, texture[Video_TexID]);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);

	gluBuild2DMipmaps(GL_TEXTURE_2D,
                      3,
                      256,
                      512,
                      GL_RGB,
                      GL_UNSIGNED_BYTE,
                      data);
}

void CloseAVI(void)
{
	DeleteObject(hBitmap);	
	DrawDibClose(hdd);
	AVIStreamGetFrameClose(pgf);
	AVIStreamRelease(pavi);		
	AVIFileExit();		
}


BOOL Initialize_Avi()	
{
	hdd = DrawDibOpen();						
	
	glEnable(GL_TEXTURE_2D);					
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

	OpenAVI("background.avi");					

	// Create The Texture
	glGenTextures(1, &texture[n_textures]);
	glBindTexture(GL_TEXTURE_2D, texture[n_textures]);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

	Video_TexID = n_textures;
	n_textures++;

	return TRUE;							
}

void Deinitialize (void)						
{
	CloseAVI();							
}

void Update_Movie(float milliseconds)					
{
	static int mfps = 0;
	int previous = frame;
	next+= milliseconds;						
	frame=next/mpf;							
	if (frame>=lastframe)						// Have We Gone Past The Last Frame?
	{
		frame=0;						
		next=0;							
		mfps++;
	}

	if(frame > previous)
	{//update video only if needed as in frame time has increased to the next frame
		GrabAVIFrame(frame);
		frame = 0;
	}
}


#endif







All i do is call Update_Movie(delta_time); in my idle callback Im using a divx encoded avi file 256 wide 512 high. I know just having an avi is taxing but i thought i could pull it off reasonably well if i kept to a low res/fps format. I was hoping to have it so i could engage a loop for boss battles etc so the video would keep playing the same section until the boss dies but as it is now each time it rewinds the video so to speak it would jerk all of a sudden. I really dont have a clue why it stutters so if anyone can shed some light id be very greatful. As best i can tell its something in the update function but i dont understand it well enough :(. [Edited by - fishleg003 on December 3, 2005 1:09:02 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this