DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
dpvsimpledecode.c
Go to the documentation of this file.
1/*
2Copyright (C) 2002-2013 DarkPlaces contributors
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20
21#include "quakedef.h"
22#include "dpvsimpledecode.h"
23
24#define HZREADERROR_OK 0
25#define HZREADERROR_EOF 1
26#define HZREADERROR_MALLOCFAILED 2
27
28//#define HZREADBLOCKSIZE 16000
29#define HZREADBLOCKSIZE 1048576
30
31typedef struct hz_bitstream_read_s
32{
33 qfile_t *file;
35}
37
38typedef struct hz_bitstream_readblock_s
39{
40 struct hz_bitstream_readblock_s *next;
41 unsigned int size;
42 unsigned char data[HZREADBLOCKSIZE];
43}
45
46typedef struct hz_bitstream_readblocks_s
47{
50 unsigned int position;
51 unsigned int store;
52 int count;
53}
55
57{
58 qfile_t *file;
59 hz_bitstream_read_t *stream;
60 if ((file = FS_OpenVirtualFile(filename, false)))
61 {
63 memset(stream, 0, sizeof(*stream));
64 stream->file = file;
65 return stream;
66 }
67 else
68 return NULL;
69}
70
72{
73 if (stream)
74 {
75 FS_Close(stream->file);
76 Z_Free(stream);
77 }
78}
79
81{
84 if (blocks == NULL)
85 return NULL;
86 memset(blocks, 0, sizeof(hz_bitstream_readblocks_t));
87 return blocks;
88}
89
91{
93 if (blocks == NULL)
94 return;
95 for (b = blocks->blocks;b;b = n)
96 {
97 n = b->next;
98 Z_Free(b);
99 }
100 Z_Free(blocks);
101}
102
104{
105 blocks->store = 0;
106 blocks->count = 0;
107}
108
110{
111 int s;
113 s = size;
114 p = NULL;
115 b = blocks->blocks;
116 while (s > 0)
117 {
118 if (b == NULL)
119 {
121 if (b == NULL)
123 b->next = NULL;
124 b->size = 0;
125 if (p != NULL)
126 p->next = b;
127 else
128 blocks->blocks = b;
129 }
130 if (s > HZREADBLOCKSIZE)
131 b->size = HZREADBLOCKSIZE;
132 else
133 b->size = s;
134 s -= b->size;
135 if (FS_Read(stream->file, b->data, b->size) != (fs_offset_t)b->size)
136 {
137 stream->endoffile = 1;
138 break;
139 }
140 p = b;
141 b = b->next;
142 }
143 while (b)
144 {
145 b->size = 0;
146 b = b->next;
147 }
148 blocks->current = blocks->blocks;
149 blocks->position = 0;
151 if (stream->endoffile)
152 return HZREADERROR_EOF;
153 return HZREADERROR_OK;
154}
155
157{
158 while (blocks->current != NULL && blocks->position >= blocks->current->size)
159 {
160 blocks->position = 0;
161 blocks->current = blocks->current->next;
162 }
163 if (blocks->current == NULL)
164 return 0;
165 return blocks->current->data[blocks->position++];
166}
167
169{
170 if (!blocks->count)
171 {
172 blocks->count += 8;
173 blocks->store <<= 8;
174 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
175 }
176 blocks->count--;
177 return (blocks->store >> blocks->count) & 1;
178}
179
181{
182 unsigned int num = 0;
183 // we can only handle about 24 bits at a time safely
184 // (there might be up to 7 bits more than we need in the bit store)
185 if (size > 24)
186 {
187 size -= 8;
188 num |= hz_bitstream_read_bits(blocks, 8) << size;
189 }
190 while (blocks->count < size)
191 {
192 blocks->count += 8;
193 blocks->store <<= 8;
194 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
195 }
196 blocks->count -= size;
197 num |= (blocks->store >> blocks->count) & ((1 << size) - 1);
198 return num;
199}
200
202{
204}
205
207{
208 return (hz_bitstream_read_byte(blocks) << 8)
209 | (hz_bitstream_read_byte(blocks));
210}
211
213{
214 return (hz_bitstream_read_byte(blocks) << 24)
215 | (hz_bitstream_read_byte(blocks) << 16)
216 | (hz_bitstream_read_byte(blocks) << 8)
217 | (hz_bitstream_read_byte(blocks));
218}
219
220static void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
221{
222 unsigned char *out;
223 out = (unsigned char *)outdata;
224 while (size--)
225 *out++ = hz_bitstream_read_byte(blocks);
226}
227
228#define BLOCKSIZE 8
229
230typedef struct dpvsimpledecodestream_s
231{
234
235 int error;
236
238 unsigned int info_frames;
239
240 unsigned int info_imagewidth;
241 unsigned int info_imageheight;
242 unsigned int info_imagebpp;
243 unsigned int info_imageRloss;
244 unsigned int info_imageRmask;
245 unsigned int info_imageRshift;
246 unsigned int info_imageGloss;
247 unsigned int info_imageGmask;
248 unsigned int info_imageGshift;
249 unsigned int info_imageBloss;
250 unsigned int info_imageBmask;
251 unsigned int info_imageBshift;
252 unsigned int info_imagesize;
254
255 // current video frame (needed because of delta compression)
257 // current video frame data (needed because of delta compression)
258 unsigned int *videopixels;
259
260 // channel the sound file is being played on
262}
264
265static int dpvsimpledecode_setpixelformat(dpvsimpledecodestream_t *s, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel)
266{
267 int Rshift, Rbits, Gshift, Gbits, Bshift, Bbits;
268 if (!Rmask)
269 {
271 return s->error;
272 }
273 if (!Gmask)
274 {
276 return s->error;
277 }
278 if (!Bmask)
279 {
281 return s->error;
282 }
283 if (Rmask & Gmask || Rmask & Bmask || Gmask & Bmask)
284 {
286 return s->error;
287 }
288 switch (bytesperpixel)
289 {
290 case 2:
291 if ((Rmask | Gmask | Bmask) > 65536)
292 {
294 return s->error;
295 }
296 break;
297 case 4:
298 break;
299 default:
301 return s->error;
302 }
303 for (Rshift = 0;!(Rmask & 1);Rshift++, Rmask >>= 1);
304 for (Gshift = 0;!(Gmask & 1);Gshift++, Gmask >>= 1);
305 for (Bshift = 0;!(Bmask & 1);Bshift++, Bmask >>= 1);
306 if (((Rmask + 1) & Rmask) != 0)
307 {
309 return s->error;
310 }
311 if (((Gmask + 1) & Gmask) != 0)
312 {
314 return s->error;
315 }
316 if (((Bmask + 1) & Bmask) != 0)
317 {
319 return s->error;
320 }
321 for (Rbits = 0;Rmask & 1;Rbits++, Rmask >>= 1);
322 for (Gbits = 0;Gmask & 1;Gbits++, Gmask >>= 1);
323 for (Bbits = 0;Bmask & 1;Bbits++, Bmask >>= 1);
324 if (Rbits > 8)
325 {
326 Rshift += (Rbits - 8);
327 Rbits = 8;
328 }
329 if (Gbits > 8)
330 {
331 Gshift += (Gbits - 8);
332 Gbits = 8;
333 }
334 if (Bbits > 8)
335 {
336 Bshift += (Bbits - 8);
337 Bbits = 8;
338 }
339 s->info_imagebpp = bytesperpixel;
340 s->info_imageRloss = 16 + (8 - Rbits);
341 s->info_imageGloss = 8 + (8 - Gbits);
342 s->info_imageBloss = 0 + (8 - Bbits);
343 s->info_imageRmask = (1 << Rbits) - 1;
344 s->info_imageGmask = (1 << Gbits) - 1;
345 s->info_imageBmask = (1 << Bbits) - 1;
346 s->info_imageRshift = Rshift;
347 s->info_imageGshift = Gshift;
348 s->info_imageBshift = Bshift;
350 return s->error;
351}
352
353// opening and closing streams
354
355// opens a stream
356void *dpvsimpledecode_open(clvideo_t *video, char *filename, const char **errorstring)
357{
359 char t[8], *wavename;
360 if (errorstring != NULL)
361 *errorstring = NULL;
363 if (s != NULL)
364 {
365 s->bitstream = hz_bitstream_read_open(filename);
366 if (s->bitstream != NULL)
367 {
368 // check file identification
370 if (s->framedatablocks != NULL)
371 {
374 if (!memcmp(t, "DPVideo", 8))
375 {
376 // check version number
379 {
383 s->info_framerate = (double) hz_bitstream_read_int(s->framedatablocks) * (1.0 / 65536.0);
384 s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
385
386 if (s->info_framerate > 0.0)
387 {
388 s->videopixels = (unsigned int *)Z_Malloc(s->info_imagewidth * s->info_imageheight * sizeof(*s->videopixels));
389 if (s->videopixels != NULL)
390 {
391 size_t namelen;
392
393 namelen = strlen(filename) + 10;
394 wavename = (char *)Z_Malloc(namelen);
395 if (wavename)
396 {
397 sfx_t* sfx;
398
399 FS_StripExtension(filename, wavename, namelen);
400 dp_strlcat(wavename, ".wav", namelen);
401 sfx = S_PrecacheSound (wavename, false, false);
402 if (sfx != NULL)
403 s->sndchan = S_StartSound (-1, 0, sfx, vec3_origin, 1.0f, 0);
404 else
405 s->sndchan = -1;
406 Z_Free(wavename);
407 }
408 // all is well...
409 // set the module functions
410 s->videoframenum = -10000;
417
418 return s;
419 }
420 else if (errorstring != NULL)
421 *errorstring = "unable to allocate video image buffer";
422 }
423 else if (errorstring != NULL)
424 *errorstring = "error in video info chunk";
425 }
426 else if (errorstring != NULL)
427 *errorstring = "read error";
428 }
429 else if (errorstring != NULL)
430 *errorstring = "not a dpvideo file";
432 }
433 else if (errorstring != NULL)
434 *errorstring = "unable to allocate memory for reading buffer";
436 }
437 else if (errorstring != NULL)
438 *errorstring = "unable to open file";
439 Z_Free(s);
440 }
441 else if (errorstring != NULL)
442 *errorstring = "unable to allocate memory for stream info structure";
443 return NULL;
444}
445
446// closes a stream
447void dpvsimpledecode_close(void *stream)
448{
450 if (s == NULL)
451 return;
452 if (s->videopixels)
454 if (s->sndchan != -1)
455 S_StopChannel (s->sndchan, true, true);
456 if (s->framedatablocks)
458 if (s->bitstream)
460 Z_Free(s);
461}
462
463// utilitarian functions
464
465// returns the current error number for the stream, and resets the error
466// number to DPVSIMPLEDECODEERROR_NONE
467// if the supplied string pointer variable is not NULL, it will be set to the
468// error message
469int dpvsimpledecode_error(void *stream, const char **errorstring)
470{
472 int e;
473 e = s->error;
474 s->error = 0;
475 if (errorstring)
476 {
477 switch (e)
478 {
480 *errorstring = "no error";
481 break;
483 *errorstring = "end of file reached (this is not an error)";
484 break;
486 *errorstring = "read error (corrupt or incomplete file)";
487 break;
489 *errorstring = "sound buffer is too small for decoding frame (please allocate it as large as dpvsimpledecode_getneededsoundbufferlength suggests)";
490 break;
492 *errorstring = "invalid red bits mask";
493 break;
495 *errorstring = "invalid green bits mask";
496 break;
498 *errorstring = "invalid blue bits mask";
499 break;
501 *errorstring = "color bit masks overlap";
502 break;
504 *errorstring = "color masks too big for specified bytes per pixel";
505 break;
507 *errorstring = "unsupported bytes per pixel (must be 2 for 16bit, or 4 for 32bit)";
508 break;
509 default:
510 *errorstring = "unknown error";
511 break;
512 }
513 }
514 return e;
515}
516
517// returns the width of the image data
518unsigned int dpvsimpledecode_getwidth(void *stream)
519{
521 return s->info_imagewidth;
522}
523
524// returns the height of the image data
525unsigned int dpvsimpledecode_getheight(void *stream)
526{
528 return s->info_imageheight;
529}
530
531// returns the framerate of the stream
533{
535 return s->info_framerate;
536}
537
538// return aspect ratio of the stream
540{
542 return s->info_aspectratio;
543}
544
545static int dpvsimpledecode_convertpixels(dpvsimpledecodestream_t *s, void *imagedata, int imagebytesperrow)
546{
547 unsigned int a, x, y, width, height;
548 unsigned int Rloss, Rmask, Rshift, Gloss, Gmask, Gshift, Bloss, Bmask, Bshift;
549 unsigned int *in;
550
553
554 Rloss = s->info_imageRloss;
555 Rmask = s->info_imageRmask;
556 Rshift = s->info_imageRshift;
557 Gloss = s->info_imageGloss;
558 Gmask = s->info_imageGmask;
559 Gshift = s->info_imageGshift;
560 Bloss = s->info_imageBloss;
561 Bmask = s->info_imageBmask;
562 Bshift = s->info_imageBshift;
563
564 in = s->videopixels;
565 if (s->info_imagebpp == 4)
566 {
567 unsigned int *outrow;
568 for (y = 0;y < height;y++)
569 {
570 outrow = (unsigned int *)((unsigned char *)imagedata + y * imagebytesperrow);
571 for (x = 0;x < width;x++)
572 {
573 a = *in++;
574 outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
575 }
576 }
577 }
578 else
579 {
580 unsigned short *outrow;
581 for (y = 0;y < height;y++)
582 {
583 outrow = (unsigned short *)((unsigned char *)imagedata + y * imagebytesperrow);
584 if (Rloss == 19 && Gloss == 10 && Bloss == 3 && Rshift == 11 && Gshift == 5 && Bshift == 0)
585 {
586 // optimized
587 for (x = 0;x < width;x++)
588 {
589 a = *in++;
590 outrow[x] = ((a >> 8) & 0xF800) | ((a >> 5) & 0x07E0) | ((a >> 3) & 0x001F);
591 }
592 }
593 else
594 {
595 for (x = 0;x < width;x++)
596 {
597 a = *in++;
598 outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
599 }
600 }
601 }
602 }
603 return s->error;
604}
605
607{
608 int i, a, b, colors, g, x1, y1, bw, bh, width, height, palettebits;
609 unsigned int palette[256], *outrow, *out;
610 g = BLOCKSIZE;
613 for (y1 = 0;y1 < height;y1 += g)
614 {
615 outrow = s->videopixels + y1 * width;
616 bh = g;
617 if (y1 + bh > height)
618 bh = height - y1;
619 for (x1 = 0;x1 < width;x1 += g)
620 {
621 out = outrow + x1;
622 bw = g;
623 if (x1 + bw > width)
624 bw = width - x1;
626 {
627 // updated block
628 palettebits = hz_bitstream_read_bits(s->framedatablocks, 3);
629 colors = 1 << palettebits;
630 for (i = 0;i < colors;i++)
631 palette[i] = hz_bitstream_read_bits(s->framedatablocks, 24);
632 if (palettebits)
633 {
634 for (b = 0;b < bh;b++, out += width)
635 for (a = 0;a < bw;a++)
636 out[a] = palette[hz_bitstream_read_bits(s->framedatablocks, palettebits)];
637 }
638 else
639 {
640 for (b = 0;b < bh;b++, out += width)
641 for (a = 0;a < bw;a++)
642 out[a] = palette[0];
643 }
644 }
645 }
646 }
647 return s->error;
648}
649
650// decodes a video frame to the supplied output pixels
651int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
652{
654 unsigned int framedatasize;
655 char t[4];
657 if (dpvsimpledecode_setpixelformat(s, Rmask, Gmask, Bmask, bytesperpixel))
658 return s->error;
659
662 if (memcmp(t, "VID0", 4))
663 {
664 if (t[0] == 0)
665 return (s->error = DPVSIMPLEDECODEERROR_EOF);
666 else
668 }
669 framedatasize = hz_bitstream_read_int(s->framedatablocks);
672 return s->error;
673
674 dpvsimpledecode_convertpixels(s, imagedata, imagebytesperrow);
675 return s->error;
676}
#define dp_strlcat(dst, src, dsize)
Definition common.h:304
vector size
static unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
static int dpvsimpledecode_decompressimage(dpvsimpledecodestream_t *s)
static void hz_bitstream_read_close(hz_bitstream_read_t *stream)
static unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
static unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
static int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
static hz_bitstream_read_t * hz_bitstream_read_open(char *filename)
double dpvsimpledecode_getframerate(void *stream)
unsigned int dpvsimpledecode_getwidth(void *stream)
void * dpvsimpledecode_open(clvideo_t *video, char *filename, const char **errorstring)
static unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
static void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
static int dpvsimpledecode_convertpixels(dpvsimpledecodestream_t *s, void *imagedata, int imagebytesperrow)
#define HZREADERROR_MALLOCFAILED
static void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
int dpvsimpledecode_error(void *stream, const char **errorstring)
void dpvsimpledecode_close(void *stream)
static int dpvsimpledecode_setpixelformat(dpvsimpledecodestream_t *s, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel)
static int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
#define HZREADERROR_EOF
double dpvsimpledecode_getaspectratio(void *stream)
int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
static hz_bitstream_readblocks_t * hz_bitstream_read_blocks_new(void)
unsigned int dpvsimpledecode_getheight(void *stream)
#define HZREADBLOCKSIZE
static void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
#define BLOCKSIZE
static unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
#define HZREADERROR_OK
#define DPVSIMPLEDECODEERROR_SOUNDBUFFERTOOSMALL
#define DPVSIMPLEDECODEERROR_INVALIDBMASK
#define DPVSIMPLEDECODEERROR_INVALIDRMASK
#define DPVSIMPLEDECODEERROR_READERROR
#define DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP
#define DPVSIMPLEDECODEERROR_INVALIDGMASK
#define DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP
#define DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP
#define DPVSIMPLEDECODEERROR_NONE
#define DPVSIMPLEDECODEERROR_EOF
#define n(x, y)
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
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3611
int FS_Close(qfile_t *file)
Definition fs.c:2970
int64_t fs_offset_t
Definition fs.h:37
GLenum GLsizei width
Definition glquake.h:622
GLenum GLsizei GLsizei height
Definition glquake.h:622
GLint GLenum GLint GLint y
Definition glquake.h:651
GLint GLenum GLint x
Definition glquake.h:651
GLsizeiptr const GLvoid * data
Definition glquake.h:639
vec3_t vec3_origin
Definition mathlib.c:26
float strlen(string s)
int i
#define NULL
Definition qtypes.h:12
dp_FragColor g
dp_FragColor b
vec3 x1
ret a
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
hz_bitstream_read_t * bitstream
hz_bitstream_readblocks_t * framedatablocks
unsigned char data[HZREADBLOCKSIZE]
struct hz_bitstream_readblock_s * next
hz_bitstream_readblock_t * current
hz_bitstream_readblock_t * blocks
#define Z_Malloc(size)
Definition zone.h:161
#define Z_Free(data)
Definition zone.h:164