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

📄 transip.cpp

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

    // Create an output pin if not already done

    if (m_pInput!=NULL && m_pOutput == NULL) {

        m_pOutput = new CTransInPlaceOutputPin( NAME("TransInPlace output pin")
                                              , this       // Owner filter
                                              , &hr        // Result code
                                              , L"Output"  // Pin name
                                              );

        // a failed return code should delete the object

        ASSERT(SUCCEEDED(hr));
        if (m_pOutput == NULL) {
            delete m_pInput;
            m_pInput = NULL;
        }
    }

    // Return the appropriate pin

    ASSERT (n>=0 && n<=1);
    if (n == 0) {
        return m_pInput;
    } else if (n==1) {
        return m_pOutput;
    } else {
        return NULL;
    }

} // GetPin



// dir is the direction of our pin.
// pReceivePin is the pin we are connecting to.
HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin)
{
    UNREFERENCED_PARAMETER(pReceivePin);
    ASSERT(m_pInput);
    ASSERT(m_pOutput);

    // if we are not part of a graph, then don't indirect the pointer
    // this probably prevents use of the filter without a filtergraph
    if (!m_pGraph) {
        return VFW_E_NOT_IN_GRAPH;
    }

    // Always reconnect the input to account for buffering changes
    //
    // Because we don't get to suggest a type on ReceiveConnection
    // we need another way of making sure the right type gets used.
    //
    // One way would be to have our EnumMediaTypes return our output
    // connection type first but more deterministic and simple is to
    // call ReconnectEx passing the type we want to reconnect with
    // via the base class ReconeectPin method.

    if (dir == PINDIR_OUTPUT) {
        if( m_pInput->IsConnected() ) {
            return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() );
        }
        return NOERROR;
    }

    ASSERT(dir == PINDIR_INPUT);

    // Reconnect output if necessary

    if( m_pOutput->IsConnected() ) {

        if (  m_pInput->CurrentMediaType()
           != m_pOutput->CurrentMediaType()
           ) {
            return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() );
        }
    }
    return NOERROR;

} // ComnpleteConnect


//
// DecideBufferSize
//
// Tell the output pin's allocator what size buffers we require.
// *pAlloc will be the allocator our output pin is using.
//

HRESULT CTransInPlaceFilter::DecideBufferSize
            ( IMemAllocator *pAlloc
            , ALLOCATOR_PROPERTIES *pProperties
            )
{
    ALLOCATOR_PROPERTIES Request, Actual;
    HRESULT hr;

    // If we are connected upstream, get his views
    if (m_pInput->IsConnected()) {
        // Get the input pin allocator, and get its size and count.
        // we don't care about his alignment and prefix.

        hr = InputPin()->PeekAllocator()->GetProperties(&Request);
        if (FAILED(hr)) {
            // Input connected but with a secretive allocator - enough!
            return hr;
        }
    } else {
        // We're reduced to blind guessing.  Let's guess one byte and if
        // this isn't enough then when the other pin does get connected
        // we can revise it.
        ZeroMemory(&Request, sizeof(Request));
        Request.cBuffers = 1;
        Request.cbBuffer = 1;
    }


    DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements")));
    DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"),
           Request.cBuffers, Request.cbBuffer));

    // Pass the allocator requirements to our output side
    // but do a little sanity checking first or we'll just hit
    // asserts in the allocator.

    pProperties->cBuffers = Request.cBuffers;
    pProperties->cbBuffer = Request.cbBuffer;
    pProperties->cbAlign = Request.cbAlign;
    if (pProperties->cBuffers<=0) {pProperties->cBuffers = 1; }
    if (pProperties->cbBuffer<=0) {pProperties->cbBuffer = 1; }
    hr = pAlloc->SetProperties(pProperties, &Actual);

    if (FAILED(hr)) {
        return hr;
    }

    DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements")));
    DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"),
           Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign));

    // Make sure we got the right alignment and at least the minimum required

    if (  (Request.cBuffers > Actual.cBuffers)
       || (Request.cbBuffer > Actual.cbBuffer)
       || (Request.cbAlign  > Actual.cbAlign)
       ) {
        return E_FAIL;
    }
    return NOERROR;

} // DecideBufferSize

