Change types of WPARAM, LPARAM and LRESULT according to MS SDK definitions.
[wine/multimedia.git] / programs / avitools / aviplay.c
blobaad111c729af948bdfd663731f4e33c8cca9f495
1 /*
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
20 * Status:
21 * - plays .avi streams, video only
22 * - requires MicroSoft avifil32.dll and builtin msvfw32.dll.
24 * Todo:
25 * - audio support (including synchronization etc)
26 * - replace DirectDraw by a 'normal' window, including dithering, controls
27 * etc.
29 * Bugs:
30 * - no time scheduling, video plays too fast using DirectDraw/XF86DGA
31 * - requires DirectDraw with all disadvantages.
34 #include <stdio.h>
35 #include <time.h>
36 #include <assert.h>
37 #include <string.h>
39 #define NONAMELESSUNION
40 #define NONAMELESSSTRUCT
41 #include "windows.h"
42 #include "wingdi.h"
43 #include "mmsystem.h"
44 #include "ddraw.h"
45 #include "vfw.h"
48 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
50 int bytesline,i,n,pos;
51 time_t tstart,tend;
52 LONG cnt;
53 BITMAPINFOHEADER *bmi;
54 HRESULT hres;
55 HMODULE avifil32 = LoadLibrary("avifil32.dll");
56 PAVIFILE avif;
57 PAVISTREAM vids=NULL,auds=NULL;
58 AVIFILEINFO afi;
59 AVISTREAMINFO asi;
60 PGETFRAME vidgetframe=NULL;
61 LPDIRECTDRAW ddraw;
62 DDSURFACEDESC dsdesc;
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);
82 #ifdef UNICODE
83 # define XXT(x) fn##x = (void*)GetProcAddress(avifil32,#x"W");assert(fn##x);
84 #else
85 # define XXT(x) fn##x = (void*)GetProcAddress(avifil32,#x"A");assert(fn##x);
86 #endif
87 /* non character dependend routines: */
88 XX (AVIFileInit);
89 XX (AVIFileExit);
90 XX (AVIFileRelease);
91 XX (AVIFileGetStream);
92 XX (AVIStreamRelease);
93 XX (AVIStreamReadFormat);
94 XX (AVIStreamGetFrameOpen);
95 XX (AVIStreamGetFrame);
96 XX (AVIStreamGetFrameClose);
97 /* A/W routines: */
98 XXT(AVIFileOpen);
99 XXT(AVIFileInfo);
100 XXT(AVIStreamInfo);
101 #undef XX
102 #undef XXT
105 fnAVIFileInit();
106 if (-1==GetFileAttributes(cmdline)) {
107 fprintf(stderr,"Usage: aviplay <avifilename>\n");
108 exit(1);
110 hres = fnAVIFileOpen(&avif,cmdline,OF_READ,NULL);
111 if (hres) {
112 fprintf(stderr,"AVIFileOpen: 0x%08lx\n",hres);
113 exit(1);
115 hres = fnAVIFileInfo(avif,&afi,sizeof(afi));
116 if (hres) {
117 fprintf(stderr,"AVIFileInfo: 0x%08lx\n",hres);
118 exit(1);
120 for (n=0;n<afi.dwStreams;n++) {
121 char buf[5];
122 PAVISTREAM ast;
124 hres = fnAVIFileGetStream(avif,&ast,0,n);
125 if (hres) {
126 fprintf(stderr,"AVIFileGetStream %d: 0x%08lx\n",n,hres);
127 exit(1);
129 hres = fnAVIStreamInfo(ast,&asi,sizeof(asi));
130 if (hres) {
131 fprintf(stderr,"AVIStreamInfo %d: 0x%08lx\n",n,hres);
132 exit(1);
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:
141 vids = ast;
142 break;
143 case streamtypeAUDIO:
144 auds = ast;
145 break;
146 default: {
147 char type[5];
148 type[4]='\0';memcpy(type,&(asi.fccType),4);
150 fprintf(stderr,"Unhandled streamtype %s\n",type);
151 fnAVIStreamRelease(ast);
152 break;
156 /********************* begin video setup ***********************************/
157 if (!vids) {
158 fprintf(stderr,"No video stream found. Good Bye.\n");
159 exit(0);
161 cnt = sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);
162 bmi = HeapAlloc(GetProcessHeap(),0,cnt);
163 hres = fnAVIStreamReadFormat(vids,0,bmi,&cnt);
164 if (hres) {
165 fprintf(stderr,"AVIStreamReadFormat vids: 0x%08lx\n",hres);
166 exit(1);
168 vidgetframe = NULL;
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);
174 if (!vidgetframe) {
175 fprintf(stderr,"AVIStreamGetFrameOpen: failed\n");
176 exit(1);
178 /********************* end video setup ***********************************/
180 /********************* begin display setup *******************************/
181 hres = DirectDrawCreate(NULL,&ddraw,NULL);
182 if (hres) {
183 fprintf(stderr,"DirectDrawCreate: 0x%08lx\n",hres);
184 exit(1);
186 hres = IDirectDraw_SetDisplayMode(ddraw,bmi->biWidth,bmi->biHeight,bmi->biBitCount);
187 if (hres) {
188 fprintf(stderr,"ddraw.SetDisplayMode: 0x%08lx (change resolution!)\n",hres);
189 exit(1);
191 dsdesc.dwSize=sizeof(dsdesc);
192 dsdesc.dwFlags = DDSD_CAPS;
193 dsdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
194 hres = IDirectDraw_CreateSurface(ddraw,&dsdesc,&dsurf,NULL);
195 if (hres) {
196 fprintf(stderr,"ddraw.CreateSurface: 0x%08lx\n",hres);
197 exit(1);
199 if (bmi->biBitCount==8) {
200 RGBQUAD *rgb = (RGBQUAD*)(bmi+1);
201 int i;
203 hres = IDirectDraw_CreatePalette(ddraw,DDPCAPS_8BIT,NULL,&dpal,NULL);
204 if (hres) {
205 fprintf(stderr,"ddraw.CreateSurface: 0x%08lx\n",hres);
206 exit(1);
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);
215 } else
216 dpal = NULL;
217 /********************* end display setup *******************************/
219 tstart = time(NULL);
220 pos = 0;
221 while (1) {
222 LPVOID decodedframe;
223 LPBITMAPINFOHEADER lpbmi;
224 LPVOID decodedbits;
226 /* video stuff */
227 if (!(decodedframe=fnAVIStreamGetFrame(vidgetframe,pos++)))
228 break;
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);
234 int i,palchanged;
236 /* skip used colorentries. */
237 decodedbits=(char*)decodedbits+bmi->biClrUsed*sizeof(RGBQUAD);
238 palchanged = 0;
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)
244 palchanged = 1;
245 break;
248 if (palchanged) {
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);
259 if (hres) {
260 fprintf(stderr,"dsurf.Lock: 0x%08lx\n",hres);
261 exit(1);
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),
267 bytesline
270 IDirectDrawSurface_Unlock(dsurf,dsdesc.lpSurface);
272 tend = time(NULL);
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);
282 fnAVIFileExit();
283 return 0;