2 * Very simple AVIPLAYER
4 * Copyright 1999 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * - plays .avi streams, video only
22 * - requires Microsoft avifil32.dll and builtin msvfw32.dll.
25 * - audio support (including synchronization etc)
26 * - replace DirectDraw by a 'normal' window, including dithering, controls
30 * - no time scheduling, video plays too fast using DirectDraw/XF86DGA
31 * - requires DirectDraw with all disadvantages.
39 #define NONAMELESSUNION
40 #define NONAMELESSSTRUCT
48 int PASCAL
WinMain(HINSTANCE hInstance
, HINSTANCE prev
, LPSTR cmdline
, int show
)
50 int bytesline
,i
,n
,pos
;
53 BITMAPINFOHEADER
*bmi
;
55 HMODULE avifil32
= LoadLibrary("avifil32.dll");
57 PAVISTREAM vids
=NULL
,auds
=NULL
;
60 PGETFRAME vidgetframe
=NULL
;
63 LPDIRECTDRAWSURFACE dsurf
;
64 LPDIRECTDRAWPALETTE dpal
;
65 PALETTEENTRY palent
[256];
68 void (WINAPI
*fnAVIFileInit
)(void);
69 void (WINAPI
*fnAVIFileExit
)(void);
70 ULONG (WINAPI
*fnAVIFileRelease
)(PAVIFILE
);
71 ULONG (WINAPI
*fnAVIStreamRelease
)(PAVISTREAM
);
72 HRESULT (WINAPI
*fnAVIFileOpen
)(PAVIFILE
* ppfile
,LPCTSTR szFile
,UINT uMode
,LPCLSID lpHandler
);
73 HRESULT (WINAPI
*fnAVIFileInfo
)(PAVIFILE ppfile
,AVIFILEINFO
*afi
,LONG size
);
74 HRESULT (WINAPI
*fnAVIFileGetStream
)(PAVIFILE ppfile
,PAVISTREAM
*afi
,DWORD fccType
,LONG lParam
);
75 HRESULT (WINAPI
*fnAVIStreamInfo
)(PAVISTREAM iface
,AVISTREAMINFO
*afi
,LONG size
);
76 HRESULT (WINAPI
*fnAVIStreamReadFormat
)(PAVISTREAM iface
,LONG pos
,LPVOID format
,LPLONG size
);
77 PGETFRAME (WINAPI
*fnAVIStreamGetFrameOpen
)(PAVISTREAM iface
,LPBITMAPINFOHEADER wanted
);
78 LPVOID (WINAPI
*fnAVIStreamGetFrame
)(PGETFRAME pg
,LONG pos
);
79 HRESULT (WINAPI
*fnAVIStreamGetFrameClose
)(PGETFRAME pg
);
81 #define XX(x) fn##x = (void*)GetProcAddress(avifil32,#x);assert(fn##x);
83 # define XXT(x) fn##x = (void*)GetProcAddress(avifil32,#x"W");assert(fn##x);
85 # define XXT(x) fn##x = (void*)GetProcAddress(avifil32,#x"A");assert(fn##x);
87 /* non character dependend routines: */
91 XX (AVIFileGetStream
);
92 XX (AVIStreamRelease
);
93 XX (AVIStreamReadFormat
);
94 XX (AVIStreamGetFrameOpen
);
95 XX (AVIStreamGetFrame
);
96 XX (AVIStreamGetFrameClose
);
106 if (-1==GetFileAttributes(cmdline
)) {
107 fprintf(stderr
,"Usage: aviplay <avifilename>\n");
110 hres
= fnAVIFileOpen(&avif
,cmdline
,OF_READ
,NULL
);
112 fprintf(stderr
,"AVIFileOpen: 0x%08lx\n",hres
);
115 hres
= fnAVIFileInfo(avif
,&afi
,sizeof(afi
));
117 fprintf(stderr
,"AVIFileInfo: 0x%08lx\n",hres
);
120 for (n
=0;n
<afi
.dwStreams
;n
++) {
124 hres
= fnAVIFileGetStream(avif
,&ast
,0,n
);
126 fprintf(stderr
,"AVIFileGetStream %d: 0x%08lx\n",n
,hres
);
129 hres
= fnAVIStreamInfo(ast
,&asi
,sizeof(asi
));
131 fprintf(stderr
,"AVIStreamInfo %d: 0x%08lx\n",n
,hres
);
134 fprintf(stderr
,"[Stream %d: ",n
);
135 buf
[4]='\0';memcpy(buf
,&(asi
.fccType
),4);
136 fprintf(stderr
,"%s.",buf
);
137 buf
[4]='\0';memcpy(buf
,&(asi
.fccHandler
),4);
138 fprintf(stderr
,"%s, %s]\n",buf
,asi
.szName
);
139 switch (asi
.fccType
) {
140 case streamtypeVIDEO
:
143 case streamtypeAUDIO
:
148 type
[4]='\0';memcpy(type
,&(asi
.fccType
),4);
150 fprintf(stderr
,"Unhandled streamtype %s\n",type
);
151 fnAVIStreamRelease(ast
);
156 /********************* begin video setup ***********************************/
158 fprintf(stderr
,"No video stream found. Good Bye.\n");
161 cnt
= sizeof(BITMAPINFOHEADER
)+256*sizeof(RGBQUAD
);
162 bmi
= HeapAlloc(GetProcessHeap(),0,cnt
);
163 hres
= fnAVIStreamReadFormat(vids
,0,bmi
,&cnt
);
165 fprintf(stderr
,"AVIStreamReadFormat vids: 0x%08lx\n",hres
);
169 bmi
->biCompression
= 0; /* we want it in raw form, uncompressed */
170 /* recalculate the image size */
171 bmi
->biSizeImage
= ((bmi
->biWidth
*bmi
->biBitCount
+31)&~0x1f)*bmi
->biPlanes
*bmi
->biHeight
/8;
172 bytesline
= ((bmi
->biWidth
*bmi
->biBitCount
+31)&~0x1f)*bmi
->biPlanes
/8;
173 vidgetframe
= fnAVIStreamGetFrameOpen(vids
,bmi
);
175 fprintf(stderr
,"AVIStreamGetFrameOpen: failed\n");
178 /********************* end video setup ***********************************/
180 /********************* begin display setup *******************************/
181 hres
= DirectDrawCreate(NULL
,&ddraw
,NULL
);
183 fprintf(stderr
,"DirectDrawCreate: 0x%08lx\n",hres
);
186 hres
= IDirectDraw_SetDisplayMode(ddraw
,bmi
->biWidth
,bmi
->biHeight
,bmi
->biBitCount
);
188 fprintf(stderr
,"ddraw.SetDisplayMode: 0x%08lx (change resolution!)\n",hres
);
191 dsdesc
.dwSize
=sizeof(dsdesc
);
192 dsdesc
.dwFlags
= DDSD_CAPS
;
193 dsdesc
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
194 hres
= IDirectDraw_CreateSurface(ddraw
,&dsdesc
,&dsurf
,NULL
);
196 fprintf(stderr
,"ddraw.CreateSurface: 0x%08lx\n",hres
);
199 if (bmi
->biBitCount
==8) {
200 RGBQUAD
*rgb
= (RGBQUAD
*)(bmi
+1);
203 hres
= IDirectDraw_CreatePalette(ddraw
,DDPCAPS_8BIT
,NULL
,&dpal
,NULL
);
205 fprintf(stderr
,"ddraw.CreateSurface: 0x%08lx\n",hres
);
208 IDirectDrawSurface_SetPalette(dsurf
,dpal
);
209 for (i
=0;i
<bmi
->biClrUsed
;i
++) {
210 palent
[i
].peRed
= rgb
[i
].rgbRed
;
211 palent
[i
].peBlue
= rgb
[i
].rgbBlue
;
212 palent
[i
].peGreen
= rgb
[i
].rgbGreen
;
214 IDirectDrawPalette_SetEntries(dpal
,0,0,bmi
->biClrUsed
,palent
);
217 /********************* end display setup *******************************/
223 LPBITMAPINFOHEADER lpbmi
;
227 if (!(decodedframe
=fnAVIStreamGetFrame(vidgetframe
,pos
++)))
229 lpbmi
= (LPBITMAPINFOHEADER
)decodedframe
;
230 decodedbits
= (LPVOID
)(((DWORD
)decodedframe
)+lpbmi
->biSize
);
231 if (lpbmi
->biBitCount
== 8) {
232 /* cant detect palette change that way I think */
233 RGBQUAD
*rgb
= (RGBQUAD
*)(lpbmi
+1);
236 /* skip used colorentries. */
237 decodedbits
=(char*)decodedbits
+bmi
->biClrUsed
*sizeof(RGBQUAD
);
239 for (i
=0;i
<bmi
->biClrUsed
;i
++) {
240 if ( (palent
[i
].peRed
!= rgb
[i
].rgbRed
) ||
241 (palent
[i
].peBlue
!= rgb
[i
].rgbBlue
) ||
242 (palent
[i
].peGreen
!= rgb
[i
].rgbGreen
)
249 for (i
=0;i
<bmi
->biClrUsed
;i
++) {
250 palent
[i
].peRed
= rgb
[i
].rgbRed
;
251 palent
[i
].peBlue
= rgb
[i
].rgbBlue
;
252 palent
[i
].peGreen
= rgb
[i
].rgbGreen
;
254 IDirectDrawPalette_SetEntries(dpal
,0,0,bmi
->biClrUsed
,palent
);
257 dsdesc
.dwSize
= sizeof(dsdesc
);
258 hres
= IDirectDrawSurface_Lock(dsurf
,NULL
,&dsdesc
,DDLOCK_WRITEONLY
,0);
260 fprintf(stderr
,"dsurf.Lock: 0x%08lx\n",hres
);
263 /* Argh. AVIs are upside down. */
264 for (i
=0;i
<dsdesc
.dwHeight
;i
++) {
265 memcpy( (char *)dsdesc
.lpSurface
+(i
*dsdesc
.u1
.lPitch
),
266 (char *)decodedbits
+bytesline
*(dsdesc
.dwHeight
-i
-1),
270 IDirectDrawSurface_Unlock(dsurf
,dsdesc
.lpSurface
);
273 fnAVIStreamGetFrameClose(vidgetframe
);
275 IDirectDrawSurface_Release(dsurf
);
276 IDirectDraw_RestoreDisplayMode(ddraw
);
277 IDirectDraw_Release(ddraw
);
278 if (vids
) fnAVIStreamRelease(vids
);
279 if (auds
) fnAVIStreamRelease(auds
);
280 fprintf(stderr
,"%d frames at %g frames/s\n",pos
,pos
*1.0/(tend
-tstart
));
281 fnAVIFileRelease(avif
);