2 #include "dpvsimpledecode.h"
4 #define HZREADERROR_OK 0
5 #define HZREADERROR_EOF 1
6 #define HZREADERROR_MALLOCFAILED 2
8 //#define HZREADBLOCKSIZE 16000
9 #define HZREADBLOCKSIZE 1048576
11 typedef struct hz_bitstream_read_s
18 typedef struct hz_bitstream_readblock_s
20 struct hz_bitstream_readblock_s *next;
22 unsigned char data[HZREADBLOCKSIZE];
24 hz_bitstream_readblock_t;
26 typedef struct hz_bitstream_readblocks_s
28 hz_bitstream_readblock_t *blocks;
29 hz_bitstream_readblock_t *current;
30 unsigned int position;
34 hz_bitstream_readblocks_t;
36 static hz_bitstream_read_t *hz_bitstream_read_open(char *filename)
39 hz_bitstream_read_t *stream;
40 if ((file = FS_OpenVirtualFile(filename, false)))
42 stream = (hz_bitstream_read_t *)Z_Malloc(sizeof(hz_bitstream_read_t));
43 memset(stream, 0, sizeof(*stream));
51 static void hz_bitstream_read_close(hz_bitstream_read_t *stream)
55 FS_Close(stream->file);
60 static hz_bitstream_readblocks_t *hz_bitstream_read_blocks_new(void)
62 hz_bitstream_readblocks_t *blocks;
63 blocks = (hz_bitstream_readblocks_t *)Z_Malloc(sizeof(hz_bitstream_readblocks_t));
66 memset(blocks, 0, sizeof(hz_bitstream_readblocks_t));
70 static void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
72 hz_bitstream_readblock_t *b, *n;
75 for (b = blocks->blocks;b;b = n)
83 static void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
89 static int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
92 hz_bitstream_readblock_t *b, *p;
100 b = (hz_bitstream_readblock_t *)Z_Malloc(sizeof(hz_bitstream_readblock_t));
102 return HZREADERROR_MALLOCFAILED;
110 if (s > HZREADBLOCKSIZE)
111 b->size = HZREADBLOCKSIZE;
115 if (FS_Read(stream->file, b->data, b->size) != (fs_offset_t)b->size)
117 stream->endoffile = 1;
128 blocks->current = blocks->blocks;
129 blocks->position = 0;
130 hz_bitstream_read_flushbits(blocks);
131 if (stream->endoffile)
132 return HZREADERROR_EOF;
133 return HZREADERROR_OK;
136 static unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
138 while (blocks->current != NULL && blocks->position >= blocks->current->size)
140 blocks->position = 0;
141 blocks->current = blocks->current->next;
143 if (blocks->current == NULL)
145 return blocks->current->data[blocks->position++];
148 static int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
154 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
157 return (blocks->store >> blocks->count) & 1;
160 static unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
162 unsigned int num = 0;
163 // we can only handle about 24 bits at a time safely
164 // (there might be up to 7 bits more than we need in the bit store)
168 num |= hz_bitstream_read_bits(blocks, 8) << size;
170 while (blocks->count < size)
174 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
176 blocks->count -= size;
177 num |= (blocks->store >> blocks->count) & ((1 << size) - 1);
181 static unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
183 return hz_bitstream_read_blocks_getbyte(blocks);
186 static unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
188 return (hz_bitstream_read_byte(blocks) << 8)
189 | (hz_bitstream_read_byte(blocks));
192 static unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
194 return (hz_bitstream_read_byte(blocks) << 24)
195 | (hz_bitstream_read_byte(blocks) << 16)
196 | (hz_bitstream_read_byte(blocks) << 8)
197 | (hz_bitstream_read_byte(blocks));
200 static void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
203 out = (unsigned char *)outdata;
205 *out++ = hz_bitstream_read_byte(blocks);
210 typedef struct dpvsimpledecodestream_s
212 hz_bitstream_read_t *bitstream;
213 hz_bitstream_readblocks_t *framedatablocks;
217 double info_framerate;
218 unsigned int info_frames;
220 unsigned int info_imagewidth;
221 unsigned int info_imageheight;
222 unsigned int info_imagebpp;
223 unsigned int info_imageRloss;
224 unsigned int info_imageRmask;
225 unsigned int info_imageRshift;
226 unsigned int info_imageGloss;
227 unsigned int info_imageGmask;
228 unsigned int info_imageGshift;
229 unsigned int info_imageBloss;
230 unsigned int info_imageBmask;
231 unsigned int info_imageBshift;
232 unsigned int info_imagesize;
233 double info_aspectratio;
235 // current video frame (needed because of delta compression)
237 // current video frame data (needed because of delta compression)
238 unsigned int *videopixels;
240 // channel the sound file is being played on
243 dpvsimpledecodestream_t;
245 static int dpvsimpledecode_setpixelformat(dpvsimpledecodestream_t *s, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel)
247 int Rshift, Rbits, Gshift, Gbits, Bshift, Bbits;
250 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
255 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
260 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
263 if (Rmask & Gmask || Rmask & Bmask || Gmask & Bmask)
265 s->error = DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP;
268 switch (bytesperpixel)
271 if ((Rmask | Gmask | Bmask) > 65536)
273 s->error = DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP;
280 s->error = DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP;
283 for (Rshift = 0;!(Rmask & 1);Rshift++, Rmask >>= 1);
284 for (Gshift = 0;!(Gmask & 1);Gshift++, Gmask >>= 1);
285 for (Bshift = 0;!(Bmask & 1);Bshift++, Bmask >>= 1);
286 if (((Rmask + 1) & Rmask) != 0)
288 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
291 if (((Gmask + 1) & Gmask) != 0)
293 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
296 if (((Bmask + 1) & Bmask) != 0)
298 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
301 for (Rbits = 0;Rmask & 1;Rbits++, Rmask >>= 1);
302 for (Gbits = 0;Gmask & 1;Gbits++, Gmask >>= 1);
303 for (Bbits = 0;Bmask & 1;Bbits++, Bmask >>= 1);
306 Rshift += (Rbits - 8);
311 Gshift += (Gbits - 8);
316 Bshift += (Bbits - 8);
319 s->info_imagebpp = bytesperpixel;
320 s->info_imageRloss = 16 + (8 - Rbits);
321 s->info_imageGloss = 8 + (8 - Gbits);
322 s->info_imageBloss = 0 + (8 - Bbits);
323 s->info_imageRmask = (1 << Rbits) - 1;
324 s->info_imageGmask = (1 << Gbits) - 1;
325 s->info_imageBmask = (1 << Bbits) - 1;
326 s->info_imageRshift = Rshift;
327 s->info_imageGshift = Gshift;
328 s->info_imageBshift = Bshift;
329 s->info_imagesize = s->info_imagewidth * s->info_imageheight * s->info_imagebpp;
333 // opening and closing streams
336 void *dpvsimpledecode_open(clvideo_t *video, char *filename, const char **errorstring)
338 dpvsimpledecodestream_t *s;
339 char t[8], *wavename;
340 if (errorstring != NULL)
342 s = (dpvsimpledecodestream_t *)Z_Malloc(sizeof(dpvsimpledecodestream_t));
345 s->bitstream = hz_bitstream_read_open(filename);
346 if (s->bitstream != NULL)
348 // check file identification
349 s->framedatablocks = hz_bitstream_read_blocks_new();
350 if (s->framedatablocks != NULL)
352 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
353 hz_bitstream_read_bytes(s->framedatablocks, t, 8);
354 if (!memcmp(t, "DPVideo", 8))
356 // check version number
357 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 2);
358 if (hz_bitstream_read_short(s->framedatablocks) == 1)
360 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 12);
361 s->info_imagewidth = hz_bitstream_read_short(s->framedatablocks);
362 s->info_imageheight = hz_bitstream_read_short(s->framedatablocks);
363 s->info_framerate = (double) hz_bitstream_read_int(s->framedatablocks) * (1.0 / 65536.0);
364 s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
366 if (s->info_framerate > 0.0)
368 s->videopixels = (unsigned int *)Z_Malloc(s->info_imagewidth * s->info_imageheight * sizeof(*s->videopixels));
369 if (s->videopixels != NULL)
373 namelen = strlen(filename) + 10;
374 wavename = (char *)Z_Malloc(namelen);
379 FS_StripExtension(filename, wavename, namelen);
380 strlcat(wavename, ".wav", namelen);
381 sfx = S_PrecacheSound (wavename, false, false);
383 s->sndchan = S_StartSound (-1, 0, sfx, vec3_origin, 1.0f, 0);
389 // set the module functions
390 s->videoframenum = -10000;
391 video->close = dpvsimpledecode_close;
392 video->getwidth = dpvsimpledecode_getwidth;
393 video->getheight = dpvsimpledecode_getheight;
394 video->getframerate = dpvsimpledecode_getframerate;
395 video->decodeframe = dpvsimpledecode_video;
396 video->getaspectratio = dpvsimpledecode_getaspectratio;
400 else if (errorstring != NULL)
401 *errorstring = "unable to allocate video image buffer";
403 else if (errorstring != NULL)
404 *errorstring = "error in video info chunk";
406 else if (errorstring != NULL)
407 *errorstring = "read error";
409 else if (errorstring != NULL)
410 *errorstring = "not a dpvideo file";
411 hz_bitstream_read_blocks_free(s->framedatablocks);
413 else if (errorstring != NULL)
414 *errorstring = "unable to allocate memory for reading buffer";
415 hz_bitstream_read_close(s->bitstream);
417 else if (errorstring != NULL)
418 *errorstring = "unable to open file";
421 else if (errorstring != NULL)
422 *errorstring = "unable to allocate memory for stream info structure";
427 void dpvsimpledecode_close(void *stream)
429 dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
433 Z_Free(s->videopixels);
434 if (s->sndchan != -1)
435 S_StopChannel (s->sndchan, true, true);
436 if (s->framedatablocks)
437 hz_bitstream_read_blocks_free(s->framedatablocks);
439 hz_bitstream_read_close(s->bitstream);
443 // utilitarian functions
445 // returns the current error number for the stream, and resets the error
446 // number to DPVSIMPLEDECODEERROR_NONE
447 // if the supplied string pointer variable is not NULL, it will be set to the
449 int dpvsimpledecode_error(void *stream, const char **errorstring)
451 dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
459 case DPVSIMPLEDECODEERROR_NONE:
460 *errorstring = "no error";
462 case DPVSIMPLEDECODEERROR_EOF:
463 *errorstring = "end of file reached (this is not an error)";
465 case DPVSIMPLEDECODEERROR_READERROR:
466 *errorstring = "read error (corrupt or incomplete file)";
468 case DPVSIMPLEDECODEERROR_SOUNDBUFFERTOOSMALL:
469 *errorstring = "sound buffer is too small for decoding frame (please allocate it as large as dpvsimpledecode_getneededsoundbufferlength suggests)";
471 case DPVSIMPLEDECODEERROR_INVALIDRMASK:
472 *errorstring = "invalid red bits mask";
474 case DPVSIMPLEDECODEERROR_INVALIDGMASK:
475 *errorstring = "invalid green bits mask";
477 case DPVSIMPLEDECODEERROR_INVALIDBMASK:
478 *errorstring = "invalid blue bits mask";
480 case DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP:
481 *errorstring = "color bit masks overlap";
483 case DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP:
484 *errorstring = "color masks too big for specified bytes per pixel";
486 case DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP:
487 *errorstring = "unsupported bytes per pixel (must be 2 for 16bit, or 4 for 32bit)";
490 *errorstring = "unknown error";
497 // returns the width of the image data
498 unsigned int dpvsimpledecode_getwidth(void *stream)
500 dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
501 return s->info_imagewidth;
504 // returns the height of the image data
505 unsigned int dpvsimpledecode_getheight(void *stream)
507 dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
508 return s->info_imageheight;
511 // returns the framerate of the stream
512 double dpvsimpledecode_getframerate(void *stream)
514 dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
515 return s->info_framerate;
518 // return aspect ratio of the stream
519 double dpvsimpledecode_getaspectratio(void *stream)
521 dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
522 return s->info_aspectratio;
525 static int dpvsimpledecode_convertpixels(dpvsimpledecodestream_t *s, void *imagedata, int imagebytesperrow)
527 unsigned int a, x, y, width, height;
528 unsigned int Rloss, Rmask, Rshift, Gloss, Gmask, Gshift, Bloss, Bmask, Bshift;
531 width = s->info_imagewidth;
532 height = s->info_imageheight;
534 Rloss = s->info_imageRloss;
535 Rmask = s->info_imageRmask;
536 Rshift = s->info_imageRshift;
537 Gloss = s->info_imageGloss;
538 Gmask = s->info_imageGmask;
539 Gshift = s->info_imageGshift;
540 Bloss = s->info_imageBloss;
541 Bmask = s->info_imageBmask;
542 Bshift = s->info_imageBshift;
545 if (s->info_imagebpp == 4)
547 unsigned int *outrow;
548 for (y = 0;y < height;y++)
550 outrow = (unsigned int *)((unsigned char *)imagedata + y * imagebytesperrow);
551 for (x = 0;x < width;x++)
554 outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
560 unsigned short *outrow;
561 for (y = 0;y < height;y++)
563 outrow = (unsigned short *)((unsigned char *)imagedata + y * imagebytesperrow);
564 if (Rloss == 19 && Gloss == 10 && Bloss == 3 && Rshift == 11 && Gshift == 5 && Bshift == 0)
567 for (x = 0;x < width;x++)
570 outrow[x] = ((a >> 8) & 0xF800) | ((a >> 5) & 0x07E0) | ((a >> 3) & 0x001F);
575 for (x = 0;x < width;x++)
578 outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
586 static int dpvsimpledecode_decompressimage(dpvsimpledecodestream_t *s)
588 int i, a, b, colors, g, x1, y1, bw, bh, width, height, palettebits;
589 unsigned int palette[256], *outrow, *out;
591 width = s->info_imagewidth;
592 height = s->info_imageheight;
593 for (y1 = 0;y1 < height;y1 += g)
595 outrow = s->videopixels + y1 * width;
597 if (y1 + bh > height)
599 for (x1 = 0;x1 < width;x1 += g)
605 if (hz_bitstream_read_bit(s->framedatablocks))
608 palettebits = hz_bitstream_read_bits(s->framedatablocks, 3);
609 colors = 1 << palettebits;
610 for (i = 0;i < colors;i++)
611 palette[i] = hz_bitstream_read_bits(s->framedatablocks, 24);
614 for (b = 0;b < bh;b++, out += width)
615 for (a = 0;a < bw;a++)
616 out[a] = palette[hz_bitstream_read_bits(s->framedatablocks, palettebits)];
620 for (b = 0;b < bh;b++, out += width)
621 for (a = 0;a < bw;a++)
630 // decodes a video frame to the supplied output pixels
631 int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
633 dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
634 unsigned int framedatasize;
636 s->error = DPVSIMPLEDECODEERROR_NONE;
637 if (dpvsimpledecode_setpixelformat(s, Rmask, Gmask, Bmask, bytesperpixel))
640 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
641 hz_bitstream_read_bytes(s->framedatablocks, t, 4);
642 if (memcmp(t, "VID0", 4))
645 return (s->error = DPVSIMPLEDECODEERROR_EOF);
647 return (s->error = DPVSIMPLEDECODEERROR_READERROR);
649 framedatasize = hz_bitstream_read_int(s->framedatablocks);
650 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, framedatasize);
651 if (dpvsimpledecode_decompressimage(s))
654 dpvsimpledecode_convertpixels(s, imagedata, imagebytesperrow);