Movie app using picture changes at 25 fps

Cuckoo's Avatar, Join Date: Dec 2006
Light Poster
i have build this engine which switches pictures on a Frame (in this case its a CDIalog) and i want it to be in a 25 fps rate.
for now all i can do is change pictures in the dialog but the timing is bad...
how can i be done?

here is my code:


Code:
BOOL MovieEngine::paintCurrFrame(BOOL onPaint)
{
	PAINTSTRUCT ps;	
	HDC hDC;
	hDC = ::BeginPaint(m_paintTarget->m_hWnd, &ps);
	HDC memDC = CreateCompatibleDC(hDC);
	m_jpegRect.bottom=m_offsetY+m_currFrame->GetHeight(); //m_currFrame is a cximage object
	m_jpegRect.right=m_offsetX+m_currFrame->GetWidth();
	m_paintTarget->GetClientRect(m_clientRect);
	HBITMAP hMemBmp = CreateCompatibleBitmap(hDC,  m_clientRect.Width(),  m_clientRect.Height());
	HBITMAP hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp);
	FillRect(memDC,m_clientRect,(HBRUSH) (COLOR_WINDOW));
	if(m_playing)
	         m_currFrame->Draw(memDC,m_jpegRect);
	BitBlt(hDC, 0, 0, m_clientRect.Width(), m_clientRect.Height(), memDC, 0, 0, SRCCOPY);
	SelectObject(memDC, hOldBmp);
	::EndPaint(m_paintTarget->m_hWnd, &ps);
	DeleteObject(hMemBmp);
	if(!onPaint){
		m_paintTarget->InvalidateRect(m_jpegRect);
		m_paintTarget->RedrawWindow(m_jpegRect);
	}
	return TRUE;
}
this is the engine itself as a thread:

Code:
UINT MovieEngine::playThread(LPVOID engine)
{
	MovieEngine* thisEngine=(MovieEngine*)engine;
	if(thisEngine->m_buffComplete){
		while (thisEngine->m_movieBuff.size()>0)//m_movieBuff is a vector of pointers to cximages (hance the movie).
		{
			thisEngine->m_currFrame=thisEngine->m_movieBuff.front();
			thisEngine->m_movieBuff.pop();
			thisEngine->paintCurrFrame(FALSE); //function above
			delete thisEngine->m_currFrame;
			Sleep(40);// 40 milisec is the time needed to get 25 fps rate but all the picture switching takes time, so i need 40-switch_time...
		}
	}
	return 0;
}
ofcourse there is a loading thread (to keep buffer full untill the movie ends) while playing but it is irelevant for now.
i hope the code is clear, couse i am new to mfc and visual at all.
i managed to make it play but nothing deterministic. sometimes it plays faster than 25 fps sometimes slower.... i donno what to do
Second year SE student.
0
Cuckoo's Avatar, Join Date: Dec 2006
Light Poster
ps. i want the engine to be outside the dialog. is there a better way of doing it? perhaps should i put the painting part in the dialog OnPanint func?
0
ever_thus's Avatar, Join Date: Jan 2007
Contributor
Sorry if I haven't read all your code, so my answer might be a bit off.

It appears that the answer to your first question is that Sleep is the wrong way to go. All sleep does is wait for 40 ms. You might wait even longer while the systems multitasks to other programs. Alternatively the system might be very unbusy, run all your other code faster and make your fps higher (although 25 should still be the max).

The solution is to use check how much time has passed since the last frame was shown. Since the check is in the same place always the amount of time that the picture switching takes won't be a factor.

Here's the code:
Code:
static DWORD time = 0;
while (thisEngine->m_movieBuff.size()>0)
{
        if (GetTickCount () - time - 40){
        time = GetTickCount ();
        //all your code
}
It's a busy wait, as opposed to Sleep which allows the system to do other things, but your program isn't consuming much resources in the meantime, so that shouldn't matter. If you're concerened you can stick in Sleep (0). This tells the system: check if something else needs doing, if not come back to my program.

Hope this helps.
0
ever_thus's Avatar, Join Date: Jan 2007
Contributor
The code wasn't well formatted. Here it is again:
Code:
static DWORD time = 0;
while (thisEngine->m_movieBuff.size()>0)
{
        if (GetTickCount () - time - 40){
                 time = GetTickCount ();
                 //all your code
        }
}
0
ever_thus's Avatar, Join Date: Jan 2007
Contributor
OK. I've got more time now, so I read your code. My naswer is still correct, but the code I posted isn't. Here's the latest (promise!!) version.

(Moderators: If I'm breaking any rules with all this reposting just let me know and I won't do it again.)

Code:
 static DWORD time = GetTickCount ();
while (thisEngine->m_movieBuff.size()>0){
while (GetTickCount () - time < 40){
Sleep (0);
}
time = GetTickCount ();
//all your code
}
0
Cuckoo's Avatar, Join Date: Dec 2006
Light Poster
Quote:
Originally Posted by ever_thus
OK. I've got more time now, so I read your code. My naswer is still correct, but the code I posted isn't. Here's the latest (promise!!) version.

(Moderators: If I'm breaking any rules with all this reposting just let me know and I won't do it again.)

Code:
 static DWORD time = GetTickCount ();
while (thisEngine->m_movieBuff.size()>0){
while (GetTickCount () - time < 40){
Sleep (0);
}
time = GetTickCount ();
//all your code
}
realy realy thanks, i dont know y didnt i think of busy-wait before.... i guess in my studies i somehow learned that busy-wait is bad thing... but in this case there is no other option isnt it?
0
ever_thus's Avatar, Join Date: Jan 2007
Contributor
Well, as I said, by calling Sleep (0) you can avoid the ill-effect of a busy wait, while still maintaining control of your timing by using GetTickCount ().