2 * Implements AVI Decompressor(CLSID_AVIDec).
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
39 #include "quartz_private.h"
43 static const WCHAR AVIDec_FilterName
[] =
44 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0};
46 typedef struct CAVIDecImpl
50 AM_MEDIA_TYPE m_mtOut
;
56 /***************************************************************************
62 static void AVIDec_ReleaseDIBBuffers(CAVIDecImpl
* This
)
66 if ( This
->m_pbiIn
!= NULL
)
68 QUARTZ_FreeMem(This
->m_pbiIn
); This
->m_pbiIn
= NULL
;
70 if ( This
->m_pbiOut
!= NULL
)
72 QUARTZ_FreeMem(This
->m_pbiOut
); This
->m_pbiOut
= NULL
;
74 if ( This
->m_pOutBuf
!= NULL
)
76 QUARTZ_FreeMem(This
->m_pOutBuf
); This
->m_pOutBuf
= NULL
;
80 static BITMAPINFO
* AVIDec_DuplicateBitmapInfo(const BITMAPINFO
* pbi
)
85 dwSize
= pbi
->bmiHeader
.biSize
;
86 if ( dwSize
< sizeof(BITMAPINFOHEADER
) )
88 if ( pbi
->bmiHeader
.biBitCount
<= 8 )
90 if ( pbi
->bmiHeader
.biClrUsed
== 0 )
91 dwSize
+= sizeof(RGBQUAD
)*(1<<pbi
->bmiHeader
.biBitCount
);
93 dwSize
+= sizeof(RGBQUAD
)*pbi
->bmiHeader
.biClrUsed
;
95 if ( pbi
->bmiHeader
.biCompression
== 3 &&
96 dwSize
== sizeof(BITMAPINFOHEADER
) )
97 dwSize
+= sizeof(DWORD
)*3;
99 pbiRet
= (BITMAPINFO
*)QUARTZ_AllocMem(dwSize
);
100 if ( pbiRet
!= NULL
)
101 memcpy( pbiRet
, pbi
, dwSize
);
106 static HRESULT
AVIDec_Init( CTransformBaseImpl
* pImpl
)
108 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
110 TRACE("(%p)\n",This
);
115 This
= (CAVIDecImpl
*)QUARTZ_AllocMem( sizeof(CAVIDecImpl
) );
117 return E_OUTOFMEMORY
;
118 ZeroMemory( This
, sizeof(CAVIDecImpl
) );
119 pImpl
->m_pUserData
= This
;
121 This
->hicCached
= (HIC
)NULL
;
122 This
->hicTrans
= (HIC
)NULL
;
123 ZeroMemory( &This
->m_mtOut
, sizeof(AM_MEDIA_TYPE
) );
124 This
->m_pbiIn
= NULL
;
125 This
->m_pbiOut
= NULL
;
126 This
->m_pOutBuf
= NULL
;
131 static HRESULT
AVIDec_Cleanup( CTransformBaseImpl
* pImpl
)
133 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
135 TRACE("(%p)\n",This
);
141 QUARTZ_MediaType_Free( &This
->m_mtOut
);
143 AVIDec_ReleaseDIBBuffers(This
);
145 if ( This
->hicCached
!= (HIC
)NULL
)
146 ICClose(This
->hicCached
);
147 if ( This
->hicTrans
!= (HIC
)NULL
)
148 ICClose(This
->hicTrans
);
150 QUARTZ_FreeMem( This
);
151 pImpl
->m_pUserData
= NULL
;
156 static HRESULT
AVIDec_CheckMediaType( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
* pmtOut
)
158 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
159 BITMAPINFO
* pbiIn
= NULL
;
160 BITMAPINFO
* pbiOut
= NULL
;
163 TRACE("(%p)\n",This
);
167 if ( !IsEqualGUID( &pmtIn
->majortype
, &MEDIATYPE_Video
) )
169 if ( !IsEqualGUID( &pmtIn
->formattype
, &FORMAT_VideoInfo
) )
171 pbiIn
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtIn
->pbFormat
)->bmiHeader
);
172 if ( pmtOut
!= NULL
)
174 if ( !IsEqualGUID( &pmtOut
->majortype
, &MEDIATYPE_Video
) )
176 if ( !IsEqualGUID( &pmtOut
->formattype
, &FORMAT_VideoInfo
) )
178 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtOut
->pbFormat
)->bmiHeader
);
181 if ( This
->hicCached
!= (HIC
)NULL
&&
182 ICDecompressQuery( This
->hicCached
, pbiIn
, pbiOut
) == ICERR_OK
)
184 TRACE("supported format\n");
188 TRACE("try to find a decoder...\n");
190 mmioFOURCC('V','I','D','C'), 0,
191 &pbiIn
->bmiHeader
, &pbiOut
->bmiHeader
, ICMODE_DECOMPRESS
);
192 if ( hic
== (HIC
)NULL
)
194 WARN("no decoder for %c%c%c%c\n",
195 (int)(( pbiIn
->bmiHeader
.biCompression
>> 0 ) & 0xff),
196 (int)(( pbiIn
->bmiHeader
.biCompression
>> 8 ) & 0xff),
197 (int)(( pbiIn
->bmiHeader
.biCompression
>> 16 ) & 0xff),
198 (int)(( pbiIn
->bmiHeader
.biCompression
>> 24 ) & 0xff) );
203 if ( This
->hicCached
!= (HIC
)NULL
)
204 ICClose(This
->hicCached
);
205 This
->hicCached
= hic
;
210 static HRESULT
AVIDec_GetOutputTypes( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
** ppmtAcceptTypes
, ULONG
* pcAcceptTypes
)
212 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
215 BITMAPINFO
* pbiIn
= NULL
;
216 BITMAPINFO
* pbiOut
= NULL
;
218 TRACE("(%p)\n",This
);
219 hr
= AVIDec_CheckMediaType( pImpl
, pmtIn
, NULL
);
223 TRACE("(%p) - get size of format\n",This
);
224 pbiIn
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtIn
->pbFormat
)->bmiHeader
);
225 cbFmt
= (LONG
)ICDecompressGetFormatSize( This
->hicCached
, pbiIn
);
226 if ( cbFmt
< sizeof(BITMAPINFOHEADER
) )
229 QUARTZ_MediaType_Free( &This
->m_mtOut
);
230 ZeroMemory( &This
->m_mtOut
, sizeof(AM_MEDIA_TYPE
) );
232 memcpy( &This
->m_mtOut
.majortype
, &MEDIATYPE_Video
, sizeof(GUID
) );
233 memcpy( &This
->m_mtOut
.formattype
, &FORMAT_VideoInfo
, sizeof(GUID
) );
234 This
->m_mtOut
.cbFormat
= sizeof(VIDEOINFOHEADER
) + cbFmt
+ sizeof(RGBQUAD
)*256;
235 This
->m_mtOut
.pbFormat
= (BYTE
*)CoTaskMemAlloc(This
->m_mtOut
.cbFormat
);
236 if ( This
->m_mtOut
.pbFormat
== NULL
)
237 return E_OUTOFMEMORY
;
238 ZeroMemory( This
->m_mtOut
.pbFormat
, This
->m_mtOut
.cbFormat
);
240 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)This
->m_mtOut
.pbFormat
)->bmiHeader
);
242 TRACE("(%p) - get format\n",This
);
243 if ( ICDecompressGetFormat( This
->hicCached
, pbiIn
, pbiOut
) != ICERR_OK
)
246 hr
= QUARTZ_MediaSubType_FromBitmap( &This
->m_mtOut
.subtype
, &pbiOut
->bmiHeader
);
250 QUARTZ_MediaSubType_FromFourCC( &This
->m_mtOut
.subtype
, pbiOut
->bmiHeader
.biCompression
);
252 This
->m_mtOut
.bFixedSizeSamples
= (pbiOut
->bmiHeader
.biCompression
== 0) ? 1 : 0;
253 This
->m_mtOut
.lSampleSize
= (pbiOut
->bmiHeader
.biCompression
== 0) ? DIBSIZE(pbiOut
->bmiHeader
) : pbiOut
->bmiHeader
.biSizeImage
;
256 if ( pbiOut
->bmiHeader
.biBitCount
<= 8 )
258 TRACE("(%p) - get palette\n",This
);
259 if ( ICDecompressGetPalette( This
->hicCached
, pbiIn
, pbiOut
) != ICERR_OK
)
261 TRACE("(%p) - use the input palette\n",This
);
262 if ( pbiIn
->bmiHeader
.biBitCount
!= pbiOut
->bmiHeader
.biBitCount
)
264 FIXME( "no palette...FIXME?\n" );
267 if ( pbiOut
->bmiHeader
.biClrUsed
== 0 )
268 pbiOut
->bmiHeader
.biClrUsed
= 1<<pbiOut
->bmiHeader
.biBitCount
;
269 if ( pbiOut
->bmiHeader
.biClrUsed
> (1<<pbiOut
->bmiHeader
.biBitCount
) )
271 ERR( "biClrUsed=%ld\n", pbiOut
->bmiHeader
.biClrUsed
);
275 memcpy( pbiOut
->bmiColors
, pbiIn
->bmiColors
,
276 sizeof(RGBQUAD
) * pbiOut
->bmiHeader
.biClrUsed
);
280 TRACE("(%p) - return format\n",This
);
281 *ppmtAcceptTypes
= &This
->m_mtOut
;
287 static HRESULT
AVIDec_GetAllocProp( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
* pmtOut
, ALLOCATOR_PROPERTIES
* pProp
, BOOL
* pbTransInPlace
, BOOL
* pbTryToReuseSample
)
289 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
290 BITMAPINFO
* pbiOut
= NULL
;
293 TRACE("(%p)\n",This
);
298 hr
= AVIDec_CheckMediaType( pImpl
, pmtIn
, pmtOut
);
302 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtOut
->pbFormat
)->bmiHeader
);
305 if ( pbiOut
->bmiHeader
.biCompression
== 0 )
306 pProp
->cbBuffer
= DIBSIZE(pbiOut
->bmiHeader
);
308 pProp
->cbBuffer
= pbiOut
->bmiHeader
.biSizeImage
;
310 *pbTransInPlace
= FALSE
;
311 *pbTryToReuseSample
= TRUE
;
316 static HRESULT
AVIDec_BeginTransform( CTransformBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmtIn
, const AM_MEDIA_TYPE
* pmtOut
, BOOL bReuseSample
)
318 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
319 BITMAPINFO
* pbiIn
= NULL
;
320 BITMAPINFO
* pbiOut
= NULL
;
323 TRACE("(%p,%p,%p,%d)\n",This
,pmtIn
,pmtOut
,bReuseSample
);
326 This
->hicTrans
!= (HIC
)NULL
)
329 hr
= AVIDec_CheckMediaType( pImpl
, pmtIn
, pmtOut
);
333 AVIDec_ReleaseDIBBuffers(This
);
335 pbiIn
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtIn
->pbFormat
)->bmiHeader
);
336 pbiOut
= (BITMAPINFO
*)(&((VIDEOINFOHEADER
*)pmtOut
->pbFormat
)->bmiHeader
);
337 This
->m_pbiIn
= AVIDec_DuplicateBitmapInfo(pbiIn
);
338 This
->m_pbiOut
= AVIDec_DuplicateBitmapInfo(pbiOut
);
339 if ( This
->m_pbiIn
== NULL
|| This
->m_pbiOut
== NULL
)
340 return E_OUTOFMEMORY
;
341 if ( This
->m_pbiOut
->bmiHeader
.biCompression
== 0 || This
->m_pbiOut
->bmiHeader
.biCompression
== 3 )
342 This
->m_pbiOut
->bmiHeader
.biSizeImage
= DIBSIZE(This
->m_pbiOut
->bmiHeader
);
346 This
->m_pOutBuf
= QUARTZ_AllocMem(This
->m_pbiOut
->bmiHeader
.biSizeImage
);
347 if ( This
->m_pOutBuf
== NULL
)
348 return E_OUTOFMEMORY
;
349 ZeroMemory( This
->m_pOutBuf
, This
->m_pbiOut
->bmiHeader
.biSizeImage
);
352 if ( ICERR_OK
!= ICDecompressBegin(
353 This
->hicCached
, This
->m_pbiIn
, This
->m_pbiOut
) )
356 This
->hicTrans
= This
->hicCached
;
357 This
->hicCached
= (HIC
)NULL
;
362 static HRESULT
AVIDec_Transform( CTransformBaseImpl
* pImpl
, IMediaSample
* pSampIn
, IMediaSample
* pSampOut
)
364 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
366 BYTE
* pDataIn
= NULL
;
367 BYTE
* pDataOut
= NULL
;
370 TRACE("(%p)\n",This
);
372 if ( This
== NULL
|| pSampOut
== NULL
||
373 This
->hicTrans
== (HIC
)NULL
||
374 This
->m_pbiIn
== NULL
||
375 This
->m_pbiOut
== NULL
)
378 hr
= IMediaSample_GetPointer( pSampIn
, &pDataIn
);
381 hr
= IMediaSample_GetPointer( pSampOut
, &pDataOut
);
388 * if ( IMediaSample_IsSyncPoint(pSampIn) != S_OK )
389 * dwFlags |= ICDECOMPRESS_NOTKEYFRAME;
392 if ( IMediaSample_IsPreroll(pSampIn
) == S_OK
)
393 dwFlags
|= ICDECOMPRESS_PREROLL
;
395 if ( ICERR_OK
!= ICDecompress(
398 &This
->m_pbiIn
->bmiHeader
,
400 &This
->m_pbiOut
->bmiHeader
,
401 ( This
->m_pOutBuf
!= NULL
) ? This
->m_pOutBuf
: pDataOut
) )
404 if ( This
->m_pOutBuf
!= NULL
)
405 memcpy( pDataOut
, This
->m_pOutBuf
,
406 This
->m_pbiOut
->bmiHeader
.biSizeImage
);
411 static HRESULT
AVIDec_EndTransform( CTransformBaseImpl
* pImpl
)
413 CAVIDecImpl
* This
= pImpl
->m_pUserData
;
415 TRACE("(%p)\n",This
);
419 if ( This
->hicTrans
== (HIC
)NULL
)
422 ICDecompressEnd(This
->hicTrans
);
424 if ( This
->hicCached
!= (HIC
)NULL
)
425 ICClose(This
->hicCached
);
426 This
->hicCached
= This
->hicTrans
;
427 This
->hicTrans
= (HIC
)NULL
;
429 AVIDec_ReleaseDIBBuffers(This
);
435 static const TransformBaseHandlers transhandlers
=
439 AVIDec_CheckMediaType
,
440 AVIDec_GetOutputTypes
,
442 AVIDec_BeginTransform
,
449 HRESULT
QUARTZ_CreateAVIDec(IUnknown
* punkOuter
,void** ppobj
)
451 return QUARTZ_CreateTransformBase(