2 * Implements AVI Decompressor(CLSID_AVIDec).
4 * hidenori@a2.ctktv.ne.jp
22 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(quartz
);
25 #include "quartz_private.h"
29 static const WCHAR AVIDec_FilterName
[] =
30 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0};
32 typedef struct CAVIDecImpl
36 AM_MEDIA_TYPE m_mtOut
;
42 /***************************************************************************
48 static void AVIDec_ReleaseDIBBuffers(CAVIDecImpl
* This
)
52 if ( This
->m_pbiIn
!= NULL
)
54 QUARTZ_FreeMem(This
->m_pbiIn
); This
->m_pbiIn
= NULL
;
56 if ( This
->m_pbiOut
!= NULL
)
58 QUARTZ_FreeMem(This
->m_pbiOut
); This
->m_pbiOut
= NULL
;
60 if ( This
->m_pOutBuf
!= NULL
)
62 QUARTZ_FreeMem(This
->m_pOutBuf
); This
->m_pOutBuf
= NULL
;
66 static BITMAPINFO
* AVIDec_DuplicateBitmapInfo(const BITMAPINFO
* pbi
)
71 dwSize
= pbi
->bmiHeader
.biSize
;
72 if ( dwSize
< sizeof(BITMAPINFOHEADER
) )
74 if ( pbi
->bmiHeader
.biBitCount
<= 8 )
76 if ( pbi
->bmiHeader
.biClrUsed
== 0 )
77 dwSize
+= sizeof(RGBQUAD
)*(1<<pbi
->bmiHeader
.biBitCount
);
79 dwSize
+= sizeof(RGBQUAD
)*pbi
->bmiHeader
.biClrUsed
;
81 if ( pbi
->bmiHeader
.biCompression
== 3 &&
82 dwSize
== sizeof(BITMAPINFOHEADER
) )
83 dwSize
+= sizeof(DWORD
)*3;
85 pbiRet
= (BITMAPINFO
*)QUARTZ_AllocMem(dwSize
);
87 memcpy( pbiRet
, pbi
, dwSize
);
92 static HRESULT
AVIDec_Init( CTransformBaseImpl
* pImpl
)
94 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
101 This
= (CAVIDecImpl
*)QUARTZ_AllocMem( sizeof(CAVIDecImpl
) );
103 return E_OUTOFMEMORY
;
104 ZeroMemory( This
, sizeof(CAVIDecImpl
) );
105 pImpl
->m_pUserData
= This
;
107 This
->hicCached
= (HIC
)NULL
;
108 This
->hicTrans
= (HIC
)NULL
;
109 ZeroMemory( &This
->m_mtOut
, sizeof(AM_MEDIA_TYPE
) );
110 This
->m_pbiIn
= NULL
;
111 This
->m_pbiOut
= NULL
;
112 This
->m_pOutBuf
= NULL
;
117 static HRESULT
AVIDec_Cleanup( CTransformBaseImpl
* pImpl
)
119 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
121 TRACE("(%p)\n",This
);
127 QUARTZ_MediaType_Free( &This
->m_mtOut
);
129 AVIDec_ReleaseDIBBuffers(This
);
131 if ( This
->hicCached
!= (HIC
)NULL
)
132 ICClose(This
->hicCached
);
133 if ( This
->hicTrans
!= (HIC
)NULL
)
134 ICClose(This
->hicTrans
);
136 QUARTZ_FreeMem( This
);
137 pImpl
->m_pUserData
= NULL
;
142 static HRESULT
AVIDec_CheckMediaType( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
* pmtOut
)
144 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
145 BITMAPINFO
* pbiIn
= NULL
;
146 BITMAPINFO
* pbiOut
= NULL
;
149 TRACE("(%p)\n",This
);
153 if ( !IsEqualGUID( &pmtIn
->majortype
, &MEDIATYPE_Video
) )
155 if ( !IsEqualGUID( &pmtIn
->formattype
, &FORMAT_VideoInfo
) )
157 pbiIn
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtIn
->pbFormat
)->bmiHeader
);
158 if ( pmtOut
!= NULL
)
160 if ( !IsEqualGUID( &pmtOut
->majortype
, &MEDIATYPE_Video
) )
162 if ( !IsEqualGUID( &pmtOut
->formattype
, &FORMAT_VideoInfo
) )
164 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtOut
->pbFormat
)->bmiHeader
);
167 if ( This
->hicCached
!= (HIC
)NULL
&&
168 ICDecompressQuery( This
->hicCached
, pbiIn
, pbiOut
) == ICERR_OK
)
170 TRACE("supported format\n");
174 TRACE("try to find a decoder...\n");
176 mmioFOURCC('V','I','D','C'), 0,
177 &pbiIn
->bmiHeader
, &pbiOut
->bmiHeader
, ICMODE_DECOMPRESS
);
178 if ( hic
== (HIC
)NULL
)
180 WARN("no decoder for %c%c%c%c\n",
181 (int)(( pbiIn
->bmiHeader
.biCompression
>> 0 ) & 0xff),
182 (int)(( pbiIn
->bmiHeader
.biCompression
>> 8 ) & 0xff),
183 (int)(( pbiIn
->bmiHeader
.biCompression
>> 16 ) & 0xff),
184 (int)(( pbiIn
->bmiHeader
.biCompression
>> 24 ) & 0xff) );
189 if ( This
->hicCached
!= (HIC
)NULL
)
190 ICClose(This
->hicCached
);
191 This
->hicCached
= hic
;
196 static HRESULT
AVIDec_GetOutputTypes( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
** ppmtAcceptTypes
, ULONG
* pcAcceptTypes
)
198 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
201 BITMAPINFO
* pbiIn
= NULL
;
202 BITMAPINFO
* pbiOut
= NULL
;
204 TRACE("(%p)\n",This
);
205 hr
= AVIDec_CheckMediaType( pImpl
, pmtIn
, NULL
);
209 TRACE("(%p) - get size of format\n",This
);
210 pbiIn
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtIn
->pbFormat
)->bmiHeader
);
211 cbFmt
= (LONG
)ICDecompressGetFormatSize( This
->hicCached
, pbiIn
);
212 if ( cbFmt
< sizeof(BITMAPINFOHEADER
) )
215 QUARTZ_MediaType_Free( &This
->m_mtOut
);
216 ZeroMemory( &This
->m_mtOut
, sizeof(AM_MEDIA_TYPE
) );
218 memcpy( &This
->m_mtOut
.majortype
, &MEDIATYPE_Video
, sizeof(GUID
) );
219 memcpy( &This
->m_mtOut
.formattype
, &FORMAT_VideoInfo
, sizeof(GUID
) );
220 This
->m_mtOut
.cbFormat
= sizeof(VIDEOINFOHEADER
) + cbFmt
+ sizeof(RGBQUAD
)*256;
221 This
->m_mtOut
.pbFormat
= (BYTE
*)CoTaskMemAlloc(This
->m_mtOut
.cbFormat
);
222 if ( This
->m_mtOut
.pbFormat
== NULL
)
223 return E_OUTOFMEMORY
;
224 ZeroMemory( This
->m_mtOut
.pbFormat
, This
->m_mtOut
.cbFormat
);
226 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)This
->m_mtOut
.pbFormat
)->bmiHeader
);
228 TRACE("(%p) - get format\n",This
);
229 if ( ICDecompressGetFormat( This
->hicCached
, pbiIn
, pbiOut
) != ICERR_OK
)
232 hr
= QUARTZ_MediaSubType_FromBitmap( &This
->m_mtOut
.subtype
, &pbiOut
->bmiHeader
);
236 QUARTZ_MediaSubType_FromFourCC( &This
->m_mtOut
.subtype
, pbiOut
->bmiHeader
.biCompression
);
238 This
->m_mtOut
.bFixedSizeSamples
= (pbiOut
->bmiHeader
.biCompression
== 0) ? 1 : 0;
239 This
->m_mtOut
.lSampleSize
= (pbiOut
->bmiHeader
.biCompression
== 0) ? DIBSIZE(pbiOut
->bmiHeader
) : pbiOut
->bmiHeader
.biSizeImage
;
242 if ( pbiOut
->bmiHeader
.biBitCount
<= 8 )
244 TRACE("(%p) - get palette\n",This
);
245 if ( ICDecompressGetPalette( This
->hicCached
, pbiIn
, pbiOut
) != ICERR_OK
)
247 TRACE("(%p) - use the input palette\n",This
);
248 if ( pbiIn
->bmiHeader
.biBitCount
!= pbiOut
->bmiHeader
.biBitCount
)
250 FIXME( "no palette...fixme?\n" );
253 if ( pbiOut
->bmiHeader
.biClrUsed
== 0 )
254 pbiOut
->bmiHeader
.biClrUsed
= 1<<pbiOut
->bmiHeader
.biBitCount
;
255 if ( pbiOut
->bmiHeader
.biClrUsed
> (1<<pbiOut
->bmiHeader
.biBitCount
) )
257 ERR( "biClrUsed=%ld\n", pbiOut
->bmiHeader
.biClrUsed
);
261 memcpy( pbiOut
->bmiColors
, pbiIn
->bmiColors
,
262 sizeof(RGBQUAD
) * pbiOut
->bmiHeader
.biClrUsed
);
266 TRACE("(%p) - return format\n",This
);
267 *ppmtAcceptTypes
= &This
->m_mtOut
;
273 static HRESULT
AVIDec_GetAllocProp( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
* pmtOut
, ALLOCATOR_PROPERTIES
* pProp
, BOOL
* pbTransInPlace
, BOOL
* pbTryToReuseSample
)
275 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
276 BITMAPINFO
* pbiOut
= NULL
;
279 TRACE("(%p)\n",This
);
284 hr
= AVIDec_CheckMediaType( pImpl
, pmtIn
, pmtOut
);
288 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtOut
->pbFormat
)->bmiHeader
);
291 if ( pbiOut
->bmiHeader
.biCompression
== 0 )
292 pProp
->cbBuffer
= DIBSIZE(pbiOut
->bmiHeader
);
294 pProp
->cbBuffer
= pbiOut
->bmiHeader
.biSizeImage
;
296 *pbTransInPlace
= FALSE
;
297 *pbTryToReuseSample
= TRUE
;
302 static HRESULT
AVIDec_BeginTransform( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
* pmtOut
, BOOL bReuseSample
)
304 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
305 BITMAPINFO
* pbiIn
= NULL
;
306 BITMAPINFO
* pbiOut
= NULL
;
309 TRACE("(%p,%p,%p,%d)\n",This
,pmtIn
,pmtOut
,bReuseSample
);
312 This
->hicTrans
!= (HIC
)NULL
)
315 hr
= AVIDec_CheckMediaType( pImpl
, pmtIn
, pmtOut
);
319 AVIDec_ReleaseDIBBuffers(This
);
321 pbiIn
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtIn
->pbFormat
)->bmiHeader
);
322 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtOut
->pbFormat
)->bmiHeader
);
323 This
->m_pbiIn
= AVIDec_DuplicateBitmapInfo(pbiIn
);
324 This
->m_pbiOut
= AVIDec_DuplicateBitmapInfo(pbiOut
);
325 if ( This
->m_pbiIn
== NULL
|| This
->m_pbiOut
== NULL
)
326 return E_OUTOFMEMORY
;
327 if ( This
->m_pbiOut
->bmiHeader
.biCompression
== 0 || This
->m_pbiOut
->bmiHeader
.biCompression
== 3 )
328 This
->m_pbiOut
->bmiHeader
.biSizeImage
= DIBSIZE(This
->m_pbiOut
->bmiHeader
);
332 This
->m_pOutBuf
= QUARTZ_AllocMem(This
->m_pbiOut
->bmiHeader
.biSizeImage
);
333 if ( This
->m_pOutBuf
== NULL
)
334 return E_OUTOFMEMORY
;
335 ZeroMemory( This
->m_pOutBuf
, This
->m_pbiOut
->bmiHeader
.biSizeImage
);
338 if ( ICERR_OK
!= ICDecompressBegin(
339 This
->hicCached
, This
->m_pbiIn
, This
->m_pbiOut
) )
342 This
->hicTrans
= This
->hicCached
;
343 This
->hicCached
= (HIC
)NULL
;
348 static HRESULT
AVIDec_Transform( CTransformBaseImpl
* pImpl
, IMediaSample
* pSampIn
, IMediaSample
* pSampOut
)
350 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
352 BYTE
* pDataIn
= NULL
;
353 BYTE
* pDataOut
= NULL
;
356 TRACE("(%p)\n",This
);
358 if ( This
== NULL
|| pSampOut
== NULL
||
359 This
->hicTrans
== (HIC
)NULL
||
360 This
->m_pbiIn
== NULL
||
361 This
->m_pbiOut
== NULL
)
364 hr
= IMediaSample_GetPointer( pSampIn
, &pDataIn
);
367 hr
= IMediaSample_GetPointer( pSampOut
, &pDataOut
);
374 * if ( IMediaSample_IsSyncPoint(pSampIn) != S_OK )
375 * dwFlags |= ICDECOMPRESS_NOTKEYFRAME;
378 if ( IMediaSample_IsPreroll(pSampIn
) == S_OK
)
379 dwFlags
|= ICDECOMPRESS_PREROLL
;
381 if ( ICERR_OK
!= ICDecompress(
384 &This
->m_pbiIn
->bmiHeader
,
386 &This
->m_pbiOut
->bmiHeader
,
387 ( This
->m_pOutBuf
!= NULL
) ? This
->m_pOutBuf
: pDataOut
) )
390 if ( This
->m_pOutBuf
!= NULL
)
391 memcpy( pDataOut
, This
->m_pOutBuf
,
392 This
->m_pbiOut
->bmiHeader
.biSizeImage
);
397 static HRESULT
AVIDec_EndTransform( CTransformBaseImpl
* pImpl
)
399 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
401 TRACE("(%p)\n",This
);
405 if ( This
->hicTrans
== (HIC
)NULL
)
408 ICDecompressEnd(This
->hicTrans
);
410 if ( This
->hicCached
!= (HIC
)NULL
)
411 ICClose(This
->hicCached
);
412 This
->hicCached
= This
->hicTrans
;
413 This
->hicTrans
= (HIC
)NULL
;
415 AVIDec_ReleaseDIBBuffers(This
);
421 static const TransformBaseHandlers transhandlers
=
425 AVIDec_CheckMediaType
,
426 AVIDec_GetOutputTypes
,
428 AVIDec_BeginTransform
,
434 HRESULT
QUARTZ_CreateAVIDec(IUnknown
* punkOuter
,void** ppobj
)
436 return QUARTZ_CreateTransformBase(