2 * Very simple AVIPLAYER
4 * Copyright 1999 Marcus Meissner
7 * - plays .avi streams, video only
8 * - requires MicroSoft avifil32.dll and builtin msvfw32.dll.
11 * - audio support (including synchronization etc)
12 * - replace DirectDraw by a 'normal' window, including dithering, controls
16 * - no time scheduling, video plays too fast using DirectDraw/XF86DGA
17 * - requires DirectDraw with all disadvantages.
31 int PASCAL
WinMain (HANDLE hInstance
, HANDLE prev
, LPSTR cmdline
, int show
)
33 int bytesline
,i
,n
,pos
;
36 BITMAPINFOHEADER
*bmi
;
38 HMODULE avifil32
= LoadLibrary("avifil32.dll");
40 PAVISTREAM vids
=NULL
,auds
=NULL
;
43 PGETFRAME vidgetframe
=NULL
;
46 LPDIRECTDRAWSURFACE dsurf
;
47 LPDIRECTDRAWPALETTE dpal
;
48 PALETTEENTRY palent
[256];
51 void (WINAPI
*fnAVIFileInit
)(void);
52 void (WINAPI
*fnAVIFileExit
)(void);
53 ULONG (WINAPI
*fnAVIFileRelease
)(PAVIFILE
);
54 ULONG (WINAPI
*fnAVIStreamRelease
)(PAVISTREAM
);
55 HRESULT (WINAPI
*fnAVIFileOpen
)(PAVIFILE
* ppfile
,LPCTSTR szFile
,UINT uMode
,LPCLSID lpHandler
);
56 HRESULT (WINAPI
*fnAVIFileInfo
)(PAVIFILE ppfile
,AVIFILEINFO
*afi
,LONG size
);
57 HRESULT (WINAPI
*fnAVIFileGetStream
)(PAVIFILE ppfile
,PAVISTREAM
*afi
,DWORD fccType
,LONG lParam
);
58 HRESULT (WINAPI
*fnAVIStreamInfo
)(PAVISTREAM iface
,AVISTREAMINFO
*afi
,LONG size
);
59 HRESULT (WINAPI
*fnAVIStreamReadFormat
)(PAVISTREAM iface
,LONG pos
,LPVOID format
,LPLONG size
);
60 PGETFRAME (WINAPI
*fnAVIStreamGetFrameOpen
)(PAVISTREAM iface
,LPBITMAPINFOHEADER wanted
);
61 LPVOID (WINAPI
*fnAVIStreamGetFrame
)(PGETFRAME pg
,LONG pos
);
62 HRESULT (WINAPI
*fnAVIStreamGetFrameClose
)(PGETFRAME pg
);
64 #define XX(x) fn##x = (void*)GetProcAddress(avifil32,#x);assert(fn##x);
66 # define XXT(x) fn##x = (void*)GetProcAddress(avifil32,#x##"W");assert(fn##x);
68 # define XXT(x) fn##x = (void*)GetProcAddress(avifil32,#x##"A");assert(fn##x);
70 /* non character dependend routines: */
74 XX (AVIFileGetStream
);
75 XX (AVIStreamRelease
);
76 XX (AVIStreamReadFormat
);
77 XX (AVIStreamGetFrameOpen
);
78 XX (AVIStreamGetFrame
);
79 XX (AVIStreamGetFrameClose
);
89 if (-1==GetFileAttributes(cmdline
)) {
90 fprintf(stderr
,"Usage: aviplay <avifilename>\n");
93 hres
= fnAVIFileOpen(&avif
,cmdline
,OF_READ
,NULL
);
95 fprintf(stderr
,"AVIFileOpen: 0x%08lx\n",hres
);
98 hres
= fnAVIFileInfo(avif
,&afi
,sizeof(afi
));
100 fprintf(stderr
,"AVIFileInfo: 0x%08lx\n",hres
);
103 for (n
=0;n
<afi
.dwStreams
;n
++) {
107 hres
= fnAVIFileGetStream(avif
,&ast
,0,n
);
109 fprintf(stderr
,"AVIFileGetStream %d: 0x%08lx\n",n
,hres
);
112 hres
= fnAVIStreamInfo(ast
,&asi
,sizeof(asi
));
114 fprintf(stderr
,"AVIStreamInfo %d: 0x%08lx\n",n
,hres
);
117 fprintf(stderr
,"[Stream %d: ",n
);
118 buf
[4]='\0';memcpy(buf
,&(asi
.fccType
),4);
119 fprintf(stderr
,"%s.",buf
);
120 buf
[4]='\0';memcpy(buf
,&(asi
.fccHandler
),4);
121 fprintf(stderr
,"%s, %s]\n",buf
,asi
.szName
);
122 switch (asi
.fccType
) {
123 case streamtypeVIDEO
:
126 case streamtypeAUDIO
:
131 type
[4]='\0';memcpy(type
,&(asi
.fccType
),4);
133 fprintf(stderr
,"Unhandled streamtype %s\n",type
);
134 fnAVIStreamRelease(ast
);
139 /********************* begin video setup ***********************************/
141 fprintf(stderr
,"No video stream found. Good Bye.\n");
144 cnt
= sizeof(BITMAPINFOHEADER
)+256*sizeof(RGBQUAD
);
145 bmi
= HeapAlloc(GetProcessHeap(),0,cnt
);
146 hres
= fnAVIStreamReadFormat(vids
,0,bmi
,&cnt
);
148 fprintf(stderr
,"AVIStreamReadFormat vids: 0x%08lx\n",hres
);
152 bmi
->biCompression
= 0; /* we want it in raw form, uncompressed */
153 /* recalculate the image size */
154 bmi
->biSizeImage
= ((bmi
->biWidth
*bmi
->biBitCount
+31)&~0x1f)*bmi
->biPlanes
*bmi
->biHeight
/8;
155 bytesline
= ((bmi
->biWidth
*bmi
->biBitCount
+31)&~0x1f)*bmi
->biPlanes
/8;
156 vidgetframe
= fnAVIStreamGetFrameOpen(vids
,bmi
);
158 fprintf(stderr
,"AVIStreamGetFrameOpen: failed\n");
161 /********************* end video setup ***********************************/
163 /********************* begin display setup *******************************/
164 hres
= DirectDrawCreate(NULL
,&ddraw
,NULL
);
166 fprintf(stderr
,"DirectDrawCreate: 0x%08lx\n",hres
);
169 hres
= IDirectDraw_SetDisplayMode(ddraw
,bmi
->biWidth
,bmi
->biHeight
,bmi
->biBitCount
);
171 fprintf(stderr
,"ddraw.SetDisplayMode: 0x%08lx (change resolution!)\n",hres
);
174 dsdesc
.dwSize
=sizeof(dsdesc
);
175 dsdesc
.dwFlags
= DDSD_CAPS
;
176 dsdesc
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
177 hres
= IDirectDraw_CreateSurface(ddraw
,&dsdesc
,&dsurf
,NULL
);
179 fprintf(stderr
,"ddraw.CreateSurface: 0x%08lx\n",hres
);
182 if (bmi
->biBitCount
==8) {
183 RGBQUAD
*rgb
= (RGBQUAD
*)(bmi
+1);
186 hres
= IDirectDraw_CreatePalette(ddraw
,DDPCAPS_8BIT
,NULL
,&dpal
,NULL
);
188 fprintf(stderr
,"ddraw.CreateSurface: 0x%08lx\n",hres
);
191 IDirectDrawSurface_SetPalette(dsurf
,dpal
);
192 for (i
=0;i
<bmi
->biClrUsed
;i
++) {
193 palent
[i
].peRed
= rgb
[i
].rgbRed
;
194 palent
[i
].peBlue
= rgb
[i
].rgbBlue
;
195 palent
[i
].peGreen
= rgb
[i
].rgbGreen
;
197 IDirectDrawPalette_SetEntries(dpal
,0,0,bmi
->biClrUsed
,palent
);
200 /********************* end display setup *******************************/
206 LPBITMAPINFOHEADER lpbmi
;
210 if (!(decodedframe
=fnAVIStreamGetFrame(vidgetframe
,pos
++)))
212 lpbmi
= (LPBITMAPINFOHEADER
)decodedframe
;
213 decodedbits
= (LPVOID
)(((DWORD
)decodedframe
)+lpbmi
->biSize
);
214 if (lpbmi
->biBitCount
== 8) {
215 /* cant detect palette change that way I think */
216 RGBQUAD
*rgb
= (RGBQUAD
*)(lpbmi
+1);
219 /* skip used colorentries. */
220 decodedbits
=(char*)decodedbits
+bmi
->biClrUsed
*sizeof(RGBQUAD
);
222 for (i
=0;i
<bmi
->biClrUsed
;i
++) {
223 if ( (palent
[i
].peRed
!= rgb
[i
].rgbRed
) ||
224 (palent
[i
].peBlue
!= rgb
[i
].rgbBlue
) ||
225 (palent
[i
].peGreen
!= rgb
[i
].rgbGreen
)
232 for (i
=0;i
<bmi
->biClrUsed
;i
++) {
233 palent
[i
].peRed
= rgb
[i
].rgbRed
;
234 palent
[i
].peBlue
= rgb
[i
].rgbBlue
;
235 palent
[i
].peGreen
= rgb
[i
].rgbGreen
;
237 IDirectDrawPalette_SetEntries(dpal
,0,0,bmi
->biClrUsed
,palent
);
240 dsdesc
.dwSize
= sizeof(dsdesc
);
241 hres
= IDirectDrawSurface_Lock(dsurf
,NULL
,&dsdesc
,DDLOCK_WRITEONLY
,0);
243 fprintf(stderr
,"dsurf.Lock: 0x%08lx\n",hres
);
246 /* Argh. AVIs are upside down. */
247 for (i
=0;i
<dsdesc
.dwHeight
;i
++) {
248 memcpy( (char *)dsdesc
.u1
.lpSurface
+(i
*dsdesc
.lPitch
),
249 (char *)decodedbits
+bytesline
*(dsdesc
.dwHeight
-i
-1),
253 IDirectDrawSurface_Unlock(dsurf
,dsdesc
.u1
.lpSurface
);
256 fnAVIStreamGetFrameClose(vidgetframe
);
258 IDirectDrawSurface_Release(dsurf
);
259 IDirectDraw_RestoreDisplayMode(ddraw
);
260 IDirectDraw_Release(ddraw
);
261 if (vids
) fnAVIStreamRelease(vids
);
262 if (auds
) fnAVIStreamRelease(auds
);
263 fprintf(stderr
,"%d frames at %g frames/s\n",pos
,pos
*1.0/(tend
-tstart
));
264 fnAVIFileRelease(avif
);