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

📄 transfrm.cpp

📁 用DirectX制作高级动画-[Advanced.Animation.with.DirectX]
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // We may have an input connection but no output connection
    // However, if we have an input pin we do have an output pin

    else if (m_pOutput->IsConnected() == FALSE) {
        m_State = State_Paused;
    }

    else {
	if (m_State == State_Stopped) {
	    // allow a class derived from CTransformFilter
	    // to know about starting and stopping streaming
            CAutoLock lck2(&m_csReceive);
	    hr = StartStreaming();
	}
	if (SUCCEEDED(hr)) {
	    hr = CBaseFilter::Pause();
	}
    }

    m_bSampleSkipped = FALSE;
    m_bQualityChanged = FALSE;
    return hr;
}

HRESULT
CTransformFilter::NewSegment(
    REFERENCE_TIME tStart,
    REFERENCE_TIME tStop,
    double dRate)
{
    if (m_pOutput != NULL) {
        return m_pOutput->DeliverNewSegment(tStart, tStop, dRate);
    }
    return S_OK;
}

// Check streaming status
HRESULT
CTransformInputPin::CheckStreaming()
{
    ASSERT(m_pTransformFilter->m_pOutput != NULL);
    if (!m_pTransformFilter->m_pOutput->IsConnected()) {
        return VFW_E_NOT_CONNECTED;
    } else {
        //  Shouldn't be able to get any data if we're not connected!
        ASSERT(IsConnected());

        //  we're flushing
        if (m_bFlushing) {
            return S_FALSE;
        }
        //  Don't process stuff in Stopped state
        if (IsStopped()) {
            return VFW_E_WRONG_STATE;
        }
        if (m_bRunTimeError) {
    	    return VFW_E_RUNTIME_ERROR;
        }
        return S_OK;
    }
}


// =================================================================
// Implements the CTransformInputPin class
// =================================================================


// constructor

CTransformInputPin::CTransformInputPin(
    TCHAR *pObjectName,
    CTransformFilter *pTransformFilter,
    HRESULT * phr,
    LPCWSTR pName)
    : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
{
    DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
    m_pTransformFilter = pTransformFilter;
}

#ifdef UNICODE
CTransformInputPin::CTransformInputPin(
    CHAR *pObjectName,
    CTransformFilter *pTransformFilter,
    HRESULT * phr,
    LPCWSTR pName)
    : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
{
    DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
    m_pTransformFilter = pTransformFilter;
}
#endif

// provides derived filter a chance to grab extra interfaces

HRESULT
CTransformInputPin::CheckConnect(IPin *pPin)
{
    HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_INPUT,pPin);
    if (FAILED(hr)) {
    	return hr;
    }
    return CBaseInputPin::CheckConnect(pPin);
}


// provides derived filter a chance to release it's extra interfaces

HRESULT
CTransformInputPin::BreakConnect()
{
    //  Can't disconnect unless stopped
    ASSERT(IsStopped());
    m_pTransformFilter->BreakConnect(PINDIR_INPUT);
    return CBaseInputPin::BreakConnect();
}


// Let derived class know when the input pin is connected

HRESULT
CTransformInputPin::CompleteConnect(IPin *pReceivePin)
{
    HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin);
    if (FAILED(hr)) {
        return hr;
    }
    return CBaseInputPin::CompleteConnect(pReceivePin);
}


// check that we can support a given media type

HRESULT
CTransformInputPin::CheckMediaType(const CMediaType* pmt)
{
    // Check the input type

    HRESULT hr = m_pTransformFilter->CheckInputType(pmt);
    if (S_OK != hr) {
        return hr;
    }

    // if the output pin is still connected, then we have
    // to check the transform not just the input format

    if ((m_pTransformFilter->m_pOutput != NULL) &&
        (m_pTransformFilter->m_pOutput->IsConnected())) {
            return m_pTransformFilter->CheckTransform(
                      pmt,
		      &m_pTransformFilter->m_pOutput->CurrentMediaType());
    } else {
        return hr;
    }
}


// set the media type for this connection

HRESULT
CTransformInputPin::SetMediaType(const CMediaType* mtIn)
{
    // Set the base class media type (should always succeed)
    HRESULT hr = CBasePin::SetMediaType(mtIn);
    if (FAILED(hr)) {
        return hr;
    }

    // check the transform can be done (should always succeed)
    ASSERT(SUCCEEDED(m_pTransformFilter->CheckInputType(mtIn)));

    return m_pTransformFilter->SetMediaType(PINDIR_INPUT,mtIn);
}


