Microsoft com vtable compatibility workaround for g++. Basically adds
[wine] / dlls / avifil32 / avifile.c
1 /*                                 
2  * Copyright 1999 Marcus Meissner
3  */
4 #include <string.h>
5 #include <stdio.h>
6 #include <assert.h>
7
8 #include "vfw.h"
9 #include "winbase.h"
10 #include "wine/winestring.h"
11 #include "driver.h"
12 #include "mmsystem.h"
13 #include "winerror.h"
14 #include "debugstr.h"
15 #include "debugtools.h"
16
17 DECLARE_DEBUG_CHANNEL(avifile)
18 DECLARE_DEBUG_CHANNEL(msvideo)
19 DECLARE_DEBUG_CHANNEL(relay)
20
21 typedef struct IAVIStreamImpl {
22         /* IUnknown stuff */
23         ICOM_VTABLE(IAVIStream)*        lpvtbl;
24         DWORD           ref;
25         /* IAVIStream stuff */
26         LPVOID          lpInputFormat;
27         DWORD           inputformatsize;
28         BOOL            iscompressing;
29         DWORD           curframe;
30
31             /* Compressor stuff */
32             HIC hic;
33             LPVOID      lpCompressFormat;
34             ICINFO      icinfo;
35             DWORD       compbufsize;
36             LPVOID      compbuffer;
37
38             DWORD       decompbufsize;
39             LPVOID      decompbuffer;
40             LPVOID      decompformat;
41             AVICOMPRESSOPTIONS  aco;
42
43             LPVOID      lpPrev; /* pointer to decompressed frame later */
44             LPVOID      lpPrevFormat; /* pointer to decompressed info later */
45 } IAVIStreamImpl;
46
47 void WINAPI
48 AVIFileInit(void) {
49         FIXME_(avifile)("(),stub!\n");
50 }
51
52 typedef struct IAVIFileImpl {
53         /* IUnknown stuff */
54         ICOM_VTABLE(IAVIFile)*  lpvtbl;
55         DWORD                           ref;
56         /* IAVIFile stuff... */
57 } IAVIFileImpl;
58
59 struct ICOM_VTABLE(IAVIStream) iavist;
60
61 static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
62         ICOM_THIS(IAVIFileImpl,iface);
63         char    xrefiid[50];
64
65         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
66         TRACE_(relay)("(%p)->QueryInterface(%s,%p)\n",This,xrefiid,obj);
67         if (    !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
68                 !memcmp(&IID_IAVIFile,refiid,sizeof(IID_IAVIFile))
69         ) {
70                 *obj = iface;
71                 return S_OK;
72         }
73         return OLE_E_ENUM_NOMORE;
74 }
75
76 static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
77         ICOM_THIS(IAVIFileImpl,iface);
78         
79         FIXME_(relay)("(%p)->AddRef()\n",iface);
80         return ++(This->ref);
81 }
82
83 static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
84         ICOM_THIS(IAVIFileImpl,iface);
85         
86         FIXME_(relay)("(%p)->Release()\n",iface);
87         if (!--(This->ref)) {
88                 HeapFree(GetProcessHeap(),0,iface);
89                 return 0;
90         }
91         return This->ref;
92 }
93
94 static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size) {
95         FIXME_(avifile)("(%p)->Info(%p,%ld)\n",iface,afi,size);
96
97         /* FIXME: fill out struct? */
98         return E_FAIL;
99 }
100
101 static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
102         FIXME_(avifile)("(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
103         /* FIXME: create interface etc. */
104         return E_FAIL;
105 }
106
107 static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
108         ICOM_THIS(IAVIStreamImpl,iface);
109         char            fcc[5];
110         IAVIStreamImpl  *istream;
111
112         FIXME_(avifile)("(%p,%p,%p)\n",This,avis,asi);
113         istream = (IAVIStreamImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIStreamImpl));
114         istream->ref = 1;
115         istream->lpvtbl = &iavist;
116         fcc[4]='\0';
117         memcpy(fcc,(char*)&(asi->fccType),4);
118         FIXME_(avifile)("\tfccType '%s'\n",fcc);
119         memcpy(fcc,(char*)&(asi->fccHandler),4);
120         FIXME_(avifile)("\tfccHandler '%s'\n",fcc);
121         FIXME_(avifile)("\tdwFlags 0x%08lx\n",asi->dwFlags);
122         FIXME_(avifile)("\tdwCaps 0x%08lx\n",asi->dwCaps);
123         FIXME_(avifile)("\tname '%s'\n",debugstr_w(asi->szName));
124
125         istream->curframe = 0;
126         *avis = (PAVISTREAM)istream;
127         return S_OK;
128 }
129
130 static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size) {
131         FIXME_(avifile)("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,ckid,lpData,size);
132         /* FIXME: write data to file */
133         return E_FAIL;
134 }
135
136 static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size) {
137         FIXME_(avifile)("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,ckid,lpData,size);
138         /* FIXME: read at most size bytes from file */
139         return E_FAIL;
140 }
141
142 static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface) {
143         FIXME_(avifile)("(%p)->EndRecord()\n",iface);
144         /* FIXME: end record? */
145         return E_FAIL;
146 }
147
148 static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam) {
149         FIXME_(avifile)("(%p)->DeleteStream(0x%08lx,%ld)\n",iface,fccType,lParam);
150         /* FIXME: delete stream? */
151         return E_FAIL;
152 }
153
154 struct ICOM_VTABLE(IAVIFile) iavift = {
155     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
156     IAVIFile_fnQueryInterface,
157     IAVIFile_fnAddRef,
158     IAVIFile_fnRelease,
159     IAVIFile_fnInfo,
160     IAVIFile_fnGetStream,
161     IAVIFile_fnCreateStream,
162     IAVIFile_fnWriteData,
163     IAVIFile_fnReadData,
164     IAVIFile_fnEndRecord,
165     IAVIFile_fnDeleteStream
166 };
167
168 HRESULT WINAPI AVIFileOpenA(
169         PAVIFILE * ppfile,LPCSTR szFile,UINT uMode,LPCLSID lpHandler
170 ) {
171         char    buf[80];
172         IAVIFileImpl    *iavi;
173
174
175         if (HIWORD(lpHandler))
176                 WINE_StringFromCLSID(lpHandler,buf);
177         else
178                 sprintf(buf,"<clsid-0x%04lx>",(DWORD)lpHandler);
179
180         FIXME_(avifile)("(%p,%s,0x%08lx,%s),stub!\n",ppfile,szFile,(DWORD)uMode,buf);
181         iavi = (IAVIFileImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIFileImpl));
182         iavi->ref = 1;
183         iavi->lpvtbl = &iavift;
184         *ppfile = (LPVOID)iavi;
185         return S_OK;
186 }
187
188 static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
189         ICOM_THIS(IAVIStreamImpl,iface);
190         char    xrefiid[50];
191
192         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
193         TRACE_(relay)("(%p)->QueryInterface(%s,%p)\n",This,xrefiid,obj);
194         if (    !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
195                 !memcmp(&IID_IAVIStream,refiid,sizeof(IID_IAVIStream))
196         ) {
197                 *obj = This;
198                 return S_OK;
199         }
200         /* can return IGetFrame interface too */
201         return OLE_E_ENUM_NOMORE;
202 }
203
204 static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface) {
205         ICOM_THIS(IAVIStreamImpl,iface);
206         
207         FIXME_(relay)("(%p)->AddRef()\n",iface);
208         return ++(This->ref);
209 }
210
211 static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
212         ICOM_THIS(IAVIStreamImpl,iface);
213         
214         FIXME_(relay)("(%p)->Release()\n",iface);
215         if (!--(This->ref)) {
216                 HeapFree(GetProcessHeap(),0,This);
217                 return 0;
218         }
219         return This->ref;
220 }
221
222 HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2) {
223         FIXME_(avifile)("(%p)->Create(0x%08lx,0x%08lx)\n",iface,lParam1,lParam2);
224         return E_FAIL;
225 }
226
227 HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size) {
228         FIXME_(avifile)("(%p)->Info(%p,%ld)\n",iface,psi,size);
229         return E_FAIL;
230 }
231
232 LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags) {
233         FIXME_(avifile)("(%p)->FindSample(%ld,0x%08lx)\n",iface,pos,flags);
234         return E_FAIL;
235 }
236
237 HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
238         FIXME_(avifile)("(%p)->ReadFormat(%ld,%p,%p)\n",iface,pos,format,formatsize);
239         return E_FAIL;
240 }
241
242 /*****************************************************************************
243  *                                              [IAVIStream::SetFormat]
244  */
245 HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
246         IAVIStreamImpl  *as = (IAVIStreamImpl*)iface;
247
248         FIXME_(avifile)("(%p)->SetFormat(%ld,%p,%ld)\n",iface,pos,format,formatsize);
249         if (as->lpInputFormat) HeapFree(GetProcessHeap(),0,as->lpInputFormat);
250         as->inputformatsize = formatsize;
251         as->lpInputFormat = HeapAlloc(GetProcessHeap(),0,formatsize);
252         memcpy(as->lpInputFormat,format,formatsize);
253         if (as->iscompressing) {
254                 int     xsize; 
255                 /* Set up the Compressor part */
256                 xsize = ICCompressGetFormatSize(as->hic,as->lpInputFormat);
257                 as->lpCompressFormat = HeapAlloc(GetProcessHeap(),0,xsize);
258                 ICCompressGetFormat(as->hic,as->lpInputFormat,as->lpCompressFormat);
259                 ICCompressBegin(as->hic,as->lpInputFormat,as->lpCompressFormat);
260                 as->compbufsize = ICCompressGetSize(as->hic,as->lpInputFormat,as->lpCompressFormat);
261                 as->compbuffer = HeapAlloc(GetProcessHeap(),0,as->compbufsize);
262
263                 /* Set up the Decompressor part (for prev frames?) */
264                 xsize=ICDecompressGetFormatSize(as->hic,as->lpCompressFormat);
265                 as->decompformat = HeapAlloc(GetProcessHeap(),0,xsize);
266                 ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
267                 as->decompbufsize=((LPBITMAPINFOHEADER)as->decompbuffer)->biSizeImage;
268                 as->decompbuffer = HeapReAlloc(GetProcessHeap(),0,as->decompbuffer,as->decompbufsize);
269                 memset(as->decompbuffer,0xff,as->decompbufsize);
270                 assert(HeapValidate(GetProcessHeap(),0,NULL));
271
272                 ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
273                 ICDecompressBegin(as->hic,as->lpCompressFormat,as->decompformat);
274                 as->lpPrev = as->lpPrevFormat = NULL;
275         }
276         return S_OK;
277 }
278
279 HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
280         FIXME_(avifile)("(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",iface,start,samples,buffer,buffersize,bytesread,samplesread);
281         return E_FAIL;
282 }
283
284 HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
285         IAVIStreamImpl  *as = (IAVIStreamImpl*)iface;
286         DWORD           ckid,xflags;
287
288         FIXME_(avifile)("(%p)->Write(%ld,%ld,%p,%ld,0x%08lx,%p,%p)\n",iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
289
290         ICCompress(
291                 as->hic,flags,
292                 as->lpCompressFormat,
293                 as->compbuffer,
294                 as->lpInputFormat,buffer,
295                 &ckid,&xflags,
296                 as->curframe,0xffffff/*framesize*/,as->aco.dwQuality,
297                 as->lpPrevFormat,as->lpPrev
298         );
299         ICDecompress(
300                 as->hic,
301                 flags,  /* FIXME: check */
302                 as->lpCompressFormat,
303                 as->compbuffer,
304                 as->decompformat,
305                 as->decompbuffer
306         );
307         /* We now have a prev format for the next compress ... */
308         as->lpPrevFormat = as->decompformat;
309         as->lpPrev = as->decompbuffer;
310         return S_OK;
311 }
312
313 HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
314         FIXME_(avifile)("(%p)->Delete(%ld,%ld)\n",iface,start,samples);
315         return E_FAIL;
316 }
317
318 HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
319         FIXME_(avifile)("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,fcc,lp,lpread);
320         return E_FAIL;
321 }
322
323 HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
324         FIXME_(avifile)("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,fcc,lp,size);
325         return E_FAIL;
326 }
327
328 HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
329         FIXME_(avifile)("(%p)->SetInfo(%p,%ld)\n",iface,info,infolen);
330         return E_FAIL;
331 }
332
333 struct ICOM_VTABLE(IAVIStream) iavist = {
334     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
335     IAVIStream_fnQueryInterface,
336     IAVIStream_fnAddRef,
337     IAVIStream_fnRelease,
338     IAVIStream_fnCreate,
339     IAVIStream_fnInfo,
340     IAVIStream_fnFindSample,
341     IAVIStream_fnReadFormat,
342     IAVIStream_fnSetFormat,
343     IAVIStream_fnRead,
344     IAVIStream_fnWrite,
345     IAVIStream_fnDelete,
346     IAVIStream_fnReadData,
347     IAVIStream_fnWriteData,
348     IAVIStream_fnSetInfo
349 };
350
351 HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE iface,PAVISTREAM *ppavi,AVISTREAMINFOA * psi) {
352         AVISTREAMINFOW  psiw;
353         
354         /* Only the szName at the end is different */
355         memcpy(&psiw,psi,sizeof(*psi)-sizeof(psi->szName));
356         lstrcpynAtoW(psiw.szName,psi->szName,sizeof(psi->szName));
357         return iface->lpvtbl->fnCreateStream(iface,ppavi,&psiw);
358 }
359
360 HRESULT WINAPI AVIFileCreateStreamW(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
361         return iface->lpvtbl->fnCreateStream(iface,avis,asi);
362 }
363
364
365 HRESULT WINAPI AVIFileGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
366         return iface->lpvtbl->fnGetStream(iface,avis,fccType,lParam);
367 }
368
369 HRESULT WINAPI AVIFileInfoA(PAVIFILE iface,LPAVIFILEINFOA afi,LONG size) {
370         AVIFILEINFOW    afiw;
371         HRESULT         hres;
372
373         if (size < sizeof(AVIFILEINFOA))
374                 return AVIERR_BADSIZE;
375         hres = iface->lpvtbl->fnInfo(iface,&afiw,sizeof(afiw));
376         memcpy(afi,&afiw,sizeof(*afi)-sizeof(afi->szFileType));
377         lstrcpynWtoA(afi->szFileType,afiw.szFileType,sizeof(afi->szFileType));
378         return hres;
379 }
380
381 HRESULT WINAPI AVIStreamInfoW(PAVISTREAM iface,AVISTREAMINFOW *asi,LONG
382  size) {
383         return iface->lpvtbl->fnInfo(iface,asi,size);
384 }
385
386 HRESULT WINAPI AVIStreamInfoA(PAVISTREAM iface,AVISTREAMINFOA *asi,LONG
387  size) {
388         AVISTREAMINFOW  asiw;
389         HRESULT                 hres;
390
391         if (size<sizeof(AVISTREAMINFOA))
392                 return AVIERR_BADSIZE;
393         hres = iface->lpvtbl->fnInfo(iface,&asiw,sizeof(asiw));
394         memcpy(asi,&asiw,sizeof(asiw)-sizeof(asiw.szName));
395         lstrcpynWtoA(asi->szName,asiw.szName,sizeof(asi->szName));
396         return hres;
397 }
398
399 HRESULT WINAPI AVIFileInfoW(PAVIFILE iface,LPAVIFILEINFOW afi,LONG size) {
400         return iface->lpvtbl->fnInfo(iface,afi,size);
401 }
402
403 HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *aco,CLSID *pclsidHandler) {
404         char                    fcc[5];
405         IAVIStreamImpl  *as;
406         FIXME_(avifile)("(%p,%p,%p,%p)\n",ppsCompressed,ppsSource,aco,pclsidHandler);
407         fcc[4]='\0';
408         memcpy(fcc,&(aco->fccType),4);
409         FIXME_(avifile)("\tfccType: '%s'\n",fcc);
410         memcpy(fcc,&(aco->fccHandler),4);
411         FIXME_(avifile)("\tfccHandler: '%s'\n",fcc);
412         FIXME_(avifile)("\tdwFlags: 0x%08lx\n",aco->dwFlags);
413
414         /* we just create a duplicate for now */
415         ((IUnknown*)ppsSource)->lpvtbl->fnAddRef((IUnknown*)ppsSource);
416         *ppsCompressed = ppsSource;
417         as = (IAVIStreamImpl*)ppsSource;
418
419         /* this is where the fun begins. Open a compressor and prepare it. */
420         as->hic = ICOpen(aco->fccType,aco->fccHandler,ICMODE_COMPRESS);
421
422         /* May happen. for instance if the codec is not able to compress */
423         if (!as->hic) 
424                 return AVIERR_UNSUPPORTED;
425
426         ICGetInfo(as->hic,&(as->icinfo),sizeof(ICINFO));
427         FIXME_(avifile)("Opened compressor: '%s' '%s'\n",debugstr_w(as->icinfo.szName),debugstr_w(as->icinfo.szDescription));
428         as->iscompressing = TRUE;
429         memcpy(&(as->aco),aco,sizeof(*aco));
430         if (as->icinfo.dwFlags & VIDCF_COMPRESSFRAMES) {
431                 ICCOMPRESSFRAMES        icf;
432
433                 /* now what to fill in there ... Hmm */
434                 memset(&icf,0,sizeof(icf));
435                 icf.lDataRate   = aco->dwBytesPerSecond;
436                 icf.lQuality    = aco->dwQuality;
437                 icf.lKeyRate    = aco->dwKeyFrameEvery;
438
439                 icf.GetData = (LONG (*)(LPARAM,LONG,LPVOID,LONG)) 0xdead4242;
440                 icf.PutData = (LONG (*)(LPARAM,LONG,LPVOID,LONG)) 0xdead4243;
441                 ICSendMessage(as->hic,ICM_COMPRESS_FRAMES_INFO,(LPARAM)&icf,sizeof(icf));
442         }
443         return S_OK;
444 }
445
446 HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG formatsize) {
447         return iface->lpvtbl->fnSetFormat(iface,pos,format,formatsize);
448 }
449
450 HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG *formatsize) {
451         return iface->lpvtbl->fnReadFormat(iface,pos,format,formatsize);
452 }
453
454 HRESULT WINAPI AVIStreamWrite(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
455         return iface->lpvtbl->fnWrite(iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
456 }
457
458 HRESULT WINAPI AVIStreamRead(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
459         return iface->lpvtbl->fnRead(iface,start,samples,buffer,buffersize,bytesread,samplesread);
460 }
461
462 HRESULT WINAPI AVIStreamWriteData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG size) {
463         return iface->lpvtbl->fnWriteData(iface,fcc,lp,size);
464 }
465
466 HRESULT WINAPI AVIStreamReadData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG *lpread) {
467         return iface->lpvtbl->fnReadData(iface,fcc,lp,lpread);
468 }
469
470 LONG WINAPI AVIStreamStart(PAVISTREAM iface) {
471         AVISTREAMINFOW  si;
472
473         iface->lpvtbl->fnInfo(iface,&si,sizeof(si));
474         return si.dwStart;
475 }
476
477 LONG WINAPI AVIStreamLength(PAVISTREAM iface) {
478         AVISTREAMINFOW  si;
479         HRESULT                 ret;
480
481         ret = iface->lpvtbl->fnInfo(iface,&si,sizeof(si));
482         if (ret) /* error */
483                 return 1;
484         return si.dwLength;
485 }
486
487 ULONG WINAPI AVIStreamRelease(PAVISTREAM iface) {
488         return ((LPUNKNOWN)iface)->lpvtbl->fnRelease((LPUNKNOWN)iface);
489 }
490
491 PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM iface,LPBITMAPINFOHEADER bmi) {
492         FIXME_(msvideo)("(%p)->(%p),stub!\n",iface,bmi);
493         return NULL;
494 }
495
496 LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg,LONG pos) {
497         return pg->lpvtbl->fnGetFrame(pg,pos);
498 }
499
500 HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg) {
501         if (pg) ((LPUNKNOWN)pg)->lpvtbl->fnRelease((LPUNKNOWN)pg);
502         return 0;
503 }
504
505 ULONG WINAPI AVIFileRelease(PAVIFILE iface) {
506         return ((LPUNKNOWN)iface)->lpvtbl->fnRelease((LPUNKNOWN)iface);
507 }
508
509 void WINAPI AVIFileExit(void) {
510         FIXME_(avifile)("(), stub.\n");
511 }