⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 renbaseasync.cpp

📁 basic class basic classbasic class
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    
    CAutoLock cSampleLock(&m_RendererLock);
    
    ASSERT(IsActive() == TRUE);
    ASSERT(m_pInputPin->IsFlushing() == FALSE);
    ASSERT(m_pInputPin->IsConnected() == TRUE);
    ASSERT(m_pMediaSample == NULL);
    
    // check that no data is being sent after the source signalled an end of stream    
    if (m_bEOS || m_bAbort) {
        Ready();
        return E_UNEXPECTED;
    }
    
    // Store the media times from this sample
    if (m_pPosition) m_pPosition->RegisterMediaTime(pMediaSample);
    
    //
    // Queue the received sample. Note that we AddRef pMediaSample since we're 
    // returning without using it immediately.
    //
    CRendererSample *pRendererSample = new CRendererSample(pMediaSample);
    if (!pRendererSample)
    {
        return E_OUTOFMEMORY;
    }
    m_RendererQueue.Insert (pRendererSample);

    //
    // If we're streaming, set an event for proper scheduling by the worker thread.
    //
    if (m_bStreaming)
    {
        m_ScheduleEvent.Set();
    }

    // Store the sample end time for EC_COMPLETE handling
    m_SignalTime = m_pInputPin->SampleProps()->tStop;
    
    if (m_bStreaming == FALSE) {
        SetRepaintStatus(TRUE);
    }
    return NOERROR;
}


//
// Called by the source filter when we have a sample to render. We just prepare for
// receiving the sample, and return immediately. The sample is going to be processed
// by the renderer thread (scheduled and rendered).
//
HRESULT CBaseRendererAsync::Receive(IMediaSample *pSample)
{
    ASSERT(pSample);

    // It may return VFW_E_SAMPLE_REJECTED code to say don't bother
    
    HRESULT hr = PrepareReceive(pSample);
    if (FAILED(hr)) {
        if (hr == VFW_E_SAMPLE_REJECTED) {
            return NOERROR;
        }
        return hr;
    }

    Ready();   // signal we have a sample now

    return NOERROR;
}


BOOL CBaseRendererAsync::HaveCurrentSample()
{
    CAutoLock cRendererLock(&m_RendererLock);
    CRendererSample *pRendererSample;

    return ((m_RendererQueue.Peek (&pRendererSample) == S_OK) ? TRUE : FALSE);
}


BOOL CBaseRendererAsync::ScheduleSample(IMediaSample *pMediaSample)
{
    // We override ShouldDrawSampleNow to add quality management
    
    return CBaseRenderer::ScheduleSample(pMediaSample);
}

//
// Verifies if there's any sample in our renderer sample queue, and if
// there's a sample which is not scheduled, schedule it.
//
HRESULT CBaseRendererAsync::ScheduleQueuedSample (void)
{
    CAutoLock cSampleLock(&m_RendererLock);        // make sure we don't try to schedule the same sample twice
    CRendererSample *pRendererSample;

    HRESULT hr = m_RendererQueue.Peek (&pRendererSample);
    if (hr == S_OK  &&  !pRendererSample->IsScheduled())
    {
        DWORD dwAdvise = m_dwAdvise;
        if (ScheduleSample (pRendererSample->MediaSample()))
        {
            pRendererSample->SetScheduled(TRUE);
            m_pScheduledSample = pRendererSample;
        }
        else
        {
            // could not schedule this sample, remove it from the queue and move on...
            hr = m_RendererQueue.Remove (&pRendererSample);
            if (hr != S_OK  ||  !pRendererSample)
            {
                return hr;
            }
            delete pRendererSample;          // we don't need the queued sample anymore
        }
    }
    return hr;
}


//
// Waits for the correct presentation time and then renders
// the sample.
//
HRESULT CBaseRendererAsync::ProcessQueuedSample (void)
{
    CRendererSample *pRendererSample;
    IMediaSample *pMediaSample;

    CAutoLock cSampleLock(&m_RendererLock);
    
    HRESULT hr = m_RendererQueue.Remove (&pRendererSample);
    if (hr != S_OK  ||  !pRendererSample)
    {
        return hr;
    }

    pMediaSample = pRendererSample->MediaSample();
    ASSERT (pMediaSample);
    if (!pMediaSample)
        return E_FAIL;

    //
    // BEWARE we sometimes keep the sample even after rendering it, 
    // such as when we go into a stopped state (we keep it
    // to refresh the device with) so we must AddRef it to keep it safely. If
    // we start flushing the source thread is released and any sample waiting
    // will be released otherwise GetBuffer may never return (see BeginFlush)
    //
    m_pMediaSample = pMediaSample;
    m_pMediaSample->AddRef();

    delete pRendererSample;          // we don't need the queued sample anymore

    PrepareRender();
        
    // since we gave away the filter wide lock, the state of the filter could
    // have changed to Stopped
    if (m_State == State_Stopped)
        return NOERROR;
    
    // Deal with this sample

    if (m_bFirstSample)
    {
        OnReceiveFirstSample(m_pMediaSample);
    }
    else
    {
        Render(m_pMediaSample);
    }

    m_bFirstSample = FALSE;

    ClearPendingSample();
    SendEndOfStream();
    CancelNotification();

    return NOERROR;
}


