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

📄 renbase.cpp

📁 用DirectX制作高级动画-[Advanced.Animation.with.DirectX]
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    if (m_pInputPin->IsConnected() == FALSE) {
        NOTE("Input pin is not connected");
        m_State = State_Stopped;
        return NOERROR;
    }

    CBaseFilter::Stop();

    // If we are going into a stopped state then we must decommit whatever
    // allocator we are using it so that any source filter waiting in the
    // GetBuffer can be released and unlock themselves for a state change

    if (m_pInputPin->Allocator()) {
        m_pInputPin->Allocator()->Decommit();
    }

    // Cancel any scheduled rendering

    SetRepaintStatus(TRUE);
    StopStreaming();
    SourceThreadCanWait(FALSE);
    ResetEndOfStream();
    CancelNotification();

    // There should be no outstanding clock advise
    ASSERT(CancelNotification() == S_FALSE);
    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
    ASSERT(m_EndOfStreamTimer == 0);

    Ready();
    WaitForReceiveToComplete();
    m_bAbort = FALSE;

    return NOERROR;
}


// When we pause the filter the things we do are:-

//      Commit the allocator being used in the connection
//      Allow a source filter thread to wait in Receive
//      Cancel any clock advise link (we may be running)
//      Possibly complete the state change if we have data
//      Allow us to be paused when we are not connected

STDMETHODIMP CBaseRenderer::Pause()
{
    CAutoLock cRendererLock(&m_InterfaceLock);
    FILTER_STATE OldState = m_State;
    ASSERT(m_pInputPin->IsFlushing() == FALSE);

    // Make sure there really is a state change

    if (m_State == State_Paused) {
        return CompleteStateChange(State_Paused);
    }

    // Has our input pin been connected

    if (m_pInputPin->IsConnected() == FALSE) {
        NOTE("Input pin is not connected");
        m_State = State_Paused;
        return CompleteStateChange(State_Paused);
    }

    // Pause the base filter class

    HRESULT hr = CBaseFilter::Pause();
    if (FAILED(hr)) {
        NOTE("Pause failed");
        return hr;
    }

    // Enable EC_REPAINT events again

    SetRepaintStatus(TRUE);
    StopStreaming();
    SourceThreadCanWait(TRUE);
    CancelNotification();
    ResetEndOfStreamTimer();

    // If we are going into a paused state then we must commit whatever
    // allocator we are using it so that any source filter can call the
    // GetBuffer and expect to get a buffer without returning an error

    if (m_pInputPin->Allocator()) {
        m_pInputPin->Allocator()->Commit();
    }

    // There should be no outstanding advise
    ASSERT(CancelNotification() == S_FALSE);
    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
    ASSERT(m_EndOfStreamTimer == 0);
    ASSERT(m_pInputPin->IsFlushing() == FALSE);

    // When we come out of a stopped state we must clear any image we were
    // holding onto for frame refreshing. Since renderers see state changes
    // first we can reset ourselves ready to accept the source thread data
    // Paused or running after being stopped causes the current position to
    // be reset so we're not interested in passing end of stream signals

    if (OldState == State_Stopped) {
        m_bAbort = FALSE;
        ClearPendingSample();
    }
    return CompleteStateChange(OldState);
}


// When we run the filter the things we do are:-

//      Commit the allocator being used in the connection
//      Allow a source filter thread to wait in Receive
//      Signal the render event just to get us going
//      Start the base class by calling StartStreaming
//      Allow us to be run when we are not connected
//      Signal EC_COMPLETE if we are not connected

STDMETHODIMP CBaseRenderer::Run(REFERENCE_TIME StartTime)
{
    CAutoLock cRendererLock(&m_InterfaceLock);
    FILTER_STATE OldState = m_State;

    // Make sure there really is a state change

    if (m_State == State_Running) {
        return NOERROR;
    }

    // Send EC_COMPLETE if we're not connected

    if (m_pInputPin->IsConnected() == FALSE) {
        NotifyEvent(EC_COMPLETE,S_OK,(LONG_PTR)(IBaseFilter *)this);
        m_State = State_Running;
        return NOERROR;
    }

    Ready();

    // Pause the base filter class

    HRESULT hr = CBaseFilter::Run(StartTime);
    if (FAILED(hr)) {
        NOTE("Run failed");
        return hr;
    }

    // Allow the source thread to wait
    ASSERT(m_pInputPin->IsFlushing() == FALSE);
    SourceThreadCanWait(TRUE);
    SetRepaintStatus(FALSE);

    // There should be no outstanding advise
    ASSERT(CancelNotification() == S_FALSE);
    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
    ASSERT(m_EndOfStreamTimer == 0);
    ASSERT(m_pInputPin->IsFlushing() == FALSE);

    // If we are going into a running state then we must commit whatever
    // allocator we are using it so that any source filter can call the
    // GetBuffer and expect to get a buffer without returning an error

    if (m_pInputPin->Allocator()) {
        m_pInputPin->Allocator()->Commit();
    }

    // When we come out of a stopped state we must clear any image we were
    // holding onto for frame refreshing. Since renderers see state changes
    // first we can reset ourselves ready to accept the source thread data
    // Paused or running after being stopped causes the current position to
    // be reset so we're not interested in passing end of stream signals

    if (OldState == State_Stopped) {
        m_bAbort = FALSE;
        ClearPendingSample();
    }
    return StartStreaming();
}


