1. We have moved from vBulletin to XenForo and you are viewing the site in the middle of the move. Though the functional aspect of everything is working fine, we are still working on other changes including the new design on Xenforo.
    Dismiss Notice

Movie app using picture changes at 25 fps

Discussion in 'MFC' started by Cuckoo, Jan 17, 2007.

  1. Cuckoo

    Cuckoo New Member

    Joined:
    Dec 23, 2006
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    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.
     
  2. Cuckoo

    Cuckoo New Member

    Joined:
    Dec 23, 2006
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    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?
     
  3. ever_thus

    ever_thus New Member

    Joined:
    Jan 3, 2007
    Messages:
    53
    Likes Received:
    0
    Trophy Points:
    0
    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.
     
  4. ever_thus

    ever_thus New Member

    Joined:
    Jan 3, 2007
    Messages:
    53
    Likes Received:
    0
    Trophy Points:
    0
    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
            }
    }
     
  5. ever_thus

    ever_thus New Member

    Joined:
    Jan 3, 2007
    Messages:
    53
    Likes Received:
    0
    Trophy Points:
    0
    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){
    [INDENT]while (GetTickCount () - time < 40){[/INDENT]
    [INDENT][INDENT]Sleep (0);[/INDENT][/INDENT]
    [INDENT]}[/INDENT]
    [INDENT]time = GetTickCount ();[/INDENT]
    [INDENT]//all your code[/INDENT]
    }
     
  6. Cuckoo

    Cuckoo New Member

    Joined:
    Dec 23, 2006
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    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?
     
  7. ever_thus

    ever_thus New Member

    Joined:
    Jan 3, 2007
    Messages:
    53
    Likes Received:
    0
    Trophy Points:
    0
    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 ().
     

Share This Page