6 #include "dpvsimpledecode.h"
9 #define EMBEDDEDHZREAD 1
11 #ifndef EMBEDDEDHZREAD
15 #define HZREADERROR_OK 0
16 #define HZREADERROR_EOF 1
17 #define HZREADERROR_MALLOCFAILED 2
19 #define HZREADBLOCKSIZE 16000
28 typedef struct hz_bitstream_readblock_s
30 struct hz_bitstream_readblock_s *next;
32 unsigned char data[HZREADBLOCKSIZE];
34 hz_bitstream_readblock_t;
38 hz_bitstream_readblock_t *blocks;
39 hz_bitstream_readblock_t *current;
40 unsigned int position;
44 hz_bitstream_readblocks_t;
46 hz_bitstream_read_t *hz_bitstream_read_open(char *filename)
49 hz_bitstream_read_t *stream;
50 if ((file = fopen(filename, "rb")))
52 stream = malloc(sizeof(hz_bitstream_read_t));
53 memset(stream, 0, sizeof(*stream));
61 void hz_bitstream_read_close(hz_bitstream_read_t *stream)
70 unsigned int hz_bitstream_read_currentbyte(hz_bitstream_read_t *stream)
72 return ftell(stream->file);
75 int hz_bitstream_read_seek(hz_bitstream_read_t *stream, unsigned int position)
77 stream->endoffile = 0;
78 return fseek(stream->file, position, SEEK_SET) != 0;
81 hz_bitstream_readblocks_t *hz_bitstream_read_blocks_new(void)
83 hz_bitstream_readblocks_t *blocks;
84 blocks = malloc(sizeof(hz_bitstream_readblocks_t));
87 memset(blocks, 0, sizeof(hz_bitstream_readblocks_t));
91 void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
93 hz_bitstream_readblock_t *b, *n;
96 for (b = blocks->blocks;b;b = n)
104 void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
110 int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
113 hz_bitstream_readblock_t *b, *p;
121 b = malloc(sizeof(hz_bitstream_readblock_t));
123 return HZREADERROR_MALLOCFAILED;
131 if (s > HZREADBLOCKSIZE)
132 b->size = HZREADBLOCKSIZE;
136 if (fread(b->data, 1, b->size, stream->file) != b->size)
138 stream->endoffile = 1;
149 blocks->current = blocks->blocks;
150 blocks->position = 0;
151 hz_bitstream_read_flushbits(blocks);
152 if (stream->endoffile)
153 return HZREADERROR_EOF;
154 return HZREADERROR_OK;
157 unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
159 while (blocks->current != NULL && blocks->position >= blocks->current->size)
161 blocks->position = 0;
162 blocks->current = blocks->current->next;
164 if (blocks->current == NULL)
166 return blocks->current->data[blocks->position++];
169 int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
175 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
178 return (blocks->store >> blocks->count) & 1;
181 unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
183 unsigned int num = 0;
184 // we can only handle about 24 bits at a time safely
185 // (there might be up to 7 bits more than we need in the bit store)
189 num |= hz_bitstream_read_bits(blocks, 8) << size;
191 while (blocks->count < size)
195 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
197 blocks->count -= size;
198 num |= (blocks->store >> blocks->count) & ((1 << size) - 1);
202 unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
204 return hz_bitstream_read_blocks_getbyte(blocks);
207 unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
209 return (hz_bitstream_read_byte(blocks) << 8)
210 | (hz_bitstream_read_byte(blocks));
213 unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
215 return (hz_bitstream_read_byte(blocks) << 24)
216 | (hz_bitstream_read_byte(blocks) << 16)
217 | (hz_bitstream_read_byte(blocks) << 8)
218 | (hz_bitstream_read_byte(blocks));
221 void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
226 *out++ = hz_bitstream_read_byte(blocks);
232 typedef struct dpvsimpledecodestream_s
234 hz_bitstream_read_t *bitstream;
235 hz_bitstream_readblocks_t *framedatablocks;
239 double info_framerate;
240 unsigned int info_frames;
242 unsigned int info_imagewidth;
243 unsigned int info_imageheight;
244 unsigned int info_imagebpp;
245 unsigned int info_imageRloss;
246 unsigned int info_imageRmask;
247 unsigned int info_imageRshift;
248 unsigned int info_imageGloss;
249 unsigned int info_imageGmask;
250 unsigned int info_imageGshift;
251 unsigned int info_imageBloss;
252 unsigned int info_imageBmask;
253 unsigned int info_imageBshift;
254 unsigned int info_imagesize;
256 // current video frame (needed because of delta compression)
258 // current video frame data (needed because of delta compression)
259 unsigned int *videopixels;
261 // wav file the sound is being read from
262 wavefile_t *wavefile;
264 dpvsimpledecodestream_t;
266 static int dpvsimpledecode_setpixelformat(dpvsimpledecodestream_t *s, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel)
268 int Rshift, Rbits, Gshift, Gbits, Bshift, Bbits;
271 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
276 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
281 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
284 if (Rmask & Gmask || Rmask & Bmask || Gmask & Bmask)
286 s->error = DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP;
289 switch (bytesperpixel)
292 if ((Rmask | Gmask | Bmask) > 65536)
294 s->error = DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP;
301 s->error = DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP;
305 for (Rshift = 0;!(Rmask & 1);Rshift++, Rmask >>= 1);
306 for (Gshift = 0;!(Gmask & 1);Gshift++, Gmask >>= 1);
307 for (Bshift = 0;!(Bmask & 1);Bshift++, Bmask >>= 1);
308 if (((Rmask + 1) & Rmask) != 0)
310 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
313 if (((Gmask + 1) & Gmask) != 0)
315 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
318 if (((Bmask + 1) & Bmask) != 0)
320 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
323 for (Rbits = 0;Rmask & 1;Rbits++, Rmask >>= 1);
324 for (Gbits = 0;Gmask & 1;Gbits++, Gmask >>= 1);
325 for (Bbits = 0;Bmask & 1;Bbits++, Bmask >>= 1);
328 Rshift += (Rbits - 8);
333 Gshift += (Gbits - 8);
338 Bshift += (Bbits - 8);
341 s->info_imagebpp = bytesperpixel;
342 s->info_imageRloss = 16 + (8 - Rbits);
343 s->info_imageGloss = 8 + (8 - Gbits);
344 s->info_imageBloss = 0 + (8 - Bbits);
345 s->info_imageRmask = (1 << Rbits) - 1;
346 s->info_imageGmask = (1 << Gbits) - 1;
347 s->info_imageBmask = (1 << Bbits) - 1;
348 s->info_imageRshift = Rshift;
349 s->info_imageGshift = Gshift;
350 s->info_imageBshift = Bshift;
351 s->info_imagesize = s->info_imagewidth * s->info_imageheight * s->info_imagebpp;
355 // opening and closing streams
357 static void StripExtension(char *in, char *out)
363 if (*c == ':' || *c == '\\' || *c == '/')
376 memcpy(out, in, dot - in);
382 void *dpvsimpledecode_open(char *filename, char **errorstring)
384 dpvsimpledecodestream_t *s;
385 char t[8], *wavename;
386 if (errorstring != NULL)
388 s = malloc(sizeof(dpvsimpledecodestream_t));
391 s->bitstream = hz_bitstream_read_open(filename);
392 if (s->bitstream != NULL)
394 // check file identification
395 s->framedatablocks = hz_bitstream_read_blocks_new();
396 if (s->framedatablocks != NULL)
398 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
399 hz_bitstream_read_bytes(s->framedatablocks, t, 8);
400 if (!memcmp(t, "DPVideo", 8))
402 // check version number
403 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 2);
404 if (hz_bitstream_read_short(s->framedatablocks) == 1)
406 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 12);
407 s->info_imagewidth = hz_bitstream_read_short(s->framedatablocks);
408 s->info_imageheight = hz_bitstream_read_short(s->framedatablocks);
409 s->info_framerate = (double) hz_bitstream_read_int(s->framedatablocks) * (1.0 / 65536.0);
411 if (s->info_framerate > 0.0)
413 s->videopixels = malloc(s->info_imagewidth * s->info_imageheight * sizeof(*s->videopixels));
414 if (s->videopixels != NULL)
416 wavename = malloc(strlen(filename) + 10);
419 StripExtension(filename, wavename);
420 strcat(wavename, ".wav");
421 s->wavefile = waveopen(wavename, NULL);
425 s->videoframenum = -10000;
428 else if (errorstring != NULL)
429 *errorstring = "unable to allocate video image buffer";
431 else if (errorstring != NULL)
432 *errorstring = "error in video info chunk";
434 else if (errorstring != NULL)
435 *errorstring = "read error";
437 else if (errorstring != NULL)
438 *errorstring = "not a dpvideo file";
439 hz_bitstream_read_blocks_free(s->framedatablocks);
441 else if (errorstring != NULL)
442 *errorstring = "unable to allocate memory for reading buffer";
443 hz_bitstream_read_close(s->bitstream);
445 else if (errorstring != NULL)
446 *errorstring = "unable to open file";
449 else if (errorstring != NULL)
450 *errorstring = "unable to allocate memory for stream info structure";
455 void dpvsimpledecode_close(void *stream)
457 dpvsimpledecodestream_t *s = stream;
461 free(s->videopixels);
463 waveclose(s->wavefile);
464 if (s->framedatablocks)
465 hz_bitstream_read_blocks_free(s->framedatablocks);
467 hz_bitstream_read_close(s->bitstream);
471 // utilitarian functions
473 // returns the current error number for the stream, and resets the error
474 // number to DPVSIMPLEDECODEERROR_NONE
475 // if the supplied string pointer variable is not NULL, it will be set to the
477 int dpvsimpledecode_error(void *stream, char **errorstring)
479 dpvsimpledecodestream_t *s = stream;
487 case DPVSIMPLEDECODEERROR_NONE:
488 *errorstring = "no error";
490 case DPVSIMPLEDECODEERROR_EOF:
491 *errorstring = "end of file reached (this is not an error)";
493 case DPVSIMPLEDECODEERROR_READERROR:
494 *errorstring = "read error (corrupt or incomplete file)";
496 case DPVSIMPLEDECODEERROR_SOUNDBUFFERTOOSMALL:
497 *errorstring = "sound buffer is too small for decoding frame (please allocate it as large as dpvsimpledecode_getneededsoundbufferlength suggests)";
499 case DPVSIMPLEDECODEERROR_INVALIDRMASK:
500 *errorstring = "invalid red bits mask";
502 case DPVSIMPLEDECODEERROR_INVALIDGMASK:
503 *errorstring = "invalid green bits mask";
505 case DPVSIMPLEDECODEERROR_INVALIDBMASK:
506 *errorstring = "invalid blue bits mask";
508 case DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP:
509 *errorstring = "color bit masks overlap";
511 case DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP:
512 *errorstring = "color masks too big for specified bytes per pixel";
514 case DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP:
515 *errorstring = "unsupported bytes per pixel (must be 2 for 16bit, or 4 for 32bit)";
518 *errorstring = "unknown error";
525 // returns the width of the image data
526 unsigned int dpvsimpledecode_getwidth(void *stream)
528 dpvsimpledecodestream_t *s = stream;
529 return s->info_imagewidth;
532 // returns the height of the image data
533 unsigned int dpvsimpledecode_getheight(void *stream)
535 dpvsimpledecodestream_t *s = stream;
536 return s->info_imageheight;
539 // returns the sound sample rate of the stream
540 unsigned int dpvsimpledecode_getsoundrate(void *stream)
542 dpvsimpledecodestream_t *s = stream;
544 return s->wavefile->info_rate;
549 // returns the framerate of the stream
550 double dpvsimpledecode_getframerate(void *stream)
552 dpvsimpledecodestream_t *s = stream;
553 return s->info_framerate;
560 static int dpvsimpledecode_convertpixels(dpvsimpledecodestream_t *s, void *imagedata, int imagebytesperrow)
562 unsigned int a, x, y, width, height;
563 unsigned int Rloss, Rmask, Rshift, Gloss, Gmask, Gshift, Bloss, Bmask, Bshift;
566 width = s->info_imagewidth;
567 height = s->info_imageheight;
569 Rloss = s->info_imageRloss;
570 Rmask = s->info_imageRmask;
571 Rshift = s->info_imageRshift;
572 Gloss = s->info_imageGloss;
573 Gmask = s->info_imageGmask;
574 Gshift = s->info_imageGshift;
575 Bloss = s->info_imageBloss;
576 Bmask = s->info_imageBmask;
577 Bshift = s->info_imageBshift;
580 if (s->info_imagebpp == 4)
582 unsigned int *outrow;
583 for (y = 0;y < height;y++)
585 outrow = (void *)((unsigned char *)imagedata + y * imagebytesperrow);
586 for (x = 0;x < width;x++)
589 outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
595 unsigned short *outrow;
596 for (y = 0;y < height;y++)
598 outrow = (void *)((unsigned char *)imagedata + y * imagebytesperrow);
599 if (Rloss == 19 && Gloss == 10 && Bloss == 3 && Rshift == 11 && Gshift == 5 && Bshift == 0)
602 for (x = 0;x < width;x++)
605 outrow[x] = ((a >> 8) & 0xF800) | ((a >> 5) & 0x07E0) | ((a >> 3) & 0x001F);
610 for (x = 0;x < width;x++)
613 outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
621 static int dpvsimpledecode_decompressimage(dpvsimpledecodestream_t *s)
623 int i, a, b, colors, g, x1, y1, bw, bh, width, height, palettebits;
624 unsigned int palette[256], *outrow, *out;
626 width = s->info_imagewidth;
627 height = s->info_imageheight;
628 for (y1 = 0;y1 < height;y1 += g)
630 outrow = s->videopixels + y1 * width;
632 if (y1 + bh > height)
634 for (x1 = 0;x1 < width;x1 += g)
640 if (hz_bitstream_read_bit(s->framedatablocks))
643 palettebits = hz_bitstream_read_bits(s->framedatablocks, 3);
644 colors = 1 << palettebits;
645 for (i = 0;i < colors;i++)
646 palette[i] = hz_bitstream_read_bits(s->framedatablocks, 24);
649 for (b = 0;b < bh;b++, out += width)
650 for (a = 0;a < bw;a++)
651 out[a] = palette[hz_bitstream_read_bits(s->framedatablocks, palettebits)];
655 for (b = 0;b < bh;b++, out += width)
656 for (a = 0;a < bw;a++)
665 // decodes a video frame to the supplied output pixels
666 int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
668 dpvsimpledecodestream_t *s = stream;
669 unsigned int framedatasize;
671 s->error = DPVSIMPLEDECODEERROR_NONE;
672 if (dpvsimpledecode_setpixelformat(s, Rmask, Gmask, Bmask, bytesperpixel))
675 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
676 hz_bitstream_read_bytes(s->framedatablocks, t, 4);
677 if (memcmp(t, "VID0", 4))
680 return (s->error = DPVSIMPLEDECODEERROR_EOF);
682 return (s->error = DPVSIMPLEDECODEERROR_READERROR);
684 framedatasize = hz_bitstream_read_int(s->framedatablocks);
685 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, framedatasize);
686 if (dpvsimpledecode_decompressimage(s))
689 dpvsimpledecode_convertpixels(s, imagedata, imagebytesperrow);
693 // (note: sound is 16bit stereo native-endian, left channel first)
694 int dpvsimpledecode_audio(void *stream, short *soundbuffer, int requestedlength)
697 dpvsimpledecodestream_t *s = stream;
698 s->error = DPVSIMPLEDECODEERROR_NONE;
702 if (s->wavefile && requestedlength)
703 samples = waveread16stereo(s->wavefile, soundbuffer, requestedlength);
704 if (samples < requestedlength)
705 memset(soundbuffer + samples * 2, 0, (requestedlength - samples) * sizeof(short[2]));