amfilter.cpp.svn-base
来自「ffshow源码」· SVN-BASE 代码 · 共 2,432 行 · 第 1/5 页
SVN-BASE
2,432 行
STDMETHODIMPCBaseFilter::Stop(){ CAutoLock cObjectLock(m_pLock); HRESULT hr = NOERROR; // notify all pins of the state change if (m_State != State_Stopped) { int cPins = GetPinCount(); for (int c = 0; c < cPins; c++) { CBasePin *pPin = GetPin(c); // Disconnected pins are not activated - this saves pins worrying // about this state themselves. We ignore the return code to make // sure everyone is inactivated regardless. The base input pin // class can return an error if it has no allocator but Stop can // be used to resync the graph state after something has gone bad if (pPin->IsConnected()) { HRESULT hrTmp = pPin->Inactive(); if (FAILED(hrTmp) && SUCCEEDED(hr)) { hr = hrTmp; } } } } m_State = State_Stopped; return hr;}// override CBaseMediaFilter Pause method to activate any pins// this filter has (also called from Run)STDMETHODIMPCBaseFilter::Pause(){ CAutoLock cObjectLock(m_pLock); // notify all pins of the change to active state if (m_State == State_Stopped) { int cPins = GetPinCount(); for (int c = 0; c < cPins; c++) { CBasePin *pPin = GetPin(c); // Disconnected pins are not activated - this saves pins // worrying about this state themselves if (pPin->IsConnected()) { HRESULT hr = pPin->Active(); if (FAILED(hr)) { return hr; } } } } 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 CBaseFilter::StreamTime and compare that against// the sample timestamp.STDMETHODIMPCBaseFilter::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; } } // notify all pins of the change to active state if (m_State != State_Running) { int cPins = GetPinCount(); for (int c = 0; c < cPins; c++) { CBasePin *pPin = GetPin(c); // Disconnected pins are not activated - this saves pins // worrying about this state themselves if (pPin->IsConnected()) { HRESULT hr = pPin->Run(tStart); 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 nowHRESULTCBaseFilter::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;}/* Create an enumerator for the pins attached to this filter */STDMETHODIMPCBaseFilter::EnumPins(IEnumPins **ppEnum){ CheckPointer(ppEnum,E_POINTER); ValidateReadWritePtr(ppEnum,sizeof(IEnumPins *)); /* Create a new ref counted enumerator */ *ppEnum = new CEnumPins(this, NULL); return *ppEnum == NULL ? E_OUTOFMEMORY : NOERROR;}// default behaviour of FindPin is to assume pins are named// by their pin namesSTDMETHODIMPCBaseFilter::FindPin( LPCWSTR Id, IPin ** ppPin){ CheckPointer(ppPin,E_POINTER); ValidateReadWritePtr(ppPin,sizeof(IPin *)); // We're going to search the pin list so maintain integrity CAutoLock lck(m_pLock); int iCount = GetPinCount(); for (int i = 0; i < iCount; i++) { CBasePin *pPin = GetPin(i); ASSERT(pPin != NULL); if (0 == lstrcmpW(pPin->Name(), Id)) { // Found one that matches // // AddRef() and return it *ppPin = pPin; pPin->AddRef(); return S_OK; } } *ppPin = NULL; return VFW_E_NOT_FOUND;}/* Return information about this filter */STDMETHODIMPCBaseFilter::QueryFilterInfo(FILTER_INFO * pInfo){ CheckPointer(pInfo,E_POINTER); ValidateReadWritePtr(pInfo,sizeof(FILTER_INFO)); if (m_pName) { lstrcpynW(pInfo->achName, m_pName, sizeof(pInfo->achName)/sizeof(WCHAR)); } else { pInfo->achName[0] = L'\0'; } pInfo->pGraph = m_pGraph; if (m_pGraph) m_pGraph->AddRef(); return NOERROR;}/* Provide the filter with a filter graph */STDMETHODIMPCBaseFilter::JoinFilterGraph( IFilterGraph * pGraph, LPCWSTR pName){ CAutoLock cObjectLock(m_pLock); // NOTE: we no longer hold references on the graph (m_pGraph, m_pSink) m_pGraph = pGraph; if (m_pGraph) { HRESULT hr = m_pGraph->QueryInterface(IID_IMediaEventSink, (void**) &m_pSink); if (FAILED(hr)) { ASSERT(m_pSink == NULL); } else m_pSink->Release(); // we do NOT keep a reference on it. } else { // if graph pointer is null, then we should // also release the IMediaEventSink on the same object - we don't // refcount it, so just set it to null m_pSink = NULL; } if (m_pName) { delete[] m_pName; m_pName = NULL; } if (pName) { DWORD nameLen = lstrlenW(pName)+1; m_pName = new WCHAR[nameLen]; if (m_pName) { CopyMemory(m_pName, pName, nameLen*sizeof(WCHAR)); } else { // !!! error here? ASSERT(FALSE); } } return NOERROR;}// return a Vendor information string. Optional - may return E_NOTIMPL.// memory returned should be freed using CoTaskMemFree// default implementation returns E_NOTIMPLSTDMETHODIMPCBaseFilter::QueryVendorInfo( LPWSTR* pVendorInfo){ UNREFERENCED_PARAMETER(pVendorInfo); return E_NOTIMPL;}// send an event notification to the filter graph if we know about it.// returns S_OK if delivered, S_FALSE if the filter graph does not sink// events, or an error otherwise.HRESULTCBaseFilter::NotifyEvent( long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2){ // Snapshot so we don't have to lock up IMediaEventSink *pSink = m_pSink; if (pSink) { if (EC_COMPLETE == EventCode) { EventParam2 = (LONG_PTR)(IBaseFilter*)this; } return pSink->Notify(EventCode, EventParam1, EventParam2); } else { return E_NOTIMPL; }}// Request reconnect// pPin is the pin to reconnect// pmt is the type to reconnect with - can be NULL// Calls ReconnectEx on the filter graphHRESULTCBaseFilter::ReconnectPin( IPin *pPin, AM_MEDIA_TYPE const *pmt){ IFilterGraph2 *pGraph2; if (m_pGraph != NULL) { HRESULT hr = m_pGraph->QueryInterface(IID_IFilterGraph2, (void **)&pGraph2); if (SUCCEEDED(hr)) { hr = pGraph2->ReconnectEx(pPin, pmt); pGraph2->Release(); return hr; } else { return m_pGraph->Reconnect(pPin); } } else { return E_NOINTERFACE; }}/* This is the same idea as the media type version does for type enumeration on pins but for the list of pins available. So if the list of pins you provide changes dynamically then either override this virtual function to provide the version number, or more simply call IncrementPinVersion */LONG CBaseFilter::GetPinVersion(){ return m_PinVersion;}/* Increment the current pin version cookie */void CBaseFilter::IncrementPinVersion(){ InterlockedIncrement(&m_PinVersion);}/* register filter */STDMETHODIMP CBaseFilter::Register(){ // get setup data, if it exists // LPAMOVIESETUP_FILTER psetupdata = GetSetupData(); // check we've got data // if( NULL == psetupdata ) return S_FALSE; // init is ref counted so call just in case // we're being called cold. // HRESULT hr = CoInitialize( (LPVOID)NULL ); ASSERT( SUCCEEDED(hr) ); // get hold of IFilterMapper // IFilterMapper *pIFM; hr = CoCreateInstance( CLSID_FilterMapper , NULL , CLSCTX_INPROC_SERVER , IID_IFilterMapper , (void **)&pIFM ); if( SUCCEEDED(hr) ) { hr = AMovieSetupRegisterFilter( psetupdata, pIFM, TRUE ); pIFM->Release(); } // and clear up // CoFreeUnusedLibraries(); CoUninitialize(); return NOERROR;}/* unregister filter */STDMETHODIMP CBaseFilter::Unregister(){ // get setup data, if it exists // LPAMOVIESETUP_FILTER psetupdata = GetSetupData(); // check we've got data // if( NULL == psetupdata ) return S_FALSE; // OLE init is ref counted so call // just in case we're being called cold. // HRESULT hr = CoInitialize( (LPVOID)NULL ); ASSERT( SUCCEEDED(hr) ); // get hold of IFilterMapper // IFilterMapper *pIFM; hr = CoCreateInstance( CLSID_FilterMapper , NULL , CLSCTX_INPROC_SERVER , IID_IFilterMapper , (void **)&pIFM ); if( SUCCEEDED(hr) ) { hr = AMovieSetupRegisterFilter( psetupdata, pIFM, FALSE ); // release interface // pIFM->Release(); } // clear up // CoFreeUnusedLibraries(); CoUninitialize(); // handle one acceptable "error" - that // of filter not being registered! // (couldn't find a suitable #define'd // name for the error!) // if( 0x80070002 == hr) return NOERROR; else return hr;}//=====================================================================//=====================================================================// Implements CEnumPins//=====================================================================//=====================================================================CEnumPins::CEnumPins(CBaseFilter *pFilter, CEnumPins *pEnumPins) : m_Position(0), m_PinCount(0), m_pFilter(pFilter), m_cRef(1), // Already ref counted m_PinCache(NAME("Pin Cache")){#ifdef DEBUG m_dwCookie = DbgRegisterObjectCreation("CEnumPins", 0);#endif /* We must be owned by a filter derived from CBaseFilter */ ASSERT(pFilter != NULL); /* Hold a reference count on our filter */ m_pFilter->AddRef(); /* Are we creating a new enumerator */ if (pEnumPins == NULL) { m_Version = m_pFilter->GetPinVersion(); m_PinCount = m_pFilter->GetPinCount(); } else { ASSERT(m_Position <= m_PinCount); m_Position = pEnumPins->m_Position; m_PinCount = pEnumPins->m_PinCount; m_Version = pEnumPins->m_Version; m_PinCache.AddTail(&(pEnumPins->m_PinCache)); }}/* Destructor releases the reference count on our filter NOTE since we hold a reference count on the filter who created us we know it is safe to release it, no access can be made to it afterwards though as we have just caused the last reference count to go and the object to be deleted */CEnumPins::~CEnumPins(){ m_pFilter->Release();#ifdef DEBUG DbgRegisterObjectDestruction(m_dwCookie);#endif}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?