My opengl "video player" freezes after a few seconds

Started by
7 comments, last by sirpaulmuaddib 13 years, 9 months ago
I have an openGL video player, it freezes after 5 seconds.

I went and stripped everything out, and faked "video" with 2 bitmaps, where I flip / flopped the image back and forth. It still freezes, I don't see what I'm doing wrong. If I set breakpoint in function, it will break in it...everything seems alright, but the "video" does not update.

You can download full vc++ project here:
http://www.mediafire.com/file/yrzhclv1z985kql/freeze.zip

Here is core function:

void CMoviePlayer::DisplayFrame(BYTE *pFrame, int width, int height, float quadWidth, float quadHeight)
{
static float sf = 1.0;

static bool b = true;
static int i = 0;

if (i++%30 == 0)
b=!b;

if (b)
glBindTexture(GL_TEXTURE_2D, tex1); //A texture you have already created with glTexImage2D
else
glBindTexture(GL_TEXTURE_2D, tex2); //A texture you have already created with glTexImage2D


glScalef(sf, sf, sf);
glBegin(GL_POLYGON);
glTexCoord2f(0.0f,1.0f); glVertex3f (-quadWidth, -quadHeight, 0.0);
glTexCoord2f(1.0f,1.0f); glVertex3f ( quadWidth, -quadHeight, 0.0);
glTexCoord2f(1.0f,0.0f); glVertex3f ( quadWidth, quadHeight, 0.0);
glTexCoord2f(0.0f,0.0f); glVertex3f (-quadWidth, quadHeight, 0.0);
glEnd();

//sf +=0.0000001f;

glutSwapBuffers();
}
Advertisement
You are lucky! I was so bored that i actually downloaded the source code and debugged it!

Here's the new version of the code :D :

no more freezing
:-)
And so that the rest of us can learn, what was the problem?
The problem was that there was a loop that run indefinetely and there was no more window messaging handling. The animation needs to be updated every frame not run in an infinite loop on the first frame. GLUT has a closed main loop so what sirpaulmuaddib was something like this(from 1000 feet up):

void rendeFrame()
{
while (true)
{
updateAnimation();
draw();
post redisplay();
}
}

The obvious solution is to do this:

void rendeFrame()
{
updateAnimation();

draw();
}

and registering renderFrame like this:

glutIdleFunc(renderFrame);
The fix for the freeze frame, while correct in the test scenario, does not work in my real scenario.

The reason is that in the real app, I go off, and decode frames.

I don't process a frame, return, and exit out of render function (which will be called repeatedly by glut of course).

The post by Deliverance, looks promising as fix for real scenario.
ack...in demo project I just noticed, in solution view, the movieplayer.cpp file is in Header Files filter folder.

That is where relevant code is
Here is abbreviated version of code flow...

void GLRender(void)
{
static bool b = true; // note 'b' is STATIC

if (b)
{
b = false;
if (mp)
mp->Play("movie path");
}
}

void CMoviePlayer::DisplayFrame(BYTE *pFrame, int width, int height, float quadWidth, float quadHeight)
{
static float sf = 1.0;

static bool b = true;
static int i = 0;

if (i++%30 == 0)
b=!b;

if (b)
glBindTexture(GL_TEXTURE_2D, tex1); //A texture you have already created with glTexImage2D
else
glBindTexture(GL_TEXTURE_2D, tex2); //A texture you have already created with glTexImage2D


glScalef(sf, sf, sf);
glBegin(GL_POLYGON);
glTexCoord2f(0.0f,1.0f); glVertex3f (-quadWidth, -quadHeight, 0.0);
glTexCoord2f(1.0f,1.0f); glVertex3f ( quadWidth, -quadHeight, 0.0);
glTexCoord2f(1.0f,0.0f); glVertex3f ( quadWidth, quadHeight, 0.0);
glTexCoord2f(0.0f,0.0f); glVertex3f (-quadWidth, quadHeight, 0.0);
glEnd();

//sf +=0.0000001f;

glutSwapBuffers();
}

GLuint CMoviePlayer::LoadTexture(char *TexName)
{
// ... CODE TO LOAD TEXTURE
}



Dimensions CMoviePlayer::FindDimensionsOfVideo(char *fn)
{
//... CODE ....
}

void CMoviePlayer::ReadFrames(int w, int h, float quadWidth, float quadHeight )
{
while (true)
{
DisplayFrame(NULL, w, h, quadWidth, quadHeight);
}
}


int CMoviePlayer::Play(char *fn, int w, int h, float quadWidth, float quadHeight)
{
ReadFrames(w, h, quadWidth, quadHeight);
return 0;
}

void CMoviePlayer::CreateMovieScreenTexture(int iw, int ih)
{
// CREATE TEXTURE, THAT FRAMES WILL BE RENDERED ON
}

void CMoviePlayer::SetupAspectRatio( double sw, double sh )
{
//... SETUP ASPECT RATIO...
}

Dimensions CMoviePlayer::GetUnitDimensions(double iw, double ih)
{
//... FOR SETING UP ASPECT RATIO...
}

void CMoviePlayer::Play(char *fn)
{
tex1 = LoadTexture("flip.tga");
tex2 = LoadTexture("flop.tga");

try
{
Dimensions dimensionsOfMovie = FindDimensionsOfVideo(fn);
if ((dimensionsOfMovie.w > 0) && (dimensionsOfMovie.h > 0))
{
SetupAspectRatio(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
CreateMovieScreenTexture(dimensionsOfMovie.w, dimensionsOfMovie.h);
Dimensions unitDim = GetUnitDimensions(dimensionsOfMovie.w, dimensionsOfMovie.h);
Play(fn, dimensionsOfMovie.w, dimensionsOfMovie.h, unitDim.fw, unitDim.fh);
}
}
catch (char* e)
{

}
catch (...)
{
}
}

CMoviePlayer::CMoviePlayer(void)
{
mp = this;
}

CMoviePlayer::~CMoviePlayer(void)
{
}

int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutDisplayFunc(&GLRender);

....

CMoviePlayer mp;

glutMainLoop();
return 0;
}
The problem is this portion.


void CMoviePlayer::ReadFrames(int w, int h, float quadWidth, float quadHeight )
{
while (true)
{
DisplayFrame(NULL, w, h, quadWidth, quadHeight);
}
}

Converting it to this "format" is difficult.
void rendeFrame()
{
updateAnimation();

draw();
}
and registering renderFrame like this:

glutIdleFunc(renderFrame);






Because we are deep in the bowels of decoding video. We are continuously pulling frames out of the video file, decoding them, and then sending them to display function (DisplayFrame). So the original approach is more natural.



This topic is closed to new replies.

Advertisement