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