directshow中有很多消息时间,DirectShow中,也有时间通知的消息机制;
但是在一般情况中,会直接用IMediaEvent接口获取事件,我们可以再线程中获取;
在帮助文档中可以参考Learning When an Event Occurs;
示例:
DWORD WINAPI ThreadFuncVideo ( LPVOID lpParam )
{
IMediaEvent * pEvent = (IMediaEvent*)lpParam;
HANDLE hEvent;
long evCode, param1, param2;
BOOLEAN bDone = FALSE;
HRESULT hr = S_OK;
hr = pEvent->GetEventHandle((OAEVENT*)&hEvent);
while(!bDone)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100))
{
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
pEvent->FreeEventParams(evCode, param1, param2);
if (EC_DEVICE_LOST == evCode) //获取消息;
{
AfxMessageBox(CString("EC_DEVICE_LOST"));
return 0;
}
}
}
}
return 0;
}
上面简单讲解了消息,下面写一个directshow的播放器:
class CVideoPlay
{
public:
CVideoPlay( CWnd * wnd )
{
pGraph = NULL;
pControl = NULL;
pEvent = NULL;
pVidWin = NULL;
hr=0;
pWnd = wnd;
}
~CVideoPlay()
{
stop();
}
public:
IGraphBuilder *pGraph ;
IMediaControl *pControl ;
IMediaEvent *pEvent ;
IVideoWindow *pVidWin ;
CWnd * pWnd;
HRESULT hr;
public:
int Play( CString strfile )
{
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph); if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return 0;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
hr = pGraph->RenderFile(strfile, NULL);
hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
pVidWin->put_Owner((OAHWND)(pWnd->GetSafeHwnd()));
pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
CRect grc;
pWnd->GetClientRect(&grc);
pVidWin->SetWindowPosition(0, 0, /*grc.right*/100, /*grc.bottom*/100);
if (SUCCEEDED(hr))
{
hr = pControl->Run();
if (!SUCCEEDED(hr))
{
stop();
return 0;
}
}
//AfxBeginThread( threadEV, this );
{
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
char szMsg[80];
hThread = CreateThread(
NULL, // no security attributes
0, // use default stack size
threadEV, // thread function
this, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
CloseHandle( hThread );
}
return 1;
}
void stop()
{
if (pControl)
{
pControl->Pause();
pControl->Stop();
if (pVidWin)
{
pVidWin->put_Visible(OAFALSE);
pVidWin->put_Owner(NULL);
}
}
if (pGraph)
{
pControl->Release();
pEvent->Release();
pGraph->Release();
pVidWin->Release();
pControl = NULL;
pEvent = NULL;
pGraph = NULL;
pVidWin = NULL;
while(m_threadok == 0)
{
Sleep(10);
}
}
}
public:
int m_threadok;
private:
UINT EV()
{
m_threadok = 0;
HANDLE hEvent;
long evCode, param1, param2;
BOOLEAN bDone = FALSE;
HRESULT hr = S_OK;
hr = pEvent->GetEventHandle((OAEVENT*)&hEvent);
if (FAILED(hr) )
{
/* Insert failure-handling code here. */
}
while( !bDone && pEvent && pControl)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 10) )
{
if (pEvent == NULL)
{
break;
}
while ( hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr) )
{
if (pEvent==NULL)
{
break;
}
OutputDebugStringA("pEvent && ");
printf("Event code: %#04x\n Params: %d, %d\n", evCode, param1, param2);
pEvent->FreeEventParams(evCode, param1, param2);
bDone = (EC_COMPLETE == evCode);
}
}
}
if (pControl==NULL)
{
AfxMessageBox( CString("播放退出") );
//播放退出;
}
else
{
//播放完成;
AfxMessageBox( CString("播放完成") );
}
m_threadok = 1;
return 0;
}
public:
static DWORD WINAPI threadEV( PVOID pParam )
{
CVideoPlay * play = (CVideoPlay*)pParam;
play->EV();
return 0;
}
};