Converted to the new debugging interface (done with the help of the
[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     IAVIFile_fnQueryInterface,
156     IAVIFile_fnAddRef,
157     IAVIFile_fnRelease,
158     IAVIFile_fnInfo,
159     IAVIFile_fnGetStream,
160     IAVIFile_fnCreateStream,
161     IAVIFile_fnWriteData,
162     IAVIFile_fnReadData,
163     IAVIFile_fnEndRecord,
164     IAVIFile_fnDeleteStream
165 };
166
167 HRESULT WINAPI AVIFileOpenA(
168         PAVIFILE * ppfile,LPCSTR szFile,UINT uMode,LPCLSID lpHandler
169 ) {
170         char    buf[80];
171         IAVIFileImpl    *iavi;
172
173
174         if (HIWORD(lpHandler))
175                 WINE_StringFromCLSID(lpHandler,buf);
176         else
177                 sprintf(buf,"<clsid-0x%04lx>",(DWORD)lpHandler);
178
179         FIXME_(avifile)("(%p,%s,0x%08lx,%s),stub!\n",ppfile,szFile,(DWORD)uMode,buf);
180         iavi = (IAVIFileImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIFileImpl));
181         iavi->ref = 1;
182         iavi->lpvtbl = &iavift;
183         *ppfile = (LPVOID)iavi;
184         return S_OK;
185 }
186
187 static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
188         ICOM_THIS(IAVIStreamImpl,iface);
189         char    xrefiid[50];
190
191         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
192         TRACE_(relay)("(%p)->QueryInterface(%s,%p)\n",This,xrefiid,obj);
193         if (    !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
194                 !memcmp(&IID_IAVIStream,refiid,sizeof(IID_IAVIStream))
195         ) {
196                 *obj = This;
197                 return S_OK;
198         }
199         /* can return IGetFrame interface too */
200         return OLE_E_ENUM_NOMORE;
201 }
202
203 static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface) {
204         ICOM_THIS(IAVIStreamImpl,iface);
205         
206         FIXME_(relay)("(%p)->AddRef()\n",iface);
207         return ++(This->ref);
208 }
209
210 static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
211         ICOM_THIS(IAVIStreamImpl,iface);
212         
213         FIXME_(relay)("(%p)->Release()\n",iface);
214         if (!--(This->ref)) {
215                 HeapFree(GetProcessHeap(),0,This);
216                 return 0;
217         }
218         return This->ref;
219 }
220
221 HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2) {
222         FIXME_(avifile)("(%p)->Create(0x%08lx,0x%08lx)\n",iface,lParam1,lParam2);
223         return E_FAIL;
224 }
225
226 HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size) {
227         FIXME_(avifile)("(%p)->Info(%p,%ld)\n",iface,psi,size);
228         return E_FAIL;
229 }
230
231 LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags) {
232         FIXME_(avifile)("(%p)->FindSample(%ld,0x%08lx)\n",iface,pos,flags);
233         return E_FAIL;
234 }
235
236 HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
237         FIXME_(avifile)("(%p)->ReadFormat(%ld,%p,%p)\n",iface,pos,format,formatsize);
238         return E_FAIL;
239 }
240
241 /*****************************************************************************
242  *                                              [IAVIStream::SetFormat]
243  */
244 HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
245         IAVIStreamImpl  *as = (IAVIStreamImpl*)iface;
246
247         FIXME_(avifile)("(%p)->SetFormat(%ld,%p,%ld)\n",iface,pos,format,formatsize);
248         if (as->lpInputFormat) HeapFree(GetProcessHeap(),0,as->lpInputFormat);
249         as->inputformatsize = formatsize;
250         as->lpInputFormat = HeapAlloc(GetProcessHeap(),0,formatsize);
251         memcpy(as->lpInputFormat,format,formatsize);
252         if (as->iscompressing) {
253                 int     xsize; 
254                 /* Set up the Compressor part */
255                 xsize = ICCompressGetFormatSize(as->hic,as->lpInputFormat);
256                 as->lpCompressFormat = HeapAlloc(GetProcessHeap(),0,xsize);
257                 ICCompressGetFormat(as->hic,as->lpInputFormat,as->lpCompressFormat);
258                 ICCompressBegin(as->hic,as->lpInputFormat,as->lpCompressFormat);
259                 as->compbufsize = ICCompressGetSize(as->hic,as->lpInputFormat,as->lpCompressFormat);
260                 as->compbuffer = HeapAlloc(GetProcessHeap(),0,as->compbufsize);
261
262                 /* Set up the Decompressor part (for prev frames?) */
263                 xsize=ICDecompressGetFormatSize(as->hic,as->lpCompressFormat);
264                 as->decompformat = HeapAlloc(GetProcessHeap(),0,xsize);
265                 ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
266                 as->decompbufsize=((LPBITMAPINFOHEADER)as->decompbuffer)->biSizeImage;
267                 as->decompbuffer = HeapReAlloc(GetProcessHeap(),0,as->decompbuffer,as->decompbufsize);
268                 memset(as->decompbuffer,0xff,as->decompbufsize);
269                 assert(HeapValidate(GetProcessHeap(),0,NULL));
270
271                 ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
272                 ICDecompressBegin(as->hic,as->lpCompressFormat,as->decompformat);
273                 as->lpPrev = as->lpPrevFormat = NULL;
274         }
275         return S_OK;
276 }
277
278 HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
279         FIXME_(avifile)("(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",iface,start,samples,buffer,buffersize,bytesread,samplesread);
280         return E_FAIL;
281 }
282
283 HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
284         IAVIStreamImpl  *as = (IAVIStreamImpl*)iface;
285         DWORD           ckid,xflags;
286
287         FIXME_(avifile)("(%p)->Write(%ld,%ld,%p,%ld,0x%08lx,%p,%p)\n",iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
288
289         ICCompress(
290                 as->hic,flags,
291                 as->lpCompressFormat,
292                 as->compbuffer,
293                 as->lpInputFormat,buffer,
294                 &ckid,&xflags,
295                 as->curframe,0xffffff/*framesize*/,as->aco.dwQuality,
296                 as->lpPrevFormat,as->lpPrev
297         );
298         ICDecompress(
299                 as->hic,
300                 flags,  /* FIXME: check */
301                 as->lpCompressFormat,
302                 as->compbuffer,
303                 as->decompformat,
304                 as->decompbuffer
305         );
306         /* We now have a prev format for the next compress ... */
307         as->lpPrevFormat = as->decompformat;
308         as->lpPrev = as->decompbuffer;
309         return S_OK;
310 }
311
312 HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
313         FIXME_(avifile)("(%p)->Delete(%ld,%ld)\n",iface,start,samples);
314         return E_FAIL;
315 }
316
317 HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
318         FIXME_(avifile)("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,fcc,lp,lpread);
319         return E_FAIL;
320 }
321
322 HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
323         FIXME_(avifile)("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,fcc,lp,size);
324         return E_FAIL;
325 }
326
327 HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
328         FIXME_(avifile)("(%p)->SetInfo(%p,%ld)\n",iface,info,infolen);
329         return E_FAIL;
330 }
331
332 struct ICOM_VTABLE(IAVIStream) iavist = {
333     IAVIStream_fnQueryInterface,
334     IAVIStream_fnAddRef,
335     IAVIStream_fnRelease,
336     IAVIStream_fnCreate,
337     IAVIStream_fnInfo,
338     IAVIStream_fnFindSample,
339     IAVIStream_fnReadFormat,
340     IAVIStream_fnSetFormat,
341     IAVIStream_fnRead,
342     IAVIStream_fnWrite,
343     IAVIStream_fnDelete,
344     IAVIStream_fnReadData,
345     IAVIStream_fnWriteData,
346     IAVIStream_fnSetInfo
347 };
348
349 HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE iface,PAVISTREAM *ppavi,AVISTREAMINFOA * psi) {
350         AVISTREAMINFOW  psiw;
351         
352         /* Only the szName at the end is different */
353         memcpy(&psiw,psi,sizeof(*psi)-sizeof(psi->szName));
354         lstrcpynAtoW(psiw.szName,psi->szName,sizeof(psi->szName));
355         return iface->lpvtbl->fnCreateStream(iface,ppavi,&psiw);
356 }
357
358 HRESULT WINAPI AVIFileCreateStreamW(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
359         return iface->lpvtbl->fnCreateStream(iface,avis,asi);
360 }
361
362
363 HRESULT WINAPI AVIFileGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
364         return iface->lpvtbl->fnGetStream(iface,avis,fccType,lParam);
365 }
366
367 HRESULT WINAPI AVIFileInfoA(PAVIFILE iface,LPAVIFILEINFOA afi,LONG size) {
368         AVIFILEINFOW    afiw;
369         HRESULT         hres;
370
371         if (size < sizeof(AVIFILEINFOA))
372                 return AVIERR_BADSIZE;
373         hres = iface->lpvtbl->fnInfo(iface,&afiw,sizeof(afiw));
374         memcpy(afi,&afiw,sizeof(*afi)-sizeof(afi->szFileType));
375         lstrcpynWtoA(afi->szFileType,afiw.szFileType,sizeof(afi->szFileType));
376         return hres;
377 }
378
379 HRESULT WINAPI AVIStreamInfoW(PAVISTREAM iface,AVISTREAMINFOW *asi,LONG
380  size) {
381         return iface->lpvtbl->fnInfo(iface,asi,size);
382 }
383
384 HRESULT WINAPI AVIStreamInfoA(PAVISTREAM iface,AVISTREAMINFOA *asi,LONG
385  size) {
386         AVISTREAMINFOW  asiw;
387         HRESULT                 hres;
388
389         if (size<sizeof(AVISTREAMINFOA))
390                 return AVIERR_BADSIZE;
391         hres = iface->lpvtbl->fnInfo(iface,&asiw,sizeof(asiw));
392         memcpy(asi,&asiw,sizeof(asiw)-sizeof(asiw.szName));
393         lstrcpynWtoA(asi->szName,asiw.szName,sizeof(asi->szName));
394         return hres;
395 }
396
397 HRESULT WINAPI AVIFileInfoW(PAVIFILE iface,LPAVIFILEINFOW afi,LONG size) {
398         return iface->lpvtbl->fnInfo(iface,afi,size);
399 }
400
401 HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *aco,CLSID *pclsidHandler) {
402         char                    fcc[5];
403         IAVIStreamImpl  *as;
404         FIXME_(avifile)("(%p,%p,%p,%p)\n",ppsCompressed,ppsSource,aco,pclsidHandler);
405         fcc[4]='\0';
406         memcpy(fcc,&(aco->fccType),4);
407         FIXME_(avifile)("\tfccType: '%s'\n",fcc);
408         memcpy(fcc,&(aco->fccHandler),4);
409         FIXME_(avifile)("\tfccHandler: '%s'\n",fcc);
410         FIXME_(avifile)("\tdwFlags: 0x%08lx\n",aco->dwFlags);
411
412         /* we just create a duplicate for now */
413         ((IUnknown*)ppsSource)->lpvtbl->fnAddRef((IUnknown*)ppsSource);
414         *ppsCompressed = ppsSource;
415         as = (IAVIStreamImpl*)ppsSource;
416
417         /* this is where the fun begins. Open a compressor and prepare it. */
418         as->hic = ICOpen(aco->fccType,aco->fccHandler,ICMODE_COMPRESS);
419
420         /* May happen. for instance if the codec is not able to compress */
421         if (!as->hic) 
422                 return AVIERR_UNSUPPORTED;
423
424         ICGetInfo(as->hic,&(as->icinfo),sizeof(ICINFO));
425         FIXME_(avifile)("Opened compressor: '%s' '%s'\n",debugstr_w(as->icinfo.szName),debugstr_w(as->icinfo.szDescription));
426         as->iscompressing = TRUE;
427         memcpy(&(as->aco),aco,sizeof(*aco));
428         if (as->icinfo.dwFlags & VIDCF_COMPRESSFRAMES) {
429                 ICCOMPRESSFRAMES        icf;
430
431                 /* now what to fill in there ... Hmm */
432                 memset(&icf,0,sizeof(icf));
433                 icf.lDataRate   = aco->dwBytesPerSecond;
434                 icf.lQuality    = aco->dwQuality;
435                 icf.lKeyRate    = aco->dwKeyFrameEvery;
436
437                 icf.GetData = (LONG (*)(LPARAM,LONG,LPVOID,LONG)) 0xdead4242;
438                 icf.PutData = (LONG (*)(LPARAM,LONG,LPVOID,LONG)) 0xdead4243;
439                 ICSendMessage(as->hic,ICM_COMPRESS_FRAMES_INFO,(LPARAM)&icf,sizeof(icf));
440         }
441         return S_OK;
442 }
443
444 HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG formatsize) {
445         return iface->lpvtbl->fnSetFormat(iface,pos,format,formatsize);
446 }
447
448 HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG *formatsize) {
449         return iface->lpvtbl->fnReadFormat(iface,pos,format,formatsize);
450 }
451
452 HRESULT WINAPI AVIStreamWrite(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
453         return iface->lpvtbl->fnWrite(iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
454 }
455
456 HRESULT WINAPI AVIStreamRead(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
457         return iface->lpvtbl->fnRead(iface,start,samples,buffer,buffersize,bytesread,samplesread);
458 }
459
460 HRESULT WINAPI AVIStreamWriteData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG size) {
461         return iface->lpvtbl->fnWriteData(iface,fcc,lp,size);
462 }
463
464 HRESULT WINAPI AVIStreamReadData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG *lpread) {
465         return iface->lpvtbl->fnReadData(iface,fcc,lp,lpread);
466 }
467
468 LONG WINAPI AVIStreamStart(PAVISTREAM iface) {
469         AVISTREAMINFOW  si;
470
471         iface->lpvtbl->fnInfo(iface,&si,sizeof(si));
472         return si.dwStart;
473 }
474
475 LONG WINAPI AVIStreamLength(PAVISTREAM iface) {
476         AVISTREAMINFOW  si;
477         HRESULT                 ret;
478
479         ret = iface->lpvtbl->fnInfo(iface,&si,sizeof(si));
480         if (ret) /* error */
481                 return 1;
482         return si.dwLength;
483 }
484
485 ULONG WINAPI AVIStreamRelease(PAVISTREAM iface) {
486         return ((LPUNKNOWN)iface)->lpvtbl->fnRelease((LPUNKNOWN)iface);
487 }
488
489 PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM iface,LPBITMAPINFOHEADER bmi) {
490         FIXME_(msvideo)("(%p)->(%p),stub!\n",iface,bmi);
491         return NULL;
492 }
493
494 LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg,LONG pos) {
495         return pg->lpvtbl->fnGetFrame(pg,pos);
496 }
497
498 HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg) {
499         if (pg) ((LPUNKNOWN)pg)->lpvtbl->fnRelease((LPUNKNOWN)pg);
500         return 0;
501 }
502
503 ULONG WINAPI AVIFileRelease(PAVIFILE iface) {
504         return ((LPUNKNOWN)iface)->lpvtbl->fnRelease((LPUNKNOWN)iface);
505 }
506
507 void WINAPI AVIFileExit(void) {
508         FIXME_(avifile)("(), stub.\n");
509 }