|
|
DirectShow 学习(四):部分Helper Classes类源代码分析 |
|
|
作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站 |
- CRefTime类[reftime.h]
CRefTime类维护了REFERENCE_TIME m_time;的成员变量。单位为100ns。 另外,几个跟该类相关的宏: const LONGLONG MILLISECONDS = (1000); // 10 ^ 3 const LONGLONG NANOSECONDS = (1000000000); // 10 ^ 9 const LONGLONG UNITS = (NANOSECONDS / 100); // 10 ^ 7 #define MILLISECONDS_TO_100NS_UNITS(lMs) \ Int32x32To64((lMs), (UNITS / MILLISECONDS)) inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT) {return (RT / (UNITS / MILLISECONDS));}
- IBaseReferenceClock接口
IReferenceClock : public IUnknown { public: // Retrieves the current reference time. virtual HRESULT STDMETHODCALLTYPE GetTime( /* [out] */ REFERENCE_TIME *pTime) = 0; // Creates a one-shot advise request. virtual HRESULT STDMETHODCALLTYPE AdviseTime( /* [in] */ REFERENCE_TIME baseTime, /* [in] */ REFERENCE_TIME streamTime, /* [in] */ HEVENT hEvent, /* [out] */ DWORD_PTR *pdwAdviseCookie) = 0; // Creates a periodic advise request. virtual HRESULT STDMETHODCALLTYPE AdvisePeriodic( /* [in] */ REFERENCE_TIME startTime, /* [in] */ REFERENCE_TIME periodTime, /* [in] */ HSEMAPHORE hSemaphore, /* [out] */ DWORD_PTR *pdwAdviseCookie) = 0; // Removes a pending advise request. virtual HRESULT STDMETHODCALLTYPE Unadvise( /* [in] */ DWORD_PTR dwAdviseCookie) = 0; };
- CCritSec和CAutoLock类[wxutil.h/wxutil.cpp]
CCritSec封装了CRITICAL_SECTION m_CritSec;成员变量,通过函数Lock()和Unlock对该变量进行EnterCriticalSection和LeaveCriticalSection,同时,Constructor和Deconstructor分别调用了InitializeCriticalSection和DeleteCriticalSection函数。 CAutoLock是和CCritSec配合使用的Helper类,它在Constructor中接受一个CCritSec的指针,并对其调用Lock函数,而在Deconstructor调用Unlock函数。
- CAMSchedule类[dsschedule.h/schedule.cpp]
派生自 CBaseObject 其实此类就是一个List,Node是类型CAdvisePacket。具体解析略。
- CBaseReferenceClock类[refclock.h/refclock.cpp]
继承了IReferenceClock接口,同时派生自CUnknown、CCritSec。
- 成员变量:
REFERENCE_TIME m_rtPrivateTime; // Current best estimate of time DWORD m_dwPrevSystemTime; // Last vaule we got from timeGetTime REFERENCE_TIME m_rtLastGotTime; // Last time returned by GetTime REFERENCE_TIME m_rtNextAdvise; // Time of next advise UINT m_TimerResolution; BOOL m_bAbort; // Flag used for thread shutdown HANDLE m_hThread; // Thread handle CAMSchedule * const m_pSchedule; // 任务列表 // 一个Static函数 static DWORD __stdcall AdviseThreadFunction(LPVOID); // Function used to get there
- IReferenceClock接口函数:
STDMETHODIMP GetTime(REFERENCE_TIME *pTime); { // 首先调用Lock(),然后rtNow = GetPrivateTime(); // 判断(rtNow > m_rtLastGotTime),是则m_rtLastGotTime = rtNow;否则设置返回值为S_FALSE // 设置返回值 *pTime = m_rtLastGotTime; } /* Ask for an async notification that a time has elapsed */ STDMETHODIMP AdviseTime( REFERENCE_TIME baseTime, // base reference time REFERENCE_TIME streamTime, // stream offset time HEVENT hEvent, // advise via this event DWORD_PTR *pdwAdviseCookie // where your cookie goes ); { // 首先初始化输出变量 *pdwAdviseCookie = 0; // 判断 ASSERT(WAIT_TIMEOUT == WaitForSingleObject(HANDLE(hEvent),0)); // 得到当前绝对时间 const REFERENCE_TIME lRefTime = baseTime + streamTime; // *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( lRefTime, 0, HANDLE(hEvent), FALSE ); } /* Ask for an asynchronous periodic notification that a time has elapsed */ STDMETHODIMP AdvisePeriodic( REFERENCE_TIME StartTime, // starting at this time REFERENCE_TIME PeriodTime, // time between notifications HSEMAPHORE hSemaphore, // advise via a semaphore DWORD_PTR *pdwAdviseCookie // where your cookie goes ); { // 同样,首先初始化输出变量 // *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( StartTime, PeriodTime, HANDLE(hSemaphore), TRUE ); } STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie); { return m_pSchedule->Unadvise(dwAdviseCookie); }
- 新增加的virtual函数:
virtual REFERENCE_TIME GetPrivateTime(); { CAutoLock cObjectLock(this); DWORD dwTime = timeGetTime(); m_rtPrivateTime += Int32x32To64(UNITS / MILLISECONDS, (DWORD)(dwTime - m_dwPrevSystemTime)); m_dwPrevSystemTime = dwTime; return m_rtPrivateTime; }
- 普通成员函数:
/* Provide a method for correcting drift */ STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta ); { CAutoLock cObjectLock(this); m_rtPrivateTime += TimeDelta; if ( TimeDelta > 5000 && m_pSchedule->GetAdviseCount() > 0 ) TriggerThread(); return NOERROR; } CAMSchedule * GetSchedule() const { return m_pSchedule; } void TriggerThread() // Wakes thread up. Need to do this if { // time to next advise needs reevaluating. EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent())); } DWORD __stdcall AdviseThreadFunction(LPVOID p) { return DWORD(reinterpret_cast<CBaseReferenceClock*>(p)->AdviseThread()); } // Method in which the advise thread runs HRESULT AdviseThread() { DWORD dwWait = INFINITE; while ( !m_bAbort ) { WaitForSingleObject(m_pSchedule->GetEvent(), dwWait); if (m_bAbort) break; const REFERENCE_TIME rtNow = GetPrivateTime(); m_rtNextAdvise = m_pSchedule->Advise( 10000 + rtNow ); LONGLONG llWait = m_rtNextAdvise - rtNow; llWait = ConvertToMilliseconds(llWait); // DON'T replace this with a max!! (The type's of these things is VERY important) dwWait = (llWait > REFERENCE_TIME(UINT_MAX)) ? UINT_MAX : DWORD(llWait); } }
- Deconstructor:
CBaseReferenceClock::~CBaseReferenceClock() { if (m_TimerResolution) timeEndPeriod(m_TimerResolution); m_pSchedule->DumpLinkedList(); // 如果m_hThread存在,设置m_bAbort为TRUE后调用TriggerThread(), // 然后等Thread结束:WaitForSingleObject( m_hThread, INFINITE ); // 关闭Thread的handle::EXECUTE_ASSERT( CloseHandle(m_hThread) ); // m_hThread = 0; // 清除任务列表的Event Handle:EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) ); }
- Constructor:
CBaseReferenceClock::CBaseReferenceClock( TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr, CAMSchedule * pShed ) : CUnknown( pName, pUnk ) , m_rtLastGotTime(0) , m_TimerResolution(0) , m_bAbort( FALSE ) , m_pSchedule( pShed ? pShed : new CAMSchedule(CreateEvent(NULL, FALSE, FALSE, NULL)) ) , m_hThread(0) { // 判断m_pSchedule是否为空,如果为空则直接返回错误 TIMECAPS tc; m_TimerResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc))) ? tc.wPeriodMin: 1; timeBeginPeriod(m_TimerResolution); /* Initialise our system times - the derived clock should set the right values */ m_dwPrevSystemTime = timeGetTime(); m_rtPrivateTime = (UNITS / MILLISECONDS) * m_dwPrevSystemTime; if ( !pShed ) { DWORD ThreadID; m_hThread = ::CreateThread(NULL, // Security attributes (DWORD) 0, // Initial stack size AdviseThreadFunction, // Thread start address (LPVOID) this, // Thread parameter (DWORD) 0, // Creation flags &ThreadID); // Thread identifier if (m_hThread) SetThreadPriority( m_hThread, THREAD_PRIORITY_TIME_CRITICAL ); else 返回错误并清除m_pSchedule } }
- CAMEvent类[wxutil.h/wxutil.cpp]
类似于CCritSec,CAMEvent封装了HANDLE m_hEvent;
- Construction:
CAMEvent(BOOL fManualReset = FALSE); {m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);}
- Deconstructor
~CAMEvent(){if (m_hEvent) EXECUTE_ASSERT(CloseHandle(m_hEvent));}
- 成员函数很简洁明了
operator HANDLE () const { return m_hEvent; }; void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent));}; BOOL Wait(DWORD dwTimeout = INFINITE) { return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0); }; void Reset() { ResetEvent(m_hEvent); }; BOOL Check() { return Wait(0); };
- CAMThread类[wxutil.h/wxutil.cpp]
CAMThread稍微复杂一点。
- 成员变量:
CAMEvent m_EventSend; CAMEvent m_EventComplete; DWORD m_dwParam; DWORD m_dwReturnVal; HANDLE m_hThread; CCritSec m_AccessLock; // locks access by client threads CCritSec m_WorkerLock; // locks access to shared objects 其中,m_EventSend默认为TRUE,m_hThread初始化为NULL。
- Deconstrutor只调用了Close函数。
- 新增加的virtual函数:
virtual DWORD ThreadProc() = 0;
- 成员函数:
// start thread running - error if already running BOOL Create(); { CAutoLock lock(&m_AccessLock); if (ThreadExists()) {return FALSE;} // 创建Thread,返回创建结果 m_hThread = CreateThread(NULL, 0, CAMThread::InitialThreadProc, this, 0, &threadid); } // signal the thread, and block for a response DWORD CallWorker(DWORD); { CAutoLock lock(&m_AccessLock); // 判断ThreadExists函数 // 设置参数 m_dwParam = dwParam; // signal the worker thread: m_EventSend.Set(); // 等待该Thread结束 m_EventComplete.Wait(); // 返回结果 return m_dwReturnVal; } // accessor thread calls this when done with thread (having told thread to exit) void Close() { HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0); if (hThread) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } }; // Return TRUE if the thread exists. FALSE otherwise BOOL ThreadExists(void) const {return (m_hThread != 0); } // wait for the next request DWORD GetRequest();{m_EventSend.Wait();return m_dwParam;} // is there a request? BOOL CheckRequest(DWORD * pParam); { // if (!m_EventSend.Check())return FALSE; // 否则设置*pParam = m_dwParam; } // reply to the request void Reply(DWORD); { m_dwReturnVal = dw; m_EventSend.Reset(); m_EventComplete.Set(); } HANDLE GetRequestHandle() const { return m_EventSend; }; DWORD GetRequestParam() const { return m_dwParam; };
- static成员函数:
// thread initially runs this. param is actually 'this'. Function // just gets this and calls ThreadProc static DWORD WINAPI InitialThreadProc(LPVOID pv); { HRESULT hrCoInit = CAMThread::CoInitializeHelper(); CAMThread * pThread = (CAMThread *) pv; HRESULT hr = pThread->ThreadProc(); if(SUCCEEDED(hrCoInit)) {CoUninitialize();} return hr; } // call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if available. S_FALSE means it's not available. static HRESULT CoInitializeHelper(); { // 通过GetModuleHandle(TEXT("ole32.dll"));来直接调用其中函数CoInitializeEx函数。 }
下几个部分将结合DirectShow中自带的例子分析CSource、CTransform和Render等类的源代码。 上一篇:学习(三) CBaseFilter类源代码解析

|
|
相关文章:相关软件: |
|