// Return the number of input pins we support

int CBaseRenderer::GetPinCount()
{
    return 1;
}


// We only support one input pin and it is numbered zero

CBasePin *CBaseRenderer::GetPin(int n)
{
    CAutoLock cObjectCreationLock(&m_ObjectCreationLock);

    // Should only ever be called with zero
    ASSERT(n == 0);

    if (n != 0) {
        return NULL;
    }

    // Create the input pin if not already done so

    if (m_pInputPin == NULL) {

        // hr must be initialized to NOERROR because
        // CRendererInputPin's constructor only changes
        // hr's value if an error occurs.
        HRESULT hr = NOERROR;

        m_pInputPin = new CRendererInputPin(this,&hr,L"In");
        if (NULL == m_pInputPin) {
            return NULL;
        }

        if (FAILED(hr)) {
            delete m_pInputPin;
            m_pInputPin = NULL;
            return NULL;
        }
    }
    return m_pInputPin;
}


// If "In" then return the IPin for our input pin, otherwise NULL and error

STDMETHODIMP CBaseRenderer::FindPin(LPCWSTR Id, IPin **ppPin)
{
    CheckPointer(ppPin,E_POINTER);

    if (0==lstrcmpW(Id,L"In")) {
        *ppPin = GetPin(0);
        ASSERT(*ppPin);
        (*ppPin)->AddRef();
    } else {
        *ppPin = NULL;
        return VFW_E_NOT_FOUND;
    }
    return NOERROR;
}


// Called when the input pin receives an EndOfStream notification. If we have
// not got a sample, then notify EC_COMPLETE now. If we have samples, then set
// m_bEOS and check for this on completing samples. If we're waiting to pause
// then complete the transition to paused state by setting the state event

HRESULT CBaseRenderer::EndOfStream()
{
    // Ignore these calls if we are stopped

    if (m_State == State_Stopped) {
        return NOERROR;
    }

    // If we have a sample then wait for it to be rendered

    m_bEOS = TRUE;
    if (m_pMediaSample) {
        return NOERROR;
    }

    // If we are waiting for pause then we are now ready since we cannot now
    // carry on waiting for a sample to arrive since we are being told there
    // won't be any. This sets an event that the GetState function picks up

    Ready();

    // Only signal completion now if we are running otherwise queue it until
    // we do run in StartStreaming. This is used when we seek because a seek
    // causes a pause where early notification of completion is misleading

    if (m_bStreaming) {
        SendEndOfStream();
    }
    return NOERROR;
}


// When we are told to flush we should release the source thread

HRESULT CBaseRenderer::BeginFlush()
{
    // If paused then report state intermediate until we get some data

    if (m_State == State_Paused) {
        NotReady();
    }

    SourceThreadCanWait(FALSE);
    CancelNotification();
    ClearPendingSample();
    //  Wait for Receive to complete
    WaitForReceiveToComplete();

    return NOERROR;
}


// After flushing the source thread can wait in Receive again

HRESULT CBaseRenderer::EndFlush()
{
    // Reset the current sample media time
    if (m_pPosition) m_pPosition->ResetMediaTime();

    // There should be no outstanding advise

    ASSERT(CancelNotification() == S_FALSE);
    SourceThreadCanWait(TRUE);
    return NOERROR;
}


// We can now send EC_REPAINTs if so required

HRESULT CBaseRenderer::CompleteConnect(IPin *pReceivePin)
{
    // The caller should always hold the interface lock because
    // the function uses CBaseFilter::m_State.
    ASSERT(CritCheckIn(&m_InterfaceLock));

    m_bAbort = FALSE;

    if (State_Running == GetRealState()) {
        HRESULT hr = StartStreaming();
        if (FAILED(hr)) {
            return hr;
        }

        SetRepaintStatus(FALSE);
    } else {
        SetRepaintStatus(TRUE);
    }

    return NOERROR;
}


// Called when we go paused or running

HRESULT CBaseRenderer::Active()
{
    return NOERROR;
}


// Called when we go into a stopped state

HRESULT CBaseRenderer::Inactive()
{
    if (m_pPosition) {
        m_pPosition->ResetMediaTime();
    }
    //  People who derive from this may want to override this behaviour
    //  to keep hold of the sample in some circumstances
    ClearPendingSample();

    return NOERROR;
}


// Tell derived classes about the media type agreed

HRESULT CBaseRenderer::SetMediaType(const CMediaType *pmt)
{
    return NOERROR;
}


// When we break the input pin connection we should reset the EOS flags. When
// we are asked for either IMediaPosition or IMediaSeeking we will create a
// CPosPassThru object to handles media time pass through. When we're handed
// samples we store (by calling CPosPassThru::RegisterMediaTime) their media
// times so we can then return a real current position of data being rendered

HRESULT CBaseRenderer::BreakConnect()
{
    // Do we have a quality management sink

    if (m_pQSink) {
        m_pQSink->Release();
        m_pQSink = NULL;
    }

    // Check we have a valid connection

    if (m_pInputPin->IsConnected() == FALSE) {
        return S_FALSE;
    }

    // Check we are stopped before disconnecting
    if (m_State != State_Stopped && !m_pInputPin->CanReconnectWhenActive()) {
        return VFW_E_NOT_STOPPED;
    }

    SetRepaintStatus(FALSE);

⌨️ 快捷键说明

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