Copy (2) of QTDec.cpp

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",             // Pins string name
00026       FALSE,                // Is it rendered
00027       FALSE,                // Is it an output
00028       FALSE,                // Are we allowed none
00029       FALSE,                // And allowed many
00030       &CLSID_NULL,          // Connects to filter
00031       NULL,                 // Connects to pin
00032       countof(sudPinTypesIn),   // Number of types
00033       sudPinTypesIn                     // Pin information
00034     },
00035     { L"Output",            // Pins string name
00036       FALSE,                // Is it rendered
00037       TRUE,                 // Is it an output
00038       FALSE,                // Are we allowed none
00039       FALSE,                // And allowed many
00040       &CLSID_NULL,          // Connects to filter
00041       NULL,                 // Connects to pin
00042       countof(sudPinTypesOut),  // Number of types
00043       sudPinTypesOut            // Pin information
00044     }
00045 };
00046 
00047 const AMOVIESETUP_FILTER sudFilter =
00048 {
00049     &CLSID_QTDec,                       // Filter CLSID
00050     L"QuickTime Decoder",       // String name
00051     MERIT_DO_NOT_USE/*MERIT_NORMAL*/,                   // Filter merit
00052     countof(sudpPins),  // Number of pins
00053     sudpPins                // Pin information
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); // "DllMain" of the dshow baseclasses;
00082 }
00083 
00084 //
00085 // CQTDec
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 //      if(EnterMovies() != 0) {TerminateQTML(); if(phr) *phr = E_FAIL; return;}
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 //              ExitMovies();
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 : // 'yuvs'
00147                 mt.subtype == MEDIASUBTYPE_UYVY ? k2vuyPixelFormat : // '2vuy'
00148                 mt.subtype == MEDIASUBTYPE_RGB32 ? k32BGRAPixelFormat : // 'BGRA'
00149                 mt.subtype == MEDIASUBTYPE_RGB565 ? k16LE565PixelFormat : // 'L565'
00150                 mt.subtype == MEDIASUBTYPE_RGB555 ? k16LE555PixelFormat : // 'L555'
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; // should be 24 for unknown/compressed types
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 //              if(fRGB32) // always can decompress to (?)
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 //              if(fRGB16) // always can decompress to (?)
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         // TODO
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; // TODO
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 }

Generated on Tue Dec 13 14:47:51 2005 for guliverkli by  doxygen 1.4.5