IPFilter.cpp
上传用户:hhs829
上传日期:2022-06-17
资源大小:586k
文件大小:10k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //
  2. // Sample DirectShow In-Place Transform Filter that accepts data for use in application
  3. //
  4. #include "stdafx.h"
  5. #include "IPFilter.h"
  6. ////////////////////////////////////////////////////////////////////////////////
  7. CAppTransform::CAppTransform(LPUNKNOWN pUnkOuter, HRESULT *phr) : 
  8. CTransInPlaceFilter(NAME("App Transform"), pUnkOuter, GUID_NULL, phr)
  9. {
  10. }
  11. HRESULT CAppTransform::Transform(IMediaSample *pSample)
  12. {
  13. // Override to do something inside the application
  14. // Such as grabbing a poster frame...
  15. // ...
  16.     return S_OK;
  17. }
  18. // Check if we can support this specific proposed type and format
  19. HRESULT CAppTransform::CheckInputType(const CMediaType *pmt) 
  20. {
  21. // We accept a series of raw media types
  22. if (pmt->majortype == MEDIATYPE_Video &&
  23. (pmt->subtype == MEDIASUBTYPE_RGB32 ||
  24. pmt->subtype == MEDIASUBTYPE_RGB24 ||
  25. pmt->subtype == MEDIASUBTYPE_RGB565 ||
  26. pmt->subtype == MEDIASUBTYPE_RGB555 ||
  27. pmt->subtype == MEDIASUBTYPE_UYVY ||
  28. pmt->subtype == MEDIASUBTYPE_YUY2))
  29. {
  30. return NOERROR;
  31. }
  32. return E_FAIL;
  33. }
  34. // --- graph building (examples) --------- 
  35. CAppGraphBuilder::CAppGraphBuilder() : 
  36. m_pFilter(NULL),
  37. m_pGraph(NULL),
  38. m_dwObjectTable(0)
  39. {
  40.     CoInitialize(NULL);
  41. }
  42. CAppGraphBuilder::~CAppGraphBuilder()
  43. {
  44.     DestroyGraph();
  45.     CoUninitialize();
  46. }
  47.     
  48. void CAppGraphBuilder::DestroyGraph(void)
  49. {
  50.     if (m_pGraph) 
  51. {
  52. RemoveFromObjectTable();
  53.         // ensure graph window is not child of ours
  54.         IVideoWindow* pVW = NULL;
  55.         HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW);
  56.         if (SUCCEEDED(hr)) 
  57. {
  58.             pVW->put_Visible(OAFALSE);
  59.             pVW->put_Owner(NULL);
  60.             pVW->put_MessageDrain(NULL);
  61.             pVW->Release();
  62.         }
  63.         m_pGraph->Release();
  64.         m_pGraph = NULL;
  65.     }
  66.     if (m_pFilter) 
  67. {
  68. m_pFilter->Release();
  69.         m_pFilter = NULL;
  70.     }
  71. }
  72. HRESULT CAppGraphBuilder::BuildFromFile(LPCWSTR pszFile)
  73. {
  74. DestroyGraph();
  75. // Build a filter graph
  76. HRESULT hr = CoCreateInstance(
  77. CLSID_FilterGraph,
  78. NULL,
  79. CLSCTX_INPROC,
  80. IID_IGraphBuilder,
  81. (void**)&m_pGraph);
  82. if (FAILED(hr))
  83. {
  84. return hr;
  85. }
  86. AddToObjectTable();
  87. // render the file to build the initial graph
  88. hr = m_pGraph->RenderFile(pszFile, NULL);
  89. if (FAILED(hr)) 
  90. {
  91. return hr;
  92. }
  93. // Try to find the video renderer, by looking for IVideoWindow
  94. IBaseFilter* pVR;
  95. hr = FindFilterByInterface(IID_IVideoWindow, &pVR);
  96. if (FAILED(hr)) 
  97. {
  98. return hr;
  99. }
  100. // Find the media type on the input pin of the Video Renderer
  101. // to check for overlay connection where no actual data is passed
  102. IPin* pPin = InputPinOf(pVR);
  103. AM_MEDIA_TYPE mt;
  104. pPin->ConnectionMediaType(&mt);
  105. pPin->Release();
  106. CMediaType mtIn = mt;
  107. FreeMediaType(mt);
  108. if (mtIn.subtype == MEDIASUBTYPE_Overlay) 
  109. {
  110. // This connection may be a overlay mixer 
  111. // need to move upstream one place
  112. IBaseFilter* pOvMix = NULL;
  113. hr = NextUpstream(pVR, &pOvMix);
  114. pVR->Release();
  115. if (FAILED(hr)) 
  116. {
  117. return hr;
  118. }
  119. pVR = pOvMix;
  120. }
  121. // Create the transform and insert in graph
  122. CreateAppFilter();
  123. // Try to insert our transform filter
  124. hr = ConnectUpstreamOf(pVR, m_pFilter);
  125. pVR->Release();
  126. return hr;
  127. }
  128. // Start the graph
  129. HRESULT CAppGraphBuilder::Run(void)
  130. {
  131.     IMediaControl* pControl = NULL;
  132.     HRESULT hr = m_pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
  133.     if (SUCCEEDED(hr)) 
  134. {
  135. hr = pControl->Run();
  136. pControl->Release();
  137.     }
  138.     return hr;
  139. }
  140. // Make the video window a child of this app
  141. HRESULT CAppGraphBuilder::MakeChild(HWND hwnd)
  142. {
  143.     if (!m_pGraph) 
  144. {
  145.         return E_FAIL;
  146.     }
  147.     IVideoWindow* pVW = NULL;
  148.     HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW);
  149.     if (SUCCEEDED(hr)) 
  150. {
  151. HWND hwndOld;
  152. pVW->get_Owner((LONG*)&hwndOld);
  153. if (hwndOld != hwnd)
  154. {
  155. pVW->put_AutoShow(OAFALSE);
  156. pVW->put_Visible(OAFALSE);
  157. long    WindowStyle = 0;
  158. // Tweak the video's window style to get rid of the caption and frame:
  159. hr = pVW->get_WindowStyle(&WindowStyle);
  160. if (SUCCEEDED(hr)) 
  161. {
  162. WindowStyle &= ~WS_OVERLAPPEDWINDOW; // No frame junk
  163. WindowStyle |= WS_CHILD;             // Needs to be child
  164. hr = pVW->put_WindowStyle(WindowStyle);
  165. }
  166. pVW->put_Owner((LONG)hwnd);
  167. pVW->put_MessageDrain((LONG)hwnd);
  168.             if (hwnd != NULL) 
  169. {
  170. RECT rc;
  171. GetClientRect(hwnd, &rc);
  172. pVW->SetWindowPosition(
  173. rc.left,
  174. rc.top,
  175. rc.right - rc.left,
  176. rc.bottom - rc.top);
  177. pVW->put_Visible(OATRUE);
  178.             }
  179. }
  180. pVW->Release();
  181.     }
  182.     return hr;
  183. }
  184. // Resize the video window
  185. HRESULT CAppGraphBuilder::ResizeVideoWindow(RECT* prc)
  186. {
  187.     if (!m_pGraph) 
  188. {
  189.         return E_FAIL;
  190.     }
  191.     IVideoWindow* pVW = NULL;
  192.     HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW);
  193.     if (SUCCEEDED(hr)) 
  194. {
  195.         hr = pVW->SetWindowPosition(
  196.                         prc->left,
  197.                         prc->top,
  198.                         prc->right - prc->left,
  199.                         prc->bottom - prc->top);
  200.         pVW->Release();
  201.     }
  202.     return hr;
  203. }
  204. // Create the app-based filter and insert into graph (unconnected)
  205. void CAppGraphBuilder::CreateAppFilter(void)
  206. {
  207. if (m_pFilter) 
  208. {
  209. m_pFilter->Release();
  210. m_pFilter = NULL;
  211. }
  212. HRESULT hr = S_OK;
  213. m_pFilter = new CAppTransform(NULL, &hr);
  214. // Make the initial refcount 1 to match COM creation!!!
  215. m_pFilter->AddRef();
  216. // Add to graph -- nb need to Query properly for the
  217. // right interface before giving that to the graph object
  218. IBaseFilter* pFilter = NULL;
  219. hr = m_pFilter->QueryInterface(IID_IBaseFilter, (void**)&pFilter);
  220. if (SUCCEEDED(hr)) 
  221. {
  222. hr = m_pGraph->AddFilter(pFilter, L"App Transform");
  223. pFilter->Release();
  224. }
  225. }
  226. // Locate a filter within the graph by searching (from renderers upstream)
  227. // looking for a specific interface on the filter
  228. HRESULT CAppGraphBuilder::FindFilterByInterface(REFIID riid, IBaseFilter** ppFilter)
  229. {
  230.     *ppFilter = NULL;
  231.     IEnumFilters* pEnum;
  232.     HRESULT hr = m_pGraph->EnumFilters(&pEnum);
  233.     if (FAILED(hr)) 
  234. {
  235. return hr;
  236.     }
  237.     IBaseFilter* pFilter = NULL;
  238.     while (pEnum->Next(1, &pFilter, NULL) == S_OK) 
  239. {
  240. // Check for required interface
  241. IUnknown* pUnk;
  242. HRESULT hrQuery = pFilter->QueryInterface(riid, (void**)&pUnk);
  243. if (SUCCEEDED(hrQuery)) 
  244. {
  245. pUnk->Release();
  246. pEnum->Release();
  247. *ppFilter = pFilter;
  248. return S_OK;
  249. }
  250. pFilter->Release();
  251.     }
  252.     pEnum->Release();
  253.     return E_FAIL;
  254. }
  255. // Connect the filter pTransform upstream of pFilter by reconnecting pins.
  256. // Assumes that pTransform has only one input and one output, and
  257. // that pFilter has only one input.
  258. HRESULT CAppGraphBuilder::ConnectUpstreamOf(IBaseFilter* pFilter, IBaseFilter* pTransform)
  259. {
  260. IPin* pPinIn = InputPinOf(pFilter);
  261. if (!pPinIn) 
  262. {
  263. return E_FAIL;
  264. }
  265. // Get the peer output pin
  266. IPin* pPinOut = NULL;
  267. HRESULT hr = pPinIn->ConnectedTo(&pPinOut);
  268. if (FAILED(hr)) 
  269. {
  270. pPinIn->Release();
  271. return hr;
  272. }
  273. // Disconnect the current connection
  274. hr = m_pGraph->Disconnect(pPinOut);
  275. if (SUCCEEDED(hr)) 
  276. {
  277. hr = m_pGraph->Disconnect(pPinIn);
  278. }
  279. // Insert pTransform filter by connecting its input pin and output pin
  280. if (SUCCEEDED(hr)) 
  281. {
  282. IPin* pPinInXfm = InputPinOf(pTransform);
  283. hr = m_pGraph->Connect(pPinOut, pPinInXfm);
  284. pPinInXfm->Release();
  285. }
  286. if (SUCCEEDED(hr)) 
  287. {
  288. IPin* pPinOutXfm = OutputPinOf(pTransform);
  289. hr = m_pGraph->Connect(pPinOutXfm, pPinIn);
  290. pPinOutXfm->Release();
  291. }
  292. pPinIn->Release();
  293. pPinOut->Release();
  294. return hr;
  295. }
  296. // Find the first pin of a specific direction on a given filter
  297. IPin* CAppGraphBuilder::GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest)
  298. {
  299. IPin * foundPin = NULL;
  300.     IEnumPins* pEnum = NULL;
  301.     HRESULT hr = pFilter->EnumPins(&pEnum);
  302.     if (SUCCEEDED(hr)) 
  303. {
  304. IPin* pPin = NULL;
  305.         while (!foundPin && pEnum->Next(1, &pPin, 0) == S_OK) 
  306. {
  307. PIN_DIRECTION dir;
  308. pPin->QueryDirection(&dir);
  309. if (dir == dirRequest) 
  310. {
  311. foundPin = pPin;
  312. }
  313. else
  314. {
  315. pPin->Release();
  316. }
  317. }
  318. pEnum->Release();
  319.     }
  320.     return foundPin;
  321. }
  322. // Follow the pin connections to return the filter that is 
  323. // connected to the first input pin of pFilter
  324. HRESULT CAppGraphBuilder::NextUpstream(IBaseFilter* pFilter, IBaseFilter** ppNext)
  325. {
  326.     IPin* pPin = InputPinOf(pFilter);
  327.     if (!pPin) 
  328. {
  329. return E_FAIL;
  330.     }
  331. // Get the peer output pin
  332.     IPin* pPinOut = NULL;
  333.     HRESULT hr = pPin->ConnectedTo(&pPinOut);
  334.     pPin->Release();
  335.     if (FAILED(hr)) 
  336. {
  337. return hr;
  338.     }
  339.     PIN_INFO info;
  340.     pPinOut->QueryPinInfo(&info);
  341. pPinOut->Release();
  342.     *ppNext = info.pFilter;
  343.     
  344.     return S_OK;
  345. }
  346. //////////////////////// For GraphEdit Dubug purpose /////////////////////////////
  347. void CAppGraphBuilder::AddToObjectTable(void)
  348. {
  349. IMoniker * pMoniker = 0;
  350.     IRunningObjectTable * objectTable = 0;
  351.     if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) 
  352. {
  353. WCHAR wsz[256];
  354. wsprintfW(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)m_pGraph, GetCurrentProcessId());
  355. HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
  356. if (SUCCEEDED(hr)) 
  357. {
  358. hr = objectTable->Register(0, m_pGraph, pMoniker, &m_dwObjectTable);
  359. pMoniker->Release();
  360. }
  361. objectTable->Release();
  362. }
  363. }
  364. void CAppGraphBuilder::RemoveFromObjectTable(void)
  365. {
  366. IRunningObjectTable * objectTable = 0;
  367.     if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) 
  368. {
  369.         objectTable->Revoke(m_dwObjectTable);
  370.         objectTable->Release();
  371. m_dwObjectTable = 0;
  372.     }
  373. }