2 * Implements AVI Decompressor(CLSID_AVIDec).
4 * FIXME - insufficient buffer for ICDecompress!!!!
6 * hidenori@a2.ctktv.ne.jp
24 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(quartz);
27 #include "quartz_private.h"
31 static const WCHAR AVIDec_FilterName[] =
32 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0};
34 typedef struct CAVIDecImpl
38 AM_MEDIA_TYPE m_mtOut;
44 /***************************************************************************
50 static void AVIDec_ReleaseDIBBuffers(CAVIDecImpl* This)
54 if ( This->m_pbiIn != NULL )
56 QUARTZ_FreeMem(This->m_pbiIn); This->m_pbiIn = NULL;
58 if ( This->m_pbiOut != NULL )
60 QUARTZ_FreeMem(This->m_pbiOut); This->m_pbiOut = NULL;
62 if ( This->m_pOutBuf != NULL )
64 QUARTZ_FreeMem(This->m_pOutBuf); This->m_pOutBuf = NULL;
68 static BITMAPINFO* AVIDec_DuplicateBitmapInfo(const BITMAPINFO* pbi)
73 dwSize = pbi->bmiHeader.biSize;
74 if ( dwSize < sizeof(BITMAPINFOHEADER) )
76 if ( pbi->bmiHeader.biBitCount <= 8 )
78 if ( pbi->bmiHeader.biClrUsed == 0 )
79 dwSize += sizeof(RGBQUAD)*(1<<pbi->bmiHeader.biBitCount);
81 dwSize += sizeof(RGBQUAD)*pbi->bmiHeader.biClrUsed;
83 if ( pbi->bmiHeader.biCompression == 3 &&
84 dwSize == sizeof(BITMAPINFOHEADER) )
85 dwSize += sizeof(DWORD)*3;
87 pbiRet = (BITMAPINFO*)QUARTZ_AllocMem(dwSize);
89 memcpy( pbiRet, pbi, dwSize );
94 static HRESULT AVIDec_Init( CTransformBaseImpl* pImpl )
96 CAVIDecImpl* This = pImpl->m_pUserData;
103 This = (CAVIDecImpl*)QUARTZ_AllocMem( sizeof(CAVIDecImpl) );
105 return E_OUTOFMEMORY;
106 ZeroMemory( This, sizeof(CAVIDecImpl) );
107 pImpl->m_pUserData = This;
109 This->hicCached = (HIC)NULL;
110 This->hicTrans = (HIC)NULL;
111 ZeroMemory( &This->m_mtOut, sizeof(AM_MEDIA_TYPE) );
112 This->m_pbiIn = NULL;
113 This->m_pbiOut = NULL;
114 This->m_pOutBuf = NULL;
119 static HRESULT AVIDec_Cleanup( CTransformBaseImpl* pImpl )
121 CAVIDecImpl* This = pImpl->m_pUserData;
123 TRACE("(%p)\n",This);
129 QUARTZ_MediaType_Free( &This->m_mtOut );
131 AVIDec_ReleaseDIBBuffers(This);
133 if ( This->hicCached != (HIC)NULL )
134 ICClose(This->hicCached);
135 if ( This->hicTrans != (HIC)NULL )
136 ICClose(This->hicTrans);
138 QUARTZ_FreeMem( This );
139 pImpl->m_pUserData = NULL;
144 static HRESULT AVIDec_CheckMediaType( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut )
146 CAVIDecImpl* This = pImpl->m_pUserData;
147 BITMAPINFO* pbiIn = NULL;
148 BITMAPINFO* pbiOut = NULL;
151 TRACE("(%p)\n",This);
155 if ( !IsEqualGUID( &pmtIn->majortype, &MEDIATYPE_Video ) )
157 if ( !IsEqualGUID( &pmtIn->formattype, &FORMAT_VideoInfo ) )
159 pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
160 if ( pmtOut != NULL )
162 if ( !IsEqualGUID( &pmtOut->majortype, &MEDIATYPE_Video ) )
164 if ( !IsEqualGUID( &pmtOut->formattype, &FORMAT_VideoInfo ) )
166 pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
169 if ( This->hicCached != (HIC)NULL &&
170 ICDecompressQuery( This->hicCached, pbiIn, pbiOut ) == ICERR_OK )
172 TRACE("supported format\n");
176 TRACE("try to find a decoder...\n");
178 mmioFOURCC('V','I','D','C'), 0,
179 &pbiIn->bmiHeader, &pbiOut->bmiHeader, ICMODE_DECOMPRESS );
180 if ( hic == (HIC)NULL )
182 WARN("no decoder for %c%c%c%c\n",
183 (int)(( pbiIn->bmiHeader.biCompression >> 0 ) & 0xff),
184 (int)(( pbiIn->bmiHeader.biCompression >> 8 ) & 0xff),
185 (int)(( pbiIn->bmiHeader.biCompression >> 16 ) & 0xff),
186 (int)(( pbiIn->bmiHeader.biCompression >> 24 ) & 0xff) );
191 if ( This->hicCached != (HIC)NULL )
192 ICClose(This->hicCached);
193 This->hicCached = hic;
198 static HRESULT AVIDec_GetOutputTypes( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes )
200 CAVIDecImpl* This = pImpl->m_pUserData;
203 BITMAPINFO* pbiIn = NULL;
204 BITMAPINFO* pbiOut = NULL;
206 TRACE("(%p)\n",This);
207 hr = AVIDec_CheckMediaType( pImpl, pmtIn, NULL );
211 TRACE("(%p) - get size of format\n",This);
212 pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
213 cbFmt = (LONG)ICDecompressGetFormatSize( This->hicCached, pbiIn );
214 if ( cbFmt < sizeof(BITMAPINFOHEADER) )
217 QUARTZ_MediaType_Free( &This->m_mtOut );
218 ZeroMemory( &This->m_mtOut, sizeof(AM_MEDIA_TYPE) );
220 memcpy( &This->m_mtOut.majortype, &MEDIATYPE_Video, sizeof(GUID) );
221 memcpy( &This->m_mtOut.formattype, &FORMAT_VideoInfo, sizeof(GUID) );
222 This->m_mtOut.cbFormat = sizeof(VIDEOINFOHEADER) + cbFmt;
223 This->m_mtOut.pbFormat = (BYTE*)CoTaskMemAlloc(This->m_mtOut.cbFormat);
224 if ( This->m_mtOut.pbFormat == NULL )
225 return E_OUTOFMEMORY;
226 ZeroMemory( This->m_mtOut.pbFormat, This->m_mtOut.cbFormat );
228 pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)This->m_mtOut.pbFormat)->bmiHeader);
230 TRACE("(%p) - get format\n",This);
231 if ( ICDecompressGetFormat( This->hicCached, pbiIn, pbiOut ) != ICERR_OK )
234 hr = QUARTZ_MediaSubType_FromBitmap( &This->m_mtOut.subtype, &pbiOut->bmiHeader );
238 QUARTZ_MediaSubType_FromFourCC( &This->m_mtOut.subtype, pbiOut->bmiHeader.biCompression );
240 This->m_mtOut.bFixedSizeSamples = (pbiOut->bmiHeader.biCompression == 0) ? 1 : 0;
241 This->m_mtOut.lSampleSize = (pbiOut->bmiHeader.biCompression == 0) ? DIBSIZE(pbiOut->bmiHeader) : pbiOut->bmiHeader.biSizeImage;
243 TRACE("(%p) - return format\n",This);
244 *ppmtAcceptTypes = &This->m_mtOut;
250 static HRESULT AVIDec_GetAllocProp( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample )
252 CAVIDecImpl* This = pImpl->m_pUserData;
253 BITMAPINFO* pbiOut = NULL;
256 TRACE("(%p)\n",This);
261 hr = AVIDec_CheckMediaType( pImpl, pmtIn, pmtOut );
265 pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
268 if ( pbiOut->bmiHeader.biCompression == 0 )
269 pProp->cbBuffer = DIBSIZE(pbiOut->bmiHeader);
271 pProp->cbBuffer = pbiOut->bmiHeader.biSizeImage;
273 *pbTransInPlace = FALSE;
274 *pbTryToReuseSample = TRUE;
279 static HRESULT AVIDec_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample )
281 CAVIDecImpl* This = pImpl->m_pUserData;
282 BITMAPINFO* pbiIn = NULL;
283 BITMAPINFO* pbiOut = NULL;
286 TRACE("(%p,%p,%p,%d)\n",This,pmtIn,pmtOut,bReuseSample);
289 This->hicTrans != (HIC)NULL )
292 hr = AVIDec_CheckMediaType( pImpl, pmtIn, pmtOut );
296 AVIDec_ReleaseDIBBuffers(This);
298 pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
299 pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
300 This->m_pbiIn = AVIDec_DuplicateBitmapInfo(pbiIn);
301 This->m_pbiOut = AVIDec_DuplicateBitmapInfo(pbiOut);
302 if ( This->m_pbiIn == NULL || This->m_pbiOut == NULL )
303 return E_OUTOFMEMORY;
304 if ( This->m_pbiOut->bmiHeader.biCompression == 0 )
305 This->m_pbiOut->bmiHeader.biSizeImage = DIBSIZE(This->m_pbiOut->bmiHeader);
309 This->m_pOutBuf = QUARTZ_AllocMem(This->m_pbiOut->bmiHeader.biSizeImage);
310 if ( This->m_pOutBuf == NULL )
311 return E_OUTOFMEMORY;
312 ZeroMemory( This->m_pOutBuf, This->m_pbiOut->bmiHeader.biSizeImage );
315 if ( ICERR_OK != ICDecompressBegin(
316 This->hicCached, This->m_pbiIn, This->m_pbiOut ) )
319 This->hicTrans = This->hicCached;
320 This->hicCached = (HIC)NULL;
325 static HRESULT AVIDec_Transform( CTransformBaseImpl* pImpl, IMediaSample* pSampIn, IMediaSample* pSampOut )
327 CAVIDecImpl* This = pImpl->m_pUserData;
329 BYTE* pDataIn = NULL;
330 BYTE* pDataOut = NULL;
333 TRACE("(%p)\n",This);
335 if ( This == NULL || pSampOut == NULL ||
336 This->hicTrans == (HIC)NULL ||
337 This->m_pbiIn == NULL ||
338 This->m_pbiOut == NULL )
341 hr = IMediaSample_GetPointer( pSampIn, &pDataIn );
344 hr = IMediaSample_GetPointer( pSampOut, &pDataOut );
351 * if ( IMediaSample_IsSyncPoint(pSampIn) != S_OK )
352 * dwFlags |= ICDECOMPRESS_NOTKEYFRAME;
355 if ( IMediaSample_IsPreroll(pSampIn) == S_OK )
356 dwFlags |= ICDECOMPRESS_PREROLL;
358 if ( ICERR_OK != ICDecompress(
361 &This->m_pbiIn->bmiHeader,
363 &This->m_pbiOut->bmiHeader,
364 ( This->m_pOutBuf != NULL ) ? This->m_pOutBuf : pDataOut ) )
367 if ( This->m_pOutBuf != NULL )
368 memcpy( pDataOut, This->m_pOutBuf,
369 This->m_pbiOut->bmiHeader.biSizeImage );
374 static HRESULT AVIDec_EndTransform( CTransformBaseImpl* pImpl )
376 CAVIDecImpl* This = pImpl->m_pUserData;
378 TRACE("(%p)\n",This);
382 if ( This->hicTrans == (HIC)NULL )
385 ICDecompressEnd(This->hicTrans);
387 if ( This->hicCached != (HIC)NULL )
388 ICClose(This->hicCached);
389 This->hicCached = This->hicTrans;
390 This->hicTrans = (HIC)NULL;
392 AVIDec_ReleaseDIBBuffers(This);
398 static const TransformBaseHandlers transhandlers =
402 AVIDec_CheckMediaType,
403 AVIDec_GetOutputTypes,
405 AVIDec_BeginTransform,
411 HRESULT QUARTZ_CreateAVIDec(IUnknown* punkOuter,void** ppobj)
413 return QUARTZ_CreateTransformBase(