您的位置:首页 > 编程语言

DirectShow学习(八): CBaseRender类及相应Pin类的源代码分析

2005-02-25 16:07 471 查看
DirectShow学习(八): CBaseRender类及相应Pin类的源代码分析
1. CRendererInputPin[/b]类[renbase.h/renbase.cpp][/b]
派生自CBaseInputPin[/b]。
a) 成员变量:
CBaseRenderer *m_pRenderer[/b];
b) IPin接口和继承的函数
HRESULT BreakConnect[/b]();
{
HRESULT hr = m_pRenderer->BreakConnect();
return CBaseInputPin::BreakConnect();
}
HRESULT CompleteConnect[/b](IPin *pReceivePin);
{
HRESULT hr = m_pRenderer->CompleteConnect(pReceivePin);
return CBaseInputPin::CompleteConnect(pReceivePin);
}
HRESULT SetMediaType[/b](const CMediaType *pmt);
{
HRESULT hr = CBaseInputPin::SetMediaType(pmt);
return m_pRenderer->SetMediaType(pmt);
}
HRESULT CheckMediaType[/b](const CMediaType *pmt);
{ return m_pRenderer->CheckMediaType(pmt); }
HRESULT Active[/b]();{ return m_pRenderer->Active();}
HRESULT Inactive[/b]();
{
ASSERT(CritCheckIn(&m_pRenderer->m_InterfaceLock));
m_bRunTimeError = FALSE;
return m_pRenderer->Inactive();
}
STDMETHODIMP QueryId[/b](LPWSTR *Id);
{
*Id = (LPWSTR)CoTaskMemAlloc(8);
lstrcpyW(*Id, L"In");
}
STDMETHODIMP EndOfStream[/b]();
{
CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
HRESULT hr = CheckStreaming();
hr = m_pRenderer->EndOfStream();
hr = CBaseInputPin::EndOfStream();
}
STDMETHODIMP BeginFlush[/b]();
{
HRESULT hr = m_pRenderer->EndFlush();
hr = CBaseInputPin::EndFlush();
}
STDMETHODIMP EndFlush[/b]();
{
CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
CBaseInputPin::BeginFlush();
m_pRenderer->BeginFlush();
return m_pRenderer->ResetEndOfStream();
}
STDMETHODIMP Receive[/b](IMediaSample *pMediaSample);
{
HRESULT hr = m_pRenderer->Receive(pSample);
if (FAILED(hr)) {
ASSERT(CritCheckOut(&m_pRenderer->m_RendererLock));
CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
if (!IsStopped() && !IsFlushing() && !m_pRenderer->m_bAbort && !m_bRunTimeError)
{
m_pRenderer->NotifyEvent(EC_ERRORABORT,hr,0);
CAutoLock alRendererLock(&m_pRenderer->m_RendererLock);
if (m_pRenderer->IsStreaming() && !m_pRenderer->IsEndOfStreamDelivered())
{ m_pRenderer->NotifyEndOfStream();}
m_bRunTimeError = TRUE;
}
}
}
2. CBaseRender[/b]类[renbase.h/renbase.cpp][/b]
派生自CBaseFilter[/b]。
a) 成员变量
CRendererPosPassThru[/b] *m_pPosition[/b]; // Media seeking pass by object
类CRendererPosPassThru派生自CPosPassThru,后者继承自接口IMediaSeeking和类CMediaPosition。而类CMediaPosition实现了接口IMediaPosition。具体实现见ctlutil.h[/b]
CAMEvent m_RenderEvent; // Used to signal timer events
CAMEvent m_ThreadSignal; // Signalled to release worker thread
CAMEvent m_evComplete; // Signalled when state complete
BOOL m_bAbort; // Stop us from rendering more data
BOOL m_bStreaming; // Are we currently streaming
DWORD_PTR m_dwAdvise; // Timer advise cookie
IMediaSample *m_pMediaSample; // Current image media sample
BOOL m_bEOS; // Any more samples in the stream
BOOL m_bEOSDelivered; // Have we delivered an EC_COMPLETE
CRendererInputPin *m_pInputPin; // Our renderer input pin object
CCritSec m_InterfaceLock; // Critical section for interfaces
CCritSec m_RendererLock; // Controls access to internals
IQualityControl * m_pQSink; // QualityControl sink
BOOL m_bRepaintStatus; // Can we signal an EC_REPAINT
// Avoid some deadlocks by tracking filter during stop
volatile BOOL m_bInReceive; // Inside Receive between PrepareReceive
// And actually processing the sample
REFERENCE_TIME m_SignalTime; // Time when we signal EC_COMPLETE
UINT m_EndOfStreamTimer; // Used to signal end of stream
CCritSec m_ObjectCreationLock; // This lock protects the creation and
// of m_pPosition and m_pInputPin. It ensures that two threads cannot create
// either object simultaneously.
构造函数中,对各成员初始化,m_evComplete(TRUE), m_bAbort(FALSE), m_pPosition(NULL), m_ThreadSignal(TRUE), m_bStreaming(FALSE), m_bEOS(FALSE), m_bEOSDelivered(FALSE), m_pMediaSample(NULL), m_dwAdvise(0), m_pQSink(NULL), m_pInputPin(NULL), m_bRepaintStatus(TRUE), m_SignalTime(0), m_bInReceive(FALSE), m_EndOfStreamTimer(0);析构函数中调用StopStreaming和ClearPendingSample;并删除m_pPosition和m_pInputPin。
b) 新增加的virtual函数
// Overriden to say what interfaces we support and where
virtual HRESULT GetMediaPositionInterface[/b](REFIID riid,void **ppv);
{
CAutoLock cObjectCreationLock(&m_ObjectCreationLock);
if (m_pPosition) {
return m_pPosition->NonDelegatingQueryInterface(riid,ppv);
}
m_pPosition = new CRendererPosPassThru(NAME("Renderer CPosPassThru"),
CBaseFilter::GetOwner(),(HRESULT *) &hr, GetPin(0));
return GetMediaPositionInterface[/b](riid,ppv);
}
virtual HRESULT SourceThreadCanWait[/b](BOOL bCanWait);
{
if (bCanWait == TRUE) m_ThreadSignal.Reset();
else m_ThreadSignal.Set();
}
virtual HRESULT WaitForRenderTime[/b]();
{
HANDLE WaitObjects[] = { m_ThreadSignal, m_RenderEvent };
OnWaitStart[/b]();
while (Result == WAIT_TIMEOUT) {
Result = WaitForMultipleObjects(2,WaitObjects,FALSE,RENDER_TIMEOUT);}
OnWaitEnd[/b]();
if (Result == WAIT_OBJECT_0) {return VFW_E_STATE_CHANGED;}
SignalTimerFired[/b]();
}
virtual HRESULT CompleteStateChange[/b](FILTER_STATE OldState);
{
if (m_pInputPin->IsConnected() == FALSE) {Ready[/b]();return S_OK;}
if (IsEndOfStream[/b]() == TRUE) {Ready[/b]();return S_OK;}
if (HaveCurrentSample[/b]() == TRUE) {
if (OldState != State_Stopped) { Ready[/b]();return S_OK;}
}
NotReady[/b]();
}
virtual void OnReceiveFirstSample[/b](IMediaSample *pMediaSample) {};
virtual void OnRenderStart[/b](IMediaSample *pMediaSample){}
virtual void OnRenderEnd[/b](IMediaSample *pMediaSample){}
virtual HRESULT OnStartStreaming[/b]() { return NOERROR; };
virtual HRESULT OnStopStreaming[/b]() { return NOERROR; };
virtual void OnWaitStart[/b]() {};
virtual void OnWaitEnd[/b]() {};
virtual void PrepareRender[/b]() {};
// Quality management implementation for scheduling rendering
virtual BOOL ScheduleSample[/b](IMediaSample *pMediaSample);
{
REFERENCE_TIME StartSample, EndSample;
if (pMediaSample == NULL) {return FALSE;}
HRESULT hr = GetSampleTimes[/b](pMediaSample, &StartSample, &EndSample);
if (FAILED(hr)) {return FALSE;}
if (hr == S_OK) {EXECUTE_ASSERT[/b](SetEvent[/b]((HANDLE) m_RenderEvent));
return TRUE;}
ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
hr = m_pClock->AdviseTime[/b](
(REFERENCE_TIME) m_tStart, // Start run time
StartSample, // Stream time
(HEVENT)(HANDLE) m_RenderEvent, // Render notification
&m_dwAdvise); // Advise cookie
if (SUCCEEDED(hr)) {return TRUE;}
return FALSE;
}
virtual HRESULT GetSampleTimes[/b](IMediaSample *pMediaSample,
REFERENCE_TIME *pStartTime,
REFERENCE_TIME *pEndTime);
{
if (SUCCEEDED(pMediaSample->GetTime[/b](pStartTime, pEndTime))) {
if (*pEndTime < *pStartTime) {return VFW_E_START_TIME_AFTER_END;}
} else {return S_OK;}
if (m_pClock == NULL) {return S_OK;}
return ShouldDrawSampleNow[/b](pMediaSample,pStartTime,pEndTime);
}
virtual HRESULT ShouldDrawSampleNow[/b](IMediaSample *pMediaSample,
REFERENCE_TIME *ptrStart,
REFERENCE_TIME *ptrEnd);{ return S_FALSE;}
virtual HRESULT SendEndOfStream[/b]();
{
ASSERT(CritCheckIn(&m_RendererLock));
if (m_bEOS == FALSE || m_bEOSDelivered || m_EndOfStreamTimer) {
return NOERROR;}
if (m_pClock == NULL) {return NotifyEndOfStream[/b]();}
REFERENCE_TIME Signal = m_tStart + m_SignalTime;
REFERENCE_TIME CurrentTime;
m_pClock->GetTime(&CurrentTime);
LONG Delay = LONG((Signal - CurrentTime) / 10000);
if (Delay < TIMEOUT_DELIVERYWAIT) {return NotifyEndOfStream();}
m_EndOfStreamTimer = CompatibleTimeSetEvent[/b]((UINT) Delay, // Period of timer
TIMEOUT_RESOLUTION, // Timer resolution
EndOfStreamTimer, // Callback function
DWORD_PTR(this), // Used information
TIME_ONESHOT); // Type of callback
if (m_EndOfStreamTimer == 0) {return NotifyEndOfStream[/b]();}
}
virtual HRESULT ResetEndOfStream[/b]();
{
ResetEndOfStreamTimer[/b]();
CAutoLock cRendererLock(&m_RendererLock);
m_bEOS = FALSE;
m_bEOSDelivered = FALSE;
m_SignalTime = 0;
}
virtual HRESULT EndOfStream[/b]();
{
m_bEOS = TRUE;
Ready[/b]();
if (m_pMediaSample) { return NOERROR;}
if (m_bStreaming) { SendEndOfStream[/b]();}
}
virtual HRESULT CancelNotification[/b]();
{
ASSERT(m_dwAdvise == 0 || m_pClock);
DWORD_PTR dwAdvise = m_dwAdvise;
if (m_dwAdvise) {
m_pClock->Unadvise(m_dwAdvise);
SignalTimerFired();}
m_RenderEvent.Reset();
return (dwAdvise ? S_OK : S_FALSE);
}
virtual HRESULT ClearPendingSample[/b]();
{
CAutoLock cRendererLock(&m_RendererLock);
if (m_pMediaSample) {
m_pMediaSample->Release();
m_pMediaSample = NULL;}
}
virtual HRESULT PrepareReceive[/b](IMediaSample *pMediaSample);
{
CAutoLock cInterfaceLock(&m_InterfaceLock);
m_bInReceive = TRUE;
HRESULT hr = m_pInputPin->CBaseInputPin::Receive(pMediaSample);
if (hr != NOERROR) {m_bInReceive = FALSE; return E_FAIL;}
if (m_pInputPin->SampleProps()->pMediaType) {
hr = m_pInputPin->SetMediaType(
(CMediaType *)m_pInputPin->SampleProps()->pMediaType);
if (FAILED(hr)) {
m_bInReceive = FALSE;
return hr;
}
}
CAutoLock cSampleLock(&m_RendererLock);
if (m_pMediaSample || m_bEOS || m_bAbort) {
Ready();m_bInReceive = FALSE; return E_UNEXPECTED;}
if (m_pPosition) m_pPosition->RegisterMediaTime[/b](pMediaSample);
if ((m_bStreaming == TRUE) && (ScheduleSample[/b](pMediaSample) == FALSE)) {
ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
ASSERT(CancelNotification() == S_FALSE);
m_bInReceive = FALSE;
return VFW_E_SAMPLE_REJECTED;
}
m_SignalTime = m_pInputPin->SampleProps()->tStop;
m_pMediaSample = pMediaSample;
m_pMediaSample->AddRef();
if (m_bStreaming == FALSE) {SetRepaintStatus[/b](TRUE);}
}
virtual BOOL HaveCurrentSample[/b]();
{
// Checks if there is a sample waiting at the renderer
CAutoLock cRendererLock(&m_RendererLock);
return (m_pMediaSample == NULL ? FALSE : TRUE);
}
virtual IMediaSample *GetCurrentSample[/b]();
{
CAutoLock cRendererLock(&m_RendererLock);
if (m_pMediaSample) {m_pMediaSample->AddRef();}
return m_pMediaSample;
}
virtual HRESULT Render[/b](IMediaSample *pMediaSample);
{
if (pMediaSample == NULL) {return S_FALSE;}
if (m_bStreaming == FALSE) {return S_FALSE;}
OnRenderStart[/b](pMediaSample);
DoRenderSample[/b](pMediaSample);
OnRenderEnd[/b](pMediaSample);
}
virtual HRESULT DoRenderSample[/b](IMediaSample *pMediaSample) PURE[/b];
c) IBaseFilter接口函数以及继承函数
virtual int GetPinCount[/b]();{1}
virtual CBasePin *GetPin[/b](int n);
{
CAutoLock cObjectCreationLock(&m_ObjectCreationLock);
if (m_pInputPin == NULL) {
m_pInputPin = new CRendererInputPin(this,&hr,L"In");}
return m_pInputPin;
}
STDMETHODIMP Stop[/b]();
{
CAutoLock cRendererLock(&m_InterfaceLock);
if (m_State == State_Stopped) { return NOERROR;}
if (m_pInputPin->IsConnected() == FALSE) {
m_State = State_Stopped;
return NOERROR;}
CBaseFilter::Stop();
if (m_pInputPin->Allocator()) { m_pInputPin->Allocator()->Decommit();}
SetRepaintStatus[/b](TRUE);
StopStreaming[/b]();
SourceThreadCanWait[/b](FALSE);
ResetEndOfStream[/b]();
CancelNotification[/b]();
Ready[/b]();
WaitForReceiveToComplete[/b]();
m_bAbort = FALSE;
}
STDMETHODIMP Pause[/b]();
{
CAutoLock cRendererLock(&m_InterfaceLock);
FILTER_STATE OldState = m_State;
if (m_State == State_Paused) { return CompleteStateChange[/b](State_Paused);}
if (m_pInputPin->IsConnected() == FALSE) {
m_State = State_Paused;
return CompleteStateChange(State_Paused);
}
HRESULT hr = CBaseFilter::Pause();
SetRepaintStatus[/b](TRUE);
StopStreaming[/b]();
SourceThreadCanWait[/b](TRUE);
CancelNotification[/b]();
ResetEndOfStreamTimer[/b]();
if (m_pInputPin->Allocator()) { m_pInputPin->Allocator()->Commit();}
if (OldState == State_Stopped) {
m_bAbort = FALSE;
ClearPendingSample[/b]();}
return CompleteStateChange[/b](OldState);
}
STDMETHODIMP Run[/b](REFERENCE_TIME StartTime);
{
CAutoLock cRendererLock(&m_InterfaceLock);
FILTER_STATE OldState = m_State;
if (m_pInputPin->IsConnected() == FALSE) {
NotifyEvent[/b](EC_COMPLETE,S_OK,(LONG_PTR)(IBaseFilter *)this);
m_State = State_Running;
return NOERROR;}
Ready[/b]();
HRESULT hr = CBaseFilter::Run(StartTime);
SourceThreadCanWait[/b](TRUE);
SetRepaintStatus[/b](FALSE);
if (m_pInputPin->Allocator()) { m_pInputPin->Allocator()->Commit();}
if (OldState == State_Stopped) {
m_bAbort = FALSE;
ClearPendingSample[/b]();}
return StartStreaming[/b] ();
}
STDMETHODIMP GetState[/b](DWORD dwMSecs,FILTER_STATE *State);
{
CheckPointer(State,E_POINTER);
if (WaitDispatchingMessages[/b](m_evComplete, dwMSecs) == WAIT_TIMEOUT) {
*State = m_State;
return VFW_S_STATE_INTERMEDIATE;}
*State = m_State;
}
STDMETHODIMP FindPin[/b](LPCWSTR Id, IPin **ppPin);
{
if (0==lstrcmpW(Id,L"In")) { *ppPin = GetPin(0); (*ppPin)->AddRef();}
}
virtual HRESULT Active[/b]();{return NOERROR;}
virtual HRESULT Inactive[/b]();
{
if (m_pPosition) { m_pPosition->ResetMediaTime();}
ClearPendingSample[/b]();
}
virtual HRESULT StartStreaming[/b]();
{
CAutoLock cRendererLock(&m_RendererLock);
if (m_bStreaming == TRUE) {return NOERROR;}
m_bStreaming = TRUE;
timeBeginPeriod(1);
OnStartStreaming[/b]();
ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
ASSERT(CancelNotification() == S_FALSE);
if (m_pMediaSample == NULL) {return SendEndOfStream();}
if (!ScheduleSample[/b](m_pMediaSample)) m_RenderEvent.Set();
}
virtual HRESULT StopStreaming[/b]();
{
CAutoLock cRendererLock(&m_RendererLock);
m_bEOSDelivered = FALSE;
if (m_bStreaming == TRUE) {
m_bStreaming = FALSE;
OnStopStreaming[/b]();
timeEndPeriod(1);}
}
virtual HRESULT BeginFlush[/b]();
{
if (m_State == State_Paused) { NotReady();}
SourceThreadCanWait[/b](FALSE);
CancelNotification[/b]();
ClearPendingSample[/b]();
WaitForReceiveToComplete[/b]();
}
virtual HRESULT EndFlush[/b]();
{
if (m_pPosition) m_pPosition->ResetMediaTime();
SourceThreadCanWait[/b](TRUE);
}
virtual HRESULT BreakConnect[/b]();
{
if (m_pQSink) {m_pQSink->Release();m_pQSink = NULL;}
if (m_pInputPin->IsConnected() == FALSE) {return S_FALSE;}
if (m_State != State_Stopped && !m_pInputPin->CanReconnectWhenActive()) {
return VFW_E_NOT_STOPPED;}
SetRepaintStatus[/b](FALSE);
ResetEndOfStream[/b]();
ClearPendingSample[/b]();
m_bAbort = FALSE;
if (State_Running == m_State) {StopStreaming[/b]();}
}
virtual HRESULT SetMediaType[/b](const CMediaType *pmt);{ return NOERROR;}
virtual HRESULT CompleteConnect[/b](IPin *pReceivePin);
{
ASSERT(CritCheckIn(&m_InterfaceLock));
m_bAbort = FALSE;
if (State_Running == GetRealState()) {
HRESULT hr = StartStreaming();
SetRepaintStatus[/b](FALSE);
} else { SetRepaintStatus[/b](TRUE);}
}
virtual HRESULT Receive[/b](IMediaSample *pMediaSample);
{
HRESULT hr = PrepareReceive[/b](pSample);
if (m_State == State_Paused) {
PrepareRender[/b]();
m_bInReceive = FALSE;
{
// We must hold both these locks
CAutoLock cRendererLock(&m_InterfaceLock);
if (m_State == State_Stopped) return NOERROR;
m_bInReceive = TRUE;
CAutoLock cSampleLock(&m_RendererLock);
OnReceiveFirstSample[/b](pSample);
}
Ready[/b]();
}
hr = WaitForRenderTime[/b]();
if (FAILED(hr)) {m_bInReceive = FALSE; return NOERROR;}
PrepareRender[/b]();
m_bInReceive = FALSE;
CAutoLock cRendererLock(&m_InterfaceLock);
if (m_State == State_Stopped) return NOERROR;
CAutoLock cSampleLock(&m_RendererLock);
Render[/b](m_pMediaSample);
ClearPendingSample[/b]();
SendEndOfStream[/b]();
CancelNotification[/b]();
}
virtual HRESULT CheckMediaType[/b](const CMediaType *) PURE[/b];
d) 其他函数
BOOL IsEndOfStream[/b]() { return m_bEOS; };
BOOL IsEndOfStreamDelivered[/b]() { return m_bEOSDelivered; };
BOOL IsStreaming[/b]() { return m_bStreaming; };
void SetAbortSignal[/b](BOOL bAbort) { m_bAbort = bAbort; };
CAMEvent *GetRenderEvent[/b]() { return &m_RenderEvent; };
// Permit access to the transition state
void Ready[/b]() { m_evComplete.Set(); };
void NotReady[/b]() { m_evComplete.Reset(); };
BOOL CheckReady[/b]() { return m_evComplete.Check(); };
FILTER_STATE GetRealState[/b](){ return m_State; };
void SendRepaint[/b]();
{
CAutoLock cSampleLock(&m_RendererLock);
if (m_bAbort == FALSE) {
if (m_pInputPin->IsConnected() == TRUE) {
if (m_pInputPin->IsFlushing() == FALSE) {
if (IsEndOfStream() == FALSE) {
if (m_bRepaintStatus == TRUE) {
IPin *pPin = (IPin *) m_pInputPin;
NotifyEvent[/b](EC_REPAINT,(LONG_PTR) pPin,0);
SetRepaintStatus[/b](FALSE);
}}}}}}
void SendNotifyWindow[/b](IPin *pPin,HWND hwnd);
{
IMediaEventSink *pSink;
HRESULT hr = pPin->QueryInterface(IID_IMediaEventSink,(void **)&pSink);
if (SUCCEEDED(hr)) {
pSink->Notify(EC_NOTIFY_WINDOW,LONG_PTR(hwnd),0);
pSink->Release();}
NotifyEvent[/b](EC_NOTIFY_WINDOW,LONG_PTR(hwnd),0);
}
BOOL OnDisplayChange[/b]();
{
CAutoLock cSampleLock(&m_RendererLock);
if (m_pInputPin->IsConnected() == FALSE) {return FALSE;}
IPin *pPin = (IPin *) m_pInputPin;
m_pInputPin->AddRef();
NotifyEvent[/b](EC_DISPLAY_CHANGED,(LONG_PTR) pPin,0);
SetAbortSignal[/b](TRUE);
ClearPendingSample[/b]();
m_pInputPin->Release();
}
void SetRepaintStatus[/b](BOOL bRepaint);
{
CAutoLock cSampleLock(&m_RendererLock);
m_bRepaintStatus = bRepaint;
}
void TimerCallback[/b]();
{
CAutoLock cRendererLock(&m_RendererLock);
if (m_EndOfStreamTimer) {
m_EndOfStreamTimer = 0;
SendEndOfStream[/b]();}
}
void ResetEndOfStreamTimer[/b]();
{
ASSERT(CritCheckOut(&m_RendererLock));
if (m_EndOfStreamTimer) {
timeKillEvent(m_EndOfStreamTimer);
m_EndOfStreamTimer = 0;}
}
HRESULT NotifyEndOfStream[/b]();
{
CAutoLock cRendererLock(&m_RendererLock);
if (m_bStreaming == FALSE) {return NOERROR;}
m_EndOfStreamTimer = 0;
if (m_pPosition) m_pPosition->EOS();
m_bEOSDelivered = TRUE;
return NotifyEvent[/b](EC_COMPLETE,S_OK,(LONG_PTR)(IBaseFilter *)this);
}
void SignalTimerFired[/b]();{m_dwAdvise = 0;}
void WaitForReceiveToComplete[/b]();
{
for (;;) {
if (!m_bInReceive) {break;}
MSG msg;
// Receive all interthread sendmessages
PeekMessage[/b](&msg, NULL, WM_NULL, WM_NULL, PM_NOREMOVE);
Sleep(1);
}
if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
PostThreadMessage[/b](GetCurrentThreadId(), WM_NULL, 0, 0);
}
}
STDMETHODIMP NonDelegatingQueryInterface[/b](REFIID riid,void **ppv)
{
if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {
return GetMediaPositionInterface[/b](riid,ppv);
} else { return CBaseFilter::NonDelegatingQueryInterface(riid,ppv); }
}
e) 友元函数
friend void CALLBACK EndOfStreamTimer[/b](UINT uID, // Timer identifier
UINT uMsg, // Not currently used
DWORD_PTR dwUser, // User information
DWORD_PTR dw1, // Windows reserved
DWORD_PTR dw2); // Is also reserved
{
CBaseRenderer *pRenderer = (CBaseRenderer *) dwUser;
pRenderer->TimerCallback();
}

前一篇: (七) CTransInPlaceFilter及相关联Pin类的源代码解析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