STDMETHODIMP MyPin::Receive(IMediaSample* pSample) { CAutoLock receiveLock(&m_receiveMutex); { CAutoLock objectLock(this); if (m_state == State_Stopped) return VFW_E_WRONG_STATE; ReturnIfNotEquals(S_OK, CBaseInputPin::Receive(pSample)); if (m_SampleProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) { // TODO: don't recreate the device when possible m_renderer.Finish(false, &m_bufferFilled); ReturnIfFailed(SetMediaType(static_cast<CMediaType*>(m_SampleProps.pMediaType))); } if (m_eosUp) return S_FALSE; } // Raise Receive() thread priority, once. if (m_hReceiveThread != GetCurrentThread()) { m_hReceiveThread = GetCurrentThread(); if (GetThreadPriority(m_hReceiveThread) < THREAD_PRIORITY_ABOVE_NORMAL) SetThreadPriority(m_hReceiveThread, THREAD_PRIORITY_ABOVE_NORMAL); } // Push() returns 'false' in case of interruption. return m_renderer.Push(pSample, m_SampleProps, &m_bufferFilled) ? S_OK : S_FALSE; }
HRESULT MyPin::Inactive() { { CAutoLock objectLock(this); assert(m_state != State_Stopped); m_state = State_Stopped; CBaseInputPin::Inactive(); } m_renderer.BeginFlush(); // Barrier for any present Receive() and EndOfStream() calls. // Subsequent ones will be rejected because m_state == State_Stopped. CAutoLock receiveLock(&m_receiveMutex); m_bufferFilled.Reset(); { CAutoLock objectLock(this); m_eosUp = false; m_eosDown = false; } m_hReceiveThread = NULL; m_renderer.Stop(); m_renderer.EndFlush(); return S_OK; }
STDMETHODIMP MyPin::BeginFlush() { // Parent method locks the object before modifying it, all is good. CBaseInputPin::BeginFlush(); m_renderer.BeginFlush(); // Barrier for any present Receive() and EndOfStream() calls. // Subsequent ones will be rejected because m_bFlushing == TRUE. CAutoLock receiveLock(&m_receiveMutex); m_bufferFilled.Reset(); { CAutoLock objectLock(this); m_eosUp = false; m_eosDown = false; } m_hReceiveThread = NULL; m_renderer.EndFlush(); return S_OK; }
STDMETHODIMP MyPin::EndOfStream() { CAutoLock receiveLock(&m_receiveMutex); { CAutoLock objectLock(this); if (m_state == State_Stopped) return VFW_E_WRONG_STATE; if (m_bFlushing) return S_FALSE; m_eosUp = true; } // We ask audio renderer to block until all samples are played. // Finish() returns 'false' in case of interruption. bool eosDown = m_renderer.Finish(true, &m_bufferFilled); { CAutoLock objectLock(this); m_eosDown = eosDown; if (m_eosDown) m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)m_pFilter); } return S_OK; }
STDMETHODIMP MyPin::NewSegment(REFERENCE_TIME startTime, REFERENCE_TIME stopTime, double rate) { CAutoLock receiveLock(&m_receiveMutex); CAutoLock objectLock(this); CBaseInputPin::NewSegment(startTime, stopTime, rate); m_renderer.NewSegment(rate); return S_OK; }
STDMETHODIMP CMpTsFilter::Stop() { LogDebug("CMpTsFilter::Stop()"); CAutoLock filterLock(m_pLock); LogDebug("Stop streaming..."); CAutoLock receiveLock(m_pReceiveLock); LogDebug("Stop filter..."); int hr = CBaseFilter::Stop(); LogDebug("HRESULT = 0x%x", hr); return hr; }