// =================================================================
// Implements IMemInputPin interface
// =================================================================


// provide EndOfStream that passes straight downstream
// (there is no queued data)
STDMETHODIMP
CTransformInputPin::EndOfStream(void)
{
    CAutoLock lck(&m_pTransformFilter->m_csReceive);
    HRESULT hr = CheckStreaming();
    if (S_OK == hr) {
       hr = m_pTransformFilter->EndOfStream();
    }
    return hr;
}


// enter flushing state. Call default handler to block Receives, then
// pass to overridable method in filter
STDMETHODIMP
CTransformInputPin::BeginFlush(void)
{
    CAutoLock lck(&m_pTransformFilter->m_csFilter);
    //  Are we actually doing anything?
    ASSERT(m_pTransformFilter->m_pOutput != NULL);
    if (!IsConnected() ||
        !m_pTransformFilter->m_pOutput->IsConnected()) {
        return VFW_E_NOT_CONNECTED;
    }
    HRESULT hr = CBaseInputPin::BeginFlush();
    if (FAILED(hr)) {
    	return hr;
    }

    return m_pTransformFilter->BeginFlush();
}


// leave flushing state.
// Pass to overridable method in filter, then call base class
// to unblock receives (finally)
STDMETHODIMP
CTransformInputPin::EndFlush(void)
{
    CAutoLock lck(&m_pTransformFilter->m_csFilter);
    //  Are we actually doing anything?
    ASSERT(m_pTransformFilter->m_pOutput != NULL);
    if (!IsConnected() ||
        !m_pTransformFilter->m_pOutput->IsConnected()) {
        return VFW_E_NOT_CONNECTED;
    }

    HRESULT hr = m_pTransformFilter->EndFlush();
    if (FAILED(hr)) {
        return hr;
    }

    return CBaseInputPin::EndFlush();
}


// here's the next block of data from the stream.
// AddRef it yourself if you need to hold it beyond the end
// of this call.

HRESULT
CTransformInputPin::Receive(IMediaSample * pSample)
{
    HRESULT hr;
    CAutoLock lck(&m_pTransformFilter->m_csReceive);
    ASSERT(pSample);

    // check all is well with the base class
    hr = CBaseInputPin::Receive(pSample);
    if (S_OK == hr) {
        hr = m_pTransformFilter->Receive(pSample);
    }
    return hr;
}




// override to pass downstream
STDMETHODIMP
CTransformInputPin::NewSegment(
    REFERENCE_TIME tStart,
    REFERENCE_TIME tStop,
    double dRate)
{
    //  Save the values in the pin
    CBasePin::NewSegment(tStart, tStop, dRate);
    return m_pTransformFilter->NewSegment(tStart, tStop, dRate);
}




// =================================================================
// Implements the CTransformOutputPin class
// =================================================================


// constructor

CTransformOutputPin::CTransformOutputPin(
    TCHAR *pObjectName,
    CTransformFilter *pTransformFilter,
    HRESULT * phr,
    LPCWSTR pPinName)
    : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
      m_pPosition(NULL)
{
    DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
    m_pTransformFilter = pTransformFilter;

}

#ifdef UNICODE
CTransformOutputPin::CTransformOutputPin(
    CHAR *pObjectName,
    CTransformFilter *pTransformFilter,
    HRESULT * phr,
    LPCWSTR pPinName)
    : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
      m_pPosition(NULL)
{
    DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
    m_pTransformFilter = pTransformFilter;

}
#endif

// destructor

CTransformOutputPin::~CTransformOutputPin()
{
    DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::~CTransformOutputPin")));

    if (m_pPosition) m_pPosition->Release();
}


// overriden to expose IMediaPosition and IMediaSeeking control interfaces

STDMETHODIMP
CTransformOutputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
    CheckPointer(ppv,E_POINTER);
    ValidateReadWritePtr(ppv,sizeof(PVOID));
    *ppv = NULL;

    if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {

        // we should have an input pin by now

        ASSERT(m_pTransformFilter->m_pInput != NULL);

        if (m_pPosition == NULL) {

            HRESULT hr = CreatePosPassThru(
                             GetOwner(),
                             FALSE,
                             (IPin *)m_pTransformFilter->m_pInput,
                             &m_pPosition);
            if (FAILED(hr)) {
                return hr;
            }
        }
        return m_pPosition->QueryInterface(riid, ppv);
    } else {
        return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
    }
}


