HRESULT HDMediaSource::SetRate(BOOL fThin,float flRate) { DbgLogPrintf(L"%s::SetRate... (Thin:%d, Rate:%.2f)",L"HDMediaSource",fThin,flRate); CritSec::AutoLock lock(_cs); HRESULT hr = CheckShutdown(); if (FAILED(hr)) return hr; if (fThin) return MF_E_THINNING_UNSUPPORTED; if (flRate < MIN_MFSOURCE_RATE_SUPPORT || flRate > MAX_MFSOURCE_RATE_SUPPORT) return MF_E_UNSUPPORTED_RATE; if (flRate == _currentRate) return _pEventQueue->QueueEventParamVar(MESourceRateChanged,GUID_NULL,S_OK,nullptr); ComPtr<SourceOperation> op; hr = SourceOperation::CreateSetRateOperation(fThin,flRate,op.GetAddressOf()); if (FAILED(hr)) return hr; DbgLogPrintf(L"%s::SetRate OK.",L"HDMediaSource"); return QueueOperation(op.Get()); }
HRESULT FlvStream::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) { HRESULT hr = S_OK; IMFMediaEventQueuePtr pQueue; { // scope for lock SourceLock lock(source); // Check shutdown hr = CheckShutdown(); // Cache a local pointer to the queue. if (SUCCEEDED(hr)) { pQueue = event_queue; } } // release lock // Use the local pointer to call GetEvent. if (SUCCEEDED(hr)) { hr = pQueue->GetEvent(dwFlags, ppEvent); } return hr; }
HRESULT PpboxStream::GetMediaSource(IMFMediaSource** ppMediaSource) { SourceLock lock(m_pSource); if (ppMediaSource == NULL) { return E_POINTER; } if (m_pSource == NULL) { return E_UNEXPECTED; } HRESULT hr = S_OK; hr = CheckShutdown(); // QI the source for IMFMediaSource. // (Does not hold the source's critical section.) if (SUCCEEDED(hr)) { hr = m_pSource->QueryInterface(IID_PPV_ARGS(ppMediaSource)); } return hr; }
HRESULT PpboxStream::Start(const PROPVARIANT& varStart) { SourceLock lock(m_pSource); HRESULT hr = S_OK; hr = CheckShutdown(); // Queue the stream-started event. if (SUCCEEDED(hr)) { hr = QueueEvent(MEStreamStarted, GUID_NULL, S_OK, &varStart); } if (SUCCEEDED(hr)) { m_state = STATE_STARTED; } // If we are restarting from paused, there may be // queue sample requests. Dispatch them now. if (SUCCEEDED(hr)) { hr = DispatchSamples(); } return hr; }
HRESULT CMPEG1Stream::GetMediaSource(IMFMediaSource **ppMediaSource) { SourceLock lock(m_spSource.Get()); if (ppMediaSource == nullptr) { return E_POINTER; } if (m_spSource == nullptr) { return E_UNEXPECTED; } HRESULT hr = S_OK; hr = CheckShutdown(); // QI the source for IMFMediaSource. // (Does not hold the source's critical section.) if (SUCCEEDED(hr)) { hr = m_spSource.CopyTo(IID_PPV_ARGS(ppMediaSource)); } return hr; }
__override HRESULT CGeometricMediaSource::DispatchOperation(CSourceOperation *pOp) { AutoLock lock(_critSec); HRESULT hr = CheckShutdown(); if (SUCCEEDED(hr)) { switch(pOp->GetOperationType()) { case CSourceOperation::Operation_Start: hr = DoStart(static_cast<CStartOperation *>(pOp)); break; case CSourceOperation::Operation_Stop: hr = DoStop(pOp); break; case CSourceOperation::Operation_SetRate: hr = DoSetRate(static_cast<CSetRateOperation *>(pOp)); break; default: hr = E_UNEXPECTED; break; } } return hr; }
HRESULT WavStream::GetStreamDescriptor(IMFStreamDescriptor** ppStreamDescriptor) { if (ppStreamDescriptor == NULL) { return E_POINTER; } if (m_pStreamDescriptor == NULL) { return E_UNEXPECTED; } EnterCriticalSection(&m_critSec); HRESULT hr = S_OK; hr = CheckShutdown(); if (SUCCEEDED(hr)) { *ppStreamDescriptor = m_pStreamDescriptor; (*ppStreamDescriptor)->AddRef(); } LeaveCriticalSection(&m_critSec); return hr; }
HRESULT WavSource::CreatePresentationDescriptor(IMFPresentationDescriptor** ppPresentationDescriptor) { if (ppPresentationDescriptor == NULL) { return E_POINTER; } EnterCriticalSection(&m_critSec); HRESULT hr = S_OK; hr = CheckShutdown(); if (SUCCEEDED(hr)) { if (m_pPresentationDescriptor == NULL) { hr = CreatePresentationDescriptor(); } } // Clone our default presentation descriptor. if (SUCCEEDED(hr)) { hr = m_pPresentationDescriptor->Clone(ppPresentationDescriptor); } LeaveCriticalSection(&m_critSec); return hr; }
HRESULT MPEG1Stream::GetMediaSource(IMFMediaSource** ppMediaSource) { SourceLock lock(m_pSource); if (ppMediaSource == NULL) { return E_POINTER; } if (m_pSource == NULL) { return E_UNEXPECTED; } HRESULT hr = S_OK; CHECK_HR(hr = CheckShutdown()); // QI the source for IMFMediaSource. // (Does not hold the source's critical section.) CHECK_HR(hr = m_pSource->QueryInterface(IID_PPV_ARGS(ppMediaSource))); done: return hr; }
HRESULT WavStream::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) { HRESULT hr = S_OK; IMFMediaEventQueue *pQueue = NULL; EnterCriticalSection(&m_critSec); hr = CheckShutdown(); if (SUCCEEDED(hr)) { pQueue = m_pEventQueue; pQueue->AddRef(); } LeaveCriticalSection(&m_critSec); if (SUCCEEDED(hr)) { hr = pQueue->GetEvent(dwFlags, ppEvent); } SafeRelease(&pQueue); return hr; }
// Called when the rate changes on the presentation clock. HRESULT STDMETHODCALLTYPE EVRCustomPresenter::OnClockSetRate(MFTIME hnsSystemTime, float fRate) { Log("EVRCustomPresenter::OnClockSetRate (rate=%f)", fRate); HRESULT hr = S_OK; CAutoLock lock(this); // We cannot set the rate after shutdown. hr = CheckShutdown(); CHECK_HR(hr, "EVRCustomPresenter::OnClockRestart cannot set rate after shutdown"); // If the rate is changing from zero (scrubbing) to non-zero, cancel the frame-step operation. if ((m_fRate == 0.0f) && (fRate != 0.0f)) { CancelFrameStep(); m_FrameStep.samples.Clear(); } m_fRate = fRate; // Tell the scheduler about the new rate. m_scheduler.SetClockRate(fRate); return hr; }
HRESULT MPEG1Stream::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) { HRESULT hr = S_OK; IMFMediaEventQueue *pQueue = NULL; { // scope for lock SourceLock lock(m_pSource); // Check shutdown CHECK_HR(hr = CheckShutdown()); // Cache a local pointer to the queue. pQueue = m_pEventQueue; pQueue->AddRef(); } // release lock // Use the local pointer to call GetEvent. CHECK_HR(hr = pQueue->GetEvent(dwFlags, ppEvent)); done: SAFE_RELEASE(pQueue); return hr; }
// Called when the presentation clock restarts from the same position while paused. HRESULT STDMETHODCALLTYPE EVRCustomPresenter::OnClockRestart(MFTIME hnsSystemTime) { Log("EVRCustomPresenter::OnClockRestart"); HRESULT hr = S_OK; CAutoLock lock(this); // We cannot restart the clock after shutdown. hr = CheckShutdown(); CHECK_HR(hr, "EVRCustomPresenter::OnClockRestart cannot restart after shutdown"); // The EVR calls OnClockRestart only while paused. assert(m_RenderState == RENDER_STATE_PAUSED); m_RenderState = RENDER_STATE_STARTED; // Possibly we are in the middle of frame-stepping OR we have samples waiting in the frame-step queue. hr = StartFrameStep(); CHECK_HR(hr, "EVRCustomPresenter::OnClockRestart EVRCustomPresenter::StartFrameStep() failed") // Now resume the presentation loop. ProcessOutputLoop(); return hr; }
// Called when the presentation clock stops. HRESULT STDMETHODCALLTYPE EVRCustomPresenter::OnClockStop(MFTIME hnssSystemTime) { Log("EVRCustomPresenter::OnClockStop"); HRESULT hr = S_OK; CAutoLock lock(this); // We cannot stop after shutdown hr = CheckShutdown(); CHECK_HR(hr, "EVRCustomPresenter::OnClockStop cannot stop after shutdown"); // set render state to stop and flush queue if (m_RenderState != RENDER_STATE_STOPPED) { m_RenderState = RENDER_STATE_STOPPED; Flush(); // If we are in the middle of frame-stepping, cancel it now. if (m_FrameStep.state != FRAMESTEP_NONE) { CancelFrameStep(); } } return hr; }
// Retrieves the presenter's media type. HRESULT STDMETHODCALLTYPE EVRCustomPresenter::GetCurrentMediaType(IMFVideoMediaType **ppMediaType) { Log("EVRCustomPresenter::GetCurrentMediaType"); HRESULT hr = S_OK; if (ppMediaType == NULL) { return E_POINTER; } *ppMediaType = NULL; CAutoLock lock(this); hr = CheckShutdown(); CHECK_HR(hr, "EVRCustomPresenter::GetCurrentMediaType presenter is shutdown"); CheckPointer(m_pMediaType, MF_E_NOT_INITIALIZED); // Get IMFVideoMediaType pointer and store as an IMFMediaType pointer by callin QueryInterface hr = m_pMediaType->QueryInterface(__uuidof(IMFVideoMediaType), (void**)&ppMediaType); CHECK_HR(hr, "EVRCustomPresenter::GetCurrentMediaType IMFMediaType::QueryInterface() failed"); return hr; }
STDMETHODIMP CMediaEventGenerator::QueueEvent( _In_ MediaEventType met, _In_ REFGUID extendedType, _In_ HRESULT hrStatus, _In_opt_ const PROPVARIANT* pvValue ) { HRESULT hr = S_OK; //MFWMITRACE(DH_THIS_FILE, TP_NORMAL, __FUNCTION__ " : MultiPinMFT QueueEvent called"); m_critSec.Lock(); hr = CheckShutdown(); if (SUCCEEDED(hr)) { hr = m_pQueue->QueueEventParamVar( met, extendedType, hrStatus, pvValue ); } m_critSec.Unlock(); return hr; }
HRESULT MPEG1Stream::Start(const PROPVARIANT& varStart) { SourceLock lock(m_pSource); HRESULT hr = S_OK; CHECK_HR(hr = CheckShutdown()); // Queue the stream-started event. CHECK_HR(hr = QueueEvent( MEStreamStarted, GUID_NULL, S_OK, &varStart )); m_state = STATE_STARTED; // If we are restarting from paused, there may be // queue sample requests. Dispatch them now. CHECK_HR(hr = DispatchSamples()); done: return hr; }
STDMETHODIMP CMediaEventGenerator::ShutdownEventGenerator( void ) { HRESULT hr = S_OK; // MFWMITRACE( DH_THIS_FILE, TP_LOWEST, __FUNCTION__ " : entering ..."); m_critSec.Lock(); hr = CheckShutdown(); if (SUCCEEDED(hr)) { if (m_pQueue) { hr = m_pQueue->Shutdown(); //MFWMITRACE( DH_THIS_FILE, TP_NORMAL, __FUNCTION__ "Event Generator Queue shutdown hr = %x", hr); } SAFE_RELEASE(m_pQueue); m_bShutdown = TRUE; } m_critSec.Unlock(); // MFWMITRACE( DH_THIS_FILE, TP_LOWEST, __FUNCTION__ " : exiting..."); return hr; }
IFACEMETHODIMP CGeometricMediaSource::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEvent) { // NOTE: // GetEvent can block indefinitely, so we don't hold the lock. // This requires some juggling with the event queue pointer. HRESULT hr = S_OK; ComPtr<IMFMediaEventQueue> spQueue; { AutoLock lock(_critSec); // Check shutdown hr = CheckShutdown(); // Get the pointer to the event queue. if (SUCCEEDED(hr)) { spQueue = _spEventQueue; } } // Now get the event. if (SUCCEEDED(hr)) { hr = spQueue->GetEvent(dwFlags, ppEvent); } return hr; }
HRESULT WavStream::GetMediaSource(IMFMediaSource** ppMediaSource) { if (ppMediaSource == NULL) { return E_POINTER; } EnterCriticalSection(&m_critSec); HRESULT hr = S_OK; // If called after shutdown, them m_pSource is NULL. // Otherwise, m_pSource should not be NULL. hr = CheckShutdown(); if (SUCCEEDED(hr)) { if (m_pSource == NULL) { hr = E_UNEXPECTED; } } if (SUCCEEDED(hr)) { hr = m_pSource->QueryInterface(IID_PPV_ARGS(ppMediaSource)); } LeaveCriticalSection(&m_critSec); return hr; }
// IMFMediaSource methods IFACEMETHODIMP CGeometricMediaSource::CreatePresentationDescriptor( IMFPresentationDescriptor **ppPresentationDescriptor ) { if (ppPresentationDescriptor == nullptr) { return E_POINTER; } AutoLock lock(_critSec); HRESULT hr = CheckShutdown(); if (SUCCEEDED(hr) && (_eSourceState == SourceState_Opening || _eSourceState == SourceState_Invalid || !_spPresentationDescriptor)) { hr = MF_E_NOT_INITIALIZED; } if (SUCCEEDED(hr)) { hr = _spPresentationDescriptor->Clone(ppPresentationDescriptor); } return hr; }
HRESULT WavSource::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) { // NOTE: GetEvent can block indefinitely, so we don't hold the // WavSource lock. This requires some juggling with the // event queue pointer. HRESULT hr = S_OK; IMFMediaEventQueue *pQueue = NULL; EnterCriticalSection(&m_critSec); // Check shutdown hr = CheckShutdown(); if (SUCCEEDED(hr)) { pQueue = m_pEventQueue; pQueue->AddRef(); } LeaveCriticalSection(&m_critSec); if (SUCCEEDED(hr)) { hr = pQueue->GetEvent(dwFlags, ppEvent); } SafeRelease(&pQueue); return hr; }
IFACEMETHODIMP CGeometricMediaSource::Shutdown() { AutoLock lock(_critSec); HRESULT hr = CheckShutdown(); if (SUCCEEDED(hr)) { if (_spEventQueue) { _spEventQueue->Shutdown(); } if (_spStream) { _spStream->Shutdown(); } _eSourceState = SourceState_Shutdown; _spEventQueue.ReleaseAndGetAddressOf(); _spStream.ReleaseAndGetAddressOf(); _spDeviceManager.ReleaseAndGetAddressOf(); } return hr; }
HRESULT CMPEG1Stream::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEvent) { HRESULT hr = S_OK; ComPtr<IMFMediaEventQueue> spQueue; { // scope for lock SourceLock lock(m_spSource.Get()); // Check shutdown hr = CheckShutdown(); // Cache a local pointer to the queue. if (SUCCEEDED(hr)) { spQueue = m_spEventQueue.Get(); } } // release lock // Use the local pointer to call GetEvent. if (SUCCEEDED(hr)) { hr = spQueue->GetEvent(dwFlags, ppEvent); } return hr; }
STDMETHODIMP CMediaEventGenerator::GetEvent( _In_ DWORD dwFlags, _Outptr_result_maybenull_ IMFMediaEvent** ppEvent ) { // // Because GetEvent can block indefinitely, it requires // a slightly different locking strategy. // HRESULT hr = S_OK; //MFWMITRACE(DH_THIS_FILE, TP_NORMAL, __FUNCTION__ " : MultiPinMFT GetEvent called"); IMFMediaEventQueue *pQueue = NULL; m_critSec.Lock(); hr = CheckShutdown(); // // Store the pointer in a local variable, so that another thread // does not release it after we leave the critical section. // if (SUCCEEDED(hr)) { pQueue = m_pQueue; } m_critSec.Unlock(); if (SUCCEEDED(hr)) { hr = pQueue->GetEvent(dwFlags, ppEvent); } return hr; }
HRESULT PpboxStream::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) { HRESULT hr = S_OK; IMFMediaEventQueue *pQueue = NULL; { // scope for lock SourceLock lock(m_pSource); // Check shutdown hr = CheckShutdown(); // Cache a local pointer to the queue. if (SUCCEEDED(hr)) { pQueue = m_pEventQueue; pQueue->AddRef(); } } // release lock // Use the local pointer to call GetEvent. if (SUCCEEDED(hr)) { hr = pQueue->GetEvent(dwFlags, ppEvent); } SafeRelease(&pQueue); return hr; }
void CMPEG1Stream::Shutdown() { if (SUCCEEDED(CheckShutdown())) { m_state = STATE_SHUTDOWN; // Shut down the event queue. if (m_spEventQueue) { m_spEventQueue->Shutdown(); } // Release objects. m_Samples.Clear(); m_Requests.Clear(); m_spStreamDescriptor.Reset(); m_spEventQueue.Reset(); // NOTE: // Do NOT release the source pointer here, because the stream uses // it to hold the critical section. In particular, the stream must // hold the critical section when checking the shutdown status, // which obviously can occur after the stream is shut down. // It is OK to hold a ref count on the source after shutdown, // because the source releases its ref count(s) on the streams, // which breaks the circular ref count. } }
HRESULT FlvStream::Shutdown() { SourceLock lock(source); auto hr = CheckShutdown(); if(fail(hr)) return hr; m_state = SourceState::STATE_SHUTDOWN; // Shut down the event queue. if (event_queue) { event_queue->Shutdown(); } // Release objects. samples.clear(); requests.clear(); event_queue = nullptr; stream_descriptor = nullptr; // NOTE: // Do NOT release the source pointer here, because the stream uses // it to hold the critical section. In particular, the stream must // hold the critical section when checking the shutdown status, // which obviously can occur after the stream is shut down. source = nullptr; return hr; }
void CMPEG1Stream::Pause() { ThrowIfError(CheckShutdown()); m_state = STATE_PAUSED; ThrowIfError(QueueEvent(MEStreamPaused, GUID_NULL, S_OK, nullptr)); }
HRESULT PpboxStream::RequestSample(IUnknown* pToken) { HRESULT hr = S_OK; IMFMediaSource *pSource = NULL; // Hold the media source object's critical section. SourceLock lock(m_pSource); hr = CheckShutdown(); if (FAILED(hr)) { goto done; } if (m_state == STATE_STOPPED) { hr = MF_E_INVALIDREQUEST; goto done; } if (!m_bActive) { // If the stream is not active, it should not get sample requests. hr = MF_E_INVALIDREQUEST; goto done; } if (m_bEOS && m_Samples.IsEmpty()) { // This stream has already reached the end of the stream, and the // sample queue is empty. hr = MF_E_END_OF_STREAM; goto done; } hr = m_Requests.InsertBack(pToken); if (FAILED(hr)) { goto done; } // Dispatch the request. hr = DispatchSamples(); if (FAILED(hr)) { goto done; } done: if (FAILED(hr) && (m_state != STATE_SHUTDOWN)) { // An error occurred. Send an MEError even from the source, // unless the source is already shut down. hr = m_pSource->QueueEvent(MEError, GUID_NULL, hr, NULL); } return hr; }