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

多媒体编程

开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include <atlbase.h>
  3. #include "......DSUtilMediaTypes.h"
  4. #include <initguid.h>
  5. #include "qtdec.h"
  6. using namespace QT;
  7. static DWORD DWSWAP(DWORD dw) {return(((dw&0xff)<<24)|((dw&0xff00)<<8)|((dw&0xff0000)>>8)|((dw&0xff000000)>>24));}
  8. #ifdef REGISTER_FILTER
  9. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  10. {
  11. {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
  12. };
  13. const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
  14. {
  15. {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
  16. };
  17. const AMOVIESETUP_PIN sudpPins[] =
  18. {
  19.     { L"Input",             // Pins string name
  20.       FALSE,                // Is it rendered
  21.       FALSE,                // Is it an output
  22.       FALSE,                // Are we allowed none
  23.       FALSE,                // And allowed many
  24.       &CLSID_NULL,          // Connects to filter
  25.       NULL,                 // Connects to pin
  26.       countof(sudPinTypesIn), // Number of types
  27.       sudPinTypesIn // Pin information
  28.     },
  29.     { L"Output",            // Pins string name
  30.       FALSE,                // Is it rendered
  31.       TRUE,                 // Is it an output
  32.       FALSE,                // Are we allowed none
  33.       FALSE,                // And allowed many
  34.       &CLSID_NULL,          // Connects to filter
  35.       NULL,                 // Connects to pin
  36.       countof(sudPinTypesOut), // Number of types
  37.       sudPinTypesOut // Pin information
  38.     }
  39. };
  40. const AMOVIESETUP_FILTER sudFilter =
  41. {
  42.     &CLSID_QTDec, // Filter CLSID
  43.     L"QuickTime Decoder", // String name
  44.     MERIT_DO_NOT_USE/*MERIT_NORMAL*/, // Filter merit
  45.     countof(sudpPins), // Number of pins
  46.     sudpPins                // Pin information
  47. };
  48. CFactoryTemplate g_Templates[] =
  49. {
  50.     { L"QuickTime Decoder"
  51.     , &CLSID_QTDec
  52.     , CQTDec::CreateInstance
  53.     , NULL
  54.     , &sudFilter }
  55. };
  56. int g_cTemplates = countof(g_Templates);
  57. STDAPI DllRegisterServer()
  58. {
  59. return AMovieDllRegisterServer2(TRUE);
  60. }
  61. STDAPI DllUnregisterServer()
  62. {
  63. return AMovieDllRegisterServer2(FALSE);
  64. }
  65. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  66. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  67. {
  68.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  69. }
  70. //
  71. // CQTDec
  72. //
  73. CUnknown* WINAPI CQTDec::CreateInstance(LPUNKNOWN lpunk, HRESULT* phr)
  74. {
  75.     CUnknown* punk = new CQTDec(lpunk, phr);
  76.     if(punk == NULL) *phr = E_OUTOFMEMORY;
  77. return punk;
  78. }
  79. #endif
  80. CQTDec::CQTDec(LPUNKNOWN lpunk, HRESULT* phr)
  81. : CTransformFilter(NAME("CQTDec"), lpunk, CLSID_QTDec)
  82. , m_fQtInitialized(false)
  83. , m_hImageDescription(NULL)
  84. , m_pImageGWorld(NULL)
  85. {
  86. if(phr) *phr = S_OK;
  87. m_fQtInitialized = false;
  88. if(InitializeQTML(0) != 0) {if(phr) *phr = E_FAIL; return;}
  89. // if(EnterMovies() != 0) {TerminateQTML(); if(phr) *phr = E_FAIL; return;}
  90. m_fQtInitialized = true;
  91. }
  92. CQTDec::~CQTDec()
  93. {
  94. FreeImageDescription(m_hImageDescription);
  95. FreeGWorld(m_pImageGWorld);
  96. if(m_fQtInitialized)
  97. {
  98. // ExitMovies();
  99. TerminateQTML();
  100. }
  101. }
  102. //
  103. bool CQTDec::CanDecompress(OSType fourcc, bool& fYUY2, bool& fUYVY)
  104. {
  105. fYUY2 = fUYVY = false;
  106. ComponentDescription cd = {decompressorComponentType, fourcc, 0, 0, cmpIsMissing};
  107. if(Component decompressor = FindNextComponent(0, &cd))
  108. {
  109. do
  110. {
  111. OSErr err;
  112. Handle cpix = NULL;
  113. if(noErr == (err = GetComponentPublicResource(decompressor, FOUR_CHAR_CODE('cpix'), 1, &cpix)))
  114. {
  115. int cpixFormatCount = GetHandleSize(cpix) / sizeof(OSType);
  116. for(int i = 0; i < cpixFormatCount; i++)
  117. {
  118. switch((*(OSType**)cpix)[i])
  119. {
  120. case 'yuvs': fYUY2 = true; break; // yuy2
  121. case '2vuy': fUYVY = true; break; // uyvy
  122. default: break;
  123. }
  124. }
  125. DisposeHandle(cpix);
  126. }
  127. decompressor = FindNextComponent(decompressor, &cd);
  128. }
  129. while(decompressor && !(fYUY2 && fUYVY));
  130. return(true);
  131. }
  132. return(false);
  133. }
  134. ImageDescriptionHandle CQTDec::MakeImageDescription()
  135. {
  136. if(!m_pInput->IsConnected())
  137. return NULL;
  138. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
  139. BITMAPINFOHEADER& bih = vih->bmiHeader;
  140. ImageDescriptionHandle h = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
  141.     if(h)
  142. {
  143.         (**h).idSize = sizeof(ImageDescription);
  144. (**h).cType = DWSWAP(bih.biCompression);
  145.         (**h).temporalQuality = 0;
  146.         (**h).spatialQuality = codecNormalQuality;
  147. (**h).width = (short)bih.biWidth;
  148.         (**h).height = (short)abs(bih.biHeight);
  149.         (**h).hRes = 72 << 16;
  150.         (**h).vRes = 72 << 16;
  151.         (**h).frameCount = 1; // ?
  152. (**h).depth = bih.biBitCount; // should be 24 for unknown/compressed types
  153.         (**h).clutID = -1;
  154.     }
  155.     return h;
  156. }
  157. GWorldPtr CQTDec::MakeGWorld()
  158. {
  159. if(!m_pOutput->IsConnected())
  160. return NULL;
  161. const CMediaType& mt = m_pOutput->CurrentMediaType();
  162. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
  163. BITMAPINFOHEADER& bih = vih->bmiHeader;
  164. GWorldPtr pImageWorld = NULL;
  165. Rect rect = {0, 0, (short)abs(bih.biHeight), (short)bih.biWidth};
  166. OSType PixelFormat = 
  167. mt.subtype == MEDIASUBTYPE_YUY2 ? kYUVSPixelFormat : // 'yuvs'
  168. mt.subtype == MEDIASUBTYPE_UYVY ? k2vuyPixelFormat : // '2vuy'
  169. mt.subtype == MEDIASUBTYPE_RGB32 ? k32BGRAPixelFormat : // 'BGRA'
  170. mt.subtype == MEDIASUBTYPE_RGB565 ? k16LE565PixelFormat : // 'L565'
  171. mt.subtype == MEDIASUBTYPE_RGB555 ? k16LE555PixelFormat : // 'L555'
  172. 0;
  173. if(!PixelFormat || noErr != QTNewGWorld(&pImageWorld, PixelFormat, &rect, NULL, NULL, 0))
  174. pImageWorld = NULL;
  175. if(pImageWorld)
  176.         LockPixels(GetGWorldPixMap(pImageWorld));
  177. return pImageWorld;
  178. }
  179. void CQTDec::FreeImageDescription(ImageDescriptionHandle& hImageDescription)
  180. {
  181. if(hImageDescription)
  182. {
  183. DisposeHandle((Handle)hImageDescription);
  184. hImageDescription = NULL;
  185. }
  186. }
  187. void CQTDec::FreeGWorld(GWorldPtr& pImageGWorld)
  188. {
  189. if(pImageGWorld)
  190. {
  191.         UnlockPixels(GetGWorldPixMap(pImageGWorld));
  192. DisposeGWorld(pImageGWorld);
  193. pImageGWorld = NULL;
  194. }
  195. }
  196. //
  197. HRESULT CQTDec::BreakConnect(PIN_DIRECTION dir)
  198. {
  199. if(dir == PINDIR_INPUT)
  200. {
  201. m_mts.RemoveAll();
  202. }
  203. else if(dir == PINDIR_OUTPUT)
  204. {
  205. FreeImageDescription(m_hImageDescription);
  206. FreeGWorld(m_pImageGWorld);
  207. }
  208. return __super::BreakConnect(dir);
  209. }
  210. HRESULT CQTDec::CompleteConnect(PIN_DIRECTION dir, IPin* pReceivePin)
  211. {
  212. if(dir == PINDIR_INPUT)
  213. {
  214. m_mts.RemoveAll();
  215. VIDEOINFOHEADER* vihin = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
  216. BITMAPINFOHEADER& bihin = vihin->bmiHeader;
  217. bool fYUY2 = false, fUYVY = false;
  218. if(CanDecompress(DWSWAP(bihin.biCompression), fYUY2, fUYVY))
  219. {
  220. CMediaType mt;
  221. mt.majortype = MEDIATYPE_Video;
  222. mt.subtype = MEDIASUBTYPE_None;
  223. mt.formattype = FORMAT_VideoInfo;
  224. mt.bFixedSizeSamples = TRUE;
  225. mt.bTemporalCompression = FALSE;
  226. mt.lSampleSize = 0;
  227. mt.pUnk = NULL;
  228. VIDEOINFOHEADER vih;
  229. memset(&vih, 0, sizeof(vih));
  230. vih.AvgTimePerFrame = vihin->AvgTimePerFrame;
  231. vih.rcSource = vihin->rcSource;
  232. vih.rcTarget = vihin->rcTarget;
  233. vih.dwBitRate = vihin->dwBitRate;
  234. vih.dwBitErrorRate = vihin->dwBitErrorRate;
  235. BITMAPINFOHEADER& bih = vih.bmiHeader;
  236. bih.biSize = sizeof(bih);
  237. bih.biWidth = bihin.biWidth;
  238. bih.biHeight = abs(bihin.biHeight);
  239. bih.biPlanes = 1;
  240. bih.biXPelsPerMeter = bih.biYPelsPerMeter = 0;
  241. bih.biClrUsed = bih.biClrImportant = 0;
  242. /*
  243. if(fYUY2 || fUYVY)
  244. {
  245. VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  246. memcpy(vihout, &vih, sizeof(vih));
  247. BITMAPINFOHEADER& bihout = vihout->bmiHeader;
  248. bihout.biBitCount = 16;
  249. bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
  250. if(fYUY2)
  251. {
  252. mt.subtype = MEDIASUBTYPE_YUY2;
  253. bihout.biCompression = '2YUY';
  254. m_mts.Add(mt);
  255. }
  256. if(fUYVY)
  257. {
  258. mt.subtype = MEDIASUBTYPE_UYVY;
  259. bihout.biCompression = 'YVYU';
  260.                     m_mts.Add(mt);
  261. }
  262. }
  263. */
  264. // if(fRGB32) // always can decompress to (?)
  265. {
  266. VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  267. memcpy(vihout, &vih, sizeof(vih));
  268. BITMAPINFOHEADER& bihout = vihout->bmiHeader;
  269. bihout.biBitCount = 32;
  270. bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
  271. mt.subtype = MEDIASUBTYPE_RGB32;
  272. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  273. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  274. CorrectMediaType(&mt);
  275. m_mts.Add(mt);
  276. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  277. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  278. CorrectMediaType(&mt);
  279. m_mts.Add(mt);
  280. }
  281. // if(fRGB16) // always can decompress to (?)
  282. {
  283. VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  284. memcpy(vihout, &vih, sizeof(vih));
  285. BITMAPINFOHEADER& bihout = vihout->bmiHeader;
  286. bihout.biBitCount = 16;
  287. bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
  288. mt.subtype = MEDIASUBTYPE_RGB565;
  289. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  290. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  291. CorrectMediaType(&mt);
  292. m_mts.Add(mt);
  293. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  294. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  295. CorrectMediaType(&mt);
  296. m_mts.Add(mt);
  297. mt.subtype = MEDIASUBTYPE_RGB555;
  298. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  299. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  300. CorrectMediaType(&mt);
  301. m_mts.Add(mt);
  302. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  303. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  304. CorrectMediaType(&mt);
  305. m_mts.Add(mt);
  306. }
  307. }
  308. }
  309. else if(dir == PINDIR_OUTPUT)
  310. {
  311. FreeGWorld(m_pImageGWorld);
  312. m_pImageGWorld = MakeGWorld();
  313. }
  314. return __super::CompleteConnect(dir, pReceivePin);
  315. }
  316. HRESULT CQTDec::StartStreaming()
  317. {
  318. FreeImageDescription(m_hImageDescription);
  319. m_hImageDescription = MakeImageDescription();
  320. if(!m_hImageDescription)
  321. return E_FAIL;
  322. /*
  323.     Rect theSrcBounds = {0, 0};
  324.     Rect theDestBounds;
  325.     GetPortBounds((CGrafPtr)m_pImageGWorld, &theDestBounds);
  326.     theSrcBounds.right  = (*m_hImageDescription)->width;
  327.     theSrcBounds.bottom = (*m_hImageDescription)->height;
  328.     MatrixRecord rMatrix;
  329.     RectMatrix(&rMatrix, &theSrcBounds, &theDestBounds);
  330. */
  331.     m_outSeqID = 0;
  332. OSErr err;
  333. DecompressorComponent decompressor = NULL; 
  334. err = FindCodec((*m_hImageDescription)->cType, anyCodec, NULL, &decompressor);
  335. CodecInfo info;
  336. err = GetCodecInfo(&info, (*m_hImageDescription)->cType, decompressor);
  337.     err = DecompressSequenceBeginS(
  338. &m_outSeqID, m_hImageDescription, 
  339. NULL, 0, 
  340. m_pImageGWorld, NULL,
  341. NULL, NULL/*&rMatrix*/, srcCopy, (RgnHandle)NULL, 
  342. codecFlagUseImageBuffer, codecNormalQuality, anyCodec);
  343. if(noErr != err || m_outSeqID == 0)
  344. return E_FAIL;
  345. return __super::StartStreaming();
  346. }
  347. HRESULT CQTDec::StopStreaming()
  348. {
  349. if(m_outSeqID)
  350. {
  351.         OSErr err = CDSequenceEnd(m_outSeqID);
  352.         m_outSeqID = 0;
  353.     }
  354. FreeImageDescription(m_hImageDescription);
  355. return __super::StopStreaming();
  356. }
  357. HRESULT CQTDec::Transform(IMediaSample* pSample, IMediaSample* pOutSample)
  358. {
  359. HRESULT hr;
  360. BYTE* pIn = NULL;
  361. if(FAILED(hr = pSample->GetPointer(&pIn))) return hr;
  362. long len = pSample->GetActualDataLength();
  363. if(len <= 0) return S_FALSE;
  364. BYTE* pOut = NULL;
  365. if(FAILED(hr = pOutSample->GetPointer(&pOut))) return hr;
  366. int size = pOutSample->GetSize();
  367. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pOutput->CurrentMediaType().pbFormat;
  368. BITMAPINFOHEADER& bih = vih->bmiHeader;
  369. OSErr err;
  370. {
  371. AM_MEDIA_TYPE* pmt = NULL;
  372. if(S_OK == pSample->GetMediaType((AM_MEDIA_TYPE**)&pmt) && pmt)
  373. {
  374. CMediaType mt(*pmt);
  375. DeleteMediaType(pmt), pmt = NULL;
  376. if(mt != m_pInput->CurrentMediaType())
  377. {
  378. StopStreaming();
  379. m_pInput->SetMediaType(&mt);
  380. StartStreaming();
  381. }
  382. }
  383. }
  384. CodecFlags inf = codecFlagNoScreenUpdate, outf = 0;
  385. err = DecompressSequenceFrameWhen(m_outSeqID, (Ptr)pIn, len, inf, &outf, NULL, NULL);
  386. // if(err == noErr)
  387. {
  388. PixMapHandle hPixMap = GetGWorldPixMap(m_pImageGWorld);
  389. Ptr pPixels = GetPixBaseAddr(hPixMap);
  390. long theRowBytes = QTGetPixMapHandleRowBytes(hPixMap);
  391. DWORD pitch = bih.biWidth*bih.biBitCount>>3;
  392. for(int i = 0, h = abs(bih.biHeight); i < h; i++)
  393. {
  394. memcpy(pOut + i*pitch, (BYTE*)pPixels + i*theRowBytes, min(pitch, theRowBytes));
  395. }
  396. }
  397. /*
  398. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pOutput->CurrentMediaType().pbFormat;
  399. BITMAPINFOHEADER& bih = vih->bmiHeader;
  400. Rect myRect = {0, 0, (short)abs(bih.biHeight), (short)bih.biWidth};
  401. // GraphicsImportComponent myImporter = NULL;
  402. // ComponentInstance myComponent = NULL;
  403. GWorldPtr myImageWorld = NULL;
  404. PixMapHandle myPixMap = NULL;
  405. ImageDescriptionHandle myDesc = NULL;
  406. Handle myHandle = NULL;
  407. OSErr myErr = noErr;
  408. myErr = QTNewGWorld(&myImageWorld, 0, &myRect, NULL, NULL, noNewDevice|keepLocal);
  409. // myErr = QTNewGWorldFromPtr(&myImageWorld, k422YpCbCr8PixelFormat, &myRect, NULL, NULL, 0, pOut, bih.biWidth*bih.biBitCount>>3);
  410. if(myErr == noErr)
  411. {
  412. myPixMap = GetGWorldPixMap(myImageWorld);
  413. if(myDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription)))
  414. {
  415. ImageDescription& id = *(ImageDescription*)*myDesc;
  416. memset(&id, 0, sizeof(id));
  417. id.idSize = sizeof(id);
  418. id.cType = DWSWAP(((VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat)->bmiHeader.biCompression);
  419. id.temporalQuality = codecNormalQuality; // ?
  420. id.spatialQuality = codecNormalQuality; // ?
  421. id.width = (short)bih.biWidth;
  422. id.height = (short)bih.biHeight;
  423. id.depth = ((VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat)->bmiHeader.biBitCount;
  424. id.dataSize = len;
  425. id.hRes = 0;
  426. id.vRes = 0;
  427. id.frameCount = 1;
  428. id.clutID = -1; // TODO
  429. myErr = DecompressImage((Ptr)pIn, myDesc, myPixMap, NULL, &myRect, srcCopy, NULL);
  430. DisposeHandle((Handle)myDesc);
  431. }
  432. }
  433. if(myImageWorld) DisposeGWorld(myImageWorld);
  434. */
  435. /*
  436. // TODO
  437. pOutSample->SetActualDataLength(0);
  438. return S_FALSE;
  439. */
  440. return S_OK;
  441. }
  442. HRESULT CQTDec::CheckInputType(const CMediaType* mtIn)
  443. {
  444. if(mtIn->majortype != MEDIATYPE_Video || mtIn->formattype != FORMAT_VideoInfo)
  445. return VFW_E_TYPE_NOT_ACCEPTED;
  446. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mtIn->pbFormat;
  447. BITMAPINFOHEADER& bih = vih->bmiHeader;
  448. OSErr err;
  449. ComponentInstance ci;
  450. if(noErr == (err = OpenADefaultComponent('imdc', DWSWAP(bih.biCompression), &ci)))
  451. {
  452. err = CloseComponent(ci);
  453. return S_OK;
  454. }
  455. return VFW_E_TYPE_NOT_ACCEPTED;
  456. }
  457. HRESULT CQTDec::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  458. {
  459. return S_OK;
  460. // TODO
  461. return VFW_E_TYPE_NOT_ACCEPTED;
  462. }
  463. HRESULT CQTDec::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  464. {
  465. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  466. CComPtr<IMemAllocator> pAllocatorIn;
  467. m_pInput->GetAllocator(&pAllocatorIn);
  468. if(!pAllocatorIn) return E_UNEXPECTED;
  469. pAllocatorIn->GetProperties(pProperties);
  470. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
  471. BITMAPINFOHEADER& bih = vih->bmiHeader;
  472. pProperties->cBuffers = 1;
  473. pProperties->cbBuffer = bih.biWidth*abs(bih.biHeight)*4; // TODO
  474. pProperties->cbAlign = 1;
  475. pProperties->cbPrefix = 0;
  476. HRESULT hr;
  477. ALLOCATOR_PROPERTIES Actual;
  478.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  479. return hr;
  480.     return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  481. ? E_FAIL
  482. : NOERROR);
  483. }
  484. HRESULT CQTDec::GetMediaType(int iPosition, CMediaType* pmt)
  485. {
  486.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  487. if(iPosition < 0) return E_INVALIDARG;
  488. if(iPosition >= m_mts.GetCount()) return VFW_S_NO_MORE_ITEMS;
  489. *pmt = m_mts[iPosition];
  490. return S_OK;
  491. }