// provides derived filter a chance to grab extra interfaces

HRESULT
CTransformOutputPin::CheckConnect(IPin *pPin)
{
    // we should have an input connection first

    ASSERT(m_pTransformFilter->m_pInput != NULL);
    if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
	    return E_UNEXPECTED;
    }

    HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_OUTPUT,pPin);
    if (FAILED(hr)) {
	    return hr;
    }
    return CBaseOutputPin::CheckConnect(pPin);
}


// provides derived filter a chance to release it's extra interfaces

HRESULT
CTransformOutputPin::BreakConnect()
{
    //  Can't disconnect unless stopped
    ASSERT(IsStopped());
    m_pTransformFilter->BreakConnect(PINDIR_OUTPUT);
    return CBaseOutputPin::BreakConnect();
}


// Let derived class know when the output pin is connected

HRESULT
CTransformOutputPin::CompleteConnect(IPin *pReceivePin)
{
    HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin);
    if (FAILED(hr)) {
        return hr;
    }
    return CBaseOutputPin::CompleteConnect(pReceivePin);
}


// check a given transform - must have selected input type first

HRESULT
CTransformOutputPin::CheckMediaType(const CMediaType* pmtOut)
{
    // must have selected input first
    ASSERT(m_pTransformFilter->m_pInput != NULL);
    if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
	        return E_INVALIDARG;
    }

    return m_pTransformFilter->CheckTransform(
				    &m_pTransformFilter->m_pInput->CurrentMediaType(),
				    pmtOut);
}


// called after we have agreed a media type to actually set it in which case
// we run the CheckTransform function to get the output format type again

HRESULT
CTransformOutputPin::SetMediaType(const CMediaType* pmtOut)
{
    HRESULT hr = NOERROR;
    ASSERT(m_pTransformFilter->m_pInput != NULL);

    ASSERT(m_pTransformFilter->m_pInput->CurrentMediaType().IsValid());

    // Set the base class media type (should always succeed)
    hr = CBasePin::SetMediaType(pmtOut);
    if (FAILED(hr)) {
        return hr;
    }

#ifdef DEBUG
    if (FAILED(m_pTransformFilter->CheckTransform(&m_pTransformFilter->
					m_pInput->CurrentMediaType(),pmtOut))) {
	DbgLog((LOG_ERROR,0,TEXT("*** This filter is accepting an output media type")));
	DbgLog((LOG_ERROR,0,TEXT("    that it can't currently transform to.  I hope")));
	DbgLog((LOG_ERROR,0,TEXT("    it's smart enough to reconnect its input.")));
    }
#endif

    return m_pTransformFilter->SetMediaType(PINDIR_OUTPUT,pmtOut);
}


// pass the buffer size decision through to the main transform class

HRESULT
CTransformOutputPin::DecideBufferSize(
    IMemAllocator * pAllocator,
    ALLOCATOR_PROPERTIES* pProp)
{
    return m_pTransformFilter->DecideBufferSize(pAllocator, pProp);
}



// return a specific media type indexed by iPosition

HRESULT
CTransformOutputPin::GetMediaType(
    int iPosition,
    CMediaType *pMediaType)
{
    ASSERT(m_pTransformFilter->m_pInput != NULL);

    //  We don't have any media types if our input is not connected

    if (m_pTransformFilter->m_pInput->IsConnected()) {
        return m_pTransformFilter->GetMediaType(iPosition,pMediaType);
    } else {
        return VFW_S_NO_MORE_ITEMS;
    }
}


// Override this if you can do something constructive to act on the
// quality message.  Consider passing it upstream as well

// Pass the quality mesage on upstream.

STDMETHODIMP
CTransformOutputPin::Notify(IBaseFilter * pSender, Quality q)
{
    UNREFERENCED_PARAMETER(pSender);
    ValidateReadPtr(pSender,sizeof(IBaseFilter));

    // First see if we want to handle this ourselves
    HRESULT hr = m_pTransformFilter->AlterQuality(q);
    if (hr!=S_FALSE) {
        return hr;        // either S_OK or a failure
    }

    // S_FALSE means we pass the message on.
    // Find the quality sink for our input pin and send it there

    ASSERT(m_pTransformFilter->m_pInput != NULL);

    return m_pTransformFilter->m_pInput->PassNotify(q);

} // Notify


// the following removes a very large number of level 4 warnings from the microsoft
// compiler output, which are not useful at all in this case.
#pragma warning(disable:4514)

⌨️ 快捷键说明

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