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

多媒体编程

开发平台:

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 <mmintrin.h>
  23. #include "BaseVideoFilter.h"
  24. #include "......DSUtilDSUtil.h"
  25. #include "......DSUtilMediaTypes.h"
  26. #include <initguid.h>
  27. #include "........includemoreuuids.h"
  28. //
  29. // CBaseVideoFilter
  30. //
  31. CBaseVideoFilter::CBaseVideoFilter(TCHAR* pName, LPUNKNOWN lpunk, HRESULT* phr, REFCLSID clsid) 
  32. : CTransformFilter(pName, lpunk, clsid)
  33. {
  34. if(phr) *phr = S_OK;
  35. if(!(m_pInput = new CBaseVideoInputPin(NAME("CBaseVideoInputPin"), this, phr, L"Video"))) *phr = E_OUTOFMEMORY;
  36. if(FAILED(*phr)) return;
  37. if(!(m_pOutput = new CBaseVideoOutputPin(NAME("CBaseVideoOutputPin"), this, phr, L"Output"))) *phr = E_OUTOFMEMORY;
  38. if(FAILED(*phr))  {delete m_pInput, m_pInput = NULL; return;}
  39. m_wout = m_win = m_w = 0;
  40. m_hout = m_hin = m_h = 0;
  41. m_arxout = m_arxin = m_arx = 0;
  42. m_aryout = m_aryin = m_ary = 0;
  43. }
  44. CBaseVideoFilter::~CBaseVideoFilter()
  45. {
  46. }
  47. int CBaseVideoFilter::GetPinCount()
  48. {
  49. return 2;
  50. }
  51. CBasePin* CBaseVideoFilter::GetPin(int n)
  52. {
  53. switch(n)
  54. {
  55. case 0: return m_pInput;
  56. case 1: return m_pOutput;
  57. }
  58. return NULL;
  59. }
  60. HRESULT CBaseVideoFilter::Receive(IMediaSample* pIn)
  61. {
  62. _mm_empty(); // just for safety
  63. CAutoLock cAutoLock(&m_csReceive);
  64. HRESULT hr;
  65.     AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
  66.     if(pProps->dwStreamId != AM_STREAM_MEDIA)
  67. return m_pOutput->Deliver(pIn);
  68. AM_MEDIA_TYPE* pmt;
  69. if(SUCCEEDED(pIn->GetMediaType(&pmt)) && pmt)
  70. {
  71. CMediaType mt(*pmt);
  72. m_pInput->SetMediaType(&mt);
  73. DeleteMediaType(pmt);
  74. }
  75. if(FAILED(hr = Transform(pIn)))
  76. return hr;
  77. return S_OK;
  78. }
  79. HRESULT CBaseVideoFilter::GetDeliveryBuffer(int w, int h, IMediaSample** ppOut)
  80. {
  81. CheckPointer(ppOut, E_POINTER);
  82. HRESULT hr;
  83. if(FAILED(hr = ReconnectOutput(w, h)))
  84. return hr;
  85. if(FAILED(hr = m_pOutput->GetDeliveryBuffer(ppOut, NULL, NULL, 0)))
  86. return hr;
  87. AM_MEDIA_TYPE* pmt;
  88. if(SUCCEEDED((*ppOut)->GetMediaType(&pmt)) && pmt)
  89. {
  90. CMediaType mt = *pmt;
  91. m_pOutput->SetMediaType(&mt);
  92. DeleteMediaType(pmt);
  93. }
  94. (*ppOut)->SetDiscontinuity(FALSE);
  95. (*ppOut)->SetSyncPoint(TRUE);
  96. // FIXME: hell knows why but without this the overlay mixer starts very skippy
  97. // (don't enable this for other renderers, the old for example will go crazy if you do)
  98. if(GetCLSID(m_pOutput->GetConnected()) == CLSID_OverlayMixer)
  99. (*ppOut)->SetDiscontinuity(TRUE);
  100. return S_OK;
  101. }
  102. HRESULT CBaseVideoFilter::ReconnectOutput(int w, int h)
  103. {
  104. CMediaType& mt = m_pOutput->CurrentMediaType();
  105. int w_org = m_w;
  106. int h_org = m_h;
  107. bool fForceReconnection = false;
  108. if(w != m_w || h != m_h)
  109. {
  110. fForceReconnection = true;
  111. m_w = w;
  112. m_h = h;
  113. }
  114. HRESULT hr = S_OK;
  115. if(fForceReconnection || m_w != m_wout || m_h != m_hout || m_arx != m_arxout || m_ary != m_aryout)
  116. {
  117. if(GetCLSID(m_pOutput->GetConnected()) == CLSID_VideoRenderer)
  118. {
  119. NotifyEvent(EC_ERRORABORT, 0, 0);
  120. return E_FAIL;
  121. }
  122. BITMAPINFOHEADER* bmi = NULL;
  123. if(mt.formattype == FORMAT_VideoInfo)
  124. {
  125. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.Format();
  126. SetRect(&vih->rcSource, 0, 0, m_w, m_h);
  127. SetRect(&vih->rcTarget, 0, 0, m_w, m_h);
  128. bmi = &vih->bmiHeader;
  129. bmi->biXPelsPerMeter = m_w * m_ary;
  130. bmi->biYPelsPerMeter = m_h * m_arx;
  131. }
  132. else if(mt.formattype == FORMAT_VideoInfo2)
  133. {
  134. VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)mt.Format();
  135. SetRect(&vih->rcSource, 0, 0, m_w, m_h);
  136. SetRect(&vih->rcTarget, 0, 0, m_w, m_h);
  137. bmi = &vih->bmiHeader;
  138. vih->dwPictAspectRatioX = m_arx;
  139. vih->dwPictAspectRatioY = m_ary;
  140. }
  141. bmi->biWidth = m_w;
  142. bmi->biHeight = m_h;
  143. bmi->biSizeImage = m_w*m_h*bmi->biBitCount>>3;
  144. hr = m_pOutput->GetConnected()->QueryAccept(&mt);
  145. ASSERT(SUCCEEDED(hr)); // should better not fail, after all "mt" is the current media type, just with a different resolution
  146. HRESULT hr1 = 0, hr2 = 0;
  147. CComPtr<IMediaSample> pOut;
  148. if(SUCCEEDED(hr1 = m_pOutput->GetConnected()->ReceiveConnection(m_pOutput, &mt))
  149. && SUCCEEDED(hr2 = m_pOutput->GetDeliveryBuffer(&pOut, NULL, NULL, 0)))
  150. {
  151. AM_MEDIA_TYPE* pmt;
  152. if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
  153. {
  154. CMediaType mt = *pmt;
  155. m_pOutput->SetMediaType(&mt);
  156. DeleteMediaType(pmt);
  157. }
  158. else // stupid overlay mixer won't let us know the new pitch...
  159. {
  160. long size = pOut->GetSize();
  161. bmi->biWidth = size / bmi->biHeight * 8 / bmi->biBitCount;
  162. }
  163. }
  164. else
  165. {
  166. m_w = w_org;
  167. m_h = h_org;
  168. return E_FAIL;
  169. }
  170. m_wout = m_w;
  171. m_hout = m_h;
  172. m_arxout = m_arx;
  173. m_aryout = m_ary;
  174. // some renderers don't send this
  175. NotifyEvent(EC_VIDEO_SIZE_CHANGED, MAKELPARAM(m_w, m_h), 0);
  176. return S_OK;
  177. }
  178. return S_FALSE;
  179. }
  180. HRESULT CBaseVideoFilter::CopyBuffer(BYTE* pOut, BYTE* pIn, int w, int h, int pitchIn, const GUID& subtype)
  181. {
  182. int abs_h = abs(h);
  183. BYTE* pInYUV[3] = {pIn, pIn + pitchIn*abs_h, pIn + pitchIn*abs_h + (pitchIn>>1)*(abs_h>>1)};
  184. return CopyBuffer(pOut, pInYUV, w, h, pitchIn, subtype);
  185. }
  186. HRESULT CBaseVideoFilter::CopyBuffer(BYTE* pOut, BYTE** ppIn, int w, int h, int pitchIn, const GUID& subtype)
  187. {
  188. BITMAPINFOHEADER bihOut;
  189. ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
  190. int pitchOut = 0;
  191. if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
  192. {
  193. pitchOut = bihOut.biWidth*bihOut.biBitCount>>3;
  194. if(bihOut.biHeight > 0)
  195. {
  196. pOut += pitchOut*(h-1);
  197. pitchOut = -pitchOut;
  198. if(h < 0) h = -h;
  199. }
  200. }
  201. if(h < 0)
  202. {
  203. h = -h;
  204. ppIn[0] += pitchIn*(h-1);
  205. ppIn[1] += (pitchIn>>1)*((h>>1)-1);
  206. ppIn[2] += (pitchIn>>1)*((h>>1)-1);
  207. pitchIn = -pitchIn;
  208. }
  209. if(subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV || subtype == MEDIASUBTYPE_YV12)
  210. {
  211. BYTE* pIn = ppIn[0];
  212. BYTE* pInU = ppIn[1];
  213. BYTE* pInV = ppIn[2];
  214. if(subtype == MEDIASUBTYPE_YV12) {BYTE* tmp = pInU; pInU = pInV; pInV = tmp;}
  215. BYTE* pOutU = pOut + bihOut.biWidth*h;
  216. BYTE* pOutV = pOut + bihOut.biWidth*h*5/4;
  217. if(bihOut.biCompression == '21VY') {BYTE* tmp = pOutU; pOutU = pOutV; pOutV = tmp;}
  218. ASSERT(w <= abs(pitchIn));
  219. if(bihOut.biCompression == '2YUY')
  220. {
  221. BitBltFromI420ToYUY2(w, h, pOut, bihOut.biWidth*2, pIn, pInU, pInV, pitchIn);
  222. }
  223. else if(bihOut.biCompression == '024I' || bihOut.biCompression == 'VUYI' || bihOut.biCompression == '21VY')
  224. {
  225. BitBltFromI420ToI420(w, h, pOut, pOutU, pOutV, bihOut.biWidth, pIn, pInU, pInV, pitchIn);
  226. }
  227. else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
  228. {
  229. if(!BitBltFromI420ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, pIn, pInU, pInV, pitchIn))
  230. {
  231. for(DWORD y = 0; y < h; y++, pOut += pitchOut)
  232. memset(pOut, 0, pitchOut);
  233. }
  234. }
  235. }
  236. else if(subtype == MEDIASUBTYPE_YUY2)
  237. {
  238. if(bihOut.biCompression == '2YUY')
  239. {
  240. BitBltFromYUY2ToYUY2(w, h, pOut, bihOut.biWidth*2, ppIn[0], pitchIn);
  241. }
  242. else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
  243. {
  244. if(!BitBltFromYUY2ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, ppIn[0], pitchIn))
  245. {
  246. for(DWORD y = 0; y < h; y++, pOut += pitchOut)
  247. memset(pOut, 0, pitchOut);
  248. }
  249. }
  250. }
  251. else if(subtype == MEDIASUBTYPE_ARGB32 || subtype == MEDIASUBTYPE_RGB32 || subtype == MEDIASUBTYPE_RGB24 || subtype == MEDIASUBTYPE_RGB565)
  252. {
  253. int sbpp = 
  254. subtype == MEDIASUBTYPE_ARGB32 || subtype == MEDIASUBTYPE_RGB32 ? 32 :
  255. subtype == MEDIASUBTYPE_RGB24 ? 24 :
  256. subtype == MEDIASUBTYPE_RGB565 ? 16 : 0;
  257. if(bihOut.biCompression == '2YUY')
  258. {
  259. // TODO
  260. // BitBltFromRGBToYUY2();
  261. }
  262. else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
  263. {
  264. if(!BitBltFromRGBToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, ppIn[0], pitchIn, sbpp))
  265. {
  266. for(DWORD y = 0; y < h; y++, pOut += pitchOut)
  267. memset(pOut, 0, pitchOut);
  268. }
  269. }
  270. }
  271. else
  272. {
  273. return VFW_E_TYPE_NOT_ACCEPTED;
  274. }
  275. return S_OK;
  276. }
  277. HRESULT CBaseVideoFilter::CheckInputType(const CMediaType* mtIn)
  278. {
  279. BITMAPINFOHEADER bih;
  280. ExtractBIH(mtIn, &bih);
  281. return mtIn->majortype == MEDIATYPE_Video 
  282. && (mtIn->subtype == MEDIASUBTYPE_YV12 
  283.  || mtIn->subtype == MEDIASUBTYPE_I420 
  284.  || mtIn->subtype == MEDIASUBTYPE_IYUV
  285.  || mtIn->subtype == MEDIASUBTYPE_YUY2
  286.  || mtIn->subtype == MEDIASUBTYPE_ARGB32
  287.  || mtIn->subtype == MEDIASUBTYPE_RGB32
  288.  || mtIn->subtype == MEDIASUBTYPE_RGB24
  289.    || mtIn->subtype == MEDIASUBTYPE_RGB565)
  290. && (mtIn->formattype == FORMAT_VideoInfo 
  291.  || mtIn->formattype == FORMAT_VideoInfo2)
  292. && bih.biHeight > 0
  293. ? S_OK
  294. : VFW_E_TYPE_NOT_ACCEPTED;
  295. }
  296. HRESULT CBaseVideoFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  297. {
  298. if(FAILED(CheckInputType(mtIn)) || mtOut->majortype != MEDIATYPE_Video)
  299. return VFW_E_TYPE_NOT_ACCEPTED;
  300. if(mtIn->majortype == MEDIATYPE_Video 
  301. && (mtIn->subtype == MEDIASUBTYPE_YV12 
  302.  || mtIn->subtype == MEDIASUBTYPE_I420 
  303.  || mtIn->subtype == MEDIASUBTYPE_IYUV))
  304. {
  305. if(mtOut->subtype != MEDIASUBTYPE_YV12
  306. && mtOut->subtype != MEDIASUBTYPE_I420
  307. && mtOut->subtype != MEDIASUBTYPE_IYUV
  308. && mtOut->subtype != MEDIASUBTYPE_YUY2
  309. && mtOut->subtype != MEDIASUBTYPE_ARGB32
  310. && mtOut->subtype != MEDIASUBTYPE_RGB32
  311. && mtOut->subtype != MEDIASUBTYPE_RGB24
  312. && mtOut->subtype != MEDIASUBTYPE_RGB565)
  313. return VFW_E_TYPE_NOT_ACCEPTED;
  314. }
  315. else if(mtIn->majortype == MEDIATYPE_Video 
  316. && (mtIn->subtype == MEDIASUBTYPE_YUY2))
  317. {
  318. if(mtOut->subtype != MEDIASUBTYPE_YUY2
  319. && mtOut->subtype != MEDIASUBTYPE_ARGB32
  320. && mtOut->subtype != MEDIASUBTYPE_RGB32
  321. && mtOut->subtype != MEDIASUBTYPE_RGB24
  322. && mtOut->subtype != MEDIASUBTYPE_RGB565)
  323. return VFW_E_TYPE_NOT_ACCEPTED;
  324. }
  325. else if(mtIn->majortype == MEDIATYPE_Video 
  326. && (mtIn->subtype == MEDIASUBTYPE_ARGB32
  327. || mtIn->subtype == MEDIASUBTYPE_RGB32
  328. || mtIn->subtype == MEDIASUBTYPE_RGB24
  329. || mtIn->subtype == MEDIASUBTYPE_RGB565))
  330. {
  331. if(mtOut->subtype != MEDIASUBTYPE_ARGB32
  332. && mtOut->subtype != MEDIASUBTYPE_RGB32
  333. && mtOut->subtype != MEDIASUBTYPE_RGB24
  334. && mtOut->subtype != MEDIASUBTYPE_RGB565)
  335. return VFW_E_TYPE_NOT_ACCEPTED;
  336. }
  337. return S_OK;
  338. }
  339. HRESULT CBaseVideoFilter::CheckOutputType(const CMediaType& mtOut)
  340. {
  341. int wout = 0, hout = 0, arxout = 0, aryout = 0;
  342. return ExtractDim(&mtOut, wout, hout, arxout, aryout)
  343. && m_h == abs((int)hout)
  344. && mtOut.subtype != MEDIASUBTYPE_ARGB32
  345. ? S_OK
  346. : VFW_E_TYPE_NOT_ACCEPTED;
  347. }
  348. HRESULT CBaseVideoFilter::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  349. {
  350. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  351. BITMAPINFOHEADER bih;
  352. ExtractBIH(&m_pOutput->CurrentMediaType(), &bih);
  353. pProperties->cBuffers = 1;
  354. pProperties->cbBuffer = bih.biSizeImage;
  355. pProperties->cbAlign = 1;
  356. pProperties->cbPrefix = 0;
  357. HRESULT hr;
  358. ALLOCATOR_PROPERTIES Actual;
  359.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  360. return hr;
  361.     return pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  362. ? E_FAIL
  363. : NOERROR;
  364. }
  365. HRESULT CBaseVideoFilter::GetMediaType(int iPosition, CMediaType* pmt)
  366. {
  367.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  368. struct {const GUID* subtype; WORD biPlanes, biBitCount; DWORD biCompression;} fmts[] =
  369. {
  370. {&MEDIASUBTYPE_YV12, 3, 12, '21VY'},
  371. {&MEDIASUBTYPE_I420, 3, 12, '024I'},
  372. {&MEDIASUBTYPE_IYUV, 3, 12, 'VUYI'},
  373. {&MEDIASUBTYPE_YUY2, 1, 16, '2YUY'},
  374. {&MEDIASUBTYPE_ARGB32, 1, 32, BI_RGB},
  375. {&MEDIASUBTYPE_RGB32, 1, 32, BI_RGB},
  376. {&MEDIASUBTYPE_RGB24, 1, 24, BI_RGB},
  377. {&MEDIASUBTYPE_RGB565, 1, 16, BI_RGB},
  378. {&MEDIASUBTYPE_RGB555, 1, 16, BI_RGB},
  379. {&MEDIASUBTYPE_ARGB32, 1, 32, BI_BITFIELDS},
  380. {&MEDIASUBTYPE_RGB32, 1, 32, BI_BITFIELDS},
  381. {&MEDIASUBTYPE_RGB24, 1, 24, BI_BITFIELDS},
  382. {&MEDIASUBTYPE_RGB565, 1, 16, BI_BITFIELDS},
  383. {&MEDIASUBTYPE_RGB555, 1, 16, BI_BITFIELDS},
  384. };
  385. // this will make sure we won't connect to the old renderer in dvd mode
  386. // that renderer can't switch the format dynamically
  387. bool fFoundDVDNavigator = false;
  388. CComPtr<IBaseFilter> pBF = this;
  389. CComPtr<IPin> pPin = m_pInput;
  390. for(; !fFoundDVDNavigator && (pBF = GetFilterFromPin(GetUpStreamPin(pBF, pPin))); pPin = GetFirstPin(pBF))
  391.         fFoundDVDNavigator = GetCLSID(pBF) == CLSID_DVDNavigator;
  392. if(fFoundDVDNavigator || m_pInput->CurrentMediaType().formattype == FORMAT_VideoInfo2)
  393. iPosition = iPosition*2;
  394. //
  395. if(iPosition < 0) return E_INVALIDARG;
  396. if(iPosition >= 2*countof(fmts)) return VFW_S_NO_MORE_ITEMS;
  397. pmt->majortype = MEDIATYPE_Video;
  398. pmt->subtype = *fmts[iPosition/2].subtype;
  399. int w = m_win, h = m_hin, arx = m_arxin, ary = m_aryin;
  400. GetOutputSize(w, h, arx, ary);
  401. BITMAPINFOHEADER bihOut;
  402. memset(&bihOut, 0, sizeof(bihOut));
  403. bihOut.biSize = sizeof(bihOut);
  404. bihOut.biWidth = w;
  405. bihOut.biHeight = h;
  406. bihOut.biPlanes = fmts[iPosition/2].biPlanes;
  407. bihOut.biBitCount = fmts[iPosition/2].biBitCount;
  408. bihOut.biCompression = fmts[iPosition/2].biCompression;
  409. bihOut.biSizeImage = w*h*bihOut.biBitCount>>3;
  410. if(iPosition&1)
  411. {
  412. pmt->formattype = FORMAT_VideoInfo;
  413. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  414. memset(vih, 0, sizeof(VIDEOINFOHEADER));
  415. vih->bmiHeader = bihOut;
  416. vih->bmiHeader.biXPelsPerMeter = vih->bmiHeader.biWidth * ary;
  417. vih->bmiHeader.biYPelsPerMeter = vih->bmiHeader.biHeight * arx;
  418. }
  419. else
  420. {
  421. pmt->formattype = FORMAT_VideoInfo2;
  422. VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER2));
  423. memset(vih, 0, sizeof(VIDEOINFOHEADER2));
  424. vih->bmiHeader = bihOut;
  425. vih->dwPictAspectRatioX = arx;
  426. vih->dwPictAspectRatioY = ary;
  427. vih->dwCopyProtectFlags &= ~AMCOPYPROTECT_RestrictDuplication; // hehe
  428. }
  429. CMediaType& mt = m_pInput->CurrentMediaType();
  430. // these fields have the same field offset in all four structs
  431. ((VIDEOINFOHEADER*)pmt->Format())->AvgTimePerFrame = ((VIDEOINFOHEADER*)mt.Format())->AvgTimePerFrame;
  432. ((VIDEOINFOHEADER*)pmt->Format())->dwBitRate = ((VIDEOINFOHEADER*)mt.Format())->dwBitRate;
  433. ((VIDEOINFOHEADER*)pmt->Format())->dwBitErrorRate = ((VIDEOINFOHEADER*)mt.Format())->dwBitErrorRate;
  434. CorrectMediaType(pmt);
  435. return S_OK;
  436. }
  437. HRESULT CBaseVideoFilter::SetMediaType(PIN_DIRECTION dir, const CMediaType* pmt)
  438. {
  439. if(dir == PINDIR_INPUT)
  440. {
  441. m_w = m_h = m_arx = m_ary = 0;
  442. ExtractDim(pmt, m_w, m_h, m_arx, m_ary);
  443. m_win = m_w;
  444. m_hin = m_h;
  445. m_arxin = m_arx;
  446. m_aryin = m_ary;
  447. GetOutputSize(m_w, m_h, m_arx, m_ary);
  448. }
  449. else if(dir == PINDIR_OUTPUT)
  450. {
  451. int wout = 0, hout = 0, arxout = 0, aryout = 0;
  452. ExtractDim(pmt, wout, hout, arxout, aryout);
  453. if(m_w == wout && m_h == hout && m_arx == arxout && m_ary == aryout)
  454. {
  455. m_wout = wout;
  456. m_hout = hout;
  457. m_arxout = arxout;
  458. m_aryout = aryout;
  459. }
  460. }
  461. return __super::SetMediaType(dir, pmt);
  462. }
  463. //
  464. // CBaseVideoInputAllocator
  465. //
  466. CBaseVideoInputAllocator::CBaseVideoInputAllocator(HRESULT* phr)
  467. : CMemAllocator(NAME("CBaseVideoInputAllocator"), NULL, phr)
  468. {
  469. if(phr) *phr = S_OK;
  470. }
  471. void CBaseVideoInputAllocator::SetMediaType(const CMediaType& mt)
  472. {
  473. m_mt = mt;
  474. }
  475. STDMETHODIMP CBaseVideoInputAllocator::GetBuffer(IMediaSample** ppBuffer, REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime, DWORD dwFlags)
  476. {
  477. if(!m_bCommitted)
  478.         return VFW_E_NOT_COMMITTED;
  479. HRESULT hr = __super::GetBuffer(ppBuffer, pStartTime, pEndTime, dwFlags);
  480. if(SUCCEEDED(hr) && m_mt.majortype != GUID_NULL)
  481. {
  482. (*ppBuffer)->SetMediaType(&m_mt);
  483. m_mt.majortype = GUID_NULL;
  484. }
  485. return hr;
  486. }
  487. //
  488. // CBaseVideoInputPin
  489. //
  490. CBaseVideoInputPin::CBaseVideoInputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName) 
  491. : CTransformInputPin(pObjectName, pFilter, phr, pName)
  492. , m_pAllocator(NULL)
  493. {
  494. }
  495. CBaseVideoInputPin::~CBaseVideoInputPin()
  496. {
  497. delete m_pAllocator;
  498. }
  499. STDMETHODIMP CBaseVideoInputPin::GetAllocator(IMemAllocator** ppAllocator)
  500. {
  501.     CheckPointer(ppAllocator, E_POINTER);
  502.     if(m_pAllocator == NULL)
  503. {
  504. HRESULT hr = S_OK;
  505.         m_pAllocator = new CBaseVideoInputAllocator(&hr);
  506.         m_pAllocator->AddRef();
  507.     }
  508.     (*ppAllocator = m_pAllocator)->AddRef();
  509.     return S_OK;
  510. STDMETHODIMP CBaseVideoInputPin::ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt)
  511. {
  512. CAutoLock cObjectLock(m_pLock);
  513. if(m_Connected)
  514. {
  515. CMediaType mt(*pmt);
  516. if(FAILED(CheckMediaType(&mt)))
  517. return VFW_E_TYPE_NOT_ACCEPTED;
  518. ALLOCATOR_PROPERTIES props, actual;
  519. CComPtr<IMemAllocator> pMemAllocator;
  520. if(FAILED(GetAllocator(&pMemAllocator))
  521. || FAILED(pMemAllocator->Decommit())
  522. || FAILED(pMemAllocator->GetProperties(&props)))
  523. return E_FAIL;
  524. BITMAPINFOHEADER bih;
  525. if(ExtractBIH(pmt, &bih) && bih.biSizeImage)
  526. props.cbBuffer = bih.biSizeImage;
  527. if(FAILED(pMemAllocator->SetProperties(&props, &actual))
  528. || FAILED(pMemAllocator->Commit())
  529. || props.cbBuffer != actual.cbBuffer)
  530. return E_FAIL;
  531. if(m_pAllocator) 
  532. m_pAllocator->SetMediaType(mt);
  533. return SetMediaType(&mt) == S_OK
  534. ? S_OK
  535. : VFW_E_TYPE_NOT_ACCEPTED;
  536. }
  537. return __super::ReceiveConnection(pConnector, pmt);
  538. }
  539. //
  540. // CBaseVideoOutputPin
  541. //
  542. CBaseVideoOutputPin::CBaseVideoOutputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName)
  543. : CTransformOutputPin(pObjectName, pFilter, phr, pName)
  544. {
  545. }
  546. HRESULT CBaseVideoOutputPin::CheckMediaType(const CMediaType* mtOut)
  547. {
  548. if(IsConnected())
  549. {
  550. HRESULT hr = ((CBaseVideoFilter*)m_pFilter)->CheckOutputType(*mtOut);
  551. if(FAILED(hr)) return hr;
  552. }
  553. return __super::CheckMediaType(mtOut);
  554. }