123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- #include <streams.h>
- #include <strmctl.h>
- CBaseStreamControl::CBaseStreamControl(__inout HRESULT *phr)
- : m_StreamState(STREAM_FLOWING)
- , m_StreamStateOnStop(STREAM_FLOWING)
- , m_tStartTime(MAX_TIME)
- , m_tStopTime(MAX_TIME)
- , m_StreamEvent(FALSE, phr)
- , m_dwStartCookie(0)
- , m_dwStopCookie(0)
- , m_pRefClock(NULL)
- , m_FilterState(State_Stopped)
- , m_bIsFlushing(FALSE)
- , m_bStopSendExtra(FALSE)
- {}
- CBaseStreamControl::~CBaseStreamControl()
- {
-
- SetSyncSource(NULL);
- return;
- }
- STDMETHODIMP CBaseStreamControl::StopAt(const REFERENCE_TIME * ptStop, BOOL bSendExtra, DWORD dwCookie)
- {
- CAutoLock lck(&m_CritSec);
- m_bStopSendExtra = FALSE;
- m_bStopExtraSent = FALSE;
- if (ptStop)
- {
- if (*ptStop == MAX_TIME)
- {
- DbgLog((LOG_TRACE,2,TEXT("StopAt: Cancel stop")));
- CancelStop();
-
-
- if (m_FilterState == State_Stopped && m_tStartTime < MAX_TIME) {
- m_StreamState = STREAM_DISCARDING;
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING")));
- }
- return NOERROR;
- }
- DbgLog((LOG_TRACE,2,TEXT("StopAt: %dms extra=%d"),
- (int)(*ptStop/10000), bSendExtra));
-
-
- if (m_FilterState == State_Stopped && m_tStartTime > *ptStop) {
- m_StreamState = STREAM_FLOWING;
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING")));
- }
- m_bStopSendExtra = bSendExtra;
- m_tStopTime = *ptStop;
- m_dwStopCookie = dwCookie;
- m_StreamStateOnStop = STREAM_DISCARDING;
- }
- else
- {
- DbgLog((LOG_TRACE,2,TEXT("StopAt: now")));
-
- m_bStopSendExtra = FALSE;
- m_tStopTime = MAX_TIME;
- m_dwStopCookie = 0;
- m_StreamState = STREAM_DISCARDING;
- m_StreamStateOnStop = STREAM_FLOWING;
- }
-
- m_StreamEvent.Set();
- return NOERROR;
- }
- STDMETHODIMP CBaseStreamControl::StartAt
- ( const REFERENCE_TIME *ptStart, DWORD dwCookie )
- {
- CAutoLock lck(&m_CritSec);
- if (ptStart)
- {
- if (*ptStart == MAX_TIME)
- {
- DbgLog((LOG_TRACE,2,TEXT("StartAt: Cancel start")));
- CancelStart();
-
-
- if (m_FilterState == State_Stopped && m_tStopTime < MAX_TIME) {
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING")));
- m_StreamState = STREAM_FLOWING;
- }
- return NOERROR;
- }
- DbgLog((LOG_TRACE,2,TEXT("StartAt: %dms"), (int)(*ptStart/10000)));
-
-
- if (m_FilterState == State_Stopped && m_tStopTime >= *ptStart) {
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING")));
- m_StreamState = STREAM_DISCARDING;
- }
- m_tStartTime = *ptStart;
- m_dwStartCookie = dwCookie;
-
- }
- else
- {
- DbgLog((LOG_TRACE,2,TEXT("StartAt: now")));
- m_tStartTime = MAX_TIME;
- m_dwStartCookie = 0;
- m_StreamState = STREAM_FLOWING;
- }
-
- m_StreamEvent.Set();
- return NOERROR;
- }
- STDMETHODIMP CBaseStreamControl::GetInfo(__out AM_STREAM_INFO *pInfo)
- {
- if (pInfo == NULL)
- return E_POINTER;
- pInfo->tStart = m_tStartTime;
- pInfo->tStop = m_tStopTime;
- pInfo->dwStartCookie = m_dwStartCookie;
- pInfo->dwStopCookie = m_dwStopCookie;
- pInfo->dwFlags = m_bStopSendExtra ? AM_STREAM_INFO_STOP_SEND_EXTRA : 0;
- pInfo->dwFlags |= m_tStartTime == MAX_TIME ? 0 : AM_STREAM_INFO_START_DEFINED;
- pInfo->dwFlags |= m_tStopTime == MAX_TIME ? 0 : AM_STREAM_INFO_STOP_DEFINED;
- switch (m_StreamState) {
- default:
- DbgBreak("Invalid stream state");
- case STREAM_FLOWING:
- break;
- case STREAM_DISCARDING:
- pInfo->dwFlags |= AM_STREAM_INFO_DISCARDING;
- break;
- }
- return S_OK;
- }
- void CBaseStreamControl::ExecuteStop()
- {
- ASSERT(CritCheckIn(&m_CritSec));
- m_StreamState = m_StreamStateOnStop;
- if (m_dwStopCookie && m_pSink) {
- DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STOPPED (%d)"),
- m_dwStopCookie));
- m_pSink->Notify(EC_STREAM_CONTROL_STOPPED, (LONG_PTR)this, m_dwStopCookie);
- }
- CancelStop();
- }
- void CBaseStreamControl::ExecuteStart()
- {
- ASSERT(CritCheckIn(&m_CritSec));
- m_StreamState = STREAM_FLOWING;
- if (m_dwStartCookie) {
- DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STARTED (%d)"),
- m_dwStartCookie));
- m_pSink->Notify(EC_STREAM_CONTROL_STARTED, (LONG_PTR)this, m_dwStartCookie);
- }
- CancelStart();
- }
- void CBaseStreamControl::CancelStop()
- {
- ASSERT(CritCheckIn(&m_CritSec));
- m_tStopTime = MAX_TIME;
- m_dwStopCookie = 0;
- m_StreamStateOnStop = STREAM_FLOWING;
- }
- void CBaseStreamControl::CancelStart()
- {
- ASSERT(CritCheckIn(&m_CritSec));
- m_tStartTime = MAX_TIME;
- m_dwStartCookie = 0;
- }
- enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckSampleTimes
- ( __in const REFERENCE_TIME * pSampleStart, __in const REFERENCE_TIME * pSampleStop )
- {
- CAutoLock lck(&m_CritSec);
- ASSERT(!m_bIsFlushing);
- ASSERT(pSampleStart && pSampleStop);
-
-
- if (m_tStopTime >= *pSampleStart)
- {
- if (m_tStartTime >= *pSampleStop)
- return m_StreamState;
- if (m_tStopTime < m_tStartTime)
- ExecuteStop();
- ExecuteStart();
- return m_StreamState;
- }
- if (m_tStartTime >= *pSampleStop)
- {
- ExecuteStop();
- return m_StreamState;
- }
- if (m_tStartTime <= m_tStopTime)
- {
- ExecuteStart();
- ExecuteStop();
- return m_StreamState;
- }
- else
- {
- ExecuteStop();
- ExecuteStart();
- return m_StreamState;
- }
- }
- enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckStreamState( IMediaSample * pSample )
- {
- REFERENCE_TIME rtBufferStart, rtBufferStop;
- const BOOL bNoBufferTimes =
- pSample == NULL ||
- FAILED(pSample->GetTime(&rtBufferStart, &rtBufferStop));
- StreamControlState state;
- LONG lWait;
- do
- {
-
- if (m_bIsFlushing || m_FilterState == State_Stopped)
- return STREAM_DISCARDING;
- if (bNoBufferTimes) {
-
- state = m_StreamState;
- break;
- } else {
- state = CheckSampleTimes( &rtBufferStart, &rtBufferStop );
- if (state == STREAM_FLOWING)
- break;
-
-
-
- if (m_bStopSendExtra && !m_bStopExtraSent &&
- m_tStopTime == MAX_TIME &&
- m_FilterState != State_Stopped) {
- m_bStopExtraSent = TRUE;
- DbgLog((LOG_TRACE,2,TEXT("%d sending an EXTRA frame"),
- m_dwStopCookie));
- state = STREAM_FLOWING;
- break;
- }
- }
-
-
- if (!m_pRefClock) {
- break;
-
-
-
-
- } else if (m_FilterState == State_Paused) {
- lWait = INFINITE;
- } else {
-
-
- REFERENCE_TIME rtNow;
- EXECUTE_ASSERT(SUCCEEDED(m_pRefClock->GetTime(&rtNow)));
- rtNow -= m_tRunStart;
- lWait = LONG((rtBufferStart - rtNow)/10000);
- if (lWait < 10) break;
- }
- } while(WaitForSingleObject(GetStreamEventHandle(), lWait) != WAIT_TIMEOUT);
- return state;
- }
- void CBaseStreamControl::NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart )
- {
- CAutoLock lck(&m_CritSec);
-
- if (m_FilterState == new_state)
- return;
- switch (new_state)
- {
- case State_Stopped:
- DbgLog((LOG_TRACE,2,TEXT("Filter is STOPPED")));
-
-
-
- if (m_tStartTime != MAX_TIME && m_tStopTime == MAX_TIME) {
- ExecuteStart();
- } else if (m_tStopTime != MAX_TIME && m_tStartTime == MAX_TIME) {
- ExecuteStop();
- } else if (m_tStopTime != MAX_TIME && m_tStartTime != MAX_TIME) {
- if (m_tStartTime <= m_tStopTime) {
- ExecuteStart();
- ExecuteStop();
- } else {
- ExecuteStop();
- ExecuteStart();
- }
- }
-
-
- m_StreamState = STREAM_FLOWING;
- m_FilterState = new_state;
- break;
- case State_Running:
- DbgLog((LOG_TRACE,2,TEXT("Filter is RUNNING")));
- m_tRunStart = tStart;
-
- default:
- m_FilterState = new_state;
- }
-
- m_StreamEvent.Set();
- }
- void CBaseStreamControl::Flushing(BOOL bInProgress)
- {
- CAutoLock lck(&m_CritSec);
- m_bIsFlushing = bInProgress;
- m_StreamEvent.Set();
- }
|