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

多媒体编程

开发平台:

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_pImageGWorld(NULL)
  84. , m_hImageDesc(NULL)
  85. , m_cinst(NULL)
  86. {
  87. if(phr) *phr = S_OK;
  88. m_fQtInitialized = false;
  89. if(InitializeQTML(0) != 0) {if(phr) *phr = E_FAIL; return;}
  90. // if(EnterMovies() != 0) {TerminateQTML(); if(phr) *phr = E_FAIL; return;}
  91. m_fQtInitialized = true;
  92. }
  93. CQTDec::~CQTDec()
  94. {
  95. if(m_cinst)
  96. CloseComponent(m_cinst),
  97. m_cinst = NULL;
  98. if(m_hImageDesc)
  99. DisposeHandle((Handle)m_hImageDesc), 
  100. m_hImageDesc = NULL;
  101. FreeGWorld(m_pImageGWorld);
  102. if(m_fQtInitialized)
  103. {
  104. // ExitMovies();
  105. TerminateQTML();
  106. }
  107. }
  108. //
  109. GWorldPtr CQTDec::MakeGWorld()
  110. {
  111. if(!m_pOutput->IsConnected())
  112. return NULL;
  113. const CMediaType& mt = m_pOutput->CurrentMediaType();
  114. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
  115. BITMAPINFOHEADER& bih = vih->bmiHeader;
  116. GWorldPtr pImageWorld = NULL;
  117. Rect rect = {0, 0, (short)abs(bih.biHeight), (short)bih.biWidth};
  118. OSType PixelFormat = 
  119. mt.subtype == MEDIASUBTYPE_YUY2 ? kYUVSPixelFormat : // 'yuvs'
  120. mt.subtype == MEDIASUBTYPE_UYVY ? k2vuyPixelFormat : // '2vuy'
  121. mt.subtype == MEDIASUBTYPE_RGB32 ? k32BGRAPixelFormat : // 'BGRA'
  122. mt.subtype == MEDIASUBTYPE_RGB565 ? k16LE565PixelFormat : // 'L565'
  123. mt.subtype == MEDIASUBTYPE_RGB555 ? k16LE555PixelFormat : // 'L555'
  124. 0;
  125. if(!PixelFormat || noErr != QTNewGWorld(&pImageWorld, PixelFormat, &rect, NULL, NULL, 0))
  126. pImageWorld = NULL;
  127. if(pImageWorld)
  128.         LockPixels(GetGWorldPixMap(pImageWorld));
  129. return pImageWorld;
  130. }
  131. void CQTDec::FreeGWorld(GWorldPtr& pImageGWorld)
  132. {
  133. if(pImageGWorld)
  134. {
  135.         UnlockPixels(GetGWorldPixMap(pImageGWorld));
  136. DisposeGWorld(pImageGWorld);
  137. pImageGWorld = NULL;
  138. }
  139. }
  140. bool CQTDec::InitComponent()
  141. {
  142. if(m_cinst)
  143. CloseComponent(m_cinst),
  144. m_cinst = NULL;
  145. if(m_hImageDesc)
  146. DisposeHandle((Handle)m_hImageDesc), 
  147. m_hImageDesc = NULL;
  148. if(!m_pInput->IsConnected())
  149. return NULL;
  150. BITMAPINFOHEADER& bih = ((VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat)->bmiHeader;
  151. ComponentDescription cd = {decompressorComponentType, DWSWAP(bih.biCompression), 0, 0, 0};
  152. Component c = FindNextComponent(0, &cd);
  153. if(!c) return(false);
  154. m_cinst = OpenComponent(c);
  155. if(!m_cinst) return(false);
  156. ComponentResult cres;
  157.     ImageSubCodecDecompressCapabilities icap;
  158.     memset(&icap, 0, sizeof(icap));
  159.     cres = ImageCodecInitialize(m_cinst, &icap);
  160.     CodecInfo cinfo;
  161.     memset(&cinfo, 0, sizeof(cinfo));
  162.     cres = ImageCodecGetCodecInfo(m_cinst, &cinfo);
  163. m_hImageDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
  164. if(!m_hImageDesc)
  165. return(false);
  166.     (**m_hImageDesc).idSize = sizeof(ImageDescription);
  167. (**m_hImageDesc).cType = DWSWAP(bih.biCompression);
  168.     (**m_hImageDesc).temporalQuality = 0;
  169.     (**m_hImageDesc).spatialQuality = codecNormalQuality;
  170. (**m_hImageDesc).width = (short)bih.biWidth;
  171.     (**m_hImageDesc).height = (short)abs(bih.biHeight);
  172.     (**m_hImageDesc).hRes = 72 << 16;
  173.     (**m_hImageDesc).vRes = 72 << 16;
  174.     (**m_hImageDesc).frameCount = 1; // ?
  175. (**m_hImageDesc).depth = bih.biBitCount; // should be 24 for unknown/compressed types
  176.     (**m_hImageDesc).clutID = -1;
  177. memset(&m_cdpar, 0, sizeof(m_cdpar));
  178.     m_cdpar.imageDescription = m_hImageDesc;
  179.     m_cdpar.startLine = 0;
  180.     m_cdpar.stopLine = (**m_hImageDesc).height;
  181.     m_cdpar.frameNumber = 1;
  182.     m_cdpar.matrixFlags = 0;
  183.     m_cdpar.matrixType = 0;
  184.     m_cdpar.matrix = 0;
  185.     m_cdpar.capabilities = &m_ccap;
  186. memset(&m_ccap, 0, sizeof(m_ccap));
  187.     m_cdpar.accuracy = codecNormalQuality;
  188.     m_cdpar.port = m_pImageGWorld;
  189. Rect rect = {0, 0, (**m_hImageDesc).height, (**m_hImageDesc).width};
  190. m_cdpar.srcRect = rect;
  191.     m_cdpar.transferMode = srcCopy;
  192.     m_cdpar.dstPixMap = **GetGWorldPixMap(m_pImageGWorld);
  193.     cres = ImageCodecPreDecompress(m_cinst, &m_cdpar);
  194. return(true);
  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. FreeGWorld(m_pImageGWorld);
  206. }
  207. return __super::BreakConnect(dir);
  208. }
  209. HRESULT CQTDec::CompleteConnect(PIN_DIRECTION dir, IPin* pReceivePin)
  210. {
  211. if(dir == PINDIR_INPUT)
  212. {
  213. m_mts.RemoveAll();
  214. VIDEOINFOHEADER* vihin = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
  215. BITMAPINFOHEADER& bihin = vihin->bmiHeader;
  216. CMediaType mt;
  217. mt.majortype = MEDIATYPE_Video;
  218. mt.subtype = MEDIASUBTYPE_None;
  219. mt.formattype = FORMAT_VideoInfo;
  220. mt.bFixedSizeSamples = TRUE;
  221. mt.bTemporalCompression = FALSE;
  222. mt.lSampleSize = 0;
  223. mt.pUnk = NULL;
  224. VIDEOINFOHEADER vih;
  225. memset(&vih, 0, sizeof(vih));
  226. vih.AvgTimePerFrame = vihin->AvgTimePerFrame;
  227. vih.rcSource = vihin->rcSource;
  228. vih.rcTarget = vihin->rcTarget;
  229. vih.dwBitRate = vihin->dwBitRate;
  230. vih.dwBitErrorRate = vihin->dwBitErrorRate;
  231. BITMAPINFOHEADER& bih = vih.bmiHeader;
  232. bih.biSize = sizeof(bih);
  233. bih.biWidth = bihin.biWidth;
  234. bih.biHeight = abs(bihin.biHeight);
  235. bih.biPlanes = 1;
  236. bih.biXPelsPerMeter = bih.biYPelsPerMeter = 0;
  237. bih.biClrUsed = bih.biClrImportant = 0;
  238. // if(fRGB32) // always can decompress to (?)
  239. {
  240. VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  241. memcpy(vihout, &vih, sizeof(vih));
  242. BITMAPINFOHEADER& bihout = vihout->bmiHeader;
  243. bihout.biBitCount = 32;
  244. bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
  245. mt.subtype = MEDIASUBTYPE_RGB32;
  246. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  247. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  248. CorrectMediaType(&mt);
  249. m_mts.Add(mt);
  250. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  251. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  252. CorrectMediaType(&mt);
  253. m_mts.Add(mt);
  254. }
  255. // if(fRGB16) // always can decompress to (?)
  256. {
  257. VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  258. memcpy(vihout, &vih, sizeof(vih));
  259. BITMAPINFOHEADER& bihout = vihout->bmiHeader;
  260. bihout.biBitCount = 16;
  261. bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
  262. mt.subtype = MEDIASUBTYPE_RGB565;
  263. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
  264. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
  265. CorrectMediaType(&mt);
  266. m_mts.Add(mt);
  267. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
  268. ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
  269. CorrectMediaType(&mt);
  270. m_mts.Add(mt);
  271. mt.subtype = MEDIASUBTYPE_RGB555;
  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. }
  282. else if(dir == PINDIR_OUTPUT)
  283. {
  284. FreeGWorld(m_pImageGWorld);
  285. m_pImageGWorld = MakeGWorld();
  286. }
  287. return __super::CompleteConnect(dir, pReceivePin);
  288. }
  289. HRESULT CQTDec::Transform(IMediaSample* pSample, IMediaSample* pOutSample)
  290. {
  291. HRESULT hr;
  292. BYTE* pIn = NULL;
  293. if(FAILED(hr = pSample->GetPointer(&pIn))) return hr;
  294. long len = pSample->GetActualDataLength();
  295. if(len <= 0) return S_FALSE;
  296. BYTE* pOut = NULL;
  297. if(FAILED(hr = pOutSample->GetPointer(&pOut))) return hr;
  298. int size = pOutSample->GetSize();
  299. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pOutput->CurrentMediaType().pbFormat;
  300. BITMAPINFOHEADER& bih = vih->bmiHeader;
  301. bool fInitialized = true;
  302. if(m_cinst)
  303. {
  304. AM_MEDIA_TYPE* pmt = NULL;
  305. if(S_OK == pSample->GetMediaType((AM_MEDIA_TYPE**)&pmt) && pmt)
  306. {
  307. CMediaType mt(*pmt);
  308. DeleteMediaType(pmt), pmt = NULL;
  309. if(mt != m_pInput->CurrentMediaType())
  310. {
  311. m_pInput->SetMediaType(&mt);
  312. fInitialized = InitComponent();
  313. }
  314. }
  315. }
  316. else
  317. {
  318. fInitialized = InitComponent();
  319. }
  320. if(!fInitialized)
  321. return E_FAIL;
  322. m_cdpar.data = (Ptr)pIn;
  323. m_cdpar.bufferSize = len;
  324. (**m_cdpar.imageDescription).dataSize = len;
  325.     ComponentResult cres = ImageCodecBandDecompress(m_cinst, &m_cdpar);
  326.     m_cdpar.frameNumber++;
  327. if(cres == noErr)
  328. {
  329. PixMapHandle hPixMap = GetGWorldPixMap(m_pImageGWorld);
  330. Ptr pPixels = GetPixBaseAddr(hPixMap);
  331. long theRowBytes = QTGetPixMapHandleRowBytes(hPixMap);
  332. DWORD pitch = bih.biWidth*bih.biBitCount>>3;
  333. for(int i = 0, h = abs(bih.biHeight); i < h; i++)
  334. {
  335. memcpy(pOut + i*pitch, (BYTE*)pPixels + i*theRowBytes, min(pitch, theRowBytes));
  336. }
  337. }
  338. return S_OK;
  339. }
  340. HRESULT CQTDec::CheckInputType(const CMediaType* mtIn)
  341. {
  342. if(mtIn->majortype != MEDIATYPE_Video || mtIn->formattype != FORMAT_VideoInfo)
  343. return VFW_E_TYPE_NOT_ACCEPTED;
  344. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mtIn->pbFormat;
  345. BITMAPINFOHEADER& bih = vih->bmiHeader;
  346. OSErr err;
  347. ComponentInstance ci;
  348. if(noErr == (err = OpenADefaultComponent('imdc', DWSWAP(bih.biCompression), &ci)))
  349. {
  350. err = CloseComponent(ci);
  351. return S_OK;
  352. }
  353. return VFW_E_TYPE_NOT_ACCEPTED;
  354. }
  355. HRESULT CQTDec::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  356. {
  357. return S_OK;
  358. // TODO
  359. return VFW_E_TYPE_NOT_ACCEPTED;
  360. }
  361. HRESULT CQTDec::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  362. {
  363. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  364. CComPtr<IMemAllocator> pAllocatorIn;
  365. m_pInput->GetAllocator(&pAllocatorIn);
  366. if(!pAllocatorIn) return E_UNEXPECTED;
  367. pAllocatorIn->GetProperties(pProperties);
  368. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
  369. BITMAPINFOHEADER& bih = vih->bmiHeader;
  370. pProperties->cBuffers = 1;
  371. pProperties->cbBuffer = bih.biWidth*abs(bih.biHeight)*4; // TODO
  372. pProperties->cbAlign = 1;
  373. pProperties->cbPrefix = 0;
  374. HRESULT hr;
  375. ALLOCATOR_PROPERTIES Actual;
  376.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  377. return hr;
  378.     return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  379. ? E_FAIL
  380. : NOERROR);
  381. }
  382. HRESULT CQTDec::GetMediaType(int iPosition, CMediaType* pmt)
  383. {
  384.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  385. if(iPosition < 0) return E_INVALIDARG;
  386. if(iPosition >= m_mts.GetCount()) return VFW_S_NO_MORE_ITEMS;
  387. *pmt = m_mts[iPosition];
  388. return S_OK;
  389. }