amfilter.cpp.svn-base

来自「ffshow源码」· SVN-BASE 代码 · 共 2,432 行 · 第 1/5 页

SVN-BASE
2,432
字号
/* Override this to say what interfaces we support where */STDMETHODIMPCEnumPins::QueryInterface(REFIID riid,void **ppv){    CheckPointer(ppv, E_POINTER);    /* Do we have this interface */    if (riid == IID_IEnumPins || riid == IID_IUnknown) {        return GetInterface((IEnumPins *) this, ppv);    } else {        *ppv = NULL;        return E_NOINTERFACE;    }}STDMETHODIMP_(ULONG)CEnumPins::AddRef(){    return InterlockedIncrement(&m_cRef);}STDMETHODIMP_(ULONG)CEnumPins::Release(){    ULONG cRef = InterlockedDecrement(&m_cRef);    if (cRef == 0) {        delete this;    }    return cRef;}/* One of an enumerator's basic member functions allows us to create a cloned   interface that initially has the same state. Since we are taking a snapshot   of an object (current position and all) we must lock access at the start */STDMETHODIMPCEnumPins::Clone(IEnumPins **ppEnum){    CheckPointer(ppEnum,E_POINTER);    ValidateReadWritePtr(ppEnum,sizeof(IEnumPins *));    HRESULT hr = NOERROR;    /* Check we are still in sync with the filter */    if (AreWeOutOfSync() == TRUE) {        *ppEnum = NULL;        hr =  VFW_E_ENUM_OUT_OF_SYNC;    } else {        *ppEnum = new CEnumPins(m_pFilter,                                this);        if (*ppEnum == NULL) {            hr = E_OUTOFMEMORY;        }    }    return hr;}/* Return the next pin after the current position */STDMETHODIMPCEnumPins::Next(ULONG cPins,        // place this many pins...        IPin **ppPins,      // ...in this array        ULONG *pcFetched)   // actual count passed returned here{    CheckPointer(ppPins,E_POINTER);    ValidateReadWritePtr(ppPins,cPins * sizeof(IPin *));    ASSERT(ppPins);    if (pcFetched!=NULL) {        ValidateWritePtr(pcFetched, sizeof(ULONG));        *pcFetched = 0;           // default unless we succeed    }    // now check that the parameter is valid    else if (cPins>1) {   // pcFetched == NULL        return E_INVALIDARG;    }    ULONG cFetched = 0;           // increment as we get each one.    /* Check we are still in sync with the filter */    if (AreWeOutOfSync() == TRUE) {    // If we are out of sync, we should refresh the enumerator.    // This will reset the position and update the other members, but    // will not clear cache of pins we have already returned.    Refresh();    }    /* Calculate the number of available pins */    int cRealPins = std::min(m_PinCount - m_Position, (int) cPins);    if (cRealPins == 0) {        return S_FALSE;    }    /* Return each pin interface NOTE GetPin returns CBasePin * not addrefed       so we must QI for the IPin (which increments its reference count)       If while we are retrieving a pin from the filter an error occurs we       assume that our internal state is stale with respect to the filter       (for example someone has deleted a pin) so we       return VFW_E_ENUM_OUT_OF_SYNC                            */    while (cRealPins && (m_PinCount - m_Position)) {        /* Get the next pin object from the filter */        CBasePin *pPin = m_pFilter->GetPin(m_Position++);        if (pPin == NULL) {            // If this happend, and it's not the first time through, then we've got a problem,            // since we should really go back and release the iPins, which we have previously            // AddRef'ed.            ASSERT( cFetched==0 );            return VFW_E_ENUM_OUT_OF_SYNC;        }        /* We only want to return this pin, if it is not in our cache */        if (0 == m_PinCache.Find(pPin))        {            /* From the object get an IPin interface */            *ppPins = pPin;            pPin->AddRef();            cFetched++;            ppPins++;            m_PinCache.AddTail(pPin);            cRealPins--;        }    }    if (pcFetched!=NULL) {        *pcFetched = cFetched;    }    return (cPins==cFetched ? NOERROR : S_FALSE);}/* Skip over one or more entries in the enumerator */STDMETHODIMPCEnumPins::Skip(ULONG cPins){    /* Check we are still in sync with the filter */    if (AreWeOutOfSync() == TRUE) {        return VFW_E_ENUM_OUT_OF_SYNC;    }    /* Work out how many pins are left to skip over */    /* We could position at the end if we are asked to skip too many... */    /* ..which would match the base implementation for CEnumMediaTypes::Skip */    ULONG PinsLeft = m_PinCount - m_Position;    if (cPins > PinsLeft) {        return S_FALSE;    }    m_Position += cPins;    return NOERROR;}/* Set the current position back to the start *//* Reset has 4 simple steps: * * Set position to head of list * Sync enumerator with object being enumerated * Clear the cache of pins already returned * return S_OK */STDMETHODIMPCEnumPins::Reset(){    m_Version = m_pFilter->GetPinVersion();    m_PinCount = m_pFilter->GetPinCount();    m_Position = 0;    // Clear the cache    m_PinCache.RemoveAll();    return S_OK;}/* Set the current position back to the start *//* Refresh has 3 simple steps: * * Set position to head of list * Sync enumerator with object being enumerated * return S_OK */STDMETHODIMPCEnumPins::Refresh(){    m_Version = m_pFilter->GetPinVersion();    m_PinCount = m_pFilter->GetPinCount();    m_Position = 0;    return S_OK;}//=====================================================================//=====================================================================// Implements CEnumMediaTypes//=====================================================================//=====================================================================CEnumMediaTypes::CEnumMediaTypes(CBasePin *pPin,                 CEnumMediaTypes *pEnumMediaTypes) :    m_Position(0),    m_pPin(pPin),    m_cRef(1){#ifdef DEBUG    m_dwCookie = DbgRegisterObjectCreation("CEnumMediaTypes", 0);#endif    /* We must be owned by a pin derived from CBasePin */    ASSERT(pPin != NULL);    /* Hold a reference count on our pin */    m_pPin->AddRef();    /* Are we creating a new enumerator */    if (pEnumMediaTypes == NULL) {        m_Version = m_pPin->GetMediaTypeVersion();        return;    }    m_Position = pEnumMediaTypes->m_Position;    m_Version = pEnumMediaTypes->m_Version;}/* Destructor releases the reference count on our base pin. NOTE since we hold   a reference count on the pin who created us we know it is safe to release   it, no access can be made to it afterwards though as we might have just   caused the last reference count to go and the object to be deleted */CEnumMediaTypes::~CEnumMediaTypes(){#ifdef DEBUG    DbgRegisterObjectDestruction(m_dwCookie);#endif    m_pPin->Release();}/* Override this to say what interfaces we support where */STDMETHODIMPCEnumMediaTypes::QueryInterface(REFIID riid,void **ppv){    CheckPointer(ppv, E_POINTER);    /* Do we have this interface */    if (riid == IID_IEnumMediaTypes || riid == IID_IUnknown) {        return GetInterface((IEnumMediaTypes *) this, ppv);    } else {        *ppv = NULL;        return E_NOINTERFACE;    }}STDMETHODIMP_(ULONG)CEnumMediaTypes::AddRef(){    return InterlockedIncrement(&m_cRef);}STDMETHODIMP_(ULONG)CEnumMediaTypes::Release(){    ULONG cRef = InterlockedDecrement(&m_cRef);    if (cRef == 0) {        delete this;    }    return cRef;}/* One of an enumerator's basic member functions allows us to create a cloned   interface that initially has the same state. Since we are taking a snapshot   of an object (current position and all) we must lock access at the start */STDMETHODIMPCEnumMediaTypes::Clone(IEnumMediaTypes **ppEnum){    CheckPointer(ppEnum,E_POINTER);    ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));    HRESULT hr = NOERROR;    /* Check we are still in sync with the pin */    if (AreWeOutOfSync() == TRUE) {        *ppEnum = NULL;        hr = VFW_E_ENUM_OUT_OF_SYNC;    } else {        *ppEnum = new CEnumMediaTypes(m_pPin,                                      this);        if (*ppEnum == NULL) {            hr =  E_OUTOFMEMORY;        }    }    return hr;}/* Enumerate the next pin(s) after the current position. The client using this   interface passes in a pointer to an array of pointers each of which will   be filled in with a pointer to a fully initialised media type format   Return NOERROR if it all works,          S_FALSE if fewer than cMediaTypes were enumerated.          VFW_E_ENUM_OUT_OF_SYNC if the enumerator has been broken by                                 state changes in the filter   The actual count always correctly reflects the number of types in the array.*/STDMETHODIMPCEnumMediaTypes::Next(ULONG cMediaTypes,          // place this many types...              AM_MEDIA_TYPE **ppMediaTypes,   // ...in this array              ULONG *pcFetched)           // actual count passed{    CheckPointer(ppMediaTypes,E_POINTER);    ValidateReadWritePtr(ppMediaTypes,cMediaTypes * sizeof(AM_MEDIA_TYPE *));    /* Check we are still in sync with the pin */    if (AreWeOutOfSync() == TRUE) {        return VFW_E_ENUM_OUT_OF_SYNC;    }    if (pcFetched!=NULL) {        ValidateWritePtr(pcFetched, sizeof(ULONG));        *pcFetched = 0;           // default unless we succeed    }    // now check that the parameter is valid    else if (cMediaTypes>1) {     // pcFetched == NULL        return E_INVALIDARG;    }    ULONG cFetched = 0;           // increment as we get each one.    /* Return each media type by asking the filter for them in turn - If we       have an error code retured to us while we are retrieving a media type       we assume that our internal state is stale with respect to the filter       (for example the window size changing) so we return       VFW_E_ENUM_OUT_OF_SYNC */    while (cMediaTypes) {        CMediaType cmt;        HRESULT hr = m_pPin->GetMediaType(m_Position++, &cmt);        if (S_OK != hr) {            break;        }        /* We now have a CMediaType object that contains the next media type           but when we assign it to the array position we CANNOT just assign           the AM_MEDIA_TYPE structure because as soon as the object goes out of           scope it will delete the memory we have just copied. The function           we use is CreateMediaType which allocates a task memory block */        /*  Transfer across the format block manually to save an allocate            and free on the format block and generally go faster */        *ppMediaTypes = (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));        if (*ppMediaTypes == NULL) {            break;        }        /*  Do a regular copy */        **ppMediaTypes = (AM_MEDIA_TYPE)cmt;        /*  Make sure the destructor doesn't free these */        cmt.pbFormat = NULL;        cmt.cbFormat = NULL;        cmt.pUnk     = NULL;        ppMediaTypes++;        cFetched++;        cMediaTypes--;    }    if (pcFetched!=NULL) {        *pcFetched = cFetched;    }    return ( cMediaTypes==0 ? NOERROR : S_FALSE );}/* Skip over one or more entries in the enumerator */STDMETHODIMPCEnumMediaTypes::Skip(ULONG cMediaTypes){    //  If we're skipping 0 elements we're guaranteed to skip the    //  correct number of elements    if (cMediaTypes == 0) {        return S_OK;    }    /* Check we are still in sync with the pin */    if (AreWeOutOfSync() == TRUE) {        return VFW_E_ENUM_OUT_OF_SYNC;    }    m_Position += cMediaTypes;    /*  See if we're over the end */    CMediaType cmt;    return S_OK == m_pPin->GetMediaType(m_Position - 1, &cmt) ? S_OK : S_FALSE;}/* Set the current position back to the start *//* Reset has 3 simple steps: * * set position to head of list * sync enumerator with object being enumerated * return S_OK */STDMETHODIMPCEnumMediaTypes::Reset(){    m_Position = 0;    // Bring the enumerator back into step with the current state.  This    // may be a noop but ensures that the enumerator will be valid on the    // next call.    m_Version = m_pPin->GetMediaTypeVersion();    return NOERROR;}//=====================================================================//=====================================================================// Implements CBasePin//=====================================================================//=====================================================================/* NOTE The implementation of this class calls the CUnknown constructor with   a NULL outer unknown pointer. This has the effect of making us a self   contained class, ie any QueryInterface, AddRef or Release calls will be   routed to the class's NonDelegatingUnknown methods. You will typically   find that the classes that do this then override one or more of these   virtual functions to provide more specialised behaviour. A good example   of this is where a class wants to keep the QueryInterface internal but   still wants its lifetime controlled by the external object *//* Constructor */static const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFFLL;   /* Maximum LONGLONG value */CBasePin::CBasePin(const TCHAR *pObjectName,           CBaseFilter *pFilter,           CCritSec *pLock,           HRESULT *phr,           LPCWSTR pName,           PIN_DIRECTION dir) :    CUnknown( pObjectName, NULL ),    m_pFilter(pFilter),    m_pLock(pLock),    m_pName(NULL),    m_Connected(NULL),    m_dir(dir),    m_bRunTimeError(FALSE),    m_pQSink(NULL),    m_TypeVersion(1),    m_tStart(),    m_tStop(MAX_TIME),

⌨️ 快捷键说明

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