source: trunk/src/avifil32/igframe.c@ 6712

Last change on this file since 6712 was 6712, checked in by sandervl, 24 years ago

restored old version

File size: 10.0 KB
Line 
1/*
2 * Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
3 *
4 * FIXME - implements color space(depth) converter.
5 */
6
7#include <string.h>
8#include <stdio.h>
9#include <assert.h>
10
11#include "winbase.h"
12#include "winnls.h"
13#include "mmsystem.h"
14#include "winerror.h"
15#include "vfw.h"
16#include "debugtools.h"
17#include "avifile_private.h"
18
19DEFAULT_DEBUG_CHANNEL(avifile);
20
21static HRESULT WINAPI IGetFrame_fnQueryInterface(IGetFrame* iface,REFIID refiid,LPVOID *obj);
22static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame* iface);
23static ULONG WINAPI IGetFrame_fnRelease(IGetFrame* iface);
24static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame* iface,LONG lPos);
25static HRESULT WINAPI IGetFrame_fnBegin(IGetFrame* iface,LONG lStart,LONG lEnd,LONG lRate);
26static HRESULT WINAPI IGetFrame_fnEnd(IGetFrame* iface);
27static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame* iface,LPBITMAPINFOHEADER lpbi,LPVOID lpBits,INT x,INT y,INT dx,INT dy);
28
29struct ICOM_VTABLE(IGetFrame) igetfrm = {
30 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
31 IGetFrame_fnQueryInterface,
32 IGetFrame_fnAddRef,
33 IGetFrame_fnRelease,
34 IGetFrame_fnGetFrame,
35 IGetFrame_fnBegin,
36 IGetFrame_fnEnd,
37 IGetFrame_fnSetFormat,
38};
39
40typedef struct IGetFrameImpl
41{
42 ICOM_VFIELD(IGetFrame);
43 /* IUnknown stuff */
44 DWORD ref;
45 /* IGetFrame stuff */
46 IAVIStream* pas;
47 HIC hIC;
48 LONG lCachedFrame;
49 BITMAPINFO* pbiICIn;
50 BITMAPINFO* pbiICOut;
51 LPVOID pvICOutBits;
52 LPVOID pvICInFmtBuf;
53 DWORD dwICInDataBufSize;
54 LPVOID pvICInDataBuf;
55 LPVOID pvICOutBuf;
56} IGetFrameImpl;
57
58static HRESULT IGetFrame_Construct( IGetFrameImpl* This,
59 IAVIStream* pstr,
60 LPBITMAPINFOHEADER lpbi );
61static void IGetFrame_Destruct( IGetFrameImpl* This );
62
63
64
65
66static LPVOID AVIFILE_IGetFrame_DecodeFrame(IGetFrameImpl* This,LONG lPos)
67{
68 HRESULT hr;
69 DWORD dwRes;
70 LONG lFrameLength;
71 LONG lSampleCount;
72 ICDECOMPRESS icd;
73
74 if ( This->hIC == (HIC)NULL )
75 return NULL;
76
77 hr = IAVIStream_Read(This->pas,lPos,1,NULL,0,
78 &lFrameLength,&lSampleCount);
79 if ( hr != S_OK || lSampleCount <= 0 )
80 {
81 FIXME( "IAVIStream_Read failed! res = %08lx\n", hr );
82 return NULL;
83 }
84 TRACE( "frame length = %ld\n", lFrameLength );
85
86 if ( This->dwICInDataBufSize < lFrameLength )
87 {
88 LPVOID lpv;
89
90 if ( This->pvICInDataBuf == NULL )
91 {
92 lpv = HeapAlloc(
93 AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
94 lFrameLength );
95 }
96 else
97 {
98 lpv = HeapReAlloc(
99 AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
100 This->pvICInDataBuf,lFrameLength );
101 }
102 if ( lpv == NULL )
103 {
104 ERR( "out of memory!\n" );
105 return NULL;
106 }
107 This->pvICInDataBuf = lpv;
108 This->dwICInDataBufSize = lFrameLength;
109 }
110
111 hr = IAVIStream_Read(This->pas,lPos,1,
112 This->pvICInDataBuf,This->dwICInDataBufSize,
113 &lFrameLength,&lSampleCount);
114 if ( hr != S_OK || lSampleCount <= 0 )
115 {
116 FIXME( "IAVIStream_Read to buffer failed! res = %08lx\n", hr );
117 return NULL;
118 }
119
120 This->pbiICIn->bmiHeader.biSizeImage = lFrameLength;
121
122 TRACE( "call ICM_DECOMPRESS\n" );
123 icd.dwFlags = (*(BYTE*)This->pvICInDataBuf) == 'c' ?
124 ICDECOMPRESS_NOTKEYFRAME : 0;
125 icd.lpbiInput = &This->pbiICIn->bmiHeader;
126 icd.lpInput = (BYTE*)This->pvICInDataBuf + 8;
127 icd.lpbiOutput = &This->pbiICOut->bmiHeader;
128 icd.lpOutput = This->pvICOutBits;
129 icd.ckid = *((DWORD*)This->pvICInDataBuf);
130 dwRes = ICSendMessage(This->hIC,ICM_DECOMPRESS,
131 (DWORD)(&icd),sizeof(ICDECOMPRESS) );
132 TRACE( "returned from ICM_DECOMPRESS\n" );
133 if ( dwRes != ICERR_OK )
134 {
135 ERR( "ICDecompress failed!\n" );
136 return NULL;
137 }
138
139 This->lCachedFrame = lPos;
140
141 return This->pvICOutBits;
142}
143
144/****************************************************************************/
145
146HRESULT AVIFILE_CreateIGetFrame(void** ppobj,
147 IAVIStream* pstr,LPBITMAPINFOHEADER lpbi)
148{
149 IGetFrameImpl *This;
150 HRESULT hr;
151
152 *ppobj = NULL;
153 This = (IGetFrameImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
154 sizeof(IGetFrameImpl));
155 This->ref = 1;
156 ICOM_VTBL(This) = &igetfrm;
157 hr = IGetFrame_Construct( This, pstr, lpbi );
158 if ( hr != S_OK )
159 {
160 IGetFrame_Destruct( This );
161 return hr;
162 }
163
164 *ppobj = (LPVOID)This;
165
166 return S_OK;
167}
168
169/****************************************************************************
170 * IUnknown interface
171 */
172
173static HRESULT WINAPI IGetFrame_fnQueryInterface(IGetFrame* iface,REFIID refiid,LPVOID *obj)
174{
175 ICOM_THIS(IGetFrameImpl,iface);
176
177 TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
178 if ( IsEqualGUID(&IID_IUnknown,refiid) ||
179 IsEqualGUID(&IID_IGetFrame,refiid) )
180 {
181 IGetFrame_AddRef(iface);
182 *obj = iface;
183 return S_OK;
184 }
185
186 return OLE_E_ENUM_NOMORE;
187}
188
189static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame* iface)
190{
191 ICOM_THIS(IGetFrameImpl,iface);
192
193 TRACE("(%p)->AddRef()\n",iface);
194 return ++(This->ref);
195}
196
197static ULONG WINAPI IGetFrame_fnRelease(IGetFrame* iface)
198{
199 ICOM_THIS(IGetFrameImpl,iface);
200
201 TRACE("(%p)->Release()\n",iface);
202 if ((--(This->ref)) > 0 )
203 return This->ref;
204 IGetFrame_Destruct(This);
205 if ( This->pas != NULL )
206 IAVIStream_Release( This->pas );
207
208 HeapFree(AVIFILE_data.hHeap,0,iface);
209 return 0;
210}
211
212/****************************************************************************
213 * IGetFrrame interface
214 */
215
216static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame* iface,LONG lPos)
217{
218 ICOM_THIS(IGetFrameImpl,iface);
219 LPVOID lpv;
220 LONG lKeyFrame;
221
222 TRACE( "(%p)->(%ld)\n", This, lPos );
223
224 if ( lPos < 0 )
225 return NULL;
226
227 if ( This->lCachedFrame == lPos )
228 return This->pvICOutBits;
229 if ( (This->lCachedFrame+1) != lPos )
230 {
231 lKeyFrame = IAVIStream_FindSample( This->pas, lPos,
232 FIND_KEY | FIND_PREV );
233 if ( lKeyFrame < 0 || lKeyFrame > lPos )
234 return NULL;
235 while ( ++lKeyFrame < lPos )
236 {
237 lpv = AVIFILE_IGetFrame_DecodeFrame(This, lKeyFrame);
238 if ( lpv == NULL )
239 return NULL;
240 }
241 }
242
243 lpv = AVIFILE_IGetFrame_DecodeFrame(This, lPos);
244 TRACE( "lpv = %p\n",lpv );
245 if ( lpv == NULL )
246 return NULL;
247
248 return lpv;
249}
250
251static HRESULT WINAPI IGetFrame_fnBegin(IGetFrame* iface,LONG lStart,LONG lEnd,LONG lRate)
252{
253 ICOM_THIS(IGetFrameImpl,iface);
254
255 TRACE( "(%p)->(%ld,%ld,%ld)\n", This, lStart, lEnd, lRate );
256
257 if ( This->hIC == (HIC)NULL )
258 return E_UNEXPECTED;
259
260 if ( ICDecompressBegin( This->hIC,
261 This->pbiICIn,
262 This->pbiICOut ) != ICERR_OK )
263 return E_FAIL;
264
265 return S_OK;
266}
267
268static HRESULT WINAPI IGetFrame_fnEnd(IGetFrame* iface)
269{
270 ICOM_THIS(IGetFrameImpl,iface);
271
272 TRACE( "(%p)->()\n", This );
273
274 if ( This->hIC == (HIC)NULL )
275 return E_UNEXPECTED;
276
277 if ( ICDecompressEnd( This->hIC ) != ICERR_OK )
278 return E_FAIL;
279
280 return S_OK;
281}
282
283static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame* iface,LPBITMAPINFOHEADER lpbi,LPVOID lpBits,INT x,INT y,INT dx,INT dy)
284{
285 ICOM_THIS(IGetFrameImpl,iface);
286 HRESULT hr;
287 LONG fmtlen;
288 BITMAPINFOHEADER biTemp;
289 DWORD dwSizeImage;
290
291 FIXME( "(%p)->(%p,%p,%d,%d,%d,%d)\n",This,lpbi,lpBits,x,y,dx,dy );
292
293 IGetFrame_Destruct(This);
294
295 hr = IAVIStream_ReadFormat(This->pas,0,NULL,&fmtlen);
296 if ( hr != S_OK )
297 return hr;
298 This->pvICInFmtBuf = HeapAlloc(
299 AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,fmtlen);
300 if ( This->pvICInFmtBuf == NULL )
301 return AVIERR_MEMORY;
302 hr = IAVIStream_ReadFormat(This->pas,0,This->pvICInFmtBuf,&fmtlen);
303 if ( hr != S_OK )
304 return hr;
305 This->pbiICIn = (LPBITMAPINFO)This->pvICInFmtBuf;
306
307 This->hIC = (HIC)ICOpen( ICTYPE_VIDEO,
308 This->pbiICIn->bmiHeader.biCompression,
309 ICMODE_DECOMPRESS );
310 if ( This->hIC == (HIC)NULL )
311 {
312 ERR( "no AVI decompressor for %c%c%c%c.\n",
313 (int)(This->pbiICIn->bmiHeader.biCompression>> 0)&0xff,
314 (int)(This->pbiICIn->bmiHeader.biCompression>> 8)&0xff,
315 (int)(This->pbiICIn->bmiHeader.biCompression>>16)&0xff,
316 (int)(This->pbiICIn->bmiHeader.biCompression>>24)&0xff );
317 return E_FAIL;
318 }
319
320 if ( lpbi == NULL || lpbi == ((LPBITMAPINFOHEADER)1) )
321 {
322 memset( &biTemp, 0, sizeof(biTemp) );
323 biTemp.biSize = sizeof(BITMAPINFOHEADER);
324 biTemp.biWidth = This->pbiICIn->bmiHeader.biWidth;
325 biTemp.biHeight = This->pbiICIn->bmiHeader.biHeight;
326 biTemp.biPlanes = 1;
327 biTemp.biBitCount = 24;
328 biTemp.biCompression = 0;
329 lpbi = &biTemp;
330 }
331
332 if ( lpbi->biPlanes != 1 || lpbi->biCompression != 0 )
333 return E_FAIL;
334
335 dwSizeImage =
336 ((This->pbiICIn->bmiHeader.biWidth*lpbi->biBitCount+7)/8)*
337 This->pbiICIn->bmiHeader.biHeight;
338 This->pvICOutBuf = HeapAlloc(
339 AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
340 (sizeof(BITMAPINFO)+sizeof(RGBQUAD)*256)*2+
341 dwSizeImage );
342 if ( This->pvICOutBuf == NULL )
343 return AVIERR_MEMORY;
344
345 This->pbiICOut = (BITMAPINFO*)This->pvICOutBuf;
346 This->pvICOutBits = (LPVOID)( (BYTE*)This->pvICOutBuf +
347 sizeof(BITMAPINFO) + sizeof(RGBQUAD)*256 );
348
349 This->pbiICOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
350 This->pbiICOut->bmiHeader.biWidth = This->pbiICIn->bmiHeader.biWidth;
351 This->pbiICOut->bmiHeader.biHeight = This->pbiICIn->bmiHeader.biHeight;
352 This->pbiICOut->bmiHeader.biPlanes = 1;
353 This->pbiICOut->bmiHeader.biBitCount = lpbi->biBitCount;
354 This->pbiICOut->bmiHeader.biSizeImage = dwSizeImage;
355 memcpy( This->pvICOutBits, This->pbiICOut, sizeof(BITMAPINFOHEADER) );
356
357 return S_OK;
358}
359
360static HRESULT IGetFrame_Construct( IGetFrameImpl* This,
361 IAVIStream* pstr,
362 LPBITMAPINFOHEADER lpbi )
363{
364 HRESULT hr;
365
366 TRACE( "(%p)->(%p,%p)\n",This,pstr,lpbi );
367
368 IAVIStream_AddRef( pstr );
369 This->pas = pstr;
370 This->hIC = (HIC)NULL;
371 This->lCachedFrame = -1L;
372 This->pbiICIn = NULL;
373 This->pbiICOut = NULL;
374 This->pvICInFmtBuf = NULL;
375 This->pvICInDataBuf = NULL;
376 This->dwICInDataBufSize = 0;
377 This->pvICOutBuf = NULL;
378
379 hr = IGetFrame_SetFormat((IGetFrame*)This,lpbi,NULL,0,0,0,0);
380 if ( hr != S_OK )
381 return hr;
382
383 return S_OK;
384}
385
386static void IGetFrame_Destruct( IGetFrameImpl* This )
387{
388 if ( This->hIC != (HIC)NULL )
389 {
390 ICClose( This->hIC );
391 This->hIC = (HIC)NULL;
392 }
393 if ( This->pvICInFmtBuf != NULL )
394 {
395 HeapFree( AVIFILE_data.hHeap, 0, This->pvICInFmtBuf );
396 This->pvICInFmtBuf = NULL;
397 }
398 if ( This->pvICInDataBuf != NULL )
399 {
400 HeapFree( AVIFILE_data.hHeap, 0, This->pvICInDataBuf );
401 This->pvICInDataBuf = NULL;
402 }
403 if ( This->pvICOutBuf != NULL )
404 {
405 HeapFree( AVIFILE_data.hHeap, 0, This->pvICOutBuf );
406 This->pvICOutBuf = NULL;
407 }
408
409 This->lCachedFrame = -1L;
410 This->pbiICIn = NULL;
411 This->pbiICOut = NULL;
412 This->dwICInDataBufSize = 0;
413}
Note: See TracBrowser for help on using the repository browser.