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

📄 amfilter.cpp

📁 包裝ffmpeg中的codecs成為DirectShow中的transform filter
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//------------------------------------------------------------------------------
// File: AMFilter.cpp
//
// Desc: DirectShow base classes - implements class hierarchy for streams
//       architecture.
//
// Copyright (c) 1992-2002 Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------


//=====================================================================
//=====================================================================
// The following classes are declared in this header:
//
//
// CBaseMediaFilter            Basic IMediaFilter support (abstract class)
// CBaseFilter                 Support for IBaseFilter (incl. IMediaFilter)
// CEnumPins                   Enumerate input and output pins
// CEnumMediaTypes             Enumerate the preferred pin formats
// CBasePin                    Abstract base class for IPin interface
//    CBaseOutputPin           Adds data provider member functions
//    CBaseInputPin            Implements IMemInputPin interface
// CMediaSample                Basic transport unit for IMemInputPin
// CBaseAllocator              General list guff for most allocators
//    CMemAllocator            Implements memory buffer allocation
//
//=====================================================================
//=====================================================================

#include <streams.h>



//=====================================================================
// Helpers
//=====================================================================
STDAPI CreateMemoryAllocator(IMemAllocator **ppAllocator)
{
    return CoCreateInstance(CLSID_MemoryAllocator,
                            0,
                            CLSCTX_INPROC_SERVER,
                            IID_IMemAllocator,
                            (void **)ppAllocator);
}

//  Put this one here rather than in ctlutil.cpp to avoid linking
//  anything brought in by ctlutil.cpp
STDAPI CreatePosPassThru(
    LPUNKNOWN pAgg,
    BOOL bRenderer,
    IPin *pPin,
    IUnknown **ppPassThru
)
{
    *ppPassThru = NULL;
    IUnknown *pUnkSeek;
    HRESULT hr = CoCreateInstance(CLSID_SeekingPassThru,
                                  pAgg,
                                  CLSCTX_INPROC_SERVER,
                                  IID_IUnknown,
                                  (void **)&pUnkSeek
                                 );
    if (FAILED(hr)) {
        return hr;
    }

    ISeekingPassThru *pPassThru;
    hr = pUnkSeek->QueryInterface(IID_ISeekingPassThru, (void**)&pPassThru);
    if (FAILED(hr)) {
        pUnkSeek->Release();
        return hr;
    }
    hr = pPassThru->Init(bRenderer, pPin);
    pPassThru->Release();
    if (FAILED(hr)) {
        pUnkSeek->Release();
        return hr;
    }
    *ppPassThru = pUnkSeek;
    return S_OK;
}



#define CONNECT_TRACE_LEVEL 3

//=====================================================================
//=====================================================================
// Implements CBaseMediaFilter
//=====================================================================
//=====================================================================


/* Constructor */

CBaseMediaFilter::CBaseMediaFilter(const TCHAR  *pName,
                   LPUNKNOWN    pUnk,
                   CCritSec *pLock,
                   REFCLSID clsid) :
    CUnknown(pName, pUnk),
    m_pLock(pLock),
    m_clsid(clsid),
    m_State(State_Stopped),
    m_pClock(NULL)
{
}


/* Destructor */

