BufferFilter.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:9k
- /*
- * Copyright (C) 2003-2005 Gabest
- * http://www.gabest.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
- #include "stdafx.h"
- #include "bufferfilter.h"
- #include "......DSUtilDSUtil.h"
- #ifdef REGISTER_FILTER
- const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
- {
- {&MEDIATYPE_NULL, &MEDIASUBTYPE_NULL},
- };
- const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
- {
- {&MEDIATYPE_NULL, &MEDIASUBTYPE_NULL},
- };
- const AMOVIESETUP_PIN sudpPins[] =
- {
- {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
- {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
- };
- const AMOVIESETUP_FILTER sudFilter[] =
- {
- {&__uuidof(CBufferFilter), L"Buffer Filter", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
- };
- CFactoryTemplate g_Templates[] =
- {
- {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CBufferFilter>, NULL, &sudFilter[0]}
- };
- int g_cTemplates = countof(g_Templates);
- STDAPI DllRegisterServer()
- {
- return AMovieDllRegisterServer2(TRUE);
- }
- STDAPI DllUnregisterServer()
- {
- return AMovieDllRegisterServer2(FALSE);
- }
- extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
- BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
- {
- return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
- }
- #endif
- //
- // CBufferFilter
- //
- CBufferFilter::CBufferFilter(LPUNKNOWN lpunk, HRESULT* phr)
- : CTransformFilter(NAME("CBufferFilter"), lpunk, __uuidof(this))
- , m_nSamplesToBuffer(2)
- {
- HRESULT hr = S_OK;
- do
- {
- if(!(m_pInput = new CTransformInputPin(NAME("Transform input pin"), this, &hr, L"In"))) hr = E_OUTOFMEMORY;
- if(FAILED(hr)) break;
- if(!(m_pOutput = new CBufferFilterOutputPin(this, &hr))) hr = E_OUTOFMEMORY;
- if(FAILED(hr)) {delete m_pInput, m_pInput = NULL; break;}
- }
- while(false);
- if(phr) *phr = hr;
- }
- CBufferFilter::~CBufferFilter()
- {
- }
- STDMETHODIMP CBufferFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
- {
- return
- QI(IBufferFilter)
- __super::NonDelegatingQueryInterface(riid, ppv);
- }
- // IBufferFilter
- STDMETHODIMP CBufferFilter::SetBuffers(int nBuffers)
- {
- if(!m_pOutput)
- return E_FAIL;
- if(m_pOutput->IsConnected()) // TODO: allow "on-the-fly" changes
- return VFW_E_ALREADY_CONNECTED;
- m_nSamplesToBuffer = nBuffers;
- return S_OK;
- }
- STDMETHODIMP_(int) CBufferFilter::GetBuffers()
- {
- return(m_nSamplesToBuffer);
- }
- STDMETHODIMP_(int) CBufferFilter::GetFreeBuffers()
- {
- CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
- return(pPin && pPin->m_pOutputQueue ? (m_nSamplesToBuffer - pPin->m_pOutputQueue->GetQueueCount()) : 0);
- }
- STDMETHODIMP CBufferFilter::SetPriority(DWORD dwPriority)
- {
- CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
- return(pPin && pPin->m_pOutputQueue ? (pPin->m_pOutputQueue->SetPriority(dwPriority) ? S_OK : E_FAIL) : E_UNEXPECTED);
- }
- //
- HRESULT CBufferFilter::Receive(IMediaSample* pSample)
- {
- /* Check for other streams and pass them on */
- AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
- if(pProps->dwStreamId != AM_STREAM_MEDIA)
- return m_pOutput->Deliver(pSample);
- HRESULT hr;
- ASSERT(pSample);
- IMediaSample* pOutSample;
- ASSERT(m_pOutput != NULL);
- // Set up the output sample
- hr = InitializeOutputSample(pSample, &pOutSample);
- if(FAILED(hr))
- return hr;
- // Start timing the transform (if PERF is defined)
- MSR_START(m_idTransform);
- // have the derived class transform the data
- hr = Transform(pSample, pOutSample);
- // Stop the clock and log it (if PERF is defined)
- MSR_STOP(m_idTransform);
- if(FAILED(hr)) {
- DbgLog((LOG_TRACE,1,TEXT("Error from transform")));
- }
- else {
- // the Transform() function can return S_FALSE to indicate that the
- // sample should not be delivered; we only deliver the sample if it's
- // really S_OK (same as NOERROR, of course.)
- if(hr == NOERROR) {
- hr = m_pOutput->Deliver(pOutSample);
- m_bSampleSkipped = FALSE; // last thing no longer dropped
- }
- else {
- // S_FALSE returned from Transform is a PRIVATE agreement
- // We should return NOERROR from Receive() in this cause because returning S_FALSE
- // from Receive() means that this is the end of the stream and no more data should
- // be sent.
- if(S_FALSE == hr) {
- // Release the sample before calling notify to avoid
- // deadlocks if the sample holds a lock on the system
- // such as DirectDraw buffers do
- pOutSample->Release();
- m_bSampleSkipped = TRUE;
- if(!m_bQualityChanged) {
- NotifyEvent(EC_QUALITY_CHANGE,0,0);
- m_bQualityChanged = TRUE;
- }
- return NOERROR;
- }
- }
- }
- // release the output buffer. If the connected pin still needs it,
- // it will have addrefed it itself.
- pOutSample->Release();
- return hr;
- }
- HRESULT CBufferFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
- {
- BYTE* pDataIn = NULL;
- BYTE* pDataOut = NULL;
- pIn->GetPointer(&pDataIn);
- pOut->GetPointer(&pDataOut);
- long len = pIn->GetActualDataLength();
- long size = pOut->GetSize();
- if(!pDataIn || !pDataOut || len > size || len <= 0) return S_FALSE;
- memcpy(pDataOut, pDataIn, min(len, size));
-
- pOut->SetActualDataLength(min(len, size));
- return S_OK;
- }
- HRESULT CBufferFilter::CheckInputType(const CMediaType* mtIn)
- {
- return S_OK;
- }
- HRESULT CBufferFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
- {
- return mtIn->MatchesPartial(mtOut) ? S_OK : VFW_E_TYPE_NOT_ACCEPTED;
- }
- HRESULT CBufferFilter::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
- {
- if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
- CComPtr<IMemAllocator> pAllocatorIn;
- m_pInput->GetAllocator(&pAllocatorIn);
- if(!pAllocatorIn) return E_UNEXPECTED;
- pAllocatorIn->GetProperties(pProperties);
- pProperties->cBuffers = max(m_nSamplesToBuffer, pProperties->cBuffers);
- HRESULT hr;
- ALLOCATOR_PROPERTIES Actual;
- if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
- return hr;
- return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
- ? E_FAIL
- : NOERROR);
- }
- HRESULT CBufferFilter::GetMediaType(int iPosition, CMediaType* pMediaType)
- {
- if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
- // TODO: offer all input types from upstream and allow reconnection at least in stopped state
- if(iPosition < 0) return E_INVALIDARG;
- if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
- CopyMediaType(pMediaType, &m_pInput->CurrentMediaType());
- return S_OK;
- }
- HRESULT CBufferFilter::StopStreaming()
- {
- CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
- if(m_pInput && pPin && pPin->m_pOutputQueue)
- {
- while(!m_pInput->IsFlushing() && pPin->m_pOutputQueue->GetQueueCount() > 0)
- Sleep(50);
- }
- return __super::StopStreaming();
- }
- //
- // CBufferFilterOutputPin
- //
- CBufferFilterOutputPin::CBufferFilterOutputPin(CTransformFilter* pFilter, HRESULT* phr)
- : CTransformOutputPin(NAME("CBufferFilterOutputPin"), pFilter, phr, L"Out")
- {
- }
- HRESULT CBufferFilterOutputPin::Active()
- {
- CAutoLock lock_it(m_pLock);
- if(m_Connected && !m_pOutputQueue)
- {
- HRESULT hr = NOERROR;
- m_pOutputQueue.Attach(new CBufferFilterOutputQueue(m_Connected, &hr));
- if(!m_pOutputQueue) hr = E_OUTOFMEMORY;
- if(FAILED(hr))
- {
- m_pOutputQueue.Free();
- return hr;
- }
- }
- return __super::Active();
- }
- HRESULT CBufferFilterOutputPin::Inactive()
- {
- CAutoLock lock_it(m_pLock);
- m_pOutputQueue.Free();
- return __super::Inactive();
- }
- HRESULT CBufferFilterOutputPin::Deliver(IMediaSample* pMediaSample)
- {
- if(!m_pOutputQueue) return NOERROR;
- pMediaSample->AddRef();
- return m_pOutputQueue->Receive(pMediaSample);
- }
- #define CallQueue(call)
- if(!m_pOutputQueue) return NOERROR;
- m_pOutputQueue->##call;
- return NOERROR;
- HRESULT CBufferFilterOutputPin::DeliverEndOfStream()
- {
- CallQueue(EOS());
- }
- HRESULT CBufferFilterOutputPin::DeliverBeginFlush()
- {
- CallQueue(BeginFlush());
- }
- HRESULT CBufferFilterOutputPin::DeliverEndFlush()
- {
- CallQueue(EndFlush());
- }
- HRESULT CBufferFilterOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
- {
- CallQueue(NewSegment(tStart, tStop, dRate));
- }