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

多媒体编程

开发平台:

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 "streamdrivethru.h"
  23. #include "......DSUtilDSUtil.h"
  24. #ifdef REGISTER_FILTER
  25. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  26. {
  27. {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
  28. };
  29. const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
  30. {
  31. {&MEDIATYPE_Stream, &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(CStreamDriveThruFilter), L"StreamDriveThru", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
  41. };
  42. CFactoryTemplate g_Templates[] =
  43. {
  44. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CStreamDriveThruFilter>, 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. // CStreamDriveThruFilter
  63. //
  64. CStreamDriveThruFilter::CStreamDriveThruFilter(LPUNKNOWN pUnk, HRESULT* phr)
  65. : CBaseFilter(NAME("CStreamDriveThruFilter"), pUnk, &m_csLock, __uuidof(this))
  66. , m_position(0)
  67. {
  68. if(phr) *phr = S_OK;
  69. m_pInput = new CStreamDriveThruInputPin(NAME("CStreamDriveThruInputPin"), this, &m_csLock, phr);
  70. m_pOutput = new CStreamDriveThruOutputPin(NAME("CStreamDriveThruOutputPin"), this, &m_csLock, phr);
  71. CAMThread::Create();
  72. }
  73. CStreamDriveThruFilter::~CStreamDriveThruFilter()
  74. {
  75. CAutoLock csAutoLock(&m_csLock);
  76. CAMThread::CallWorker(CMD_EXIT);
  77. CAMThread::Close();
  78. delete m_pInput;
  79. delete m_pOutput;
  80. }
  81. STDMETHODIMP CStreamDriveThruFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  82. {
  83. CheckPointer(ppv, E_POINTER);
  84. return 
  85. QI(IMediaSeeking)
  86. __super::NonDelegatingQueryInterface(riid, ppv);
  87. }
  88. #define PACKETSIZE 65536
  89. DWORD CStreamDriveThruFilter::ThreadProc()
  90. {
  91. while(1)
  92. {
  93. DWORD cmd = GetRequest();
  94. switch(cmd)
  95. {
  96. default:
  97. case CMD_EXIT: 
  98. Reply(S_OK);
  99. return 0;
  100. case CMD_STOP:
  101. Reply(S_OK);
  102. break;
  103. case CMD_PAUSE:
  104. Reply(S_OK);
  105. break;
  106. case CMD_RUN:
  107. Reply(S_OK);
  108. do
  109. {
  110. CComPtr<IAsyncReader> pAsyncReader;
  111. CComPtr<IStream> pStream;
  112. if(!m_pInput || !m_pInput->IsConnected() || FAILED(m_pInput->GetAsyncReader(&pAsyncReader))
  113. || !m_pOutput || !m_pOutput->IsConnected() || FAILED(m_pOutput->GetStream(&pStream)))
  114. break;
  115. LARGE_INTEGER li = {0};
  116. ULARGE_INTEGER uli = {0};
  117. if(FAILED(pStream->Seek(li, STREAM_SEEK_SET, NULL))
  118. || FAILED(pStream->SetSize(uli)))
  119. break;
  120. if(CComQIPtr<IFileSinkFilter2> pFSF = GetFilterFromPin(m_pOutput->GetConnected()))
  121. {
  122. pFSF->SetMode(AM_FILE_OVERWRITE);
  123. LPOLESTR pfn;
  124. if(SUCCEEDED(pFSF->GetCurFile(&pfn, NULL)))
  125. {
  126. pFSF->SetFileName(pfn, NULL);
  127. CoTaskMemFree(pfn);
  128. }
  129. }
  130. m_position = 0;
  131. BYTE buff[PACKETSIZE];
  132. do
  133. {
  134. while(!CheckRequest(&cmd))
  135. {
  136. CAutoLock csAutoLock(&m_csLock);
  137. LONGLONG total = 0, available = 0;
  138. if(FAILED(pAsyncReader->Length(&total, &available)) || m_position >= total)
  139. {
  140. cmd = CMD_STOP;
  141. break;
  142. }
  143. LONG size = (LONG)min(PACKETSIZE, total - m_position);
  144. if(FAILED(pAsyncReader->SyncRead(m_position, size, buff)))
  145. {
  146. cmd = CMD_STOP;
  147. break;
  148. }
  149. ULONG written = 0;
  150. if(FAILED(pStream->Write(buff, (ULONG)size, &written)) || (ULONG)size != written)
  151. {
  152. cmd = CMD_STOP;
  153. break;
  154. }
  155. m_position += size;
  156. }
  157. if(cmd == CMD_PAUSE)
  158. {
  159. Reply(S_OK); // reply to CMD_PAUSE
  160. while(!CheckRequest(&cmd))
  161. Sleep(50);
  162. Reply(S_OK); // reply to something
  163. }
  164. }
  165. while(cmd == CMD_RUN);
  166. uli.QuadPart = m_position;
  167. pStream->SetSize(uli);
  168. if(CComPtr<IPin> pPin = m_pOutput->GetConnected())
  169. pPin->EndOfStream();
  170. }
  171. while(false);
  172. break;
  173. }
  174. }
  175. return 0;
  176. }
  177. int CStreamDriveThruFilter::GetPinCount()
  178. {
  179. return 2;
  180. }
  181. CBasePin* CStreamDriveThruFilter::GetPin(int n)
  182. {
  183.     CAutoLock csAutoLock(&m_csLock);
  184. if(n == 0) return m_pInput;
  185. else if(n == 1) return m_pOutput;
  186.     return NULL;
  187. }
  188. STDMETHODIMP CStreamDriveThruFilter::Stop()
  189. {
  190. HRESULT hr;
  191. if(FAILED(hr = __super::Stop()))
  192. return hr;
  193. CallWorker(CMD_STOP);
  194. return S_OK;
  195. }
  196. STDMETHODIMP CStreamDriveThruFilter::Pause()
  197. {
  198. HRESULT hr;
  199. if(FAILED(hr = __super::Pause()))
  200. return hr;
  201. CallWorker(CMD_PAUSE);
  202. return S_OK;
  203. }
  204. STDMETHODIMP CStreamDriveThruFilter::Run(REFERENCE_TIME tStart)
  205. {
  206. HRESULT hr;
  207. if(FAILED(hr = __super::Run(tStart)))
  208. return hr;
  209. CallWorker(CMD_RUN);
  210. return S_OK;
  211. }
  212. // IMediaSeeking
  213. STDMETHODIMP CStreamDriveThruFilter::GetCapabilities(DWORD* pCapabilities)
  214. {
  215. return pCapabilities ? *pCapabilities = AM_SEEKING_CanGetCurrentPos|AM_SEEKING_CanGetStopPos|AM_SEEKING_CanGetDuration, S_OK : E_POINTER;
  216. }
  217. STDMETHODIMP CStreamDriveThruFilter::CheckCapabilities(DWORD* pCapabilities)
  218. {
  219. CheckPointer(pCapabilities, E_POINTER);
  220. if(*pCapabilities == 0) return S_OK;
  221. DWORD caps;
  222. GetCapabilities(&caps);
  223. DWORD caps2 = caps & *pCapabilities;
  224. return caps2 == 0 ? E_FAIL : caps2 == *pCapabilities ? S_OK : S_FALSE;
  225. }
  226. STDMETHODIMP CStreamDriveThruFilter::IsFormatSupported(const GUID* pFormat)
  227. {
  228. return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
  229. }
  230. STDMETHODIMP CStreamDriveThruFilter::QueryPreferredFormat(GUID* pFormat)
  231. {
  232. return GetTimeFormat(pFormat);
  233. }
  234. STDMETHODIMP CStreamDriveThruFilter::GetTimeFormat(GUID* pFormat)
  235. {
  236. return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;
  237. }
  238. STDMETHODIMP CStreamDriveThruFilter::IsUsingTimeFormat(const GUID* pFormat)
  239. {
  240. return IsFormatSupported(pFormat);
  241. }
  242. STDMETHODIMP CStreamDriveThruFilter::SetTimeFormat(const GUID* pFormat)
  243. {
  244. return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;
  245. }
  246. STDMETHODIMP CStreamDriveThruFilter::GetDuration(LONGLONG* pDuration)
  247. {
  248. CheckPointer(pDuration, E_POINTER);
  249. CheckPointer(m_pInput, VFW_E_NOT_CONNECTED);
  250. if(CComQIPtr<IAsyncReader> pAsyncReader = m_pInput->GetConnected())
  251. {
  252. LONGLONG total, available;
  253. if(SUCCEEDED(pAsyncReader->Length(&total, &available)))
  254. {
  255. *pDuration = total;
  256. return S_OK;
  257. }
  258. }
  259. return E_NOINTERFACE;
  260. }
  261. STDMETHODIMP CStreamDriveThruFilter::GetStopPosition(LONGLONG* pStop)
  262. {
  263. return GetDuration(pStop);
  264. }
  265. STDMETHODIMP CStreamDriveThruFilter::GetCurrentPosition(LONGLONG* pCurrent)
  266. {
  267. return pCurrent ? *pCurrent = m_position, S_OK : E_POINTER;
  268. }
  269. STDMETHODIMP CStreamDriveThruFilter::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
  270. STDMETHODIMP CStreamDriveThruFilter::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags) {return E_NOTIMPL;}
  271. STDMETHODIMP CStreamDriveThruFilter::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop) {return E_NOTIMPL;}
  272. STDMETHODIMP CStreamDriveThruFilter::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) {return E_NOTIMPL;}
  273. STDMETHODIMP CStreamDriveThruFilter::SetRate(double dRate) {return E_NOTIMPL;}
  274. STDMETHODIMP CStreamDriveThruFilter::GetRate(double* pdRate) {return E_NOTIMPL;}
  275. STDMETHODIMP CStreamDriveThruFilter::GetPreroll(LONGLONG* pllPreroll)
  276. {
  277. return pllPreroll ? *pllPreroll = 0, S_OK : E_POINTER;
  278. }
  279. //
  280. // CStreamDriveThruInputPin
  281. //
  282. CStreamDriveThruInputPin::CStreamDriveThruInputPin(TCHAR* pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  283. : CBasePin(pName, pFilter, pLock, phr, L"Input", PINDIR_INPUT)
  284. {
  285. }
  286. CStreamDriveThruInputPin::~CStreamDriveThruInputPin()
  287. {
  288. }
  289. HRESULT CStreamDriveThruInputPin::GetAsyncReader(IAsyncReader** ppAsyncReader)
  290. {
  291. CheckPointer(ppAsyncReader, E_POINTER);
  292. *ppAsyncReader = NULL;
  293. CheckPointer(m_pAsyncReader, VFW_E_NOT_CONNECTED);
  294. (*ppAsyncReader = m_pAsyncReader)->AddRef();
  295. return S_OK;
  296. }
  297. STDMETHODIMP CStreamDriveThruInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  298. {
  299. CheckPointer(ppv, E_POINTER);
  300. return 
  301. __super::NonDelegatingQueryInterface(riid, ppv);
  302. }
  303. HRESULT CStreamDriveThruInputPin::CheckMediaType(const CMediaType* pmt)
  304. {
  305. return pmt->majortype == MEDIATYPE_Stream
  306. ? S_OK
  307. : E_INVALIDARG;
  308. }
  309. HRESULT CStreamDriveThruInputPin::CheckConnect(IPin* pPin)
  310. {
  311. HRESULT hr;
  312. if(FAILED(hr = __super::CheckConnect(pPin)))
  313. return hr;
  314. if(!CComQIPtr<IAsyncReader>(pPin))
  315. return E_NOINTERFACE;
  316. return S_OK;
  317. }
  318. HRESULT CStreamDriveThruInputPin::BreakConnect()
  319. {
  320. HRESULT hr;
  321. if(FAILED(hr = __super::BreakConnect()))
  322. return hr;
  323. m_pAsyncReader.Release();
  324. return S_OK;
  325. }
  326. HRESULT CStreamDriveThruInputPin::CompleteConnect(IPin* pPin)
  327. {
  328. HRESULT hr;
  329. if(FAILED(hr = __super::CompleteConnect(pPin)))
  330. return hr;
  331. CheckPointer(pPin, E_POINTER);
  332. m_pAsyncReader = pPin;
  333. CheckPointer(m_pAsyncReader, E_NOINTERFACE);
  334. return S_OK;
  335. }
  336. STDMETHODIMP CStreamDriveThruInputPin::BeginFlush()
  337. {
  338. return E_UNEXPECTED;
  339. }
  340. STDMETHODIMP CStreamDriveThruInputPin::EndFlush()
  341. {
  342. return E_UNEXPECTED;
  343. }
  344. //
  345. // CStreamDriveThruOutputPin
  346. //
  347. CStreamDriveThruOutputPin::CStreamDriveThruOutputPin(TCHAR* pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  348. : CBaseOutputPin(pName, pFilter, pLock, phr, L"Output")
  349. {
  350. }
  351. CStreamDriveThruOutputPin::~CStreamDriveThruOutputPin()
  352. {
  353. }
  354. HRESULT CStreamDriveThruOutputPin::GetStream(IStream** ppStream)
  355. {
  356. CheckPointer(ppStream, E_POINTER);
  357. *ppStream = NULL;
  358. CheckPointer(m_pStream, VFW_E_NOT_CONNECTED);
  359. (*ppStream = m_pStream)->AddRef();
  360. return S_OK;
  361. }
  362. STDMETHODIMP CStreamDriveThruOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  363. {
  364. CheckPointer(ppv, E_POINTER);
  365. return 
  366. __super::NonDelegatingQueryInterface(riid, ppv);
  367. }
  368. HRESULT CStreamDriveThruOutputPin::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
  369. {
  370.     ASSERT(pAlloc);
  371.     ASSERT(pProperties);
  372.     HRESULT hr = NOERROR;
  373. pProperties->cBuffers = 1;
  374. pProperties->cbBuffer = PACKETSIZE;
  375.     ALLOCATOR_PROPERTIES Actual;
  376.     if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
  377.     if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
  378.     ASSERT(Actual.cBuffers == pProperties->cBuffers);
  379.     return NOERROR;
  380. }
  381. HRESULT CStreamDriveThruOutputPin::CheckMediaType(const CMediaType* pmt)
  382. {
  383. return pmt->majortype == MEDIATYPE_Stream
  384. ? S_OK
  385. : E_INVALIDARG;
  386. }
  387. HRESULT CStreamDriveThruOutputPin::GetMediaType(int iPosition, CMediaType* pmt)
  388. {
  389.     CAutoLock cAutoLock(m_pLock);
  390. if(iPosition < 0) return E_INVALIDARG;
  391. if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
  392. pmt->majortype = MEDIATYPE_Stream;
  393. pmt->subtype = GUID_NULL;
  394. pmt->formattype = GUID_NULL;
  395. pmt->SetSampleSize(PACKETSIZE);
  396. return S_OK;
  397. }
  398. HRESULT CStreamDriveThruOutputPin::CheckConnect(IPin* pPin)
  399. {
  400. HRESULT hr;
  401. if(FAILED(hr = __super::CheckConnect(pPin)))
  402. return hr;
  403. if(!CComQIPtr<IStream>(pPin))
  404. return E_NOINTERFACE;
  405. return S_OK;
  406. }
  407. HRESULT CStreamDriveThruOutputPin::BreakConnect()
  408. {
  409. HRESULT hr;
  410. if(FAILED(hr = __super::BreakConnect()))
  411. return hr;
  412. m_pStream.Release();
  413. return S_OK;
  414. }
  415. HRESULT CStreamDriveThruOutputPin::CompleteConnect(IPin* pPin)
  416. {
  417. HRESULT hr;
  418. if(FAILED(hr = __super::CompleteConnect(pPin)))
  419. return hr;
  420. CheckPointer(pPin, E_POINTER);
  421. m_pStream = pPin;
  422. CheckPointer(m_pStream, E_NOINTERFACE);
  423. return S_OK;
  424. }
  425. STDMETHODIMP CStreamDriveThruOutputPin::BeginFlush()
  426. {
  427. return E_UNEXPECTED;
  428. }
  429. STDMETHODIMP CStreamDriveThruOutputPin::EndFlush()
  430. {
  431. return E_UNEXPECTED;
  432. }
  433. STDMETHODIMP CStreamDriveThruOutputPin::Notify(IBaseFilter* pSender, Quality q)
  434. {
  435. return E_NOTIMPL;
  436. }