00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include <atlbase.h>
00024 #include "..\..\..\DSUtil\MediaTypes.h"
00025 #include <initguid.h>
00026 #include "qtdec.h"
00027
00028 using namespace QT;
00029
00030 static DWORD DWSWAP(DWORD dw) {return(((dw&0xff)<<24)|((dw&0xff00)<<8)|((dw&0xff0000)>>8)|((dw&0xff000000)>>24));}
00031
00032 #ifdef REGISTER_FILTER
00033
00034 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00035 {
00036 {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
00037 };
00038
00039 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00040 {
00041 {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
00042 };
00043
00044 const AMOVIESETUP_PIN sudpPins[] =
00045 {
00046 { L"Input",
00047 FALSE,
00048 FALSE,
00049 FALSE,
00050 FALSE,
00051 &CLSID_NULL,
00052 NULL,
00053 countof(sudPinTypesIn),
00054 sudPinTypesIn
00055 },
00056 { L"Output",
00057 FALSE,
00058 TRUE,
00059 FALSE,
00060 FALSE,
00061 &CLSID_NULL,
00062 NULL,
00063 countof(sudPinTypesOut),
00064 sudPinTypesOut
00065 }
00066 };
00067
00068 const AMOVIESETUP_FILTER sudFilter =
00069 {
00070 &CLSID_QTDec,
00071 L"QuickTime Decoder",
00072 MERIT_DO_NOT_USE,
00073 countof(sudpPins),
00074 sudpPins
00075 };
00076
00077 CFactoryTemplate g_Templates[] =
00078 {
00079 { L"QuickTime Decoder"
00080 , &CLSID_QTDec
00081 , CQTDec::CreateInstance
00082 , NULL
00083 , &sudFilter }
00084 };
00085
00086 int g_cTemplates = countof(g_Templates);
00087
00088 STDAPI DllRegisterServer()
00089 {
00090 return AMovieDllRegisterServer2(TRUE);
00091 }
00092
00093 STDAPI DllUnregisterServer()
00094 {
00095 return AMovieDllRegisterServer2(FALSE);
00096 }
00097
00098 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00099
00100 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00101 {
00102 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00103 }
00104
00105
00106
00107
00108
00109 CUnknown* WINAPI CQTDec::CreateInstance(LPUNKNOWN lpunk, HRESULT* phr)
00110 {
00111 CUnknown* punk = new CQTDec(lpunk, phr);
00112 if(punk == NULL) *phr = E_OUTOFMEMORY;
00113 return punk;
00114 }
00115
00116 #endif
00117
00118 CQTDec::CQTDec(LPUNKNOWN lpunk, HRESULT* phr)
00119 : CTransformFilter(NAME("CQTDec"), lpunk, CLSID_QTDec)
00120 , m_fQtInitialized(false)
00121 , m_pImageGWorld(NULL)
00122 , m_hImageDesc(NULL)
00123 , m_cinst(NULL)
00124 {
00125 if(phr) *phr = S_OK;
00126
00127 m_fQtInitialized = false;
00128 if(InitializeQTML(0) != 0) {if(phr) *phr = E_FAIL; return;}
00129
00130 m_fQtInitialized = true;
00131 }
00132
00133 CQTDec::~CQTDec()
00134 {
00135 if(m_cinst)
00136 CloseComponent(m_cinst),
00137 m_cinst = NULL;
00138
00139 if(m_hImageDesc)
00140 DisposeHandle((Handle)m_hImageDesc),
00141 m_hImageDesc = NULL;
00142
00143 FreeGWorld(m_pImageGWorld);
00144
00145 if(m_fQtInitialized)
00146 {
00147
00148 TerminateQTML();
00149 }
00150 }
00151
00152
00153
00154 GWorldPtr CQTDec::MakeGWorld()
00155 {
00156 if(!m_pOutput->IsConnected())
00157 return NULL;
00158
00159 const CMediaType& mt = m_pOutput->CurrentMediaType();
00160 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
00161 BITMAPINFOHEADER& bih = vih->bmiHeader;
00162
00163 GWorldPtr pImageWorld = NULL;
00164 Rect rect = {0, 0, (short)abs(bih.biHeight), (short)bih.biWidth};
00165
00166 OSType PixelFormat =
00167 mt.subtype == MEDIASUBTYPE_YUY2 ? kYUVSPixelFormat :
00168 mt.subtype == MEDIASUBTYPE_UYVY ? k2vuyPixelFormat :
00169 mt.subtype == MEDIASUBTYPE_RGB32 ? k32BGRAPixelFormat :
00170 mt.subtype == MEDIASUBTYPE_RGB565 ? k16LE565PixelFormat :
00171 mt.subtype == MEDIASUBTYPE_RGB555 ? k16LE555PixelFormat :
00172 0;
00173
00174 if(!PixelFormat || noErr != QTNewGWorld(&pImageWorld, PixelFormat, &rect, NULL, NULL, 0))
00175 pImageWorld = NULL;
00176
00177 if(pImageWorld)
00178 LockPixels(GetGWorldPixMap(pImageWorld));
00179
00180 return pImageWorld;
00181 }
00182
00183 void CQTDec::FreeGWorld(GWorldPtr& pImageGWorld)
00184 {
00185 if(pImageGWorld)
00186 {
00187 UnlockPixels(GetGWorldPixMap(pImageGWorld));
00188 DisposeGWorld(pImageGWorld);
00189 pImageGWorld = NULL;
00190 }
00191 }
00192
00193 bool CQTDec::InitComponent()
00194 {
00195 if(m_cinst)
00196 CloseComponent(m_cinst),
00197 m_cinst = NULL;
00198
00199 if(m_hImageDesc)
00200 DisposeHandle((Handle)m_hImageDesc),
00201 m_hImageDesc = NULL;
00202
00203 if(!m_pInput->IsConnected())
00204 return NULL;
00205
00206 BITMAPINFOHEADER& bih = ((VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat)->bmiHeader;
00207
00208 ComponentDescription cd = {decompressorComponentType, DWSWAP(bih.biCompression), 0, 0, 0};
00209 Component c = FindNextComponent(0, &cd);
00210 if(!c) return(false);
00211
00212 m_cinst = OpenComponent(c);
00213 if(!m_cinst) return(false);
00214
00215 ComponentResult cres;
00216
00217 ImageSubCodecDecompressCapabilities icap;
00218 memset(&icap, 0, sizeof(icap));
00219 cres = ImageCodecInitialize(m_cinst, &icap);
00220
00221 CodecInfo cinfo;
00222 memset(&cinfo, 0, sizeof(cinfo));
00223 cres = ImageCodecGetCodecInfo(m_cinst, &cinfo);
00224
00225 m_hImageDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
00226 if(!m_hImageDesc)
00227 return(false);
00228
00229 (**m_hImageDesc).idSize = sizeof(ImageDescription);
00230 (**m_hImageDesc).cType = DWSWAP(bih.biCompression);
00231 (**m_hImageDesc).temporalQuality = 0;
00232 (**m_hImageDesc).spatialQuality = codecNormalQuality;
00233 (**m_hImageDesc).width = (short)bih.biWidth;
00234 (**m_hImageDesc).height = (short)abs(bih.biHeight);
00235 (**m_hImageDesc).hRes = 72 << 16;
00236 (**m_hImageDesc).vRes = 72 << 16;
00237 (**m_hImageDesc).frameCount = 1;
00238 (**m_hImageDesc).depth = bih.biBitCount;
00239 (**m_hImageDesc).clutID = -1;
00240
00241 memset(&m_cdpar, 0, sizeof(m_cdpar));
00242 m_cdpar.imageDescription = m_hImageDesc;
00243 m_cdpar.startLine = 0;
00244 m_cdpar.stopLine = (**m_hImageDesc).height;
00245 m_cdpar.frameNumber = 1;
00246 m_cdpar.matrixFlags = 0;
00247 m_cdpar.matrixType = 0;
00248 m_cdpar.matrix = 0;
00249 m_cdpar.capabilities = &m_ccap;
00250 memset(&m_ccap, 0, sizeof(m_ccap));
00251 m_cdpar.accuracy = codecNormalQuality;
00252 m_cdpar.port = m_pImageGWorld;
00253 Rect rect = {0, 0, (**m_hImageDesc).height, (**m_hImageDesc).width};
00254 m_cdpar.srcRect = rect;
00255 m_cdpar.transferMode = srcCopy;
00256 m_cdpar.dstPixMap = **GetGWorldPixMap(m_pImageGWorld);
00257
00258 cres = ImageCodecPreDecompress(m_cinst, &m_cdpar);
00259
00260 return(true);
00261 }
00262
00263
00264
00265 HRESULT CQTDec::BreakConnect(PIN_DIRECTION dir)
00266 {
00267 if(dir == PINDIR_INPUT)
00268 {
00269 m_mts.RemoveAll();
00270 }
00271 else if(dir == PINDIR_OUTPUT)
00272 {
00273 FreeGWorld(m_pImageGWorld);
00274 }
00275
00276 return __super::BreakConnect(dir);
00277 }
00278
00279 HRESULT CQTDec::CompleteConnect(PIN_DIRECTION dir, IPin* pReceivePin)
00280 {
00281 if(dir == PINDIR_INPUT)
00282 {
00283 m_mts.RemoveAll();
00284
00285 VIDEOINFOHEADER* vihin = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
00286 BITMAPINFOHEADER& bihin = vihin->bmiHeader;
00287
00288 CMediaType mt;
00289 mt.majortype = MEDIATYPE_Video;
00290 mt.subtype = MEDIASUBTYPE_None;
00291 mt.formattype = FORMAT_VideoInfo;
00292 mt.bFixedSizeSamples = TRUE;
00293 mt.bTemporalCompression = FALSE;
00294 mt.lSampleSize = 0;
00295 mt.pUnk = NULL;
00296
00297 VIDEOINFOHEADER vih;
00298 memset(&vih, 0, sizeof(vih));
00299 vih.AvgTimePerFrame = vihin->AvgTimePerFrame;
00300 vih.rcSource = vihin->rcSource;
00301 vih.rcTarget = vihin->rcTarget;
00302 vih.dwBitRate = vihin->dwBitRate;
00303 vih.dwBitErrorRate = vihin->dwBitErrorRate;
00304
00305 BITMAPINFOHEADER& bih = vih.bmiHeader;
00306 bih.biSize = sizeof(bih);
00307 bih.biWidth = bihin.biWidth;
00308 bih.biHeight = abs(bihin.biHeight);
00309 bih.biPlanes = 1;
00310 bih.biXPelsPerMeter = bih.biYPelsPerMeter = 0;
00311 bih.biClrUsed = bih.biClrImportant = 0;
00312
00313
00314 {
00315 VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00316 memcpy(vihout, &vih, sizeof(vih));
00317
00318 BITMAPINFOHEADER& bihout = vihout->bmiHeader;
00319 bihout.biBitCount = 32;
00320 bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
00321
00322 mt.subtype = MEDIASUBTYPE_RGB32;
00323
00324 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
00325 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
00326 CorrectMediaType(&mt);
00327 m_mts.Add(mt);
00328
00329 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
00330 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
00331 CorrectMediaType(&mt);
00332 m_mts.Add(mt);
00333 }
00334
00335
00336 {
00337 VIDEOINFOHEADER* vihout = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00338 memcpy(vihout, &vih, sizeof(vih));
00339
00340 BITMAPINFOHEADER& bihout = vihout->bmiHeader;
00341 bihout.biBitCount = 16;
00342 bihout.biSizeImage = bihout.biWidth*abs(bihout.biHeight)*bihout.biBitCount>>3;
00343
00344 mt.subtype = MEDIASUBTYPE_RGB565;
00345
00346 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
00347 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
00348 CorrectMediaType(&mt);
00349 m_mts.Add(mt);
00350
00351 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
00352 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
00353 CorrectMediaType(&mt);
00354 m_mts.Add(mt);
00355
00356 mt.subtype = MEDIASUBTYPE_RGB555;
00357
00358 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_BITFIELDS;
00359 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = -bih.biHeight;
00360 CorrectMediaType(&mt);
00361 m_mts.Add(mt);
00362
00363 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression = BI_RGB;
00364 ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biHeight = bih.biHeight;
00365 CorrectMediaType(&mt);
00366 m_mts.Add(mt);
00367 }
00368 }
00369 else if(dir == PINDIR_OUTPUT)
00370 {
00371 FreeGWorld(m_pImageGWorld);
00372 m_pImageGWorld = MakeGWorld();
00373 }
00374
00375 return __super::CompleteConnect(dir, pReceivePin);
00376 }
00377
00378 HRESULT CQTDec::Transform(IMediaSample* pSample, IMediaSample* pOutSample)
00379 {
00380 HRESULT hr;
00381
00382 BYTE* pIn = NULL;
00383 if(FAILED(hr = pSample->GetPointer(&pIn))) return hr;
00384 long len = pSample->GetActualDataLength();
00385 if(len <= 0) return S_FALSE;
00386
00387 BYTE* pOut = NULL;
00388 if(FAILED(hr = pOutSample->GetPointer(&pOut))) return hr;
00389 int size = pOutSample->GetSize();
00390
00391 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pOutput->CurrentMediaType().pbFormat;
00392 BITMAPINFOHEADER& bih = vih->bmiHeader;
00393
00394 bool fInitialized = true;
00395
00396 if(m_cinst)
00397 {
00398 AM_MEDIA_TYPE* pmt = NULL;
00399 if(S_OK == pSample->GetMediaType((AM_MEDIA_TYPE**)&pmt) && pmt)
00400 {
00401 CMediaType mt(*pmt);
00402 DeleteMediaType(pmt), pmt = NULL;
00403
00404 if(mt != m_pInput->CurrentMediaType())
00405 {
00406 m_pInput->SetMediaType(&mt);
00407 fInitialized = InitComponent();
00408 }
00409 }
00410 }
00411 else
00412 {
00413 fInitialized = InitComponent();
00414 }
00415
00416 if(!fInitialized)
00417 return E_FAIL;
00418
00419 m_cdpar.data = (Ptr)pIn;
00420 m_cdpar.bufferSize = len;
00421 (**m_cdpar.imageDescription).dataSize = len;
00422 ComponentResult cres = ImageCodecBandDecompress(m_cinst, &m_cdpar);
00423 m_cdpar.frameNumber++;
00424
00425 if(cres == noErr)
00426 {
00427 PixMapHandle hPixMap = GetGWorldPixMap(m_pImageGWorld);
00428 Ptr pPixels = GetPixBaseAddr(hPixMap);
00429 long theRowBytes = QTGetPixMapHandleRowBytes(hPixMap);
00430
00431 DWORD pitch = bih.biWidth*bih.biBitCount>>3;
00432
00433 for(int i = 0, h = abs(bih.biHeight); i < h; i++)
00434 {
00435 memcpy(pOut + i*pitch, (BYTE*)pPixels + i*theRowBytes, min(pitch, theRowBytes));
00436 }
00437 }
00438
00439 return S_OK;
00440 }
00441
00442 HRESULT CQTDec::CheckInputType(const CMediaType* mtIn)
00443 {
00444 if(mtIn->majortype != MEDIATYPE_Video || mtIn->formattype != FORMAT_VideoInfo)
00445 return VFW_E_TYPE_NOT_ACCEPTED;
00446
00447 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mtIn->pbFormat;
00448 BITMAPINFOHEADER& bih = vih->bmiHeader;
00449
00450 OSErr err;
00451 ComponentInstance ci;
00452 if(noErr == (err = OpenADefaultComponent('imdc', DWSWAP(bih.biCompression), &ci)))
00453 {
00454 err = CloseComponent(ci);
00455 return S_OK;
00456 }
00457
00458 return VFW_E_TYPE_NOT_ACCEPTED;
00459 }
00460
00461 HRESULT CQTDec::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00462 {
00463 return S_OK;
00464
00465 return VFW_E_TYPE_NOT_ACCEPTED;
00466 }
00467
00468 HRESULT CQTDec::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
00469 {
00470 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00471
00472 CComPtr<IMemAllocator> pAllocatorIn;
00473 m_pInput->GetAllocator(&pAllocatorIn);
00474 if(!pAllocatorIn) return E_UNEXPECTED;
00475
00476 pAllocatorIn->GetProperties(pProperties);
00477
00478 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_pInput->CurrentMediaType().pbFormat;
00479 BITMAPINFOHEADER& bih = vih->bmiHeader;
00480
00481 pProperties->cBuffers = 1;
00482 pProperties->cbBuffer = bih.biWidth*abs(bih.biHeight)*4;
00483 pProperties->cbAlign = 1;
00484 pProperties->cbPrefix = 0;
00485
00486 HRESULT hr;
00487 ALLOCATOR_PROPERTIES Actual;
00488 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
00489 return hr;
00490
00491 return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
00492 ? E_FAIL
00493 : NOERROR);
00494 }
00495
00496 HRESULT CQTDec::GetMediaType(int iPosition, CMediaType* pmt)
00497 {
00498 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00499
00500 if(iPosition < 0) return E_INVALIDARG;
00501 if(iPosition >= m_mts.GetCount()) return VFW_S_NO_MORE_ITEMS;
00502
00503 *pmt = m_mts[iPosition];
00504
00505 return S_OK;
00506 }