4 #include "dpvsimpledecode.h"
6 // constants (and semi-constants)
7 static int cl_videormask;
8 static int cl_videobmask;
9 static int cl_videogmask;
10 static int cl_videobytesperpixel;
12 static int cl_activevideos;
13 static clvideo_t videoarray[ MAXCLVIDEOS ];
14 static rtexturepool_t *cl_videotexturepool;
16 static qboolean OpenStream( clvideo_t * video )
19 video->stream = dpvsimpledecode_open( video->filename, &errorstring);
22 Con_Printf("unable to open \"%s\", error: %s\n", video->filename, errorstring);
28 static void SuspendVideo( clvideo_t * video )
30 if( video->suspended )
32 video->suspended = true;
34 R_FreeTexture( video->cpif.tex );
35 // free the image data
36 Mem_Free( video->imagedata );
37 // if we are in firstframe mode, also close the stream
38 if( video->state == CLVIDEO_FIRSTFRAME )
39 dpvsimpledecode_close( video->stream );
42 static qboolean WakeVideo( clvideo_t * video )
44 if( !video->suspended )
46 video->suspended = false;
48 if( video->state == CLVIDEO_FIRSTFRAME )
49 if( !OpenStream( video ) ) {
50 video->state = CLVIDEO_UNUSED;
54 video->imagedata = Mem_Alloc( cl_mempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel );
55 video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name,
56 video->cpif.width, video->cpif.height, NULL, TEXTYPE_RGBA, 0, NULL );
59 video->starttime += realtime - video->lasttime;
64 clvideo_t* CL_OpenVideo( const char *filename, const char *name, int owner, qboolean cinematic )
76 for (i = 1, video = videoarray; i < cl_activevideos;i++, video++)
77 if (videoarray[i].state == CLVIDEO_UNUSED)
81 Con_Printf( "unable to open video \"%s\" - video limit reached\n", filename );
86 strncpy( video->filename, filename, MAX_QPATH );
87 video->ownertag = owner;
89 if( strncmp( name, CLVIDEOPREFIX, sizeof( CLVIDEOPREFIX ) - 1 ) )
92 strncpy( video->cpif.name, name, MAX_QPATH );
94 if( !OpenStream( video ) )
97 video->state = CLVIDEO_FIRSTFRAME;
99 video->framerate = dpvsimpledecode_getframerate( video->stream );
100 video->lasttime = realtime;
102 video->cpif.width = dpvsimpledecode_getwidth( video->stream );
103 video->cpif.height = dpvsimpledecode_getheight( video->stream );
104 video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name, video->cpif.width, video->cpif.height, NULL, TEXTYPE_RGBA, 0, NULL );
106 video->imagedata = Mem_Alloc( cl_mempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel );
108 // expand the active range to include the new entry
109 cl_activevideos = max(cl_activevideos, i + 1);
113 clvideo_t* CL_GetVideo( const char *name )
118 for( i = 0 ; i < cl_activevideos ; i++ )
119 if( videoarray[ i ].state != CLVIDEO_UNUSED
120 && !strcmp( videoarray[ i ].cpif.name , name ) )
122 if( i == cl_activevideos )
124 video = &videoarray[ i ];
126 if( video->suspended )
128 if( !WakeVideo( video ) )
130 else if( video->state == CLVIDEO_RESETONWAKEUP )
131 video->framenum = -1;
134 video->lasttime = realtime;
139 void CL_SetVideoState( clvideo_t *video, clvideostate_t state )
144 video->lasttime = realtime;
145 video->state = state;
146 if( state == CLVIDEO_FIRSTFRAME )
147 CL_RestartVideo( video );
150 void CL_RestartVideo( clvideo_t *video )
155 video->starttime = video->lasttime = realtime;
156 video->framenum = -1;
158 dpvsimpledecode_close( video->stream );
159 if( !OpenStream( video ) )
160 video->state = CLVIDEO_UNUSED;
163 void CL_CloseVideo( clvideo_t * video )
165 if( !video || video->state == CLVIDEO_UNUSED )
168 if( !video->suspended || video->state != CLVIDEO_FIRSTFRAME )
169 dpvsimpledecode_close( video->stream );
170 if( !video->suspended ) {
171 Mem_Free( video->imagedata );
172 R_FreeTexture( video->cpif.tex );
175 video->state = CLVIDEO_UNUSED;
178 static void VideoFrame( clvideo_t *video )
182 if( video->state == CLVIDEO_FIRSTFRAME )
185 destframe = (realtime - video->starttime) * video->framerate;
188 if( video->framenum < destframe ) {
191 if( dpvsimpledecode_video( video->stream, video->imagedata, cl_videormask,
192 cl_videogmask, cl_videobmask, cl_videobytesperpixel,
193 cl_videobytesperpixel * video->cpif.width )
195 CL_RestartVideo( video );
196 if( video->state == CLVIDEO_PLAY )
197 video->state = CLVIDEO_FIRSTFRAME;
200 } while( video->framenum < destframe );
201 R_UpdateTexture( video->cpif.tex, (unsigned char *)video->imagedata );
205 void CL_VideoFrame( void ) // update all videos
210 for( video = videoarray, i = 0 ; i < cl_activevideos ; video++, i++ )
211 if( video->state != CLVIDEO_UNUSED && !video->suspended )
213 if( realtime - video->lasttime > CLTHRESHOLD )
214 SuspendVideo( video );
215 else if( video->state == CLVIDEO_PAUSE )
216 video->starttime = realtime - video->framenum * video->framerate;
221 if( videoarray->state == CLVIDEO_FIRSTFRAME )
224 // reduce range to exclude unnecessary entries
225 while (cl_activevideos > 0 && videoarray[cl_activevideos-1].state == CLVIDEO_UNUSED)
229 void CL_Video_Shutdown( void )
232 for( i = 0 ; i < cl_activevideos ; i++ )
233 CL_CloseVideo( &videoarray[ i ] );
236 void CL_PurgeOwner( int owner )
239 for( i = 0 ; i < cl_activevideos ; i++ )
240 if( videoarray[ i ].ownertag == owner )
241 CL_CloseVideo( &videoarray[ i ] );
244 int cl_videoplaying = false; // old, but still supported
246 void CL_DrawVideo(void)
249 DrawQ_Pic(0, 0, &videoarray->cpif, vid_conwidth.integer, vid_conheight.integer, 1, 1, 1, 1, 0);
252 void CL_VideoStart(char *filename)
256 if( videoarray->state != CLVIDEO_UNUSED )
257 CL_CloseVideo( videoarray );
258 if( !CL_OpenVideo( filename, va( CLVIDEOPREFIX "%s", filename ), 0, true ) )
261 cl_videoplaying = true;
263 CL_SetVideoState( videoarray, CLVIDEO_PLAY );
264 CL_RestartVideo( videoarray );
267 void CL_VideoStop(void)
269 cl_videoplaying = false;
271 CL_CloseVideo( videoarray );
274 static void CL_PlayVideo_f(void)
276 char name[MAX_QPATH];
282 Con_Print("usage: playvideo <videoname>\nplays video named video/<videoname>.dpv\n");
286 sprintf(name, "video/%s.dpv", Cmd_Argv(1));
290 static void CL_StopVideo_f(void)
295 static void cl_video_start( void )
300 cl_videotexturepool = R_AllocTexturePool();
302 for( video = videoarray, i = 0 ; i < cl_activevideos ; i++, video++ )
303 if( video->state != CLVIDEO_UNUSED && !video->suspended )
304 video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name,
305 video->cpif.width, video->cpif.height, NULL, TEXTYPE_RGBA, 0, NULL );
308 static void cl_video_shutdown( void )
310 R_FreeTexturePool( &cl_videotexturepool );
313 static void cl_video_newmap( void )
317 void CL_Video_Init( void )
320 cl_videobytesperpixel = 4;
321 cl_videormask = BigLong(0xFF000000);
322 cl_videogmask = BigLong(0x00FF0000);
323 cl_videobmask = BigLong(0x0000FF00);
325 Cmd_AddCommand( "playvideo", CL_PlayVideo_f, "play a .dpv video file" );
326 Cmd_AddCommand( "stopvideo", CL_StopVideo_f, "stop playing a .dpv video file" );
328 R_RegisterModule( "CL_Video", cl_video_start, cl_video_shutdown, cl_video_newmap );