]> git.xonotic.org Git - xonotic/darkplaces.git/blob - dpvsimpledecode.c
cl_main: Delete comment
[xonotic/darkplaces.git] / dpvsimpledecode.c
1 #include "quakedef.h"
2 #include "dpvsimpledecode.h"
3
4 #define HZREADERROR_OK 0
5 #define HZREADERROR_EOF 1
6 #define HZREADERROR_MALLOCFAILED 2
7
8 //#define HZREADBLOCKSIZE 16000
9 #define HZREADBLOCKSIZE 1048576
10
11 typedef struct hz_bitstream_read_s
12 {
13         qfile_t *file;
14         int endoffile;
15 }
16 hz_bitstream_read_t;
17
18 typedef struct hz_bitstream_readblock_s
19 {
20         struct hz_bitstream_readblock_s *next;
21         unsigned int size;
22         unsigned char data[HZREADBLOCKSIZE];
23 }
24 hz_bitstream_readblock_t;
25
26 typedef struct hz_bitstream_readblocks_s
27 {
28         hz_bitstream_readblock_t *blocks;
29         hz_bitstream_readblock_t *current;
30         unsigned int position;
31         unsigned int store;
32         int count;
33 }
34 hz_bitstream_readblocks_t;
35
36 static hz_bitstream_read_t *hz_bitstream_read_open(char *filename)
37 {
38         qfile_t *file;
39         hz_bitstream_read_t *stream;
40         if ((file = FS_OpenVirtualFile(filename, false)))
41         {
42                 stream = (hz_bitstream_read_t *)Z_Malloc(sizeof(hz_bitstream_read_t));
43                 memset(stream, 0, sizeof(*stream));
44                 stream->file = file;
45                 return stream;
46         }
47         else
48                 return NULL;
49 }
50
51 static void hz_bitstream_read_close(hz_bitstream_read_t *stream)
52 {
53         if (stream)
54         {
55                 FS_Close(stream->file);
56                 Z_Free(stream);
57         }
58 }
59
60 static hz_bitstream_readblocks_t *hz_bitstream_read_blocks_new(void)
61 {
62         hz_bitstream_readblocks_t *blocks;
63         blocks = (hz_bitstream_readblocks_t *)Z_Malloc(sizeof(hz_bitstream_readblocks_t));
64         if (blocks == NULL)
65                 return NULL;
66         memset(blocks, 0, sizeof(hz_bitstream_readblocks_t));
67         return blocks;
68 }
69
70 static void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
71 {
72         hz_bitstream_readblock_t *b, *n;
73         if (blocks == NULL)
74                 return;
75         for (b = blocks->blocks;b;b = n)
76         {
77                 n = b->next;
78                 Z_Free(b);
79         }
80         Z_Free(blocks);
81 }
82
83 static void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
84 {
85         blocks->store = 0;
86         blocks->count = 0;
87 }
88
89 static int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
90 {
91         int s;
92         hz_bitstream_readblock_t *b, *p;
93         s = size;
94         p = NULL;
95         b = blocks->blocks;
96         while (s > 0)
97         {
98                 if (b == NULL)
99                 {
100                         b = (hz_bitstream_readblock_t *)Z_Malloc(sizeof(hz_bitstream_readblock_t));
101                         if (b == NULL)
102                                 return HZREADERROR_MALLOCFAILED;
103                         b->next = NULL;
104                         b->size = 0;
105                         if (p != NULL)
106                                 p->next = b;
107                         else
108                                 blocks->blocks = b;
109                 }
110                 if (s > HZREADBLOCKSIZE)
111                         b->size = HZREADBLOCKSIZE;
112                 else
113                         b->size = s;
114                 s -= b->size;
115                 if (FS_Read(stream->file, b->data, b->size) != (fs_offset_t)b->size)
116                 {
117                         stream->endoffile = 1;
118                         break;
119                 }
120                 p = b;
121                 b = b->next;
122         }
123         while (b)
124         {
125                 b->size = 0;
126                 b = b->next;
127         }
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;
134 }
135
136 static unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
137 {
138         while (blocks->current != NULL && blocks->position >= blocks->current->size)
139         {
140                 blocks->position = 0;
141                 blocks->current = blocks->current->next;
142         }
143         if (blocks->current == NULL)
144                 return 0;
145         return blocks->current->data[blocks->position++];
146 }
147
148 static int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
149 {
150         if (!blocks->count)
151         {
152                 blocks->count += 8;
153                 blocks->store <<= 8;
154                 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
155         }
156         blocks->count--;
157         return (blocks->store >> blocks->count) & 1;
158 }
159
160 static unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
161 {
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)
165         if (size > 24)
166         {
167                 size -= 8;
168                 num |= hz_bitstream_read_bits(blocks, 8) << size;
169         }
170         while (blocks->count < size)
171         {
172                 blocks->count += 8;
173                 blocks->store <<= 8;
174                 blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
175         }
176         blocks->count -= size;
177         num |= (blocks->store >> blocks->count) & ((1 << size) - 1);
178         return num;
179 }
180
181 static unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
182 {
183         return hz_bitstream_read_blocks_getbyte(blocks);
184 }
185
186 static unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
187 {
188         return (hz_bitstream_read_byte(blocks) << 8)
189              | (hz_bitstream_read_byte(blocks));
190 }
191
192 static unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
193 {
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));
198 }
199
200 static void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
201 {
202         unsigned char *out;
203         out = (unsigned char *)outdata;
204         while (size--)
205                 *out++ = hz_bitstream_read_byte(blocks);
206 }
207
208 #define BLOCKSIZE 8
209
210 typedef struct dpvsimpledecodestream_s
211 {
212         hz_bitstream_read_t *bitstream;
213         hz_bitstream_readblocks_t *framedatablocks;
214
215         int error;
216
217         double info_framerate;
218         unsigned int info_frames;
219
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;
234
235         // current video frame (needed because of delta compression)
236         int videoframenum;
237         // current video frame data (needed because of delta compression)
238         unsigned int *videopixels;
239
240         // channel the sound file is being played on
241         int sndchan;
242 }
243 dpvsimpledecodestream_t;
244
245 static int dpvsimpledecode_setpixelformat(dpvsimpledecodestream_t *s, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel)
246 {
247         int Rshift, Rbits, Gshift, Gbits, Bshift, Bbits;
248         if (!Rmask)
249         {
250                 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
251                 return s->error;
252         }
253         if (!Gmask)
254         {
255                 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
256                 return s->error;
257         }
258         if (!Bmask)
259         {
260                 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
261                 return s->error;
262         }
263         if (Rmask & Gmask || Rmask & Bmask || Gmask & Bmask)
264         {
265                 s->error = DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP;
266                 return s->error;
267         }
268         switch (bytesperpixel)
269         {
270         case 2:
271                 if ((Rmask | Gmask | Bmask) > 65536)
272                 {
273                         s->error = DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP;
274                         return s->error;
275                 }
276                 break;
277         case 4:
278                 break;
279         default:
280                 s->error = DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP;
281                 return s->error;
282         }
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)
287         {
288                 s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
289                 return s->error;
290         }
291         if (((Gmask + 1) & Gmask) != 0)
292         {
293                 s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
294                 return s->error;
295         }
296         if (((Bmask + 1) & Bmask) != 0)
297         {
298                 s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
299                 return s->error;
300         }
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);
304         if (Rbits > 8)
305         {
306                 Rshift += (Rbits - 8);
307                 Rbits = 8;
308         }
309         if (Gbits > 8)
310         {
311                 Gshift += (Gbits - 8);
312                 Gbits = 8;
313         }
314         if (Bbits > 8)
315         {
316                 Bshift += (Bbits - 8);
317                 Bbits = 8;
318         }
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;
330         return s->error;
331 }
332
333 // opening and closing streams
334
335 // opens a stream
336 void *dpvsimpledecode_open(clvideo_t *video, char *filename, const char **errorstring)
337 {
338         dpvsimpledecodestream_t *s;
339         char t[8], *wavename;
340         if (errorstring != NULL)
341                 *errorstring = NULL;
342         s = (dpvsimpledecodestream_t *)Z_Malloc(sizeof(dpvsimpledecodestream_t));
343         if (s != NULL)
344         {
345                 s->bitstream = hz_bitstream_read_open(filename);
346                 if (s->bitstream != NULL)
347                 {
348                         // check file identification
349                         s->framedatablocks = hz_bitstream_read_blocks_new();
350                         if (s->framedatablocks != NULL)
351                         {
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))
355                                 {
356                                         // check version number
357                                         hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 2);
358                                         if (hz_bitstream_read_short(s->framedatablocks) == 1)
359                                         {
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;
365
366                                                 if (s->info_framerate > 0.0)
367                                                 {
368                                                         s->videopixels = (unsigned int *)Z_Malloc(s->info_imagewidth * s->info_imageheight * sizeof(*s->videopixels));
369                                                         if (s->videopixels != NULL)
370                                                         {
371                                                                 size_t namelen;
372
373                                                                 namelen = strlen(filename) + 10;
374                                                                 wavename = (char *)Z_Malloc(namelen);
375                                                                 if (wavename)
376                                                                 {
377                                                                         sfx_t* sfx;
378
379                                                                         FS_StripExtension(filename, wavename, namelen);
380                                                                         strlcat(wavename, ".wav", namelen);
381                                                                         sfx = S_PrecacheSound (wavename, false, false);
382                                                                         if (sfx != NULL)
383                                                                                 s->sndchan = S_StartSound (-1, 0, sfx, vec3_origin, 1.0f, 0);
384                                                                         else
385                                                                                 s->sndchan = -1;
386                                                                         Z_Free(wavename);
387                                                                 }
388                                                                 // all is well...
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;
397
398                                                                 return s;
399                                                         }
400                                                         else if (errorstring != NULL)
401                                                                 *errorstring = "unable to allocate video image buffer";
402                                                 }
403                                                 else if (errorstring != NULL)
404                                                         *errorstring = "error in video info chunk";
405                                         }
406                                         else if (errorstring != NULL)
407                                                 *errorstring = "read error";
408                                 }
409                                 else if (errorstring != NULL)
410                                         *errorstring = "not a dpvideo file";
411                                 hz_bitstream_read_blocks_free(s->framedatablocks);
412                         }
413                         else if (errorstring != NULL)
414                                 *errorstring = "unable to allocate memory for reading buffer";
415                         hz_bitstream_read_close(s->bitstream);
416                 }
417                 else if (errorstring != NULL)
418                         *errorstring = "unable to open file";
419                 Z_Free(s);
420         }
421         else if (errorstring != NULL)
422                 *errorstring = "unable to allocate memory for stream info structure";
423         return NULL;
424 }
425
426 // closes a stream
427 void dpvsimpledecode_close(void *stream)
428 {
429         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
430         if (s == NULL)
431                 return;
432         if (s->videopixels)
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);
438         if (s->bitstream)
439                 hz_bitstream_read_close(s->bitstream);
440         Z_Free(s);
441 }
442
443 // utilitarian functions
444
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
448 // error message
449 int dpvsimpledecode_error(void *stream, const char **errorstring)
450 {
451         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
452         int e;
453         e = s->error;
454         s->error = 0;
455         if (errorstring)
456         {
457                 switch (e)
458                 {
459                         case DPVSIMPLEDECODEERROR_NONE:
460                                 *errorstring = "no error";
461                                 break;
462                         case DPVSIMPLEDECODEERROR_EOF:
463                                 *errorstring = "end of file reached (this is not an error)";
464                                 break;
465                         case DPVSIMPLEDECODEERROR_READERROR:
466                                 *errorstring = "read error (corrupt or incomplete file)";
467                                 break;
468                         case DPVSIMPLEDECODEERROR_SOUNDBUFFERTOOSMALL:
469                                 *errorstring = "sound buffer is too small for decoding frame (please allocate it as large as dpvsimpledecode_getneededsoundbufferlength suggests)";
470                                 break;
471                         case DPVSIMPLEDECODEERROR_INVALIDRMASK:
472                                 *errorstring = "invalid red bits mask";
473                                 break;
474                         case DPVSIMPLEDECODEERROR_INVALIDGMASK:
475                                 *errorstring = "invalid green bits mask";
476                                 break;
477                         case DPVSIMPLEDECODEERROR_INVALIDBMASK:
478                                 *errorstring = "invalid blue bits mask";
479                                 break;
480                         case DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP:
481                                 *errorstring = "color bit masks overlap";
482                                 break;
483                         case DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP:
484                                 *errorstring = "color masks too big for specified bytes per pixel";
485                                 break;
486                         case DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP:
487                                 *errorstring = "unsupported bytes per pixel (must be 2 for 16bit, or 4 for 32bit)";
488                                 break;
489                         default:
490                                 *errorstring = "unknown error";
491                                 break;
492                 }
493         }
494         return e;
495 }
496
497 // returns the width of the image data
498 unsigned int dpvsimpledecode_getwidth(void *stream)
499 {
500         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
501         return s->info_imagewidth;
502 }
503
504 // returns the height of the image data
505 unsigned int dpvsimpledecode_getheight(void *stream)
506 {
507         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
508         return s->info_imageheight;
509 }
510
511 // returns the framerate of the stream
512 double dpvsimpledecode_getframerate(void *stream)
513 {
514         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
515         return s->info_framerate;
516 }
517
518 // return aspect ratio of the stream
519 double dpvsimpledecode_getaspectratio(void *stream)
520 {
521         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
522         return s->info_aspectratio;
523 }
524
525 static int dpvsimpledecode_convertpixels(dpvsimpledecodestream_t *s, void *imagedata, int imagebytesperrow)
526 {
527         unsigned int a, x, y, width, height;
528         unsigned int Rloss, Rmask, Rshift, Gloss, Gmask, Gshift, Bloss, Bmask, Bshift;
529         unsigned int *in;
530
531         width = s->info_imagewidth;
532         height = s->info_imageheight;
533
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;
543
544         in = s->videopixels;
545         if (s->info_imagebpp == 4)
546         {
547                 unsigned int *outrow;
548                 for (y = 0;y < height;y++)
549                 {
550                         outrow = (unsigned int *)((unsigned char *)imagedata + y * imagebytesperrow);
551                         for (x = 0;x < width;x++)
552                         {
553                                 a = *in++;
554                                 outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
555                         }
556                 }
557         }
558         else
559         {
560                 unsigned short *outrow;
561                 for (y = 0;y < height;y++)
562                 {
563                         outrow = (unsigned short *)((unsigned char *)imagedata + y * imagebytesperrow);
564                         if (Rloss == 19 && Gloss == 10 && Bloss == 3 && Rshift == 11 && Gshift == 5 && Bshift == 0)
565                         {
566                                 // optimized
567                                 for (x = 0;x < width;x++)
568                                 {
569                                         a = *in++;
570                                         outrow[x] = ((a >> 8) & 0xF800) | ((a >> 5) & 0x07E0) | ((a >> 3) & 0x001F);
571                                 }
572                         }
573                         else
574                         {
575                                 for (x = 0;x < width;x++)
576                                 {
577                                         a = *in++;
578                                         outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
579                                 }
580                         }
581                 }
582         }
583         return s->error;
584 }
585
586 static int dpvsimpledecode_decompressimage(dpvsimpledecodestream_t *s)
587 {
588         int i, a, b, colors, g, x1, y1, bw, bh, width, height, palettebits;
589         unsigned int palette[256], *outrow, *out;
590         g = BLOCKSIZE;
591         width = s->info_imagewidth;
592         height = s->info_imageheight;
593         for (y1 = 0;y1 < height;y1 += g)
594         {
595                 outrow = s->videopixels + y1 * width;
596                 bh = g;
597                 if (y1 + bh > height)
598                         bh = height - y1;
599                 for (x1 = 0;x1 < width;x1 += g)
600                 {
601                         out = outrow + x1;
602                         bw = g;
603                         if (x1 + bw > width)
604                                 bw = width - x1;
605                         if (hz_bitstream_read_bit(s->framedatablocks))
606                         {
607                                 // updated block
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);
612                                 if (palettebits)
613                                 {
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)];
617                                 }
618                                 else
619                                 {
620                                         for (b = 0;b < bh;b++, out += width)
621                                                 for (a = 0;a < bw;a++)
622                                                         out[a] = palette[0];
623                                 }
624                         }
625                 }
626         }
627         return s->error;
628 }
629
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)
632 {
633         dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
634         unsigned int framedatasize;
635         char t[4];
636         s->error = DPVSIMPLEDECODEERROR_NONE;
637         if (dpvsimpledecode_setpixelformat(s, Rmask, Gmask, Bmask, bytesperpixel))
638                 return s->error;
639
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))
643         {
644                 if (t[0] == 0)
645                         return (s->error = DPVSIMPLEDECODEERROR_EOF);
646                 else
647                         return (s->error = DPVSIMPLEDECODEERROR_READERROR);
648         }
649         framedatasize = hz_bitstream_read_int(s->framedatablocks);
650         hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, framedatasize);
651         if (dpvsimpledecode_decompressimage(s))
652                 return s->error;
653
654         dpvsimpledecode_convertpixels(s, imagedata, imagebytesperrow);
655         return s->error;
656 }