//
// This is called when we start running so that we can schedule any pending
// image we have with the clock and display any timing information. If we
// don't have any sample but we have queued an EOS flag then we send it. If
// we do have a sample then we wait until that has been rendered before we
// signal the filter graph otherwise we may change state before it's done
//
HRESULT CBaseRendererAsync::StartStreaming()
{
    CAutoLock cRendererLock(&m_RendererLock);
    CRendererSample *pRendererSample;

    if (m_bStreaming == TRUE) {
        return NOERROR;
    }
    
    // Reset the streaming times ready for running
    
    m_bStreaming = TRUE;
    timeBeginPeriod(1);
    OnStartStreaming();
    
    // There should be no outstanding advise
    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
    ASSERT(CancelNotification() == S_FALSE);
    
    //
    // If we have an EOS and no data then deliver it now
    //
    if (m_RendererQueue.Peek(&pRendererSample) != S_OK)
    {
        return SendEndOfStream();
    }

    //
    // Set an event for the worker thread to start scheduling
    //
    m_ScheduleEvent.Set();
    
    return NOERROR;
}


//
// This is called when we stop streaming so that we can set our internal flag
// indicating we are not to schedule any more samples arriving. The state
// change methods in the filter implementation take care of cancelling any
// clock advise link we have set up and clearing any pending samples we have
//
HRESULT CBaseRendererAsync::StopStreaming()
{
    CAutoLock cRendererLock(&m_RendererLock);
    m_bEOSDelivered = FALSE;

    if (m_bStreaming == TRUE) {
        m_bStreaming = FALSE;
        OnStopStreaming();
        timeEndPeriod(1);
    }
    return NOERROR;
}


//
// When a video window detects a display change (WM_DISPLAYCHANGE message) it
// can send an EC_DISPLAY_CHANGED event code along with the renderer pin. The
// filtergraph will stop everyone and reconnect our input pin. As we're then
// reconnected we can accept the media type that matches the new display mode
// since we may no longer be able to draw the current image type efficiently
//
BOOL CBaseRendererAsync::OnDisplayChange()
{
    BOOL bOk = CBaseRenderer::OnDisplayChange();
    m_RendererQueue.Flush();
    
    return bOk;
}


//
// Worker thread related functionality
//


HRESULT CBaseRendererAsync::RunThread()
{
    DbgLog((LOG_TRACE, 2, TEXT("CBaseRenderer::RunThread")));
    return CallWorker(CMD_RUN);
}

HRESULT CBaseRendererAsync::StopThread()
{
    DbgLog((LOG_TRACE, 2, TEXT("CBaseRenderer::StopThread")));
    return CallWorker(CMD_STOP);
}


HRESULT CBaseRendererAsync::KillThread()
{
    // !!! CAutoLock lock(&m_AccessLock);

    DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync:KillThread")));

    HRESULT hr = CallWorker(CMD_EXIT);
    if (FAILED(hr))
    {
	    return hr;
    }

    // wait for thread completion and then close
    // handle (and clear so we can start another later)
    Close();

    return NOERROR;
}


//
// This thread is running the whole time the graph is active. It needs to monitor the
// passing of stream time and wake up when it wants to render an object.
//
DWORD CBaseRendererAsync::ThreadProc()
{
    BOOL bExit = FALSE;
    DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync::ThreadProc - Starting thread = 0x%x"), m_hThread));

    while (!bExit)
    {
        Command req = GetRequest();
        switch (req)
        {
            case CMD_EXIT:
                DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync::ThreadProc - CMD_EXIT received")));
                m_RendererQueue.Flush();
                bExit = TRUE;
                Reply(NOERROR);
                break;

            case CMD_STOP:
                DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync::ThreadProc - CMD_STOP received")));
                m_RendererQueue.Flush();
                Reply(NOERROR);
                break;

            case CMD_RUN:
                HANDLE events[4];
                BOOL bRunning = TRUE;

                DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync::ThreadProc - CMD_RUN received")));
                Reply(NOERROR);

                DWORD dwCurrentPriority = CeGetThreadPriority(GetCurrentThread());

                if (dwCurrentPriority != s_dwVideoThreadPriority)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -