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());
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #6
0
__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;
}
Beispiel #19
0
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;
}
Beispiel #21
0
// 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;
}
Beispiel #23
0
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;
}
Beispiel #26
0
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.
    }
}
Beispiel #28
0
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));
}
Beispiel #30
0
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;
}