Return a true boolean value (0 or 1).
[wine/wine64.git] / programs / avitools / aviplay.c
blob2aad746136e9e97846930117e672de47c1bca5f8
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 PAVIFILE avif;
56 PAVISTREAM vids=NULL,auds=NULL;
57 AVIFILEINFO afi;
58 AVISTREAMINFO asi;
59 PGETFRAME vidgetframe=NULL;
60 LPDIRECTDRAW ddraw;
61 DDSURFACEDESC dsdesc;
62 LPDIRECTDRAWSURFACE dsurf;
63 LPDIRECTDRAWPALETTE dpal;
64 PALETTEENTRY palent[256];
66 AVIFileInit();
67 if (GetFileAttributes(cmdline) == INVALID_FILE_ATTRIBUTES) {
68 fprintf(stderr,"Usage: aviplay <avifilename>\n");
69 exit(1);
71 hres = AVIFileOpen(&avif,cmdline,OF_READ,NULL);
72 if (hres) {
73 fprintf(stderr,"AVIFileOpen: 0x%08lx\n",hres);
74 exit(1);
76 hres = AVIFileInfo(avif,&afi,sizeof(afi));
77 if (hres) {
78 fprintf(stderr,"AVIFileInfo: 0x%08lx\n",hres);
79 exit(1);
81 for (n=0;n<afi.dwStreams;n++) {
82 char buf[5];
83 PAVISTREAM ast;
85 hres = AVIFileGetStream(avif,&ast,0,n);
86 if (hres) {
87 fprintf(stderr,"AVIFileGetStream %d: 0x%08lx\n",n,hres);
88 exit(1);
90 hres = AVIStreamInfo(ast,&asi,sizeof(asi));
91 if (hres) {
92 fprintf(stderr,"AVIStreamInfo %d: 0x%08lx\n",n,hres);
93 exit(1);
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:
102 vids = ast;
103 break;
104 case streamtypeAUDIO:
105 auds = ast;
106 break;
107 default: {
108 char type[5];
109 type[4]='\0';memcpy(type,&(asi.fccType),4);
111 fprintf(stderr,"Unhandled streamtype %s\n",type);
112 AVIStreamRelease(ast);
113 break;
117 /********************* begin video setup ***********************************/
118 if (!vids) {
119 fprintf(stderr,"No video stream found. Good Bye.\n");
120 exit(0);
122 cnt = sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);
123 bmi = HeapAlloc(GetProcessHeap(),0,cnt);
124 hres = AVIStreamReadFormat(vids,0,bmi,&cnt);
125 if (hres) {
126 fprintf(stderr,"AVIStreamReadFormat vids: 0x%08lx\n",hres);
127 exit(1);
129 vidgetframe = NULL;
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);
135 if (!vidgetframe) {
136 fprintf(stderr,"AVIStreamGetFrameOpen: failed\n");
137 exit(1);
139 /********************* end video setup ***********************************/
141 /********************* begin display setup *******************************/
142 hres = DirectDrawCreate(NULL,&ddraw,NULL);
143 if (hres) {
144 fprintf(stderr,"DirectDrawCreate: 0x%08lx\n",hres);
145 exit(1);
147 hres = IDirectDraw_SetDisplayMode(ddraw,bmi->biWidth,bmi->biHeight,bmi->biBitCount);
148 if (hres) {
149 fprintf(stderr,"ddraw.SetDisplayMode: 0x%08lx (change resolution!)\n",hres);
150 exit(1);
152 dsdesc.dwSize=sizeof(dsdesc);
153 dsdesc.dwFlags = DDSD_CAPS;
154 dsdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
155 hres = IDirectDraw_CreateSurface(ddraw,&dsdesc,&dsurf,NULL);
156 if (hres) {
157 fprintf(stderr,"ddraw.CreateSurface: 0x%08lx\n",hres);
158 exit(1);
160 if (bmi->biBitCount==8) {
161 RGBQUAD *rgb = (RGBQUAD*)(bmi+1);
162 int i;
164 hres = IDirectDraw_CreatePalette(ddraw,DDPCAPS_8BIT,NULL,&dpal,NULL);
165 if (hres) {
166 fprintf(stderr,"ddraw.CreateSurface: 0x%08lx\n",hres);
167 exit(1);
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);
176 } else
177 dpal = NULL;
178 /********************* end display setup *******************************/
180 tstart = time(NULL);
181 pos = 0;
182 while (1) {
183 LPVOID decodedframe;
184 LPBITMAPINFOHEADER lpbmi;
185 LPVOID decodedbits;
187 /* video stuff */
188 if (!(decodedframe=AVIStreamGetFrame(vidgetframe,pos++)))
189 break;
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);
195 int i,palchanged;
197 /* skip used colorentries. */
198 decodedbits=(char*)decodedbits+bmi->biClrUsed*sizeof(RGBQUAD);
199 palchanged = 0;
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)
205 palchanged = 1;
206 break;
209 if (palchanged) {
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);
220 if (hres) {
221 fprintf(stderr,"dsurf.Lock: 0x%08lx\n",hres);
222 exit(1);
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),
228 bytesline
231 IDirectDrawSurface_Unlock(dsurf,dsdesc.lpSurface);
233 tend = time(NULL);
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);
243 AVIFileExit();
244 return 0;