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 + -
显示快捷键?