00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include "bufferfilter.h"
00024 #include "..\..\..\DSUtil\DSUtil.h"
00025
00026 #ifdef REGISTER_FILTER
00027
00028 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00029 {
00030 {&MEDIATYPE_NULL, &MEDIASUBTYPE_NULL},
00031 };
00032
00033 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00034 {
00035 {&MEDIATYPE_NULL, &MEDIASUBTYPE_NULL},
00036 };
00037
00038 const AMOVIESETUP_PIN sudpPins[] =
00039 {
00040 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00041 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00042 };
00043
00044 const AMOVIESETUP_FILTER sudFilter[] =
00045 {
00046 {&__uuidof(CBufferFilter), L"Buffer Filter", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
00047 };
00048
00049 CFactoryTemplate g_Templates[] =
00050 {
00051 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CBufferFilter>, NULL, &sudFilter[0]}
00052 };
00053
00054 int g_cTemplates = countof(g_Templates);
00055
00056 STDAPI DllRegisterServer()
00057 {
00058 return AMovieDllRegisterServer2(TRUE);
00059 }
00060
00061 STDAPI DllUnregisterServer()
00062 {
00063 return AMovieDllRegisterServer2(FALSE);
00064 }
00065
00066 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00067
00068 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00069 {
00070 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00071 }
00072
00073 #endif
00074
00075
00076
00077
00078
00079 CBufferFilter::CBufferFilter(LPUNKNOWN lpunk, HRESULT* phr)
00080 : CTransformFilter(NAME("CBufferFilter"), lpunk, __uuidof(this))
00081 , m_nSamplesToBuffer(2)
00082 {
00083 HRESULT hr = S_OK;
00084
00085 do
00086 {
00087 if(!(m_pInput = new CTransformInputPin(NAME("Transform input pin"), this, &hr, L"In"))) hr = E_OUTOFMEMORY;
00088 if(FAILED(hr)) break;
00089
00090 if(!(m_pOutput = new CBufferFilterOutputPin(this, &hr))) hr = E_OUTOFMEMORY;
00091 if(FAILED(hr)) {delete m_pInput, m_pInput = NULL; break;}
00092 }
00093 while(false);
00094
00095 if(phr) *phr = hr;
00096 }
00097
00098 CBufferFilter::~CBufferFilter()
00099 {
00100 }
00101
00102 STDMETHODIMP CBufferFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00103 {
00104 return
00105 QI(IBufferFilter)
00106 __super::NonDelegatingQueryInterface(riid, ppv);
00107 }
00108
00109
00110
00111 STDMETHODIMP CBufferFilter::SetBuffers(int nBuffers)
00112 {
00113 if(!m_pOutput)
00114 return E_FAIL;
00115
00116 if(m_pOutput->IsConnected())
00117 return VFW_E_ALREADY_CONNECTED;
00118
00119 m_nSamplesToBuffer = nBuffers;
00120
00121 return S_OK;
00122 }
00123
00124 STDMETHODIMP_(int) CBufferFilter::GetBuffers()
00125 {
00126 return(m_nSamplesToBuffer);
00127 }
00128
00129 STDMETHODIMP_(int) CBufferFilter::GetFreeBuffers()
00130 {
00131 CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
00132 return(pPin && pPin->m_pOutputQueue ? (m_nSamplesToBuffer - pPin->m_pOutputQueue->GetQueueCount()) : 0);
00133 }
00134
00135 STDMETHODIMP CBufferFilter::SetPriority(DWORD dwPriority)
00136 {
00137 CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
00138 return(pPin && pPin->m_pOutputQueue ? (pPin->m_pOutputQueue->SetPriority(dwPriority) ? S_OK : E_FAIL) : E_UNEXPECTED);
00139 }
00140
00141
00142
00143 HRESULT CBufferFilter::Receive(IMediaSample* pSample)
00144 {
00145
00146 AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
00147 if(pProps->dwStreamId != AM_STREAM_MEDIA)
00148 return m_pOutput->Deliver(pSample);
00149
00150 HRESULT hr;
00151 ASSERT(pSample);
00152 IMediaSample* pOutSample;
00153
00154 ASSERT(m_pOutput != NULL);
00155
00156
00157 hr = InitializeOutputSample(pSample, &pOutSample);
00158
00159 if(FAILED(hr))
00160 return hr;
00161
00162
00163 MSR_START(m_idTransform);
00164
00165
00166
00167 hr = Transform(pSample, pOutSample);
00168
00169
00170 MSR_STOP(m_idTransform);
00171
00172 if(FAILED(hr)) {
00173 DbgLog((LOG_TRACE,1,TEXT("Error from transform")));
00174 }
00175 else {
00176
00177
00178
00179 if(hr == NOERROR) {
00180 hr = m_pOutput->Deliver(pOutSample);
00181 m_bSampleSkipped = FALSE;
00182 }
00183 else {
00184
00185
00186
00187
00188 if(S_FALSE == hr) {
00189
00190
00191
00192
00193 pOutSample->Release();
00194 m_bSampleSkipped = TRUE;
00195 if(!m_bQualityChanged) {
00196 NotifyEvent(EC_QUALITY_CHANGE,0,0);
00197 m_bQualityChanged = TRUE;
00198 }
00199 return NOERROR;
00200 }
00201 }
00202 }
00203
00204
00205
00206 pOutSample->Release();
00207
00208 return hr;
00209 }
00210
00211 HRESULT CBufferFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
00212 {
00213 BYTE* pDataIn = NULL;
00214 BYTE* pDataOut = NULL;
00215
00216 pIn->GetPointer(&pDataIn);
00217 pOut->GetPointer(&pDataOut);
00218
00219 long len = pIn->GetActualDataLength();
00220 long size = pOut->GetSize();
00221
00222 if(!pDataIn || !pDataOut || len > size || len <= 0) return S_FALSE;
00223
00224 memcpy(pDataOut, pDataIn, min(len, size));
00225
00226 pOut->SetActualDataLength(min(len, size));
00227
00228 return S_OK;
00229 }
00230
00231 HRESULT CBufferFilter::CheckInputType(const CMediaType* mtIn)
00232 {
00233 return S_OK;
00234 }
00235
00236 HRESULT CBufferFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00237 {
00238 return mtIn->MatchesPartial(mtOut) ? S_OK : VFW_E_TYPE_NOT_ACCEPTED;
00239 }
00240
00241 HRESULT CBufferFilter::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
00242 {
00243 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00244
00245 CComPtr<IMemAllocator> pAllocatorIn;
00246 m_pInput->GetAllocator(&pAllocatorIn);
00247 if(!pAllocatorIn) return E_UNEXPECTED;
00248
00249 pAllocatorIn->GetProperties(pProperties);
00250
00251 pProperties->cBuffers = max(m_nSamplesToBuffer, pProperties->cBuffers);
00252
00253 HRESULT hr;
00254 ALLOCATOR_PROPERTIES Actual;
00255 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
00256 return hr;
00257
00258 return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
00259 ? E_FAIL
00260 : NOERROR);
00261 }
00262
00263 HRESULT CBufferFilter::GetMediaType(int iPosition, CMediaType* pMediaType)
00264 {
00265 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00266
00267
00268 if(iPosition < 0) return E_INVALIDARG;
00269 if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
00270
00271 CopyMediaType(pMediaType, &m_pInput->CurrentMediaType());
00272
00273 return S_OK;
00274 }
00275
00276 HRESULT CBufferFilter::StopStreaming()
00277 {
00278 CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
00279 if(m_pInput && pPin && pPin->m_pOutputQueue)
00280 {
00281 while(!m_pInput->IsFlushing() && pPin->m_pOutputQueue->GetQueueCount() > 0)
00282 Sleep(50);
00283 }
00284
00285 return __super::StopStreaming();
00286 }
00287
00288
00289
00290
00291
00292 CBufferFilterOutputPin::CBufferFilterOutputPin(CTransformFilter* pFilter, HRESULT* phr)
00293 : CTransformOutputPin(NAME("CBufferFilterOutputPin"), pFilter, phr, L"Out")
00294 {
00295 }
00296
00297 HRESULT CBufferFilterOutputPin::Active()
00298 {
00299 CAutoLock lock_it(m_pLock);
00300
00301 if(m_Connected && !m_pOutputQueue)
00302 {
00303 HRESULT hr = NOERROR;
00304
00305 m_pOutputQueue.Attach(new CBufferFilterOutputQueue(m_Connected, &hr));
00306 if(!m_pOutputQueue) hr = E_OUTOFMEMORY;
00307
00308 if(FAILED(hr))
00309 {
00310 m_pOutputQueue.Free();
00311 return hr;
00312 }
00313 }
00314
00315 return __super::Active();
00316 }
00317
00318 HRESULT CBufferFilterOutputPin::Inactive()
00319 {
00320 CAutoLock lock_it(m_pLock);
00321 m_pOutputQueue.Free();
00322 return __super::Inactive();
00323 }
00324
00325 HRESULT CBufferFilterOutputPin::Deliver(IMediaSample* pMediaSample)
00326 {
00327 if(!m_pOutputQueue) return NOERROR;
00328 pMediaSample->AddRef();
00329 return m_pOutputQueue->Receive(pMediaSample);
00330 }
00331
00332 #define CallQueue(call) \
00333 if(!m_pOutputQueue) return NOERROR; \
00334 m_pOutputQueue->##call; \
00335 return NOERROR; \
00336
00337 HRESULT CBufferFilterOutputPin::DeliverEndOfStream()
00338 {
00339 CallQueue(EOS());
00340 }
00341
00342 HRESULT CBufferFilterOutputPin::DeliverBeginFlush()
00343 {
00344 CallQueue(BeginFlush());
00345 }
00346
00347 HRESULT CBufferFilterOutputPin::DeliverEndFlush()
00348 {
00349 CallQueue(EndFlush());
00350 }
00351
00352 HRESULT CBufferFilterOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
00353 {
00354 CallQueue(NewSegment(tStart, tStop, dRate));
00355 }