用了半年的settimer,愚以为这个定时器真是方便好用,与多线程相比优势明显,不禁怀疑为什么多线程还有存在的意义。
直到今天使用定时器播放视频,问题出来了,定时器播放视频与普通的媒体播放视频相比,播放速度总是很慢,而且精度不仅不能保证,误差相当大,有时候,我播放30秒的视频,在Ontimer中执行40多秒才播放完,这是不能容忍的。
顿时发觉ontimer在处理这种对时间精度要求很高的程序中,没有任何优势了,所以只能另开线程,执行播放视频的功能。
在mfc中,使用
CWinThread*m_pThread2PlayVideo = AfxBeginThread(Thread2PlayVideo,this);
其中,Thread2PlayVideo是播放视频的线程函数,而this是线程函数所在类的指针。为什么需要传入类的指针这个参数呢,因为类中的线程函数必须为静态函数(static),而类的静态函数如果想访问非静态成员变量的话是无法直接实现的,必须间接达到目的。
下面是执行的代码:
UINT CxxView::Thread2PlayVideo(LPVOID pParam)
{
CxxView*pView = (CxxView*)pParam;
CMainFrame *pMain=(CMainFrame *)AfxGetApp()->m_pMainWnd;
pView->m_hWndStatic = pMain->m_wndNativeView.m_wndDrawContent.m_oPictureCtrlNativeViedo.GetSafeHwnd();
pView->m_pWndStatic = FromHandle(pView->m_hWndStatic);
pView->m_pWndStatic->GetClientRect(&pView->m_oRect);
static int s_nC = 0;
if (pView->m_oOperativeparamsWnd.getplaybackparams()->m_strVideoPath!="")
{
pView->m_PlayBackCapture = cvCreateFileCapture(pView->m_oOperativeparamsWnd.getplaybackparams()->m_strVideoPath);
int numFrames = (int) cvGetCaptureProperty(pView->m_PlayBackCapture, CV_CAP_PROP_FRAME_COUNT);
pView->m_PlayBackFrame = cvQueryFrame(pView->m_PlayBackCapture);
}
if (pView->m_PlayBackCapture==NULL || pView->m_PlayBackFrame==NULL)
{
return 0;
}
<strong> while (pView->m_PlayBackCapture)
{
long lt1 = GetTickCount();
s_nC++;
if (s_nC*15.0/1000.0>125.0 && (s_nC-1)*15.0/1000.0<125.0)
{
pView->SetTimer(3,pView->m_nElapse,NULL);
}
pView->m_PlayBackFrame = cvQueryFrame(pView->m_PlayBackCapture);
drawIplmageOnMFC(pView->m_PlayBackFrame,pView->m_oRect,pView->m_hWndStatic,pView->m_pWndStatic->GetDC(),1);
long lt2 = GetTickCount();
long a = lt2-lt1;
Sleep(1000.0/15.0-a);
}</strong>
return 0;
}
加粗的代码为主要的实现方式,可以通过实时调节sleep()时间来达到精确播放视频的目的。