DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
cl_video_libavw.c
Go to the documentation of this file.
1/*
2 Libavcodec integration for Darkplaces by Timofeyev Pavel
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to:
17
18 Free Software Foundation, Inc.
19 59 Temple Place - Suite 330
20 Boston, MA 02111-1307, USA
21
22*/
23
24// LadyHavoc: for some reason this is being #include'd rather than treated as its own file...
25
26#include "quakedef.h"
27#include "client.h"
28#include "cl_video.h"
29#include "cl_video_libavw.h"
30
31// scaler type
32#define LIBAVW_SCALER_BILINEAR 0
33#define LIBAVW_SCALER_BICUBIC 1
34#define LIBAVW_SCALER_X 2
35#define LIBAVW_SCALER_POINT 3
36#define LIBAVW_SCALER_AREA 4
37#define LIBAVW_SCALER_BICUBLIN 5
38#define LIBAVW_SCALER_GAUSS 6
39#define LIBAVW_SCALER_SINC 7
40#define LIBAVW_SCALER_LANCZOS 8
41#define LIBAVW_SCALER_SPLINE 9
42// output format
43#define LIBAVW_PIXEL_FORMAT_BGR 0
44#define LIBAVW_PIXEL_FORMAT_BGRA 1
45// print levels
46#define LIBAVW_PRINT_WARNING 1
47#define LIBAVW_PRINT_ERROR 2
48#define LIBAVW_PRINT_FATAL 3
49#define LIBAVW_PRINT_PANIC 4
50// exported callback functions:
51typedef void avwCallbackPrint(int, const char *);
52typedef int avwCallbackIoRead(void *, uint8_t *, int);
53typedef uint64_t avwCallbackIoSeek(void *, uint64_t, int);
54typedef uint64_t avwCallbackIoSeekSize(void *);
55// exported functions:
56int (*qLibAvW_Init)(avwCallbackPrint *printfunction); // init library, returns error code
57const char *(*qLibAvW_ErrorString)(int errorcode); // get string for error code
58const char *(*qLibAvW_AvcVersion)(void); // get a string containing libavcodec version wrapper was built for
59float (*qLibAvW_Version)(void); // get wrapper version
60int (*qLibAvW_CreateStream)(void **stream); // create stream, returns error code
61void (*qLibAvW_RemoveStream)(void *stream); // flush and remove stream
62int (*qLibAvW_StreamGetVideoWidth)(void *stream); // get video parameters of stream
64double (*qLibAvW_StreamGetFramerate)(void *stream);
65int (*qLibAvW_StreamGetError)(void *stream); // get last function errorcode from stream
66// simple API to play video
67int (*qLibAvW_PlayVideo)(void *stream, void *file, avwCallbackIoRead *IoRead, avwCallbackIoSeek *IoSeek, avwCallbackIoSeekSize *IoSeekSize);
69int (*qLibAvW_PlayGetFrameImage)(void *stream, int pixel_format, void *imagedata, int imagewidth, int imageheight, int scaler);
70
72{
73 {"LibAvW_Init", (void **) &qLibAvW_Init },
74 {"LibAvW_ErrorString", (void **) &qLibAvW_ErrorString },
75 {"LibAvW_AvcVersion", (void **) &qLibAvW_AvcVersion },
76 {"LibAvW_Version", (void **) &qLibAvW_Version },
77 {"LibAvW_CreateStream", (void **) &qLibAvW_CreateStream },
78 {"LibAvW_RemoveStream", (void **) &qLibAvW_RemoveStream },
79 {"LibAvW_StreamGetVideoWidth", (void **) &qLibAvW_StreamGetVideoWidth },
80 {"LibAvW_StreamGetVideoHeight",(void **) &qLibAvW_StreamGetVideoHeight },
81 {"LibAvW_StreamGetFramerate", (void **) &qLibAvW_StreamGetFramerate },
82 {"LibAvW_StreamGetError", (void **) &qLibAvW_StreamGetError },
83 {"LibAvW_PlayVideo", (void **) &qLibAvW_PlayVideo },
84 {"LibAvW_PlaySeekNextFrame", (void **) &qLibAvW_PlaySeekNextFrame },
85 {"LibAvW_PlayGetFrameImage", (void **) &qLibAvW_PlayGetFrameImage },
86 {NULL, NULL}
87};
88
89const char* dllnames_libavw[] =
90{
91#if defined(WIN32)
92 "libavcodec.dll",
93#elif defined(MACOSX)
94 "libavcodec.dylib",
95#else
96 "libavcodec.so",
97#endif
98 NULL
99};
100
102
103// DP videostream
104typedef struct libavwstream_s
105{
106 qfile_t *file;
108 unsigned int info_imagewidth;
109 unsigned int info_imageheight;
111 void *stream;
112
113 // channel the sound file is being played on
114 sfx_t *sfx;
117}
119
120cvar_t cl_video_libavw_minwidth = {CF_ARCHIVE, "cl_video_libavw_minwidth", "0", "if videos width is lesser than minimal, thay will be upscaled"};
121cvar_t cl_video_libavw_minheight = {CF_ARCHIVE, "cl_video_libavw_minheight", "0", "if videos height is lesser than minimal, thay will be upscaled"};
122cvar_t cl_video_libavw_scaler = {CF_ARCHIVE, "cl_video_libavw_scaler", "1", "selects a scaler for libavcode played videos. Scalers are: 0 - bilinear, 1 - bicubic, 2 - x, 3 - point, 4 - area, 5 - bicublin, 6 - gauss, 7 - sinc, 8 - lanczos, 9 - spline."};
123
124// video extensions
125const char* libavw_extensions[] =
126{
127 "ogv",
128 "avi",
129 "mpg",
130 "mp4",
131 "mkv",
132 "webm",
133 "bik",
134 "roq",
135 "flv",
136 "wmv",
137 "mpeg",
138 "mjpeg",
139 "mpeg4",
140 NULL
141};
142
143/*
144=================================================================
145
146 Video decoding
147 a features that is not supported yet and likely to be done
148 - streaming audio from videofiles
149 - streaming subtitles
150
151=================================================================
152*/
153
154unsigned int libavw_getwidth(void *stream);
155unsigned int libavw_getheight(void *stream);
156double libavw_getframerate(void *stream);
157double libavw_getaspectratio(void *stream);
158void libavw_close(void *stream);
159
160static int libavw_decodeframe(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
161{
162 int pixel_format = LIBAVW_PIXEL_FORMAT_BGR;
163 int errorcode;
164
165 libavwstream_t *s = (libavwstream_t *)stream;
166
167 // start sound
168 if (!s->sndstarted)
169 {
170 if (s->sfx != NULL)
171 s->sndchan = S_StartSound(-1, 0, s->sfx, vec3_origin, 1.0f, 0);
172 s->sndstarted = 1;
173 }
174
175 // read frame
177 {
178 // got error or file end
179 errorcode = qLibAvW_StreamGetError(s->stream);
180 if (errorcode)
181 Con_Printf(CON_ERROR "LibAvW: %s\n", qLibAvW_ErrorString(errorcode));
182 return 1;
183 }
184
185 // decode into bgr texture
186 if (bytesperpixel == 4)
187 pixel_format = LIBAVW_PIXEL_FORMAT_BGRA;
188 else if (bytesperpixel == 3)
189 pixel_format = LIBAVW_PIXEL_FORMAT_BGR;
190 else
191 {
192 Con_Printf(CON_ERROR "LibAvW: cannot determine pixel format for bpp %i\n", bytesperpixel);
193 return 1;
194 }
197 return 0;
198}
199
200// get stream info
201unsigned int libavw_getwidth(void *stream)
202{
203 return ((libavwstream_t *)stream)->info_imagewidth;
204}
205
206unsigned int libavw_getheight(void *stream)
207{
208 return ((libavwstream_t *)stream)->info_imageheight;
209}
210
211double libavw_getframerate(void *stream)
212{
213 return ((libavwstream_t *)stream)->info_framerate;
214}
215
216double libavw_getaspectratio(void *stream)
217{
218 return ((libavwstream_t *)stream)->info_aspectratio;
219}
220
221// close stream
222void libavw_close(void *stream)
223{
224 libavwstream_t *s = (libavwstream_t *)stream;
225
226 if (s->stream)
228 s->stream = NULL;
229 if (s->file)
230 FS_Close(s->file);
231 s->file = NULL;
232 if (s->sndchan >= 0)
233 S_StopChannel(s->sndchan, true, true);
234 s->sndchan = -1;
235}
236
237// IO wrapper
238static int LibAvW_FS_Read(void *opaque, uint8_t *buf, int buf_size)
239{
240 return FS_Read((qfile_t *)opaque, buf, buf_size);
241}
242static uint64_t LibAvW_FS_Seek(void *opaque, uint64_t pos, int whence)
243{
244 return (uint64_t)FS_Seek((qfile_t *)opaque, pos, whence);
245}
246static uint64_t LibAvW_FS_SeekSize(void *opaque)
247{
248 return (uint64_t)FS_FileSize((qfile_t *)opaque);
249}
250
251// open as DP video stream
252void *LibAvW_OpenVideo(clvideo_t *video, char *filename, const char **errorstring)
253{
255 char filebase[MAX_OSPATH], check[MAX_OSPATH];
256 unsigned int i;
257 int errorcode;
258 char *wavename;
259 size_t len;
260
261 if (!libavw_dll)
262 return NULL;
263
264 // allocate stream
265 s = (libavwstream_t *)Z_Malloc(sizeof(libavwstream_t));
266 if (s == NULL)
267 {
268 *errorstring = "unable to allocate memory for stream info structure";
269 return NULL;
270 }
271 memset(s, 0, sizeof(libavwstream_t));
272 s->sndchan = -1;
273
274 // open file
275 s->file = FS_OpenVirtualFile(filename, true);
276 if (!s->file)
277 {
278 FS_StripExtension(filename, filebase, sizeof(filebase));
279 // we tried .dpv, try another extensions
280 for (i = 0; libavw_extensions[i] != NULL; i++)
281 {
282 dpsnprintf(check, sizeof(check), "%s.%s", filebase, libavw_extensions[i]);
283 s->file = FS_OpenVirtualFile(check, true);
284 if (s->file)
285 break;
286 }
287 if (!s->file)
288 {
289 *errorstring = "unable to open videofile";
290 libavw_close(s);
291 Z_Free(s);
292 return NULL;
293 }
294 }
295
296 // allocate libavw stream
297 if ((errorcode = qLibAvW_CreateStream(&s->stream)))
298 {
299 *errorstring = qLibAvW_ErrorString(errorcode);
300 libavw_close(s);
301 Z_Free(s);
302 return NULL;
303 }
304
305 // open video for playing
307 {
309 libavw_close(s);
310 Z_Free(s);
311 return NULL;
312 }
313
314 // all right, start codec
318 s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
319 video->close = libavw_close;
320 video->getwidth = libavw_getwidth;
325
326 // apply min-width, min-height, keep aspect rate
331
332 // provide sound in separate .wav
333 len = strlen(filename) + 10;
334 wavename = (char *)Z_Malloc(len);
335 if (wavename)
336 {
337 FS_StripExtension(filename, wavename, len-1);
338 dp_strlcat(wavename, ".wav", len);
339 s->sfx = S_PrecacheSound(wavename, false, false);
340 s->sndchan = -1;
341 Z_Free(wavename);
342 }
343 return s;
344}
345
346static void libavw_message(int level, const char *message)
347{
349 Con_Printf(CON_WARN "LibAvcodec warning: %s\n", message);
350 else if (level == LIBAVW_PRINT_ERROR)
351 Con_Printf(CON_ERROR "LibAvcodec error: %s\n", message);
352 else if (level == LIBAVW_PRINT_FATAL)
353 Con_Printf(CON_ERROR "LibAvcodec fatal error: %s\n", message);
354 else
355 Con_Printf(CON_ERROR "LibAvcodec panic: %s\n", message);
356}
357
359{
360 int errorcode;
361
362 // COMMANDLINEOPTION: Video: -nolibavw disables libavcodec wrapper support
363 if (Sys_CheckParm("-nolibavw"))
364 return false;
365
366 // load DLL's
368 if (!libavw_dll)
369 return false;
370
371 // initialize libav wrapper
372 if ((errorcode = qLibAvW_Init(&libavw_message)))
373 {
374 Con_Printf(CON_ERROR "LibAvW failed to initialize: %s\n", qLibAvW_ErrorString(errorcode));
376 }
377
381
382 return true;
383}
384
int(* qLibAvW_PlayVideo)(void *stream, void *file, avwCallbackIoRead *IoRead, avwCallbackIoSeek *IoSeek, avwCallbackIoSeekSize *IoSeekSize)
double(* qLibAvW_StreamGetFramerate)(void *stream)
static void libavw_message(int level, const char *message)
int(* qLibAvW_CreateStream)(void **stream)
unsigned int libavw_getheight(void *stream)
unsigned int libavw_getwidth(void *stream)
#define LIBAVW_PIXEL_FORMAT_BGRA
int(* qLibAvW_StreamGetVideoWidth)(void *stream)
cvar_t cl_video_libavw_minwidth
int(* qLibAvW_StreamGetVideoHeight)(void *stream)
static dllfunction_t libavwfuncs[]
static int LibAvW_FS_Read(void *opaque, uint8_t *buf, int buf_size)
int(* qLibAvW_StreamGetError)(void *stream)
cvar_t cl_video_libavw_scaler
double libavw_getaspectratio(void *stream)
cvar_t cl_video_libavw_minheight
const char *(* qLibAvW_ErrorString)(int errorcode)
int(* qLibAvW_Init)(avwCallbackPrint *printfunction)
void(* qLibAvW_RemoveStream)(void *stream)
const char * dllnames_libavw[]
float(* qLibAvW_Version)(void)
void libavw_close(void *stream)
uint64_t avwCallbackIoSeek(void *, uint64_t, int)
static dllhandle_t libavw_dll
uint64_t avwCallbackIoSeekSize(void *)
const char *(* qLibAvW_AvcVersion)(void)
double libavw_getframerate(void *stream)
void * LibAvW_OpenVideo(clvideo_t *video, char *filename, const char **errorstring)
qbool LibAvW_OpenLibrary(void)
int avwCallbackIoRead(void *, uint8_t *, int)
#define LIBAVW_PIXEL_FORMAT_BGR
static int libavw_decodeframe(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
static uint64_t LibAvW_FS_SeekSize(void *opaque)
int(* qLibAvW_PlayGetFrameImage)(void *stream, int pixel_format, void *imagedata, int imagewidth, int imageheight, int scaler)
static uint64_t LibAvW_FS_Seek(void *opaque, uint64_t pos, int whence)
int(* qLibAvW_PlaySeekNextFrame)(void *stream)
const char * libavw_extensions[]
#define LIBAVW_PRINT_FATAL
void LibAvW_CloseLibrary(void)
void avwCallbackPrint(int, const char *)
#define LIBAVW_PRINT_WARNING
#define LIBAVW_PRINT_ERROR
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
#define dp_strlcat(dst, src, dsize)
Definition common.h:304
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_WARN
Definition console.h:101
#define CON_ERROR
Definition console.h:102
void() predraw
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
fs_offset_t FS_Read(qfile_t *file, void *buffer, size_t buffersize)
Definition fs.c:3066
qfile_t * FS_OpenVirtualFile(const char *filepath, qbool quiet)
Definition fs.c:2928
int FS_Seek(qfile_t *file, fs_offset_t offset, int whence)
Definition fs.c:3359
static int(ZEXPORT *qz_inflate)(z_stream *strm
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3611
static int level
Definition fs.c:481
fs_offset_t FS_FileSize(qfile_t *file)
Definition fs.c:3474
int FS_Close(qfile_t *file)
Definition fs.c:2970
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
vec3_t vec3_origin
Definition mathlib.c:26
#define max(A, B)
Definition mathlib.h:38
#define min(A, B)
Definition mathlib.h:37
float strlen(string s)
string message
Definition progsdefs.qc:205
int i
#define MAX_OSPATH
max length of a filesystem pathname
Definition qdefs.h:175
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
precision highp float
Definition shader_glsl.h:53
int S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
S_StartSound returns the channel index, or -1 if an error occurred.
Definition snd_main.c:1643
void S_StopChannel(unsigned int channel_ind, qbool lockmutex, qbool freesfx)
Definition snd_main.c:1648
sfx_t * S_PrecacheSound(const char *name, qbool complain, qbool levelsound)
Definition snd_main.c:1048
void(* close)(void *stream)
Definition cl_video.h:62
double(* getframerate)(void *stream)
Definition cl_video.h:65
unsigned int(* getheight)(void *stream)
Definition cl_video.h:64
int(* decodeframe)(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
Definition cl_video.h:67
double(* getaspectratio)(void *stream)
Definition cl_video.h:66
unsigned int(* getwidth)(void *stream)
Definition cl_video.h:63
Definition cvar.h:66
int integer
Definition cvar.h:73
unsigned int info_imagewidth
unsigned int info_imageheight
void * dllhandle_t
Definition sys.h:169
qbool Sys_LoadDependency(const char **dllnames, dllhandle_t *handle, const dllfunction_t *fcts)
Definition sys_shared.c:131
void Sys_FreeLibrary(dllhandle_t *handle)
Definition sys_shared.c:245
int Sys_CheckParm(const char *parm)
Definition sys_shared.c:327
#define Z_Malloc(size)
Definition zone.h:161
#define Z_Free(data)
Definition zone.h:164