//
// Copy
//
// return a pointer to an identical copy of pSample
IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource)
{
    IMediaSample * pDest;

    HRESULT hr;
    REFERENCE_TIME tStart, tStop;
    const BOOL bTime = S_OK == pSource->GetTime( &tStart, &tStop);

    // this may block for an indeterminate amount of time
    hr = OutputPin()->PeekAllocator()->GetBuffer(
              &pDest
              , bTime ? &tStart : NULL
              , bTime ? &tStop : NULL
              , m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0
              );

    if (FAILED(hr)) {
        return NULL;
    }

    ASSERT(pDest);
    IMediaSample2 *pSample2;
    if (SUCCEEDED(pDest->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) {
        HRESULT hr = pSample2->SetProperties(
            FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer),
            (PBYTE)m_pInput->SampleProps());
        pSample2->Release();
        if (FAILED(hr)) {
            pDest->Release();
            return NULL;
        }
    } else {
        if (bTime) {
            pDest->SetTime(&tStart, &tStop);
        }

        if (S_OK == pSource->IsSyncPoint()) {
            pDest->SetSyncPoint(TRUE);
        }
        if (S_OK == pSource->IsDiscontinuity() || m_bSampleSkipped) {
            pDest->SetDiscontinuity(TRUE);
        }
        if (S_OK == pSource->IsPreroll()) {
            pDest->SetPreroll(TRUE);
        }

        // Copy the media type
        AM_MEDIA_TYPE *pMediaType;
        if (S_OK == pSource->GetMediaType(&pMediaType)) {
            pDest->SetMediaType(pMediaType);
            DeleteMediaType( pMediaType );
        }

    }

    m_bSampleSkipped = FALSE;

    // Copy the sample media times
    REFERENCE_TIME TimeStart, TimeEnd;
    if (pSource->GetMediaTime(&TimeStart,&TimeEnd) == NOERROR) {
        pDest->SetMediaTime(&TimeStart,&TimeEnd);
    }

    // Copy the actual data length and the actual data.
    {
        const long lDataLength = pSource->GetActualDataLength();
        pDest->SetActualDataLength(lDataLength);

        // Copy the sample data
        {
            BYTE *pSourceBuffer, *pDestBuffer;
            long lSourceSize  = pSource->GetSize();
            long lDestSize = pDest->GetSize();

            ASSERT(lDestSize >= lSourceSize && lDestSize >= lDataLength);

            pSource->GetPointer(&pSourceBuffer);
            pDest->GetPointer(&pDestBuffer);
            ASSERT(lDestSize == 0 || pSourceBuffer != NULL && pDestBuffer != NULL);

            CopyMemory( (PVOID) pDestBuffer, (PVOID) pSourceBuffer, lDataLength );
        }
    }

    return pDest;

} // Copy


// override this to customize the transform process

HRESULT
CTransInPlaceFilter::Receive(IMediaSample *pSample)
{
    /*  Check for other streams and pass them on */
    AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
    if (pProps->dwStreamId != AM_STREAM_MEDIA) {
        return m_pOutput->Deliver(pSample);
    }
    HRESULT hr;

    // Start timing the TransInPlace (if PERF is defined)
    MSR_START(m_idTransInPlace);

    if (UsingDifferentAllocators()) {

        // We have to copy the data.

        pSample = Copy(pSample);

        if (pSample==NULL) {
            MSR_STOP(m_idTransInPlace);
            return E_UNEXPECTED;
        }
    }

    // have the derived class transform the data
    hr = Transform(pSample);

    // Stop the clock and log it (if PERF is defined)
    MSR_STOP(m_idTransInPlace);

    if (FAILED(hr)) {
        DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace")));
        if (UsingDifferentAllocators()) {
            pSample->Release();
        }
        return hr;
    }

    // the Transform() function can return S_FALSE to indicate that the
    // sample should not be delivered; we only deliver the sample if it's
    // really S_OK (same as NOERROR, of course.)
    if (hr == NOERROR) {
        hr = m_pOutput->Deliver(pSample);
    } else {
        //  But it would be an error to return this private workaround
        //  to the caller ...
        if (S_FALSE == hr) {
            // S_FALSE returned from Transform is a PRIVATE agreement
            // We should return NOERROR from Receive() in this cause because
            // returning S_FALSE from Receive() means that this is the end
            // of the stream and no more data should be sent.
            m_bSampleSkipped = TRUE;
            if (!m_bQualityChanged) {
                NotifyEvent(EC_QUALITY_CHANGE,0,0);
                m_bQualityChanged = TRUE;
            }
            hr = NOERROR;
        }
    }

    // release the output buffer. If the connected pin still needs it,
    // it will have addrefed it itself.
    if (UsingDifferentAllocators()) {
        pSample->Release();
    }

    return hr;

} // Receive



// =================================================================

⌨️ 快捷键说明

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