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

多媒体编程

开发平台:

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 <atlbase.h>
  23. #include "......DSUtilMediaTypes.h"
  24. #include <initguid.h>
  25. #include "qtdec.h"
  26. using namespace QT;
  27. static DWORD DWSWAP(DWORD dw) {return(((dw&0xff)<<24)|((dw&0xff00)<<8)|((dw&0xff0000)>>8)|((dw&0xff000000)>>24));}
  28. #ifdef REGISTER_FILTER
  29. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  30. {
  31. {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
  32. };
  33. const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
  34. {
  35. {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
  36. };
  37. const AMOVIESETUP_PIN sudpPins[] =
  38. {
  39.     { L"Input",             // Pins string name
  40.       FALSE,                // Is it rendered
  41.       FALSE,                // Is it an output
  42.       FALSE,                // Are we allowed none
  43.       FALSE,                // And allowed many
  44.       &CLSID_NULL,          // Connects to filter
  45.       NULL,                 // Connects to pin
  46.       countof(sudPinTypesIn), // Number of types
  47.       sudPinTypesIn // Pin information
  48.     },
  49.     { L"Output",            // Pins string name
  50.       FALSE,                // Is it rendered
  51.       TRUE,                 // Is it an output
  52.       FALSE,                // Are we allowed none
  53.       FALSE,                // And allowed many
  54.       &CLSID_NULL,          // Connects to filter
  55.       NULL,                 // Connects to pin
  56.       countof(sudPinTypesOut), // Number of types
  57.       sudPinTypesOut // Pin information
  58.     }
  59. };
  60. const AMOVIESETUP_FILTER sudFilter =
  61. {
  62.     &CLSID_QTDec, // Filter CLSID
  63.     L"QuickTime Decoder", // String name
  64.     MERIT_DO_NOT_USE/*MERIT_NORMAL*/, // Filter merit
  65.     countof(sudpPins), // Number of pins
  66.     sudpPins                // Pin information
  67. };
  68. CFactoryTemplate g_Templates[] =
  69. {
  70.     { L"QuickTime Decoder"
  71.     , &CLSID_QTDec
  72.     , CQTDec::CreateInstance
  73.     , NULL
  74.     , &sudFilter }
  75. };
  76. int g_cTemplates = countof(g_Templates);
  77. STDAPI DllRegisterServer()
  78. {
  79. return AMovieDllRegisterServer2(TRUE);
  80. }
  81. STDAPI DllUnregisterServer()
  82. {
  83. return AMovieDllRegisterServer2(FALSE);
  84. }
  85. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  86. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  87. {
  88.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  89. }
  90. //
  91. // CQTDec
  92. //
  93. CUnknown* WINAPI CQTDec::CreateInstance(LPUNKNOWN lpunk, HRESULT* phr)
  94. {
  95.     CUnknown* punk = new CQTDec(lpunk, phr);
  96.     if(punk == NULL) *phr = E_OUTOFMEMORY;
  97. return punk;
  98. }
  99. #endif
  100. CQTDec::CQTDec(LPUNKNOWN lpunk, HRESULT* phr)
  101. : CTransformFilter(NAME("CQTDec"), lpunk, CLSID_QTDec)
  102. , m_fQtInitialized(false)
  103. , m_pImageGWorld(NULL)
  104. , m_hImageDesc(NULL)
  105. , m_cinst(NULL)
  106. {
  107. if(phr) *phr = S_OK;
  108. m_fQtInitialized = false;
  109. if(InitializeQTML(0) != 0) {if(phr) *phr = E_FAIL; return;}
  110. // if(EnterMovies() != 0) {TerminateQTML(); if(phr) *phr = E_FAIL; return;}
  111. m_fQtInitialized = true;
  112. }
  113. CQTDec::~CQTDec()
  114. {
  115. if(m_cinst)
  116. CloseComponent(m_cinst),
  117. m_cinst = NULL;
  118. if(m_hImageDesc)
  119. DisposeHandle((Handle)m_hImageDesc), 
  120. m_hImageDesc = NULL;
  121. FreeGWorld(m_pImageGWorld);
  122. if(m_fQtInitialized)
  123. {
  124. // ExitMovies();
  125. TerminateQTML();
  126. }
  127. }
  128. //
  129. GWorldPtr CQTDec::MakeGWorld()
  130. {
  131. if(!m_pOutput->IsConnected())
  132. return NULL;
  133. const CMediaType& mt = m_pOutput->CurrentMediaType();
  134. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
  135. BITMAPINFOHEADER& bih = vih->bmiHeader;
  136. GWorldPtr pImageWorld = NULL;
  137. Rect rect = {0, 0, (short)abs(bih.biHeight), (short)bih.biWidth};
  138. OSType PixelFormat = 
  139. mt.subtype == MEDIASUBTYPE_YUY2 ? kYUVSPixelFormat : // 'yuvs'
  140. mt.subtype == MEDIASUBTYPE_UYVY ? k2vuyPixelFormat : // '2vuy'
  141. mt.subtype == MEDIASUBTYPE_RGB32 ? k32BGRAPixelFormat : // 'BGRA'
  142. mt.subtype == MEDIASUBTYPE_RGB565 ? k16LE565PixelFormat : // 'L565'
  143. mt.subtype == MEDIASUBTYPE_RGB555 ? k16LE555PixelFormat : // 'L555'
  144. 0;
  145. if(!PixelFormat || noErr != QTNewGWorld(&pImageWorld, PixelFormat, &rect, NULL, NULL, 0))
  146. pImageWorld = NULL;
  147. if(pImageWorld)
  148.         LockPixels(GetGWorldPixMap(pImageWorld));
  149. return pImageWorld;
  150. }
  151. void CQTDec::FreeGWorld(GWorldPtr& pImageGWorld)
  152. {
  153. if(pImageGWorld)
  154. {
  155.         UnlockPixels(GetGWorldPixMap(pImageGWorld));
  156. DisposeGWorld(pImageGWorld);
  157. pImageGWorld = NULL;
  158. }
  159. }
  160. bool CQTDec::InitComponent()
  161. {
  162. if(m_cinst)
  163. CloseComponent(m_cinst),
  164. m_cinst = NULL;
  165. if(m_hImageDesc)
  166. DisposeHandle((Handle)m_hImageDesc), 
  167. m_hImageDesc = NULL;
  168. if(!m_pInput->IsConnected())
  169. return NULL;
  170. BITMAPINFOHEADER& bih = ((VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat)->bmiHeader;
  171. ComponentDescription cd = {decompressorComponentType, DWSWAP(bih.biCompression), 0, 0, 0};
  172. Component c = FindNextComponent(0, &cd);
  173. if(!c) return(false);
  174. m_cinst = OpenComponent(c);
  175. if(!m_cinst) return(false);
  176. ComponentResult cres;
  177.     ImageSubCodecDecompressCapabilities icap;
  178.     memset(&icap, 0, sizeof(icap));
  179.     cres = ImageCodecInitialize(m_cinst, &icap);
  180.     CodecInfo cinfo;
  181.     memset(&cinfo, 0, sizeof(cinfo));
  182.     cres = ImageCodecGetCodecInfo(m_cinst, &cinfo);
  183. m_hImageDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
  184. if(!m_hImageDesc)
  185. return(false);
  186.     (**m_hImageDesc).idSize = sizeof(ImageDescription);
  187. (**m_hImageDesc).cType = DWSWAP(bih.biCompression);
  188.     (**m_hImageDesc).temporalQuality = 0;
  189.     (**m_hImageDesc).spatialQuality = codecNormalQuality;
  190. (**m_hImageDesc).width = (short)bih.biWidth;
  191.     (**m_hImageDesc).height = (short)abs(bih.biHeight);
  192.     (**m_hImageDesc).hRes = 72 << 16;
  193.     (**m_hImageDesc).vRes = 72 << 16;
  194.     (**m_hImageDesc).frameCount = 1; // ?
  195. (**m_hImageDesc).depth = bih.biBitCount; // should be 24 for unknown/compressed types
  196.     (**m_hImageDesc).clutID = -1;
  197. memset(&m_cdpar, 0, sizeof(m_cdpar));
  198.     m_cdpar.imageDescription = m_hImageDesc;
  199.     m_cdpar.startLine = 0;
  200.     m_cdpar.stopLine = (**m_hImageDesc).height;
  201.     m_cdpar.frameNumber = 1;
  202.     m_cdpar.matrixFlags = 0;
  203.     m_cdpar.matrixType = 0;
  204.     m_cdpar.matrix = 0;
  205.     m_cdpar.capabilities = &m_ccap;
  206. memset(&m_ccap, 0, sizeof(m_ccap));
  207.     m_cdpar.accuracy = codecNormalQuality;
  208.     m_cdpar.port = m_pImageGWorld;
  209. Rect rect = {0, 0, (**m_hImageDesc).height, (**m_hImageDesc).width};
  210. m_cdpar.srcRect = rect;
  211.     m_cdpar.transferMode = srcCopy;
  212.     m_cdpar.dstPixMap = **GetGWorldPixMap(m_pImageGWorld);
  213.     cres = ImageCodecPreDecompress(m_cinst, &m_cdpar);
  214. return(true);
  215. }
  216. //
  217. HRESULT CQTDec::BreakConnect(PIN_DIRECTION dir)
  218. {
  219. if(dir == PINDIR_INPUT)
  220. {
  221. m_mts.RemoveAll();
  222. }
  223. else if(dir == PINDIR_OUTPUT)
  224. {
  225. FreeGWorld(m_pImageGWorld);
  226. }
  227. return __super::BreakConnect(dir);
  228. }
  229. HRESULT CQTDec::CompleteConnect(PIN_DIRECTION dir, IPin* pReceivePin)
  230. {
  231. if(dir == PINDIR_INPUT)
  232. {
  233. m_mts.RemoveAll();
  234. VIDEOINFOHEADER* vihin = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
  235. BITMAPINFOHEADER& bihin = vihin->bmiHeader;
  236. CMediaType mt;
  237. mt.majortype = MEDIATYPE_Video;
  238. mt.subtype = MEDIASUBTYPE_None;
  239. mt.formattype = FORMAT_VideoInfo;
  240. mt.bFixedSizeSamples = TRUE;
  241. mt.bTemporalCompression = FALSE;
  242. mt.lSampleSize = 0;
  243. mt.pUnk = NULL;
  244. VIDEOINFOHEADER vih;
  245. memset(&vih, 0, sizeof(vih));
  246. vih.AvgTimePerFrame = vihin->AvgTimePerFrame;
  247. vih.rcSource = vihin->rcSource;
  248. vih.rcTarget = vihin->rcTarget;
  249. vih.dwBitRate = vihin->dwBitRate;
  250. vih.dwBitErrorRate = vihin->dwBitErrorRate;
  251. BITMAPINFOHEADER& bih = vih.bmiHeader;
  252. bih.biSize = sizeof(bih);
  253. bih.biWidth = bihin.biWidth;
  254. bih.biHeight = abs(bihin.biHeight);
  255. bih.biPlanes = 1;
  256. bih.biXPelsPerMeter = bih.biYPelsPerMeter = 0;
  257. bih.biClrUsed = bih.biClrImportant = 0;
  258. // if(fRGB32) // always can decompress to (?)
  259. {
  260. VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  261. memcpy(vihout, &vih, sizeof(vih));
  262. BITMAPINFOHEADER& bihout = vihout->bmiHeader;
  263. bihout.biBitCount = 32;
  264. bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
  265. mt.subtype = MEDIASUBTYPE_RGB32;
  266. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  267. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  268. CorrectMediaType(&mt);
  269. m_mts.Add(mt);
  270. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  271. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  272. CorrectMediaType(&mt);
  273. m_mts.Add(mt);
  274. }
  275. // if(fRGB16) // always can decompress to (?)
  276. {
  277. VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  278. memcpy(vihout, &vih, sizeof(vih));
  279. BITMAPINFOHEADER& bihout = vihout->bmiHeader;
  280. bihout.biBitCount = 16;
  281. bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
  282. mt.subtype = MEDIASUBTYPE_RGB565;
  283. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  284. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  285. CorrectMediaType(&mt);
  286. m_mts.Add(mt);
  287. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  288. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  289. CorrectMediaType(&mt);
  290. m_mts.Add(mt);
  291. mt.subtype = MEDIASUBTYPE_RGB555;
  292. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  293. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  294. CorrectMediaType(&mt);
  295. m_mts.Add(mt);
  296. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  297. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  298. CorrectMediaType(&mt);
  299. m_mts.Add(mt);
  300. }
  301. }
  302. else if(dir == PINDIR_OUTPUT)
  303. {
  304. FreeGWorld(m_pImageGWorld);
  305. m_pImageGWorld = MakeGWorld();
  306. }
  307. return __super::CompleteConnect(dir, pReceivePin);
  308. }
  309. HRESULT CQTDec::Transform(IMediaSample* pSample, IMediaSample* pOutSample)
  310. {
  311. HRESULT hr;
  312. BYTE* pIn = NULL;
  313. if(FAILED(hr = pSample->GetPointer(&pIn))) return hr;
  314. long len = pSample->GetActualDataLength();
  315. if(len <= 0) return S_FALSE;
  316. BYTE* pOut = NULL;
  317. if(FAILED(hr = pOutSample->GetPointer(&pOut))) return hr;
  318. int size = pOutSample->GetSize();
  319. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pOutput->CurrentMediaType().pbFormat;
  320. BITMAPINFOHEADER& bih = vih->bmiHeader;
  321. bool fInitialized = true;
  322. if(m_cinst)
  323. {
  324. AM_MEDIA_TYPE* pmt = NULL;
  325. if(S_OK == pSample->GetMediaType((AM_MEDIA_TYPE**)&pmt) && pmt)
  326. {
  327. CMediaType mt(*pmt);
  328. DeleteMediaType(pmt), pmt = NULL;
  329. if(mt != m_pInput->CurrentMediaType())
  330. {
  331. m_pInput->SetMediaType(&mt);
  332. fInitialized = InitComponent();
  333. }
  334. }
  335. }
  336. else
  337. {
  338. fInitialized = InitComponent();
  339. }
  340. if(!fInitialized)
  341. return E_FAIL;
  342. m_cdpar.data = (Ptr)pIn;
  343. m_cdpar.bufferSize = len;
  344. (**m_cdpar.imageDescription).dataSize = len;
  345.     ComponentResult cres = ImageCodecBandDecompress(m_cinst, &m_cdpar);
  346.     m_cdpar.frameNumber++;
  347. if(cres == noErr)
  348. {
  349. PixMapHandle hPixMap = GetGWorldPixMap(m_pImageGWorld);
  350. Ptr pPixels = GetPixBaseAddr(hPixMap);
  351. long theRowBytes = QTGetPixMapHandleRowBytes(hPixMap);
  352. DWORD pitch = bih.biWidth*bih.biBitCount>>3;
  353. for(int i = 0, h = abs(bih.biHeight); i < h; i++)
  354. {
  355. memcpy(pOut + i*pitch, (BYTE*)pPixels + i*theRowBytes, min(pitch, theRowBytes));
  356. }
  357. }
  358. return S_OK;
  359. }
  360. HRESULT CQTDec::CheckInputType(const CMediaType* mtIn)
  361. {
  362. if(mtIn->majortype != MEDIATYPE_Video || mtIn->formattype != FORMAT_VideoInfo)
  363. return VFW_E_TYPE_NOT_ACCEPTED;
  364. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mtIn->pbFormat;
  365. BITMAPINFOHEADER& bih = vih->bmiHeader;
  366. OSErr err;
  367. ComponentInstance ci;
  368. if(noErr == (err = OpenADefaultComponent('imdc', DWSWAP(bih.biCompression), &ci)))
  369. {
  370. err = CloseComponent(ci);
  371. return S_OK;
  372. }
  373. return VFW_E_TYPE_NOT_ACCEPTED;
  374. }
  375. HRESULT CQTDec::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  376. {
  377. return S_OK;
  378. // TODO
  379. return VFW_E_TYPE_NOT_ACCEPTED;
  380. }
  381. HRESULT CQTDec::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  382. {
  383. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  384. CComPtr<IMemAllocator> pAllocatorIn;
  385. m_pInput->GetAllocator(&pAllocatorIn);
  386. if(!pAllocatorIn) return E_UNEXPECTED;
  387. pAllocatorIn->GetProperties(pProperties);
  388. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
  389. BITMAPINFOHEADER& bih = vih->bmiHeader;
  390. pProperties->cBuffers = 1;
  391. pProperties->cbBuffer = bih.biWidth*abs(bih.biHeight)*4; // TODO
  392. pProperties->cbAlign = 1;
  393. pProperties->cbPrefix = 0;
  394. HRESULT hr;
  395. ALLOCATOR_PROPERTIES Actual;
  396.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  397. return hr;
  398.     return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  399. ? E_FAIL
  400. : NOERROR);
  401. }
  402. HRESULT CQTDec::GetMediaType(int iPosition, CMediaType* pmt)
  403. {
  404.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  405. if(iPosition < 0) return E_INVALIDARG;
  406. if(iPosition >= m_mts.GetCount()) return VFW_S_NO_MORE_ITEMS;
  407. *pmt = m_mts[iPosition];
  408. return S_OK;
  409. }