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;
56 PAVISTREAM vids=NULL,auds=NULL;
59 PGETFRAME vidgetframe=NULL;
62 LPDIRECTDRAWSURFACE dsurf;
63 LPDIRECTDRAWPALETTE dpal;
64 PALETTEENTRY palent[256];
67 if (GetFileAttributes(cmdline) == INVALID_FILE_ATTRIBUTES) {
68 fprintf(stderr,"Usage: aviplay <avifilename>\n");
71 hres = AVIFileOpen(&avif,cmdline,OF_READ,NULL);
73 fprintf(stderr,"AVIFileOpen: 0x%08lx\n",hres);
76 hres = AVIFileInfo(avif,&afi,sizeof(afi));
78 fprintf(stderr,"AVIFileInfo: 0x%08lx\n",hres);
81 for (n=0;n<afi.dwStreams;n++) {
85 hres = AVIFileGetStream(avif,&ast,0,n);
87 fprintf(stderr,"AVIFileGetStream %d: 0x%08lx\n",n,hres);
90 hres = AVIStreamInfo(ast,&asi,sizeof(asi));
92 fprintf(stderr,"AVIStreamInfo %d: 0x%08lx\n",n,hres);
95 fprintf(stderr,"[Stream %d: ",n);
96 buf[4]='\0';memcpy(buf,&(asi.fccType),4);
97 fprintf(stderr,"%s.",buf);
98 buf[4]='\0';memcpy(buf,&(asi.fccHandler),4);
99 fprintf(stderr,"%s, %s]\n",buf,asi.szName);
100 switch (asi.fccType) {
101 case streamtypeVIDEO:
104 case streamtypeAUDIO:
109 type[4]='\0';memcpy(type,&(asi.fccType),4);
111 fprintf(stderr,"Unhandled streamtype %s\n",type);
112 AVIStreamRelease(ast);
117 /********************* begin video setup ***********************************/
119 fprintf(stderr,"No video stream found. Good Bye.\n");
122 cnt = sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);
123 bmi = HeapAlloc(GetProcessHeap(),0,cnt);
124 hres = AVIStreamReadFormat(vids,0,bmi,&cnt);
126 fprintf(stderr,"AVIStreamReadFormat vids: 0x%08lx\n",hres);
130 bmi->biCompression = 0; /* we want it in raw form, uncompressed */
131 /* recalculate the image size */
132 bmi->biSizeImage = ((bmi->biWidth*bmi->biBitCount+31)&~0x1f)*bmi->biPlanes*bmi->biHeight/8;
133 bytesline = ((bmi->biWidth*bmi->biBitCount+31)&~0x1f)*bmi->biPlanes/8;
134 vidgetframe = AVIStreamGetFrameOpen(vids,bmi);
136 fprintf(stderr,"AVIStreamGetFrameOpen: failed\n");
139 /********************* end video setup ***********************************/
141 /********************* begin display setup *******************************/
142 hres = DirectDrawCreate(NULL,&ddraw,NULL);
144 fprintf(stderr,"DirectDrawCreate: 0x%08lx\n",hres);
147 hres = IDirectDraw_SetDisplayMode(ddraw,bmi->biWidth,bmi->biHeight,bmi->biBitCount);
149 fprintf(stderr,"ddraw.SetDisplayMode: 0x%08lx (change resolution!)\n",hres);
152 dsdesc.dwSize=sizeof(dsdesc);
153 dsdesc.dwFlags = DDSD_CAPS;
154 dsdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
155 hres = IDirectDraw_CreateSurface(ddraw,&dsdesc,&dsurf,NULL);
157 fprintf(stderr,"ddraw.CreateSurface: 0x%08lx\n",hres);
160 if (bmi->biBitCount==8) {
161 RGBQUAD *rgb = (RGBQUAD*)(bmi+1);
164 hres = IDirectDraw_CreatePalette(ddraw,DDPCAPS_8BIT,NULL,&dpal,NULL);
166 fprintf(stderr,"ddraw.CreateSurface: 0x%08lx\n",hres);
169 IDirectDrawSurface_SetPalette(dsurf,dpal);
170 for (i=0;i<bmi->biClrUsed;i++) {
171 palent[i].peRed = rgb[i].rgbRed;
172 palent[i].peBlue = rgb[i].rgbBlue;
173 palent[i].peGreen = rgb[i].rgbGreen;
175 IDirectDrawPalette_SetEntries(dpal,0,0,bmi->biClrUsed,palent);
178 /********************* end display setup *******************************/
184 LPBITMAPINFOHEADER lpbmi;
188 if (!(decodedframe=AVIStreamGetFrame(vidgetframe,pos++)))
190 lpbmi = (LPBITMAPINFOHEADER)decodedframe;
191 decodedbits = (LPVOID)(((DWORD)decodedframe)+lpbmi->biSize);
192 if (lpbmi->biBitCount == 8) {
193 /* can't detect palette change that way I think */
194 RGBQUAD *rgb = (RGBQUAD*)(lpbmi+1);
197 /* skip used colorentries. */
198 decodedbits=(char*)decodedbits+bmi->biClrUsed*sizeof(RGBQUAD);
200 for (i=0;i<bmi->biClrUsed;i++) {
201 if ( (palent[i].peRed != rgb[i].rgbRed) ||
202 (palent[i].peBlue != rgb[i].rgbBlue) ||
203 (palent[i].peGreen != rgb[i].rgbGreen)
210 for (i=0;i<bmi->biClrUsed;i++) {
211 palent[i].peRed = rgb[i].rgbRed;
212 palent[i].peBlue = rgb[i].rgbBlue;
213 palent[i].peGreen = rgb[i].rgbGreen;
215 IDirectDrawPalette_SetEntries(dpal,0,0,bmi->biClrUsed,palent);
218 dsdesc.dwSize = sizeof(dsdesc);
219 hres = IDirectDrawSurface_Lock(dsurf,NULL,&dsdesc,DDLOCK_WRITEONLY,0);
221 fprintf(stderr,"dsurf.Lock: 0x%08lx\n",hres);
224 /* Argh. AVIs are upside down. */
225 for (i=0;i<dsdesc.dwHeight;i++) {
226 memcpy( (char *)dsdesc.lpSurface+(i*dsdesc.u1.lPitch),
227 (char *)decodedbits+bytesline*(dsdesc.dwHeight-i-1),
231 IDirectDrawSurface_Unlock(dsurf,dsdesc.lpSurface);
234 AVIStreamGetFrameClose(vidgetframe);
236 IDirectDrawSurface_Release(dsurf);
237 IDirectDraw_RestoreDisplayMode(ddraw);
238 IDirectDraw_Release(ddraw);
239 if (vids) AVIStreamRelease(vids);
240 if (auds) AVIStreamRelease(auds);
241 fprintf(stderr,"%d frames at %g frames/s\n",pos,pos*1.0/(tend-tstart));
242 AVIFileRelease(avif);