BufferFilter.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "bufferfilter.h"
  23. #include "......DSUtilDSUtil.h"
  24. #ifdef REGISTER_FILTER
  25. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  26. {
  27. {&MEDIATYPE_NULL, &MEDIASUBTYPE_NULL},
  28. };
  29. const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
  30. {
  31. {&MEDIATYPE_NULL, &MEDIASUBTYPE_NULL},
  32. };
  33. const AMOVIESETUP_PIN sudpPins[] =
  34. {
  35.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
  36.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
  37. };
  38. const AMOVIESETUP_FILTER sudFilter[] =
  39. {
  40. {&__uuidof(CBufferFilter), L"Buffer Filter", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
  41. };
  42. CFactoryTemplate g_Templates[] =
  43. {
  44. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CBufferFilter>, NULL, &sudFilter[0]}
  45. };
  46. int g_cTemplates = countof(g_Templates);
  47. STDAPI DllRegisterServer()
  48. {
  49. return AMovieDllRegisterServer2(TRUE);
  50. }
  51. STDAPI DllUnregisterServer()
  52. {
  53. return AMovieDllRegisterServer2(FALSE);
  54. }
  55. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  56. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  57. {
  58.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  59. }
  60. #endif
  61. //
  62. // CBufferFilter
  63. //
  64. CBufferFilter::CBufferFilter(LPUNKNOWN lpunk, HRESULT* phr) 
  65. : CTransformFilter(NAME("CBufferFilter"), lpunk, __uuidof(this))
  66. , m_nSamplesToBuffer(2)
  67. {
  68. HRESULT hr = S_OK;
  69. do
  70. {
  71. if(!(m_pInput = new CTransformInputPin(NAME("Transform input pin"), this, &hr, L"In"))) hr = E_OUTOFMEMORY;
  72. if(FAILED(hr)) break;
  73. if(!(m_pOutput = new CBufferFilterOutputPin(this, &hr))) hr = E_OUTOFMEMORY;
  74. if(FAILED(hr)) {delete m_pInput, m_pInput = NULL; break;}
  75. }
  76. while(false);
  77. if(phr) *phr = hr;
  78. }
  79. CBufferFilter::~CBufferFilter()
  80. {
  81. }
  82. STDMETHODIMP CBufferFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  83. {
  84. return
  85. QI(IBufferFilter)
  86. __super::NonDelegatingQueryInterface(riid, ppv);
  87. }
  88. // IBufferFilter
  89. STDMETHODIMP CBufferFilter::SetBuffers(int nBuffers)
  90. {
  91. if(!m_pOutput)
  92. return E_FAIL;
  93. if(m_pOutput->IsConnected()) // TODO: allow "on-the-fly" changes
  94. return VFW_E_ALREADY_CONNECTED;
  95. m_nSamplesToBuffer = nBuffers;
  96. return S_OK;
  97. }
  98. STDMETHODIMP_(int) CBufferFilter::GetBuffers()
  99. {
  100. return(m_nSamplesToBuffer);
  101. }
  102. STDMETHODIMP_(int) CBufferFilter::GetFreeBuffers()
  103. {
  104. CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
  105. return(pPin && pPin->m_pOutputQueue ? (m_nSamplesToBuffer - pPin->m_pOutputQueue->GetQueueCount()) : 0);
  106. }
  107. STDMETHODIMP CBufferFilter::SetPriority(DWORD dwPriority)
  108. {
  109. CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
  110. return(pPin && pPin->m_pOutputQueue ? (pPin->m_pOutputQueue->SetPriority(dwPriority) ? S_OK : E_FAIL) : E_UNEXPECTED);
  111. }
  112. //
  113. HRESULT CBufferFilter::Receive(IMediaSample* pSample)
  114. {
  115. /*  Check for other streams and pass them on */
  116. AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
  117. if(pProps->dwStreamId != AM_STREAM_MEDIA)
  118. return m_pOutput->Deliver(pSample);
  119. HRESULT hr;
  120. ASSERT(pSample);
  121. IMediaSample* pOutSample;
  122. ASSERT(m_pOutput != NULL);
  123. // Set up the output sample
  124. hr = InitializeOutputSample(pSample, &pOutSample);
  125. if(FAILED(hr))
  126. return hr;
  127. // Start timing the transform (if PERF is defined)
  128. MSR_START(m_idTransform);
  129. // have the derived class transform the data
  130. hr = Transform(pSample, pOutSample);
  131. // Stop the clock and log it (if PERF is defined)
  132. MSR_STOP(m_idTransform);
  133. if(FAILED(hr)) {
  134. DbgLog((LOG_TRACE,1,TEXT("Error from transform")));
  135. }
  136. else {
  137. // the Transform() function can return S_FALSE to indicate that the
  138. // sample should not be delivered; we only deliver the sample if it's
  139. // really S_OK (same as NOERROR, of course.)
  140. if(hr == NOERROR) {
  141. hr = m_pOutput->Deliver(pOutSample);
  142. m_bSampleSkipped = FALSE;   // last thing no longer dropped
  143. }
  144. else {
  145. // S_FALSE returned from Transform is a PRIVATE agreement
  146. // We should return NOERROR from Receive() in this cause because returning S_FALSE
  147. // from Receive() means that this is the end of the stream and no more data should
  148. // be sent.
  149. if(S_FALSE == hr) {
  150. //  Release the sample before calling notify to avoid
  151. //  deadlocks if the sample holds a lock on the system
  152. //  such as DirectDraw buffers do
  153. pOutSample->Release();
  154. m_bSampleSkipped = TRUE;
  155. if(!m_bQualityChanged) {
  156. NotifyEvent(EC_QUALITY_CHANGE,0,0);
  157. m_bQualityChanged = TRUE;
  158. }
  159. return NOERROR;
  160. }
  161. }
  162. }
  163. // release the output buffer. If the connected pin still needs it,
  164. // it will have addrefed it itself.
  165. pOutSample->Release();
  166. return hr;
  167. }
  168. HRESULT CBufferFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
  169. {
  170. BYTE* pDataIn = NULL;
  171. BYTE* pDataOut = NULL;
  172. pIn->GetPointer(&pDataIn);
  173. pOut->GetPointer(&pDataOut);
  174. long len = pIn->GetActualDataLength();
  175. long size = pOut->GetSize();
  176. if(!pDataIn || !pDataOut || len > size || len <= 0) return S_FALSE;
  177. memcpy(pDataOut, pDataIn, min(len, size));
  178. pOut->SetActualDataLength(min(len, size));
  179. return S_OK;
  180. }
  181. HRESULT CBufferFilter::CheckInputType(const CMediaType* mtIn)
  182. {
  183. return S_OK;
  184. }
  185. HRESULT CBufferFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  186. {
  187. return mtIn->MatchesPartial(mtOut) ? S_OK : VFW_E_TYPE_NOT_ACCEPTED;
  188. }
  189. HRESULT CBufferFilter::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  190. {
  191. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  192. CComPtr<IMemAllocator> pAllocatorIn;
  193. m_pInput->GetAllocator(&pAllocatorIn);
  194. if(!pAllocatorIn) return E_UNEXPECTED;
  195. pAllocatorIn->GetProperties(pProperties);
  196. pProperties->cBuffers = max(m_nSamplesToBuffer, pProperties->cBuffers);
  197. HRESULT hr;
  198. ALLOCATOR_PROPERTIES Actual;
  199.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  200. return hr;
  201.     return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  202. ? E_FAIL
  203. : NOERROR);
  204. }
  205. HRESULT CBufferFilter::GetMediaType(int iPosition, CMediaType* pMediaType)
  206. {
  207.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  208. // TODO: offer all input types from upstream and allow reconnection at least in stopped state
  209. if(iPosition < 0) return E_INVALIDARG;
  210.     if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
  211. CopyMediaType(pMediaType, &m_pInput->CurrentMediaType());
  212. return S_OK;
  213. }
  214. HRESULT CBufferFilter::StopStreaming()
  215. {
  216. CBufferFilterOutputPin* pPin = (CBufferFilterOutputPin*)m_pOutput;
  217. if(m_pInput && pPin && pPin->m_pOutputQueue)
  218. {
  219. while(!m_pInput->IsFlushing() && pPin->m_pOutputQueue->GetQueueCount() > 0) 
  220. Sleep(50);
  221. }
  222. return __super::StopStreaming();
  223. }
  224. //
  225. // CBufferFilterOutputPin
  226. //
  227. CBufferFilterOutputPin::CBufferFilterOutputPin(CTransformFilter* pFilter, HRESULT* phr)
  228. : CTransformOutputPin(NAME("CBufferFilterOutputPin"), pFilter, phr, L"Out")
  229. {
  230. }
  231. HRESULT CBufferFilterOutputPin::Active()
  232. {
  233. CAutoLock lock_it(m_pLock);
  234. if(m_Connected && !m_pOutputQueue)
  235. {
  236. HRESULT hr = NOERROR;
  237. m_pOutputQueue.Attach(new CBufferFilterOutputQueue(m_Connected, &hr));
  238. if(!m_pOutputQueue) hr = E_OUTOFMEMORY;
  239. if(FAILED(hr))
  240. {
  241. m_pOutputQueue.Free();
  242. return hr;
  243. }
  244. }
  245. return __super::Active();
  246. }
  247. HRESULT CBufferFilterOutputPin::Inactive()
  248. {
  249. CAutoLock lock_it(m_pLock);
  250. m_pOutputQueue.Free();
  251. return __super::Inactive();
  252. }
  253. HRESULT CBufferFilterOutputPin::Deliver(IMediaSample* pMediaSample)
  254. {
  255. if(!m_pOutputQueue) return NOERROR;
  256. pMediaSample->AddRef();
  257. return m_pOutputQueue->Receive(pMediaSample);
  258. }
  259. #define CallQueue(call) 
  260. if(!m_pOutputQueue) return NOERROR; 
  261. m_pOutputQueue->##call; 
  262. return NOERROR; 
  263. HRESULT CBufferFilterOutputPin::DeliverEndOfStream()
  264. {
  265. CallQueue(EOS());
  266. }
  267. HRESULT CBufferFilterOutputPin::DeliverBeginFlush()
  268. {
  269. CallQueue(BeginFlush());
  270. }
  271. HRESULT CBufferFilterOutputPin::DeliverEndFlush()
  272. {
  273. CallQueue(EndFlush());
  274. }
  275. HRESULT CBufferFilterOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  276. {
  277. CallQueue(NewSegment(tStart, tStop, dRate));
  278. }