CBaseMediaFilter::~CBaseMediaFilter()
{
    // must be stopped, but can't call Stop here since
    // our critsec has been destroyed.

    /* Release any clock we were using */

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


/* Override this to say what interfaces we support and where */

STDMETHODIMP
CBaseMediaFilter::NonDelegatingQueryInterface(
    REFIID riid,
    void ** ppv)
{
    if (riid == IID_IMediaFilter) {
        return GetInterface((IMediaFilter *) this, ppv);
    } else if (riid == IID_IPersist) {
        return GetInterface((IPersist *) this, ppv);
    } else {
        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
    }
}

/* Return the filter's clsid */
STDMETHODIMP
CBaseMediaFilter::GetClassID(CLSID *pClsID)
{
    CheckPointer(pClsID,E_POINTER);
    ValidateReadWritePtr(pClsID,sizeof(CLSID));
    *pClsID = m_clsid;
    return NOERROR;
}

/* Override this if your state changes are not done synchronously */

STDMETHODIMP
CBaseMediaFilter::GetState(DWORD dwMSecs, FILTER_STATE *State)
{
    UNREFERENCED_PARAMETER(dwMSecs);
    CheckPointer(State,E_POINTER);
    ValidateReadWritePtr(State,sizeof(FILTER_STATE));

    *State = m_State;
    return S_OK;
}


/* Set the clock we will use for synchronisation */

STDMETHODIMP
CBaseMediaFilter::SetSyncSource(IReferenceClock *pClock)
{
    CAutoLock cObjectLock(m_pLock);

    // Ensure the new one does not go away - even if the same as the old
    if (pClock) {
        pClock->AddRef();
    }

    // if we have a clock, release it
    if (m_pClock) {
        m_pClock->Release();
    }

    // Set the new reference clock (might be NULL)
    // Should we query it to ensure it is a clock?  Consider for a debug build.
    m_pClock = pClock;

    return NOERROR;
}

/* Return the clock we are using for synchronisation */
STDMETHODIMP
CBaseMediaFilter::GetSyncSource(IReferenceClock **pClock)
{
    CheckPointer(pClock,E_POINTER);
    ValidateReadWritePtr(pClock,sizeof(IReferenceClock *));
    CAutoLock cObjectLock(m_pLock);

    if (m_pClock) {
        // returning an interface... addref it...
        m_pClock->AddRef();
    }
    *pClock = (IReferenceClock*)m_pClock;
    return NOERROR;
}


/* Put the filter into a stopped state */

STDMETHODIMP
CBaseMediaFilter::Stop()
{
    CAutoLock cObjectLock(m_pLock);

    m_State = State_Stopped;
    return S_OK;
}


/* Put the filter into a paused state */

STDMETHODIMP
CBaseMediaFilter::Pause()
{
    CAutoLock cObjectLock(m_pLock);

    m_State = State_Paused;
    return S_OK;
}


// Put the filter into a running state.

// The time parameter is the offset to be added to the samples'
// stream time to get the reference time at which they should be presented.
//
// you can either add these two and compare it against the reference clock,
// or you can call CBaseMediaFilter::StreamTime and compare that against
// the sample timestamp.

STDMETHODIMP
CBaseMediaFilter::Run(REFERENCE_TIME tStart)
{
    CAutoLock cObjectLock(m_pLock);

    // remember the stream time offset
    m_tStart = tStart;

    if (m_State == State_Stopped){
        HRESULT hr = Pause();

        if (FAILED(hr)) {
            return hr;
        }
    }
    m_State = State_Running;
    return S_OK;
}


//
// return the current stream time - samples with start timestamps of this
// time or before should be rendered by now
HRESULT
CBaseMediaFilter::StreamTime(CRefTime& rtStream)
{
    // Caller must lock for synchronization
    // We can't grab the filter lock because we want to be able to call
    // this from worker threads without deadlocking

    if (m_pClock == NULL) {
        return VFW_E_NO_CLOCK;
    }

    // get the current reference time
    HRESULT hr = m_pClock->GetTime((REFERENCE_TIME*)&rtStream);
    if (FAILED(hr)) {
        return hr;
    }

    // subtract the stream offset to get stream time
    rtStream -= m_tStart;

    return S_OK;
}


//=====================================================================
//=====================================================================
// Implements CBaseFilter
//=====================================================================
//=====================================================================


/* Override this to say what interfaces we support and where */

STDMETHODIMP CBaseFilter::NonDelegatingQueryInterface(REFIID riid,
                                                      void **ppv)
{
    /* Do we have this interface */

    if (riid == IID_IBaseFilter) {
        return GetInterface((IBaseFilter *) this, ppv);
    } else if (riid == IID_IMediaFilter) {
        return GetInterface((IMediaFilter *) this, ppv);
    } else if (riid == IID_IPersist) {
        return GetInterface((IPersist *) this, ppv);
    } else if (riid == IID_IAMovieSetup) {
        return GetInterface((IAMovieSetup *) this, ppv);
    } else {
        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
    }
}

#ifdef DEBUG
STDMETHODIMP_(ULONG) CBaseFilter::NonDelegatingRelease()
{
    if (m_cRef == 1) {
        KASSERT(m_pGraph == NULL);
    }
    return CUnknown::NonDelegatingRelease();
}
#endif


/* Constructor */

CBaseFilter::CBaseFilter(const TCHAR    *pName,
             LPUNKNOWN  pUnk,
             CCritSec   *pLock,
             REFCLSID   clsid) :
    CUnknown( pName, pUnk ),
    m_pLock(pLock),
    m_clsid(clsid),
    m_State(State_Stopped),
    m_pClock(NULL),
    m_pGraph(NULL),
    m_pSink(NULL),
    m_pName(NULL),
    m_PinVersion(1)
{

    ASSERT(pLock != NULL);
}

/* Passes in a redundant HRESULT argument */

CBaseFilter::CBaseFilter(TCHAR     *pName,
                         LPUNKNOWN  pUnk,
                         CCritSec  *pLock,
                         REFCLSID   clsid,
                         HRESULT   *phr) :
    CUnknown( pName, pUnk ),
    m_pLock(pLock),
    m_clsid(clsid),
    m_State(State_Stopped),
    m_pClock(NULL),
    m_pGraph(NULL),
    m_pSink(NULL),
    m_pName(NULL),
    m_PinVersion(1)
{

    ASSERT(pLock != NULL);
    UNREFERENCED_PARAMETER(phr);
}

#ifdef UNICODE
CBaseFilter::CBaseFilter(const CHAR *pName,
             LPUNKNOWN  pUnk,
             CCritSec   *pLock,
             REFCLSID   clsid) :
    CUnknown( pName, pUnk ),
    m_pLock(pLock),
    m_clsid(clsid),
    m_State(State_Stopped),
    m_pClock(NULL),
    m_pGraph(NULL),
    m_pSink(NULL),
    m_pName(NULL),
    m_PinVersion(1)
{

    ASSERT(pLock != NULL);
}
CBaseFilter::CBaseFilter(CHAR     *pName,
                         LPUNKNOWN  pUnk,
                         CCritSec  *pLock,
                         REFCLSID   clsid,
                         HRESULT   *phr) :
    CUnknown( pName, pUnk ),
    m_pLock(pLock),
    m_clsid(clsid),
    m_State(State_Stopped),
    m_pClock(NULL),
    m_pGraph(NULL),
    m_pSink(NULL),
    m_pName(NULL),
    m_PinVersion(1)
{

    ASSERT(pLock != NULL);
    UNREFERENCED_PARAMETER(phr);
}
#endif

/* Destructor */

CBaseFilter::~CBaseFilter()
{

    // NOTE we do NOT hold references on the filtergraph for m_pGraph or m_pSink
    // When we did we had the circular reference problem.  Nothing would go away.

    delete[] m_pName;

    // must be stopped, but can't call Stop here since
    // our critsec has been destroyed.

    /* Release any clock we were using */
    if (m_pClock) {
        m_pClock->Release();
        m_pClock = NULL;
    }
}

/* Return the filter's clsid */
STDMETHODIMP
CBaseFilter::GetClassID(CLSID *pClsID)
{
    CheckPointer(pClsID,E_POINTER);
    ValidateReadWritePtr(pClsID,sizeof(CLSID));
    *pClsID = m_clsid;
    return NOERROR;
}

/* Override this if your state changes are not done synchronously */
STDMETHODIMP
CBaseFilter::GetState(DWORD dwMSecs, FILTER_STATE *State)
{
    UNREFERENCED_PARAMETER(dwMSecs);
    CheckPointer(State,E_POINTER);
    ValidateReadWritePtr(State,sizeof(FILTER_STATE));

    *State = m_State;
    return S_OK;
}


/* Set the clock we will use for synchronisation */

STDMETHODIMP
CBaseFilter::SetSyncSource(IReferenceClock *pClock)
{
    CAutoLock cObjectLock(m_pLock);

    // Ensure the new one does not go away - even if the same as the old
    if (pClock) {
        pClock->AddRef();
    }

    // if we have a clock, release it
    if (m_pClock) {
        m_pClock->Release();
    }

    // Set the new reference clock (might be NULL)
    // Should we query it to ensure it is a clock?  Consider for a debug build.
    m_pClock = pClock;

    return NOERROR;
}

/* Return the clock we are using for synchronisation */

⌨️ 快捷键说明

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