Dutch translation of clock and cmdlgtst.
[wine] / programs / avitools / aviplay.c
1 /*
2  * Very simple AVIPLAYER
3  *
4  * Copyright 1999 Marcus Meissner
5  *
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.
10  *
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.
15  *
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
19  *
20  * Status:
21  *      - plays .avi streams, video only
22  *      - requires Microsoft avifil32.dll and builtin msvfw32.dll.
23  *
24  * Todo:
25  *      - audio support (including synchronization etc)
26  *      - replace DirectDraw by a 'normal' window, including dithering, controls
27  *        etc.
28  *
29  * Bugs:
30  *      - no time scheduling, video plays too fast using DirectDraw/XF86DGA
31  *      - requires DirectDraw with all disadvantages.
32  */
33
34 #include <stdio.h>
35 #include <time.h>
36 #include <assert.h>
37 #include <string.h>
38
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"
46
47
48 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
49 {
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];
66
67
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);
80
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
103
104
105     fnAVIFileInit();
106     if (-1==GetFileAttributes(cmdline)) {
107         fprintf(stderr,"Usage: aviplay <avifilename>\n");
108         exit(1);
109     }
110     hres = fnAVIFileOpen(&avif,cmdline,OF_READ,NULL);
111     if (hres) {
112         fprintf(stderr,"AVIFileOpen: 0x%08lx\n",hres);
113         exit(1);
114     }
115     hres = fnAVIFileInfo(avif,&afi,sizeof(afi));
116     if (hres) {
117         fprintf(stderr,"AVIFileInfo: 0x%08lx\n",hres);
118         exit(1);
119     }
120     for (n=0;n<afi.dwStreams;n++) {
121             char buf[5];
122             PAVISTREAM  ast;
123
124             hres = fnAVIFileGetStream(avif,&ast,0,n);
125             if (hres) {
126                 fprintf(stderr,"AVIFileGetStream %d: 0x%08lx\n",n,hres);
127                 exit(1);
128             }
129             hres = fnAVIStreamInfo(ast,&asi,sizeof(asi));
130             if (hres) {
131                 fprintf(stderr,"AVIStreamInfo %d: 0x%08lx\n",n,hres);
132                 exit(1);
133             }
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);
149
150                 fprintf(stderr,"Unhandled streamtype %s\n",type);
151                 fnAVIStreamRelease(ast);
152                 break;
153             }
154             }
155     }
156 /********************* begin video setup ***********************************/
157     if (!vids) {
158         fprintf(stderr,"No video stream found. Good Bye.\n");
159         exit(0);
160     }
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);
167     }
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);
177     }
178 /********************* end video setup ***********************************/
179
180 /********************* begin display setup *******************************/
181     hres = DirectDrawCreate(NULL,&ddraw,NULL);
182     if (hres) {
183         fprintf(stderr,"DirectDrawCreate: 0x%08lx\n",hres);
184         exit(1);
185     }
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);
190     }
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);
198     }
199     if (bmi->biBitCount==8) {
200         RGBQUAD         *rgb = (RGBQUAD*)(bmi+1);
201         int             i;
202
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);
207         }
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;
213         }
214         IDirectDrawPalette_SetEntries(dpal,0,0,bmi->biClrUsed,palent);
215     } else
216         dpal = NULL;
217 /********************* end display setup *******************************/
218
219     tstart = time(NULL);
220     pos = 0;
221     while (1) {
222         LPVOID          decodedframe;
223         LPBITMAPINFOHEADER lpbmi;
224         LPVOID          decodedbits;
225
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;
235
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)
243                 ) {
244                         palchanged = 1;
245                         break;
246                 }
247             }
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;
253                 }
254                 IDirectDrawPalette_SetEntries(dpal,0,0,bmi->biClrUsed,palent);
255             }
256         }
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);
262         }
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
268             );
269         }
270         IDirectDrawSurface_Unlock(dsurf,dsdesc.lpSurface);
271     }
272     tend = time(NULL);
273     fnAVIStreamGetFrameClose(vidgetframe);
274
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;
284 }