Example #1
0
//
// NonDelegatingQueryInterface
//
// This function is overwritten to expose IMediaPosition and IMediaSelection
// Note that only one output stream can be allowed to expose this to avoid
// conflicts, the other pins will just return E_NOINTERFACE and therefore
// appear as non seekable streams. We have a LONG value that if exchanged to
// produce a TRUE means that we have the honor. If it exchanges to FALSE then
// someone is already in. If we do get it and error occurs then we reset it
// to TRUE so someone else can get it.
//
STDMETHODIMP
CTeeOutputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
    CheckPointer(ppv,E_POINTER);
    ASSERT(ppv);

    *ppv = NULL;
    HRESULT hr = NOERROR;

    // See what interface the caller is interested in.
    if(riid == IID_IMediaPosition || riid == IID_IMediaSeeking)
    {
        if(m_pPosition)
        {
            if(m_bHoldsSeek == FALSE)
                return E_NOINTERFACE;
            return m_pPosition->QueryInterface(riid, ppv);
        }
    }
    else
    {
        return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
    }

    CAutoLock lock_it(m_pLock);
    ASSERT(m_pPosition == NULL);
    IUnknown *pMediaPosition = NULL;

    // Try to create a seeking implementation
    if(InterlockedExchange(&m_pTee->m_lCanSeek, FALSE) == FALSE)
        return E_NOINTERFACE;

    // Create implementation of this dynamically as sometimes we may never
    // try and seek. The helper object implements IMediaPosition and also
    // the IMediaSelection control interface and simply takes the calls
    // normally from the downstream filter and passes them upstream

    hr = CreatePosPassThru(GetOwner(),
                           FALSE,
                           (IPin *)&m_pTee->m_Input,
                           &pMediaPosition);

    if(pMediaPosition == NULL)
    {
        InterlockedExchange(&m_pTee->m_lCanSeek, TRUE);
        return E_OUTOFMEMORY;
    }

    if(FAILED(hr))
    {
        InterlockedExchange(&m_pTee->m_lCanSeek, TRUE);
        pMediaPosition->Release();
        return hr;
    }

    m_pPosition = pMediaPosition;
    m_bHoldsSeek = TRUE;
    return NonDelegatingQueryInterface(riid, ppv);

} // NonDelegatingQueryInterface
HRESULT VMRSurfaceAllocator::QueryInterface( REFIID iid, PVOID *pvInterface )
{
	return NonDelegatingQueryInterface( iid, pvInterface );
}