]> git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_video.c
you can now (try to) play in maps you don't have, and models you don't have are shown...
[xonotic/darkplaces.git] / cl_video.c
1
2 #include "quakedef.h"
3 #include "cl_video.h"
4 #include "dpvsimpledecode.h"
5
6 mempool_t *clvideomempool;
7
8 int cl_videoplaying = false;
9 void *cl_videostream;
10
11 double cl_videostarttime;
12 int cl_videoframenum;
13 double cl_videoframerate;
14
15 int cl_videoimagewidth;
16 int cl_videoimageheight;
17 int cl_videoimagedata_rmask;
18 int cl_videoimagedata_gmask;
19 int cl_videoimagedata_bmask;
20 int cl_videoimagedata_bytesperpixel;
21 void *cl_videoimagedata;
22
23 int cl_videosoundrate;
24 int cl_videosoundlength;
25 short *cl_videosounddata;
26 int cl_videosoundresamplelength;
27 short *cl_videosoundresampledata;
28
29 rtexture_t *cl_videotexture;
30 rtexturepool_t *cl_videotexturepool;
31
32 void CL_VideoFrame(void)
33 {
34         int frames, framenum, samples, s;
35         if (!cl_videoplaying)
36                 return;
37         framenum = (realtime - cl_videostarttime) * cl_videoframerate;
38         //Con_Printf("frame %i\n", framenum);
39         if (framenum < 0)
40                 framenum = 0;
41         frames = 0;
42         while (cl_videoframenum < framenum)
43         {
44                 frames++;
45                 cl_videoframenum++;
46                 if (dpvsimpledecode_video(cl_videostream, cl_videoimagedata, cl_videoimagedata_rmask, cl_videoimagedata_gmask, cl_videoimagedata_bmask, cl_videoimagedata_bytesperpixel, cl_videoimagewidth * cl_videoimagedata_bytesperpixel))
47                 {
48                         CL_VideoStop();
49                         return;
50                 }
51         }
52         if (frames)
53         {
54                 R_UpdateTexture(cl_videotexture, cl_videoimagedata);
55                 //Draw_NewPic("engine_videoframe", cl_videoimagewidth, cl_videoimageheight, false, cl_videoimagedata);
56         }
57         if (cl_videosoundrate && (samples = S_RawSamples_QueueWantsMore()))
58         {
59                 Con_Printf("%i = S_RawSamples_QueueWantsMore()\n", samples);
60
61                 // calculate how much source data we need to fill the output...
62                 s = samples * cl_videosoundrate / shm->speed;
63
64                 // reallocate processing buffer if needed
65                 if (cl_videosoundresamplelength < samples)
66                 {
67                         cl_videosoundresamplelength = samples + 100;
68                         if (cl_videosoundresampledata)
69                                 Mem_Free(cl_videosoundresampledata);
70                         cl_videosoundresampledata = Mem_Alloc(clvideomempool, cl_videosoundresamplelength * sizeof(short[2]));
71                 }
72
73                 // reallocate loading buffer if needed
74                 if (cl_videosoundlength < s)
75                 {
76                         cl_videosoundlength = s + 100;
77                         if (cl_videosounddata)
78                                 Mem_Free(cl_videosounddata);
79                         cl_videosounddata = Mem_Alloc(clvideomempool, cl_videosoundlength * sizeof(short[2]));
80                 }
81
82                 dpvsimpledecode_audio(cl_videostream, cl_videosounddata, s);
83                 S_ResampleBuffer16Stereo(cl_videosounddata, s, cl_videosoundresampledata, samples);
84                 S_RawSamples_Enqueue(cl_videosoundresampledata, samples);
85         }
86 }
87
88 void CL_DrawVideo(void)
89 {
90         if (cl_videoplaying)
91         {
92                 drawqueuemesh_t mesh;
93                 int indices[6];
94                 float vertices[12];
95                 float texcoords[8];
96                 qbyte colorsb[16];
97                 float s1, t1, s2, t2, x1, y1, x2, y2;
98                 indices[0] = 0;
99                 indices[1] = 1;
100                 indices[2] = 2;
101                 indices[3] = 0;
102                 indices[4] = 2;
103                 indices[5] = 3;
104                 x1 = 0;
105                 y1 = 0;
106                 x2 = vid.conwidth;
107                 y2 = vid.conheight;
108                 vertices[0] = y1;
109                 vertices[1] = y1;
110                 vertices[2] = 0;
111                 vertices[3] = x2;
112                 vertices[4] = y1;
113                 vertices[5] = 0;
114                 vertices[6] = x2;
115                 vertices[7] = y2;
116                 vertices[8] = 0;
117                 vertices[9] = x1;
118                 vertices[10] = y2;
119                 vertices[11] = 0;
120                 R_FragmentLocation(cl_videotexture, NULL, NULL, &s1, &t1, &s2, &t2);
121                 texcoords[0] = s1;
122                 texcoords[1] = t1;
123                 texcoords[2] = s2;
124                 texcoords[3] = t1;
125                 texcoords[4] = s2;
126                 texcoords[5] = t2;
127                 texcoords[6] = s1;
128                 texcoords[7] = t2;
129                 colorsb[0] = 255 >> v_overbrightbits.integer;
130                 colorsb[1] = 255 >> v_overbrightbits.integer;
131                 colorsb[2] = 255 >> v_overbrightbits.integer;
132                 colorsb[3] = 255;
133                 colorsb[4] = 255 >> v_overbrightbits.integer;
134                 colorsb[5] = 255 >> v_overbrightbits.integer;
135                 colorsb[6] = 255 >> v_overbrightbits.integer;
136                 colorsb[7] = 255;
137                 colorsb[8] = 255 >> v_overbrightbits.integer;
138                 colorsb[9] = 255 >> v_overbrightbits.integer;
139                 colorsb[10] = 255 >> v_overbrightbits.integer;
140                 colorsb[11] = 255;
141                 colorsb[12] = 255 >> v_overbrightbits.integer;
142                 colorsb[13] = 255 >> v_overbrightbits.integer;
143                 colorsb[14] = 255 >> v_overbrightbits.integer;
144                 colorsb[15] = 255;
145                 mesh.texture = cl_videotexture;
146                 mesh.numindices = 6;
147                 mesh.numvertices = 4;
148                 mesh.indices = indices;
149                 mesh.vertices = vertices;
150                 mesh.texcoords = texcoords;
151                 mesh.colors = colorsb;
152                 DrawQ_Mesh(&mesh, 0);
153                 //DrawQ_Pic(0, 0, "engine_videoframe", vid.conwidth, vid.conheight, 1, 1, 1, 1, 0);
154         }
155 }
156
157 void CL_VideoStart(char *filename)
158 {
159         char *errorstring;
160         cl_videostream = dpvsimpledecode_open(filename, &errorstring);
161         if (!cl_videostream)
162         {
163                 Con_Printf("unable to open \"%s\", error: %s\n", filename, errorstring);
164                 return;
165         }
166
167         cl_videoplaying = true;
168         cl_videostarttime = realtime;
169         cl_videoframenum = -1;
170         cl_videoframerate = dpvsimpledecode_getframerate(cl_videostream);
171         cl_videoimagewidth = dpvsimpledecode_getwidth(cl_videostream);
172         cl_videoimageheight = dpvsimpledecode_getheight(cl_videostream);
173
174         // RGBA format
175         cl_videoimagedata_bytesperpixel = 4;
176         cl_videoimagedata_rmask = BigLong(0xFF000000);
177         cl_videoimagedata_gmask = BigLong(0x00FF0000);
178         cl_videoimagedata_bmask = BigLong(0x0000FF00);
179         cl_videoimagedata = Mem_Alloc(clvideomempool, cl_videoimagewidth * cl_videoimageheight * cl_videoimagedata_bytesperpixel);
180         //memset(cl_videoimagedata, 97, cl_videoimagewidth * cl_videoimageheight * cl_videoimagedata_bytesperpixel);
181
182         cl_videosoundrate = dpvsimpledecode_getsoundrate(cl_videostream);
183         cl_videosoundlength = 0;
184         cl_videosounddata = NULL;
185         cl_videosoundresamplelength = 0;
186         cl_videosoundresampledata = NULL;
187
188         cl_videotexturepool = R_AllocTexturePool();
189         cl_videotexture = R_LoadTexture(cl_videotexturepool, "videotexture", cl_videoimagewidth, cl_videoimageheight, NULL, TEXTYPE_RGBA, TEXF_FRAGMENT);
190 }
191
192 void CL_VideoStop(void)
193 {
194         cl_videoplaying = false;
195
196         S_RawSamples_ClearQueue();
197
198         if (cl_videostream)
199                 dpvsimpledecode_close(cl_videostream);
200         cl_videostream = NULL;
201
202         if (cl_videoimagedata)
203                 Mem_Free(cl_videoimagedata);
204         cl_videoimagedata = NULL;
205
206         if (cl_videosounddata)
207                 Mem_Free(cl_videosounddata);
208         cl_videosounddata = NULL;
209
210         if (cl_videosoundresampledata)
211                 Mem_Free(cl_videosoundresampledata);
212         cl_videosoundresampledata = NULL;
213
214         cl_videotexture = NULL;
215         R_FreeTexturePool(&cl_videotexturepool);
216
217         Draw_FreePic("engine_videoframe");
218 }
219
220 static void CL_PlayVideo_f(void)
221 {
222         char name[1024];
223
224         if (Cmd_Argc() != 2)
225         {
226                 Con_Printf ("usage: playvideo <videoname>\nplays video named video/<videoname>.dpv\n");
227                 return;
228         }
229
230         sprintf(name, "%s/video/%s.dpv", com_gamedir, Cmd_Argv(1));
231         CL_VideoStart(name);
232 }
233
234 static void CL_StopVideo_f(void)
235 {
236         CL_VideoStop();
237 }
238
239 void CL_Video_Init(void)
240 {
241         Cmd_AddCommand("playvideo", CL_PlayVideo_f);
242         Cmd_AddCommand("stopvideo", CL_StopVideo_f);
243
244         clvideomempool = Mem_AllocPool("CL_Video");
245 }