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

Last change on this file since 6652 was 6652, checked in by bird, 24 years ago

Added $Id:$ keyword.

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