2 * Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
4 * FIXME - implements color space(depth) converter.
16 #include "debugtools.h"
17 #include "avifile_private.h"
19 DEFAULT_DEBUG_CHANNEL(avifile
);
21 static HRESULT WINAPI
IGetFrame_fnQueryInterface(IGetFrame
* iface
,REFIID refiid
,LPVOID
*obj
);
22 static ULONG WINAPI
IGetFrame_fnAddRef(IGetFrame
* iface
);
23 static ULONG WINAPI
IGetFrame_fnRelease(IGetFrame
* iface
);
24 static LPVOID WINAPI
IGetFrame_fnGetFrame(IGetFrame
* iface
,LONG lPos
);
25 static HRESULT WINAPI
IGetFrame_fnBegin(IGetFrame
* iface
,LONG lStart
,LONG lEnd
,LONG lRate
);
26 static HRESULT WINAPI
IGetFrame_fnEnd(IGetFrame
* iface
);
27 static HRESULT WINAPI
IGetFrame_fnSetFormat(IGetFrame
* iface
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
,INT x
,INT y
,INT dx
,INT dy
);
29 struct ICOM_VTABLE(IGetFrame
) igetfrm
= {
30 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
31 IGetFrame_fnQueryInterface
,
37 IGetFrame_fnSetFormat
,
40 typedef struct IGetFrameImpl
42 ICOM_VFIELD(IGetFrame
);
53 DWORD dwICInDataBufSize
;
58 static HRESULT
IGetFrame_Construct( IGetFrameImpl
* This
,
60 LPBITMAPINFOHEADER lpbi
);
61 static void IGetFrame_Destruct( IGetFrameImpl
* This
);
66 static LPVOID
AVIFILE_IGetFrame_DecodeFrame(IGetFrameImpl
* This
,LONG lPos
)
74 if ( This
->hIC
== (HIC
)NULL
)
77 hr
= IAVIStream_Read(This
->pas
,lPos
,1,NULL
,0,
78 &lFrameLength
,&lSampleCount
);
79 if ( hr
!= S_OK
|| lSampleCount
<= 0 )
81 FIXME( "IAVIStream_Read failed! res = %08lx\n", hr
);
84 TRACE( "frame length = %ld\n", lFrameLength
);
86 if ( This
->dwICInDataBufSize
< lFrameLength
)
90 if ( This
->pvICInDataBuf
== NULL
)
93 AVIFILE_data
.hHeap
,HEAP_ZERO_MEMORY
,
99 AVIFILE_data
.hHeap
,HEAP_ZERO_MEMORY
,
100 This
->pvICInDataBuf
,lFrameLength
);
104 ERR( "out of memory!\n" );
107 This
->pvICInDataBuf
= lpv
;
108 This
->dwICInDataBufSize
= lFrameLength
;
111 hr
= IAVIStream_Read(This
->pas
,lPos
,1,
112 This
->pvICInDataBuf
,This
->dwICInDataBufSize
,
113 &lFrameLength
,&lSampleCount
);
114 if ( hr
!= S_OK
|| lSampleCount
<= 0 )
116 FIXME( "IAVIStream_Read to buffer failed! res = %08lx\n", hr
);
120 This
->pbiICIn
->bmiHeader
.biSizeImage
= lFrameLength
;
122 TRACE( "call ICM_DECOMPRESS\n" );
124 if ( IAVIStream_FindSample(This
->pas
,lPos
,FIND_PREV
|FIND_KEY
) != lPos
)
125 icd
.dwFlags
= ICDECOMPRESS_NOTKEYFRAME
;
126 icd
.lpbiInput
= &This
->pbiICIn
->bmiHeader
;
127 icd
.lpInput
= (BYTE
*)This
->pvICInDataBuf
;
128 icd
.lpbiOutput
= &This
->pbiICOut
->bmiHeader
;
129 icd
.lpOutput
= This
->pvICOutBits
;
130 icd
.ckid
= *((DWORD
*)This
->pvICInDataBuf
);
131 dwRes
= ICSendMessage(This
->hIC
,ICM_DECOMPRESS
,
132 (DWORD
)(&icd
),sizeof(ICDECOMPRESS
) );
133 TRACE( "returned from ICM_DECOMPRESS\n" );
134 if ( dwRes
!= ICERR_OK
)
136 ERR( "ICDecompress failed!\n" );
140 This
->lCachedFrame
= lPos
;
142 return This
->pvICOutBits
;
145 /****************************************************************************/
147 HRESULT
AVIFILE_CreateIGetFrame(void** ppobj
,
148 IAVIStream
* pstr
,LPBITMAPINFOHEADER lpbi
)
154 This
= (IGetFrameImpl
*)HeapAlloc(AVIFILE_data
.hHeap
,HEAP_ZERO_MEMORY
,
155 sizeof(IGetFrameImpl
));
157 ICOM_VTBL(This
) = &igetfrm
;
158 hr
= IGetFrame_Construct( This
, pstr
, lpbi
);
161 IGetFrame_Destruct( This
);
165 *ppobj
= (LPVOID
)This
;
170 /****************************************************************************
174 static HRESULT WINAPI
IGetFrame_fnQueryInterface(IGetFrame
* iface
,REFIID refiid
,LPVOID
*obj
)
176 ICOM_THIS(IGetFrameImpl
,iface
);
178 TRACE("(%p)->QueryInterface(%s,%p)\n",This
,debugstr_guid(refiid
),obj
);
179 if ( IsEqualGUID(&IID_IUnknown
,refiid
) ||
180 IsEqualGUID(&IID_IGetFrame
,refiid
) )
182 IGetFrame_AddRef(iface
);
187 return OLE_E_ENUM_NOMORE
;
190 static ULONG WINAPI
IGetFrame_fnAddRef(IGetFrame
* iface
)
192 ICOM_THIS(IGetFrameImpl
,iface
);
194 TRACE("(%p)->AddRef()\n",iface
);
195 return ++(This
->ref
);
198 static ULONG WINAPI
IGetFrame_fnRelease(IGetFrame
* iface
)
200 ICOM_THIS(IGetFrameImpl
,iface
);
202 TRACE("(%p)->Release()\n",iface
);
203 if ((--(This
->ref
)) > 0 )
205 IGetFrame_Destruct(This
);
206 if ( This
->pas
!= NULL
)
207 IAVIStream_Release( This
->pas
);
209 HeapFree(AVIFILE_data
.hHeap
,0,iface
);
213 /****************************************************************************
214 * IGetFrrame interface
217 static LPVOID WINAPI
IGetFrame_fnGetFrame(IGetFrame
* iface
,LONG lPos
)
219 ICOM_THIS(IGetFrameImpl
,iface
);
223 TRACE( "(%p)->(%ld)\n", This
, lPos
);
228 if ( This
->lCachedFrame
== lPos
)
229 return This
->pvICOutBits
;
230 if ( (This
->lCachedFrame
+1) != lPos
)
232 lKeyFrame
= IAVIStream_FindSample( This
->pas
, lPos
,
233 FIND_KEY
| FIND_PREV
);
234 if ( lKeyFrame
< 0 || lKeyFrame
> lPos
)
236 while ( ++lKeyFrame
< lPos
)
238 lpv
= AVIFILE_IGetFrame_DecodeFrame(This
, lKeyFrame
);
244 lpv
= AVIFILE_IGetFrame_DecodeFrame(This
, lPos
);
245 TRACE( "lpv = %p\n",lpv
);
252 static HRESULT WINAPI
IGetFrame_fnBegin(IGetFrame
* iface
,LONG lStart
,LONG lEnd
,LONG lRate
)
254 ICOM_THIS(IGetFrameImpl
,iface
);
256 TRACE( "(%p)->(%ld,%ld,%ld)\n", This
, lStart
, lEnd
, lRate
);
258 if ( This
->hIC
== (HIC
)NULL
)
261 if ( ICDecompressBegin( This
->hIC
,
263 This
->pbiICOut
) != ICERR_OK
)
269 static HRESULT WINAPI
IGetFrame_fnEnd(IGetFrame
* iface
)
271 ICOM_THIS(IGetFrameImpl
,iface
);
273 TRACE( "(%p)->()\n", This
);
275 if ( This
->hIC
== (HIC
)NULL
)
278 if ( ICDecompressEnd( This
->hIC
) != ICERR_OK
)
284 static HRESULT WINAPI
IGetFrame_fnSetFormat(IGetFrame
* iface
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
,INT x
,INT y
,INT dx
,INT dy
)
286 ICOM_THIS(IGetFrameImpl
,iface
);
289 BITMAPINFOHEADER biTemp
;
292 FIXME( "(%p)->(%p,%p,%d,%d,%d,%d)\n",This
,lpbi
,lpBits
,x
,y
,dx
,dy
);
294 IGetFrame_Destruct(This
);
296 hr
= IAVIStream_ReadFormat(This
->pas
,0,NULL
,&fmtlen
);
299 This
->pvICInFmtBuf
= HeapAlloc(
300 AVIFILE_data
.hHeap
,HEAP_ZERO_MEMORY
,fmtlen
);
301 if ( This
->pvICInFmtBuf
== NULL
)
302 return AVIERR_MEMORY
;
303 hr
= IAVIStream_ReadFormat(This
->pas
,0,This
->pvICInFmtBuf
,&fmtlen
);
306 This
->pbiICIn
= (LPBITMAPINFO
)This
->pvICInFmtBuf
;
308 This
->hIC
= (HIC
)ICOpen( ICTYPE_VIDEO
,
309 This
->pbiICIn
->bmiHeader
.biCompression
,
311 if ( This
->hIC
== (HIC
)NULL
)
313 ERR( "no AVI decompressor for %c%c%c%c.\n",
314 (int)(This
->pbiICIn
->bmiHeader
.biCompression
>> 0)&0xff,
315 (int)(This
->pbiICIn
->bmiHeader
.biCompression
>> 8)&0xff,
316 (int)(This
->pbiICIn
->bmiHeader
.biCompression
>>16)&0xff,
317 (int)(This
->pbiICIn
->bmiHeader
.biCompression
>>24)&0xff );
321 if ( lpbi
== NULL
|| lpbi
== ((LPBITMAPINFOHEADER
)1) )
323 memset( &biTemp
, 0, sizeof(biTemp
) );
324 biTemp
.biSize
= sizeof(BITMAPINFOHEADER
);
325 biTemp
.biWidth
= This
->pbiICIn
->bmiHeader
.biWidth
;
326 biTemp
.biHeight
= This
->pbiICIn
->bmiHeader
.biHeight
;
328 biTemp
.biBitCount
= 24;
329 biTemp
.biCompression
= 0;
333 if ( lpbi
->biPlanes
!= 1 || lpbi
->biCompression
!= 0 )
337 ((This
->pbiICIn
->bmiHeader
.biWidth
*lpbi
->biBitCount
+7)/8)*
338 This
->pbiICIn
->bmiHeader
.biHeight
;
339 This
->pvICOutBuf
= HeapAlloc(
340 AVIFILE_data
.hHeap
,HEAP_ZERO_MEMORY
,
341 (sizeof(BITMAPINFO
)+sizeof(RGBQUAD
)*256)*2+
343 if ( This
->pvICOutBuf
== NULL
)
344 return AVIERR_MEMORY
;
346 This
->pbiICOut
= (BITMAPINFO
*)This
->pvICOutBuf
;
347 This
->pvICOutBits
= (LPVOID
)( (BYTE
*)This
->pvICOutBuf
+
348 sizeof(BITMAPINFO
) + sizeof(RGBQUAD
)*256 );
350 This
->pbiICOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
351 This
->pbiICOut
->bmiHeader
.biWidth
= This
->pbiICIn
->bmiHeader
.biWidth
;
352 This
->pbiICOut
->bmiHeader
.biHeight
= This
->pbiICIn
->bmiHeader
.biHeight
;
353 This
->pbiICOut
->bmiHeader
.biPlanes
= 1;
354 This
->pbiICOut
->bmiHeader
.biBitCount
= lpbi
->biBitCount
;
355 This
->pbiICOut
->bmiHeader
.biSizeImage
= dwSizeImage
;
356 memcpy( This
->pvICOutBits
, This
->pbiICOut
, sizeof(BITMAPINFOHEADER
) );
361 static HRESULT
IGetFrame_Construct( IGetFrameImpl
* This
,
363 LPBITMAPINFOHEADER lpbi
)
367 TRACE( "(%p)->(%p,%p)\n",This
,pstr
,lpbi
);
369 IAVIStream_AddRef( pstr
);
371 This
->hIC
= (HIC
)NULL
;
372 This
->lCachedFrame
= -1L;
373 This
->pbiICIn
= NULL
;
374 This
->pbiICOut
= NULL
;
375 This
->pvICInFmtBuf
= NULL
;
376 This
->pvICInDataBuf
= NULL
;
377 This
->dwICInDataBufSize
= 0;
378 This
->pvICOutBuf
= NULL
;
380 hr
= IGetFrame_SetFormat((IGetFrame
*)This
,lpbi
,NULL
,0,0,0,0);
387 static void IGetFrame_Destruct( IGetFrameImpl
* This
)
389 if ( This
->hIC
!= (HIC
)NULL
)
391 ICClose( This
->hIC
);
392 This
->hIC
= (HIC
)NULL
;
394 if ( This
->pvICInFmtBuf
!= NULL
)
396 HeapFree( AVIFILE_data
.hHeap
, 0, This
->pvICInFmtBuf
);
397 This
->pvICInFmtBuf
= NULL
;
399 if ( This
->pvICInDataBuf
!= NULL
)
401 HeapFree( AVIFILE_data
.hHeap
, 0, This
->pvICInDataBuf
);
402 This
->pvICInDataBuf
= NULL
;
404 if ( This
->pvICOutBuf
!= NULL
)
406 HeapFree( AVIFILE_data
.hHeap
, 0, This
->pvICOutBuf
);
407 This
->pvICOutBuf
= NULL
;
410 This
->lCachedFrame
= -1L;
411 This
->pbiICIn
= NULL
;
412 This
->pbiICOut
= NULL
;
413 This
->dwICInDataBufSize
= 0;