]> git.xonotic.org Git - xonotic/darkplaces.git/blob - dpvsimpledecode.c
Merge PR 'Make particles solid squares when cl_particles_quake is set to 2'
[xonotic/darkplaces.git] / dpvsimpledecode.c
1 /*
2 Copyright (C) 2002-2013 DarkPlaces contributors
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 the Free Software
17 Foundation, 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
31 typedef struct hz_bitstream_read_s
32 {
33         qfile_t *file;
34         int endoffile;
35 }
36 hz_bitstream_read_t;
37
38 typedef struct hz_bitstream_readblock_s
39 {
40         struct hz_bitstream_readblock_s *next;
41         unsigned int size;
42         unsigned char data[HZREADBLOCKSIZE];
43 }
44 hz_bitstream_readblock_t;
45
46 typedef struct hz_bitstream_readblocks_s
47 {
48         hz_bitstream_readblock_t *blocks;
49         hz_bitstream_readblock_t *current;
50         unsigned int position;
51         unsigned int store;
52         int count;
53 }
54 hz_bitstream_readblocks_t;
55
56 static hz_bitstream_read_t *hz_bitstream_read_open(char *filename)
57 {
58         qfile_t *file;
59         hz_bitstream_read_t *stream;
60         if ((file = FS_OpenVirtualFile(filename, false)))
61         {
62                 stream = (hz_bitstream_read_t *)Z_Malloc(sizeof(hz_bitstream_read_t));
63                 memset(stream, 0, sizeof(*stream));
64                 stream->file = file;
65                 return stream;
66         }
67         else
68                 return NULL;
69 }
70
71 static void hz_bitstream_read_close(hz_bitstream_read_t *stream)
72 {
73         if (stream)
74         {
75                 FS_Close(stream->file);
76                 Z_Free(stream);
77         }
78 }
79
80 static hz_bitstream_readblocks_t *hz_bitstream_read_blocks_new(void)
81 {
82         hz_bitstream_readblocks_t *blocks;
83         blocks = (hz_bitstream_readblocks_t *)Z_Malloc(sizeof(hz_bitstream_readblocks_t));
84         if (blocks == NULL)
85                 return NULL;
86         memset(blocks, 0, sizeof(hz_bitstream_readblocks_t));
87         return blocks;
88 }
89
90 static void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
91 {
92         hz_bitstream_readblock_t *b, *n;
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
103 static void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
104 {
105         blocks->store = 0;
106         blocks->count = 0;
107 }
108
109 static int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
110 {
111         int s;
112         hz_bitstream_readblock_t *b, *p;
113         s = size;
114         p = NULL;
115         b = blocks->blocks;
116         while (s > 0)
117         {
118                 if (b == NULL)
119                 {
120                         b = (hz_bitstream_readblock_t *)Z_Malloc(sizeof(hz_bitstream_readblock_t));
121                         if (b == NULL)
122                                 return HZREADERROR_MALLOCFAILED;
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;
150         hz_bitstream_read_flushbits(blocks);
151         if (stream->endoffile)
152                 return HZREADERROR_EOF;
153         return HZREADERROR_OK;
154 }
155
156 static unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
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
168 static int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
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
180 static unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
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
201 static unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
202 {
203         return hz_bitstream_read_blocks_getbyte(blocks);
204 }
205
206 static unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
207 {
208         return (hz_bitstream_read_byte(blocks) << 8)
209              | (hz_bitstream_read_byte(blocks));
210 }
211
212 static unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
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
220 static 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
230 typedef struct dpvsimpledecodestream_s
231 {
232         hz_bitstream_read_t *bitstream;
233         hz_bitstream_readblocks_t *framedatablocks;
234
235         int error;
236
237         double info_framerate;
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;
253         double info_aspectratio;
254
255         // current video frame (needed because of delta compression)
256         int videoframenum;
257         // current video frame data (needed because of delta compression)
258         unsigned int *videopixels;
259
260         // channel the sound file is being played on
261         int sndchan;
262 }
263 dpvsimpledecodestream_t;
264
265 static 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         {
270                 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
271                 return s->error;
272         }
273         if (!Gmask)
274         {
275                 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
276                 return s->error;
277         }
278         if (!Bmask)
279         {
280                 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
281                 return s->error;
282         }
283         if (Rmask & Gmask || Rmask & Bmask || Gmask & Bmask)
284         {
285                 s->error = DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP;
286                 return s->error;
287         }
288         switch (bytesperpixel)
289         {
290         case 2:
291                 if ((Rmask | Gmask | Bmask) > 65536)
292                 {
293                         s->error = DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP;
294                         return s->error;
295                 }
296                 break;
297         case 4:
298                 break;
299         default:
300                 s->error = DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP;
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         {
308                 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
309                 return s->error;
310         }
311         if (((Gmask + 1) & Gmask) != 0)
312         {
313                 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
314                 return s->error;
315         }
316         if (((Bmask + 1) & Bmask) != 0)
317         {
318                 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
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;
349         s->info_imagesize = s->info_imagewidth * s->info_imageheight * s->info_imagebpp;
350         return s->error;
351 }
352
353 // opening and closing streams
354
355 // opens a stream
356 void *dpvsimpledecode_open(clvideo_t *video, char *filename, const char **errorstring)
357 {
358         dpvsimpledecodestream_t *s;
359         char t[8], *wavename;
360         if (errorstring != NULL)
361                 *errorstring = NULL;
362         s = (dpvsimpledecodestream_t *)Z_Malloc(sizeof(dpvsimpledecodestream_t));
363         if (s != NULL)
364         {
365                 s->bitstream = hz_bitstream_read_open(filename);
366                 if (s->bitstream != NULL)
367                 {
368                         // check file identification
369                         s->framedatablocks = hz_bitstream_read_blocks_new();
370                         if (s->framedatablocks != NULL)
371                         {
372                                 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
373                                 hz_bitstream_read_bytes(s->framedatablocks, t, 8);
374                                 if (!memcmp(t, "DPVideo", 8))
375                                 {
376                                         // check version number
377                                         hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 2);
378                                         if (hz_bitstream_read_short(s->framedatablocks) == 1)
379                                         {
380                                                 hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 12);
381                                                 s->info_imagewidth = hz_bitstream_read_short(s->framedatablocks);
382                                                 s->info_imageheight = hz_bitstream_read_short(s->framedatablocks);
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                                                                         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;
411                                                                 video->close = dpvsimpledecode_close;
412                                                                 video->getwidth = dpvsimpledecode_getwidth;
413                                                                 video->getheight = dpvsimpledecode_getheight;
414                                                                 video->getframerate = dpvsimpledecode_getframerate;
415                                                                 video->decodeframe = dpvsimpledecode_video;
416                                                                 video->getaspectratio = dpvsimpledecode_getaspectratio;
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";
431                                 hz_bitstream_read_blocks_free(s->framedatablocks);
432                         }
433                         else if (errorstring != NULL)
434                                 *errorstring = "unable to allocate memory for reading buffer";
435                         hz_bitstream_read_close(s->bitstream);
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
447 void dpvsimpledecode_close(void *stream)
448 {
449         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
450         if (s == NULL)
451                 return;
452         if (s->videopixels)
453                 Z_Free(s->videopixels);
454         if (s->sndchan != -1)
455                 S_StopChannel (s->sndchan, true, true);
456         if (s->framedatablocks)
457                 hz_bitstream_read_blocks_free(s->framedatablocks);
458         if (s->bitstream)
459                 hz_bitstream_read_close(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
469 int dpvsimpledecode_error(void *stream, const char **errorstring)
470 {
471         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
472         int e;
473         e = s->error;
474         s->error = 0;
475         if (errorstring)
476         {
477                 switch (e)
478                 {
479                         case DPVSIMPLEDECODEERROR_NONE:
480                                 *errorstring = "no error";
481                                 break;
482                         case DPVSIMPLEDECODEERROR_EOF:
483                                 *errorstring = "end of file reached (this is not an error)";
484                                 break;
485                         case DPVSIMPLEDECODEERROR_READERROR:
486                                 *errorstring = "read error (corrupt or incomplete file)";
487                                 break;
488                         case DPVSIMPLEDECODEERROR_SOUNDBUFFERTOOSMALL:
489                                 *errorstring = "sound buffer is too small for decoding frame (please allocate it as large as dpvsimpledecode_getneededsoundbufferlength suggests)";
490                                 break;
491                         case DPVSIMPLEDECODEERROR_INVALIDRMASK:
492                                 *errorstring = "invalid red bits mask";
493                                 break;
494                         case DPVSIMPLEDECODEERROR_INVALIDGMASK:
495                                 *errorstring = "invalid green bits mask";
496                                 break;
497                         case DPVSIMPLEDECODEERROR_INVALIDBMASK:
498                                 *errorstring = "invalid blue bits mask";
499                                 break;
500                         case DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP:
501                                 *errorstring = "color bit masks overlap";
502                                 break;
503                         case DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP:
504                                 *errorstring = "color masks too big for specified bytes per pixel";
505                                 break;
506                         case DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP:
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
518 unsigned int dpvsimpledecode_getwidth(void *stream)
519 {
520         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
521         return s->info_imagewidth;
522 }
523
524 // returns the height of the image data
525 unsigned int dpvsimpledecode_getheight(void *stream)
526 {
527         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
528         return s->info_imageheight;
529 }
530
531 // returns the framerate of the stream
532 double dpvsimpledecode_getframerate(void *stream)
533 {
534         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
535         return s->info_framerate;
536 }
537
538 // return aspect ratio of the stream
539 double dpvsimpledecode_getaspectratio(void *stream)
540 {
541         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
542         return s->info_aspectratio;
543 }
544
545 static 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
551         width = s->info_imagewidth;
552         height = s->info_imageheight;
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
606 static int dpvsimpledecode_decompressimage(dpvsimpledecodestream_t *s)
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;
611         width = s->info_imagewidth;
612         height = s->info_imageheight;
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;
625                         if (hz_bitstream_read_bit(s->framedatablocks))
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
651 int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
652 {
653         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
654         unsigned int framedatasize;
655         char t[4];
656         s->error = DPVSIMPLEDECODEERROR_NONE;
657         if (dpvsimpledecode_setpixelformat(s, Rmask, Gmask, Bmask, bytesperpixel))
658                 return s->error;
659
660         hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
661         hz_bitstream_read_bytes(s->framedatablocks, t, 4);
662         if (memcmp(t, "VID0", 4))
663         {
664                 if (t[0] == 0)
665                         return (s->error = DPVSIMPLEDECODEERROR_EOF);
666                 else
667                         return (s->error = DPVSIMPLEDECODEERROR_READERROR);
668         }
669         framedatasize = hz_bitstream_read_int(s->framedatablocks);
670         hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, framedatasize);
671         if (dpvsimpledecode_decompressimage(s))
672                 return s->error;
673
674         dpvsimpledecode_convertpixels(s, imagedata, imagebytesperrow);
675         return s->error;
676 }