CMPEG1Builder.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:7k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. //
  2. // CMPEG1Builder.cpp
  3. //
  4. #include <streams.h>
  5. #include "FltGuids.h"
  6. #include "CMPEG1Builder.h"
  7. /////////////////////////////////////////////////////////////////////////////
  8. CMPEG1Builder::CMPEG1Builder(LPUNKNOWN pUnk, HRESULT *phr) :
  9. CUnknown(NAME("MPEG1 Builder"), pUnk)
  10. {
  11. }
  12. CMPEG1Builder::~CMPEG1Builder()
  13. {
  14. }
  15. //
  16. // Expose our own interface
  17. STDMETHODIMP CMPEG1Builder::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
  18. {
  19. CheckPointer(ppv, E_POINTER);
  20. if (riid == IID_IMPEG1Builder) 
  21. {
  22. return GetInterface((IMPEG1Builder *) this, ppv);
  23. }
  24. else if (riid == IID_IDistributorNotify)
  25. {
  26. return GetInterface((IDistributorNotify *) this, ppv);
  27. }
  28. else
  29. {
  30. return CUnknown::NonDelegatingQueryInterface(riid, ppv);
  31. }
  32. }
  33. // --- IMPEG1Builder methods ---
  34. STDMETHODIMP CMPEG1Builder::IsMPEG1File(const char * inFilePath)
  35. {
  36. IGraphBuilder * pBuilder = RetrieveGraphBuilder();
  37. // Create a file source filter
  38. IBaseFilter * pSource = NULL;
  39. WCHAR  wcFilePath[MAX_PATH];
  40. MultiByteToWideChar(CP_ACP, 0, inFilePath, -1, wcFilePath, MAX_PATH);
  41. pBuilder->AddSourceFilter(wcFilePath, L"Source", &pSource);
  42. pSource->Release();
  43. // Create microsoft MPEG-1 Stream Splitter
  44. IBaseFilter * pSplitter = NULL;
  45. CoCreateInstance(CLSID_MPEG1Splitter , NULL, CLSCTX_INPROC_SERVER,
  46. IID_IBaseFilter, (void **)&pSplitter);
  47. pBuilder->AddFilter(pSplitter, L"MPEG-1 Splitter");
  48. pSplitter->Release();
  49. // Try to connect them...
  50. IPin * pOut = GetPinByDirection(pSource, PINDIR_OUTPUT);
  51. IPin * pIn  = GetPinByDirection(pSplitter, PINDIR_INPUT);
  52. HRESULT hr  = pBuilder->ConnectDirect(pOut, pIn, NULL);
  53. pBuilder->RemoveFilter(pSplitter);
  54. pBuilder->RemoveFilter(pSource);
  55. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  56. }
  57. STDMETHODIMP CMPEG1Builder::RenderMPEG1File(const char * inFilePath)
  58. {
  59. IGraphBuilder * pBuilder = RetrieveGraphBuilder();
  60. // Create a file source filter
  61. IBaseFilter * pSource = NULL;
  62. WCHAR  wcFilePath[MAX_PATH];
  63. MultiByteToWideChar(CP_ACP, 0, inFilePath, -1, wcFilePath, MAX_PATH);
  64. pBuilder->AddSourceFilter(wcFilePath, L"Source", &pSource);
  65. pSource->Release();
  66. // Create microsoft MPEG-1 Stream Splitter
  67. IBaseFilter * pSplitter = NULL;
  68. CoCreateInstance(CLSID_MPEG1Splitter , NULL, CLSCTX_INPROC_SERVER,
  69. IID_IBaseFilter, (void **)&pSplitter);
  70. pBuilder->AddFilter(pSplitter, L"MPEG-1 Splitter");
  71. pSplitter->Release();
  72. // Create microsoft MPEG-1 Video Decoder
  73. IBaseFilter * pVideoDec = NULL;
  74. CoCreateInstance(CLSID_CMpegVideoCodec, NULL, CLSCTX_INPROC_SERVER,
  75. IID_IBaseFilter, (void **)&pVideoDec);
  76. pBuilder->AddFilter(pVideoDec, L"MPEG-1 Video Decoder");
  77. pVideoDec->Release();
  78. // Create microsoft MPEG-1 Audio Dedocer
  79. IBaseFilter * pAudioDec = NULL;
  80. CoCreateInstance(CLSID_CMpegAudioCodec, NULL, CLSCTX_INPROC_SERVER,
  81. IID_IBaseFilter, (void **)&pAudioDec);
  82. pBuilder->AddFilter(pAudioDec, L"MPEG-1 Audio Decoder");
  83. pAudioDec->Release();
  84. // Connect filters...
  85. IPin * pOut = GetPinByDirection(pSource, PINDIR_OUTPUT);
  86. IPin * pIn  = GetPinByDirection(pSplitter, PINDIR_INPUT);
  87. HRESULT hr  = pBuilder->ConnectDirect(pOut, pIn, NULL);
  88. pOut = GetPinByName(pSplitter, "Video");
  89. pIn  = GetPinByDirection(pVideoDec, PINDIR_INPUT);
  90. if (pOut && pIn)
  91. {
  92. hr = pBuilder->ConnectDirect(pOut, pIn, NULL);
  93. }
  94. pOut = GetPinByName(pSplitter, "Audio");
  95. pIn  = GetPinByDirection(pAudioDec, PINDIR_INPUT);
  96. if (pOut && pIn)
  97. {
  98. hr = pBuilder->ConnectDirect(pOut, pIn, NULL);
  99. }
  100. // Auto-build the rest of the filter graph
  101. IPin * connected = NULL;
  102. pIn = GetPinByDirection(pVideoDec, PINDIR_INPUT);
  103. hr  = pIn->ConnectedTo(&connected);
  104. if (SUCCEEDED(hr) && connected)
  105. {
  106. connected->Release();
  107. hr = pBuilder->Render(GetPinByDirection(pVideoDec, PINDIR_OUTPUT));
  108. }
  109. else
  110. {
  111. pBuilder->RemoveFilter(pVideoDec);
  112. }
  113. pIn = GetPinByDirection(pAudioDec, PINDIR_INPUT);
  114. hr  = pIn->ConnectedTo(&connected);
  115. if (SUCCEEDED(hr) && connected)
  116. {
  117. connected->Release();
  118. hr = pBuilder->Render(GetPinByDirection(pAudioDec, PINDIR_OUTPUT));
  119. }
  120. else
  121. {
  122. pBuilder->RemoveFilter(pAudioDec);
  123. }
  124. return hr;
  125. }
  126. // Utilities
  127. IGraphBuilder * CMPEG1Builder::RetrieveGraphBuilder(void)
  128. {
  129. IGraphBuilder * pBuilder = NULL;
  130. QueryInterface(IID_IGraphBuilder, (void**)&pBuilder);
  131. pBuilder->Release();
  132. return pBuilder;
  133. }
  134. IPin * CMPEG1Builder::GetPinByDirection(IBaseFilter * inFilter, PIN_DIRECTION inDirection)
  135. {
  136. IPin * foundPin = NULL;
  137. if (inFilter)
  138. {
  139. IEnumPins * pinEnum = 0;
  140. if (SUCCEEDED(inFilter->EnumPins(&pinEnum)))
  141. {
  142. pinEnum->Reset();
  143. IPin * pin = 0;
  144. ULONG fetchCount = 0;
  145. while (!foundPin && SUCCEEDED(pinEnum->Next(1, &pin, &fetchCount)) && fetchCount)
  146. {
  147. if (pin)
  148. {
  149. PIN_INFO pinInfo;
  150. if (SUCCEEDED(pin->QueryPinInfo(&pinInfo)))
  151. {
  152. pinInfo.pFilter->Release();
  153. if (pinInfo.dir == inDirection)
  154. {
  155. foundPin = pin;
  156. }
  157. }
  158. // If found pin, we keep pin reference.
  159. // If not, we release it here.
  160. if (!foundPin)
  161. {
  162. pin->Release();
  163. }
  164. pin = 0;
  165. }
  166. }
  167. pinEnum->Release();
  168. }
  169. }
  170. // We don't keep outstanding reference count
  171. if (foundPin)
  172. {
  173. foundPin->Release();
  174. }
  175. return foundPin;
  176. }
  177. IPin * CMPEG1Builder::GetPinByName(IBaseFilter * inFilter, const char * inPinName, BOOL inInput)
  178. {
  179. PIN_DIRECTION pinType = inInput ? PINDIR_INPUT : PINDIR_OUTPUT;
  180. IPin * foundPin = 0;
  181. if (inFilter)
  182. {
  183. IEnumPins * pinEnum = 0;
  184. if (SUCCEEDED(inFilter->EnumPins(&pinEnum)))
  185. {
  186. pinEnum->Reset();
  187. IPin * pin = 0;
  188. ULONG fetchCount = 0;
  189. while (!foundPin && SUCCEEDED(pinEnum->Next(1, &pin, &fetchCount)) && fetchCount)
  190. {
  191. if (pin)
  192. {
  193. PIN_INFO pinInfo;
  194. if (SUCCEEDED(pin->QueryPinInfo(&pinInfo)))
  195. {
  196. if (pinInfo.dir == pinType)
  197. {
  198. char pinName[128];
  199. ::WideCharToMultiByte(CP_ACP, 0, pinInfo.achName, -1,
  200. pinName, 128, NULL, NULL);
  201. if (::strstr(pinName, inPinName))
  202. {
  203. foundPin = pin;
  204. }
  205. }
  206. pinInfo.pFilter->Release();
  207. }
  208. if (!foundPin)
  209. {
  210. pin->Release();
  211. }
  212. pin = 0;
  213. }
  214. }
  215. pinEnum->Release();
  216. }
  217. }
  218. // We don't keep outstanding reference count
  219. if (foundPin)
  220. {
  221. foundPin->Release();
  222. }
  223. return foundPin;
  224. }
  225. // --- IDistributorNotify methods ---
  226. STDMETHODIMP CMPEG1Builder::NotifyGraphChange(void)
  227. {
  228. return S_OK;
  229. }
  230. STDMETHODIMP CMPEG1Builder::Pause(void)
  231. {
  232. return S_OK;
  233. }
  234. STDMETHODIMP CMPEG1Builder::Run(REFERENCE_TIME tStart)
  235. {
  236. return S_OK;
  237. }
  238. STDMETHODIMP CMPEG1Builder::Stop(void)
  239. {
  240. return S_OK;
  241. }
  242. STDMETHODIMP CMPEG1Builder::SetSyncSource(IReferenceClock *pClock)
  243. {
  244. return S_OK;
  245. }