Mercurial > mplayer.hg
comparison cinepak.c @ 3643:fb9fd7e2dd35
native opensourec Cinepak (CVID) codec by im Ferguson <timf@mail.csse.monash.edu.au>
author | arpi |
---|---|
date | Fri, 21 Dec 2001 16:39:54 +0000 |
parents | |
children | 3f25f07f4e92 |
comparison
equal
deleted
inserted
replaced
3642:2cef9d562af0 | 3643:fb9fd7e2dd35 |
---|---|
1 /* ------------------------------------------------------------------------ | |
2 * Radius Cinepak Video Decoder | |
3 * | |
4 * Dr. Tim Ferguson, 2001. | |
5 * For more details on the algorithm: | |
6 * http://www.csse.monash.edu.au/~timf/videocodec.html | |
7 * | |
8 * This is basically a vector quantiser with adaptive vector density. The | |
9 * frame is segmented into 4x4 pixel blocks, and each block is coded using | |
10 * either 1 or 4 vectors. | |
11 * | |
12 * There are still some issues with this code yet to be resolved. In | |
13 * particular with decoding in the strip boundaries. | |
14 * ------------------------------------------------------------------------ */ | |
15 #include <stdio.h> | |
16 #include <stdlib.h> | |
17 #include <string.h> | |
18 #include <sys/types.h> | |
19 #include <unistd.h> | |
20 #include <math.h> | |
21 | |
22 #include "config.h" | |
23 | |
24 #define DBUG 0 | |
25 #define MAX_STRIPS 32 | |
26 | |
27 /* ------------------------------------------------------------------------ */ | |
28 typedef struct | |
29 { | |
30 unsigned char y0, y1, y2, y3; | |
31 char u, v; | |
32 unsigned long rgb0, rgb1, rgb2, rgb3; /* should be a union */ | |
33 unsigned char r[4], g[4], b[4]; | |
34 } cvid_codebook; | |
35 | |
36 typedef struct { | |
37 cvid_codebook *v4_codebook[MAX_STRIPS]; | |
38 cvid_codebook *v1_codebook[MAX_STRIPS]; | |
39 int strip_num; | |
40 } cinepak_info; | |
41 | |
42 | |
43 /* ------------------------------------------------------------------------ */ | |
44 static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL; | |
45 | |
46 #define get_byte() *(in_buffer++) | |
47 #define skip_byte() in_buffer++ | |
48 #define get_word() ((unsigned short)(in_buffer += 2, \ | |
49 (in_buffer[-2] << 8 | in_buffer[-1]))) | |
50 #define get_long() ((unsigned long)(in_buffer += 4, \ | |
51 (in_buffer[-4] << 24 | in_buffer[-3] << 16 | in_buffer[-2] << 8 | in_buffer[-1]))) | |
52 | |
53 | |
54 /* ---------------------------------------------------------------------- */ | |
55 static inline void read_codebook_32(cvid_codebook *c, int mode) | |
56 { | |
57 int uvr, uvg, uvb; | |
58 | |
59 if(mode) /* black and white */ | |
60 { | |
61 c->y0 = get_byte(); | |
62 c->y1 = get_byte(); | |
63 c->y2 = get_byte(); | |
64 c->y3 = get_byte(); | |
65 c->u = c->v = 0; | |
66 | |
67 c->rgb0 = (c->y0 << 16) | (c->y0 << 8) | c->y0; | |
68 c->rgb1 = (c->y1 << 16) | (c->y1 << 8) | c->y1; | |
69 c->rgb2 = (c->y2 << 16) | (c->y2 << 8) | c->y2; | |
70 c->rgb3 = (c->y3 << 16) | (c->y3 << 8) | c->y3; | |
71 } | |
72 else /* colour */ | |
73 { | |
74 c->y0 = get_byte(); /* luma */ | |
75 c->y1 = get_byte(); | |
76 c->y2 = get_byte(); | |
77 c->y3 = get_byte(); | |
78 c->u = get_byte(); /* chroma */ | |
79 c->v = get_byte(); | |
80 | |
81 uvr = c->v << 1; | |
82 uvg = -((c->u+1) >> 1) - c->v; | |
83 uvb = c->u << 1; | |
84 | |
85 c->rgb0 = (uiclp[c->y0 + uvr] << 16) | (uiclp[c->y0 + uvg] << 8) | uiclp[c->y0 + uvb]; | |
86 c->rgb1 = (uiclp[c->y1 + uvr] << 16) | (uiclp[c->y1 + uvg] << 8) | uiclp[c->y1 + uvb]; | |
87 c->rgb2 = (uiclp[c->y2 + uvr] << 16) | (uiclp[c->y2 + uvg] << 8) | uiclp[c->y2 + uvb]; | |
88 c->rgb3 = (uiclp[c->y3 + uvr] << 16) | (uiclp[c->y3 + uvg] << 8) | uiclp[c->y3 + uvb]; | |
89 } | |
90 } | |
91 | |
92 | |
93 /* ------------------------------------------------------------------------ */ | |
94 inline void cvid_v1_32(unsigned char *frm, unsigned char *end, int stride, cvid_codebook *cb) | |
95 { | |
96 unsigned long *vptr = (unsigned long *)frm, rgb; | |
97 int row_inc = stride/4; | |
98 | |
99 vptr[0] = rgb = cb->rgb0; vptr[1] = rgb; | |
100 vptr[2] = rgb = cb->rgb1; vptr[3] = rgb; | |
101 vptr += row_inc; if(vptr > (unsigned long *)end) return; | |
102 vptr[0] = rgb = cb->rgb0; vptr[1] = rgb; | |
103 vptr[2] = rgb = cb->rgb1; vptr[3] = rgb; | |
104 vptr += row_inc; if(vptr > (unsigned long *)end) return; | |
105 vptr[0] = rgb = cb->rgb2; vptr[1] = rgb; | |
106 vptr[2] = rgb = cb->rgb3; vptr[3] = rgb; | |
107 vptr += row_inc; if(vptr > (unsigned long *)end) return; | |
108 vptr[0] = rgb = cb->rgb2; vptr[1] = rgb; | |
109 vptr[2] = rgb = cb->rgb3; vptr[3] = rgb; | |
110 } | |
111 | |
112 | |
113 /* ------------------------------------------------------------------------ */ | |
114 inline void cvid_v4_32(unsigned char *frm, unsigned char *end, int stride, cvid_codebook *cb0, | |
115 cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) | |
116 { | |
117 unsigned long *vptr = (unsigned long *)frm; | |
118 int row_inc = stride/4; | |
119 | |
120 vptr[0] = cb0->rgb0; | |
121 vptr[1] = cb0->rgb1; | |
122 vptr[2] = cb1->rgb0; | |
123 vptr[3] = cb1->rgb1; | |
124 vptr += row_inc; if(vptr > (unsigned long *)end) return; | |
125 vptr[0] = cb0->rgb2; | |
126 vptr[1] = cb0->rgb3; | |
127 vptr[2] = cb1->rgb2; | |
128 vptr[3] = cb1->rgb3; | |
129 vptr += row_inc; if(vptr > (unsigned long *)end) return; | |
130 vptr[0] = cb2->rgb0; | |
131 vptr[1] = cb2->rgb1; | |
132 vptr[2] = cb3->rgb0; | |
133 vptr[3] = cb3->rgb1; | |
134 vptr += row_inc; if(vptr > (unsigned long *)end) return; | |
135 vptr[0] = cb2->rgb2; | |
136 vptr[1] = cb2->rgb3; | |
137 vptr[2] = cb3->rgb2; | |
138 vptr[3] = cb3->rgb3; | |
139 } | |
140 | |
141 | |
142 /* ---------------------------------------------------------------------- */ | |
143 static inline void read_codebook_24(cvid_codebook *c, int mode) | |
144 { | |
145 int uvr, uvg, uvb; | |
146 | |
147 if(mode) /* black and white */ | |
148 { | |
149 c->y0 = get_byte(); | |
150 c->y1 = get_byte(); | |
151 c->y2 = get_byte(); | |
152 c->y3 = get_byte(); | |
153 c->u = c->v = 0; | |
154 | |
155 c->r[0] = c->g[0] = c->b[0] = c->y0; | |
156 c->r[1] = c->g[1] = c->b[1] = c->y1; | |
157 c->r[2] = c->g[2] = c->b[2] = c->y2; | |
158 c->r[3] = c->g[3] = c->b[3] = c->y3; | |
159 } | |
160 else /* colour */ | |
161 { | |
162 c->y0 = get_byte(); /* luma */ | |
163 c->y1 = get_byte(); | |
164 c->y2 = get_byte(); | |
165 c->y3 = get_byte(); | |
166 c->u = get_byte(); /* chroma */ | |
167 c->v = get_byte(); | |
168 | |
169 uvr = c->v << 1; | |
170 uvg = -((c->u+1) >> 1) - c->v; | |
171 uvb = c->u << 1; | |
172 | |
173 c->r[0] = uiclp[c->y0 + uvr]; c->g[0] = uiclp[c->y0 + uvg]; c->b[0] = uiclp[c->y0 + uvb]; | |
174 c->r[1] = uiclp[c->y1 + uvr]; c->g[1] = uiclp[c->y1 + uvg]; c->b[1] = uiclp[c->y1 + uvb]; | |
175 c->r[2] = uiclp[c->y2 + uvr]; c->g[2] = uiclp[c->y2 + uvg]; c->b[2] = uiclp[c->y2 + uvb]; | |
176 c->r[3] = uiclp[c->y3 + uvr]; c->g[3] = uiclp[c->y3 + uvg]; c->b[3] = uiclp[c->y3 + uvb]; | |
177 } | |
178 } | |
179 | |
180 | |
181 /* ------------------------------------------------------------------------ */ | |
182 void cvid_v1_24(unsigned char *vptr, unsigned char *end, int stride, cvid_codebook *cb) | |
183 { | |
184 unsigned char r, g, b; | |
185 int row_inc = stride-4*3; | |
186 | |
187 *vptr++ = b = cb->b[0]; *vptr++ = g = cb->g[0]; *vptr++ = r = cb->r[0]; | |
188 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
189 *vptr++ = b = cb->b[1]; *vptr++ = g = cb->g[1]; *vptr++ = r = cb->r[1]; | |
190 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
191 vptr += row_inc; if(vptr > end) return; | |
192 *vptr++ = b = cb->b[0]; *vptr++ = g = cb->g[0]; *vptr++ = r = cb->r[0]; | |
193 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
194 *vptr++ = b = cb->b[1]; *vptr++ = g = cb->g[1]; *vptr++ = r = cb->r[1]; | |
195 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
196 vptr += row_inc; if(vptr > end) return; | |
197 *vptr++ = b = cb->b[2]; *vptr++ = g = cb->g[2]; *vptr++ = r = cb->r[2]; | |
198 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
199 *vptr++ = b = cb->b[3]; *vptr++ = g = cb->g[3]; *vptr++ = r = cb->r[3]; | |
200 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
201 vptr += row_inc; if(vptr > end) return; | |
202 *vptr++ = b = cb->b[2]; *vptr++ = g = cb->g[2]; *vptr++ = r = cb->r[2]; | |
203 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
204 *vptr++ = b = cb->b[3]; *vptr++ = g = cb->g[3]; *vptr++ = r = cb->r[3]; | |
205 *vptr++ = b; *vptr++ = g; *vptr++ = r; | |
206 } | |
207 | |
208 | |
209 /* ------------------------------------------------------------------------ */ | |
210 void cvid_v4_24(unsigned char *vptr, unsigned char *end, int stride, cvid_codebook *cb0, | |
211 cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) | |
212 { | |
213 int row_inc = stride-4*3; | |
214 | |
215 *vptr++ = cb0->b[0]; *vptr++ = cb0->g[0]; *vptr++ = cb0->r[0]; | |
216 *vptr++ = cb0->b[1]; *vptr++ = cb0->g[1]; *vptr++ = cb0->r[1]; | |
217 *vptr++ = cb1->b[0]; *vptr++ = cb1->g[0]; *vptr++ = cb1->r[0]; | |
218 *vptr++ = cb1->b[1]; *vptr++ = cb1->g[1]; *vptr++ = cb1->r[1]; | |
219 vptr += row_inc; if(vptr > end) return; | |
220 *vptr++ = cb0->b[2]; *vptr++ = cb0->g[2]; *vptr++ = cb0->r[2]; | |
221 *vptr++ = cb0->b[3]; *vptr++ = cb0->g[3]; *vptr++ = cb0->r[3]; | |
222 *vptr++ = cb1->b[2]; *vptr++ = cb1->g[2]; *vptr++ = cb1->r[2]; | |
223 *vptr++ = cb1->b[3]; *vptr++ = cb1->g[3]; *vptr++ = cb1->r[3]; | |
224 vptr += row_inc; if(vptr > end) return; | |
225 *vptr++ = cb2->b[0]; *vptr++ = cb2->g[0]; *vptr++ = cb2->r[0]; | |
226 *vptr++ = cb2->b[1]; *vptr++ = cb2->g[1]; *vptr++ = cb2->r[1]; | |
227 *vptr++ = cb3->b[0]; *vptr++ = cb3->g[0]; *vptr++ = cb3->r[0]; | |
228 *vptr++ = cb3->b[1]; *vptr++ = cb3->g[1]; *vptr++ = cb3->r[1]; | |
229 vptr += row_inc; if(vptr > end) return; | |
230 *vptr++ = cb2->b[2]; *vptr++ = cb2->g[2]; *vptr++ = cb2->r[2]; | |
231 *vptr++ = cb2->b[3]; *vptr++ = cb2->g[3]; *vptr++ = cb2->r[3]; | |
232 *vptr++ = cb3->b[2]; *vptr++ = cb3->g[2]; *vptr++ = cb3->r[2]; | |
233 *vptr++ = cb3->b[3]; *vptr++ = cb3->g[3]; *vptr++ = cb3->r[3]; | |
234 } | |
235 | |
236 | |
237 /* ------------------------------------------------------------------------ | |
238 * Call this function once at the start of the sequence and save the | |
239 * returned context for calls to decode_cinepak(). | |
240 */ | |
241 void *decode_cinepak_init(void) | |
242 { | |
243 cinepak_info *cvinfo; | |
244 int i; | |
245 | |
246 if((cvinfo = calloc(sizeof(cinepak_info), 1)) == NULL) return NULL; | |
247 cvinfo->strip_num = 0; | |
248 | |
249 if(uiclp == NULL) | |
250 { | |
251 uiclp = uiclip+512; | |
252 for(i = -512; i < 512; i++) | |
253 uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i)); | |
254 } | |
255 | |
256 return (void *)cvinfo; | |
257 } | |
258 | |
259 | |
260 /* ------------------------------------------------------------------------ | |
261 * This function decodes a buffer containing a Cinepak encoded frame. | |
262 * | |
263 * context - the context created by decode_cinepak_init(). | |
264 * buf - the input buffer to be decoded | |
265 * size - the size of the input buffer | |
266 * frame - the output frame buffer (24 or 32 bit per pixel) | |
267 * width - the width of the output frame | |
268 * height - the height of the output frame | |
269 * bit_per_pixel - the number of bits per pixel allocated to the output | |
270 * frame (only 24 or 32 bpp are supported) | |
271 */ | |
272 void decode_cinepak(void *context, unsigned char *buf, int size, unsigned char *frame, int width, int height, int bit_per_pixel) | |
273 { | |
274 cinepak_info *cvinfo = (cinepak_info *)context; | |
275 cvid_codebook *v4_codebook, *v1_codebook, *codebook = NULL; | |
276 unsigned long x, y, y_bottom, frame_flags, strips, cv_width, cv_height, cnum, | |
277 strip_id, chunk_id, x0, y0, x1, y1, ci, flag, mask; | |
278 long len, top_size, chunk_size; | |
279 unsigned char *frm_ptr, *frm_end; | |
280 int i, cur_strip, d0, d1, d2, d3, frm_stride, bpp = 3; | |
281 void (*read_codebook)(cvid_codebook *c, int mode) = read_codebook_24; | |
282 void (*cvid_v1)(unsigned char *frm, unsigned char *end, int stride, cvid_codebook *cb) = cvid_v1_24; | |
283 void (*cvid_v4)(unsigned char *frm, unsigned char *end, int stride, cvid_codebook *cb0, | |
284 cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) = cvid_v4_24; | |
285 | |
286 x = y = 0; | |
287 y_bottom = 0; | |
288 in_buffer = buf; | |
289 | |
290 frame_flags = get_byte(); | |
291 len = get_byte() << 16; | |
292 len |= get_byte() << 8; | |
293 len |= get_byte(); | |
294 | |
295 switch(bit_per_pixel) | |
296 { | |
297 case 24: | |
298 bpp = 3; | |
299 read_codebook = read_codebook_24; | |
300 cvid_v1 = cvid_v1_24; | |
301 cvid_v4 = cvid_v4_24; | |
302 break; | |
303 case 32: | |
304 bpp = 4; | |
305 read_codebook = read_codebook_32; | |
306 cvid_v1 = cvid_v1_32; | |
307 cvid_v4 = cvid_v4_32; | |
308 break; | |
309 } | |
310 | |
311 frm_stride = width * bpp; | |
312 frm_ptr = frame; | |
313 frm_end = frm_ptr + width * height * bpp; | |
314 | |
315 if(len != size) | |
316 { | |
317 if(len & 0x01) len++; /* AVIs tend to have a size mismatch */ | |
318 if(len != size) | |
319 { | |
320 printf("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, len); | |
321 // return; | |
322 } | |
323 } | |
324 | |
325 cv_width = get_word(); | |
326 cv_height = get_word(); | |
327 strips = get_word(); | |
328 | |
329 if(strips > cvinfo->strip_num) | |
330 { | |
331 if(strips >= MAX_STRIPS) | |
332 { | |
333 printf("CVID: strip overflow (more than %d)\n", MAX_STRIPS); | |
334 return; | |
335 } | |
336 | |
337 for(i = cvinfo->strip_num; i < strips; i++) | |
338 { | |
339 if((cvinfo->v4_codebook[i] = (cvid_codebook *)calloc(sizeof(cvid_codebook), 260)) == NULL) | |
340 { | |
341 printf("CVID: codebook v4 alloc err\n"); | |
342 return; | |
343 } | |
344 | |
345 if((cvinfo->v1_codebook[i] = (cvid_codebook *)calloc(sizeof(cvid_codebook), 260)) == NULL) | |
346 { | |
347 printf("CVID: codebook v1 alloc err\n"); | |
348 return; | |
349 } | |
350 } | |
351 } | |
352 cvinfo->strip_num = strips; | |
353 | |
354 #if DBUG | |
355 printf("CVID: <%ld,%ld> strips %ld\n", cv_width, cv_height, strips); | |
356 #endif | |
357 | |
358 for(cur_strip = 0; cur_strip < strips; cur_strip++) | |
359 { | |
360 v4_codebook = cvinfo->v4_codebook[cur_strip]; | |
361 v1_codebook = cvinfo->v1_codebook[cur_strip]; | |
362 | |
363 if((cur_strip > 0) && (!(frame_flags & 0x01))) | |
364 { | |
365 memcpy(cvinfo->v4_codebook[cur_strip], cvinfo->v4_codebook[cur_strip-1], 260 * sizeof(cvid_codebook)); | |
366 memcpy(cvinfo->v1_codebook[cur_strip], cvinfo->v1_codebook[cur_strip-1], 260 * sizeof(cvid_codebook)); | |
367 } | |
368 | |
369 strip_id = get_word(); /* 1000 = key strip, 1100 = iter strip */ | |
370 top_size = get_word(); | |
371 y0 = get_word(); /* FIXME: most of these are ignored at the moment */ | |
372 x0 = get_word(); | |
373 y1 = get_word(); | |
374 x1 = get_word(); | |
375 | |
376 y_bottom += y1; | |
377 top_size -= 12; | |
378 x = 0; | |
379 if(x1 != width) | |
380 printf("CVID: Warning x1 (%ld) != width (%d)\n", x1, width); | |
381 | |
382 #if DBUG | |
383 printf(" %d) %04lx %04ld <%ld,%ld> <%ld,%ld> yt %ld %d\n", | |
384 cur_strip, strip_id, top_size, x0, y0, x1, y1, y_bottom); | |
385 #endif | |
386 | |
387 while(top_size > 0) | |
388 { | |
389 chunk_id = get_word(); | |
390 chunk_size = get_word(); | |
391 | |
392 #if DBUG | |
393 printf(" %04lx %04ld\n", chunk_id, chunk_size); | |
394 #endif | |
395 top_size -= chunk_size; | |
396 chunk_size -= 4; | |
397 | |
398 switch(chunk_id) | |
399 { | |
400 /* -------------------- Codebook Entries -------------------- */ | |
401 case 0x2000: | |
402 case 0x2200: | |
403 codebook = (chunk_id == 0x2200 ? v1_codebook : v4_codebook); | |
404 cnum = chunk_size/6; | |
405 for(i = 0; i < cnum; i++) read_codebook(codebook+i, 0); | |
406 break; | |
407 | |
408 case 0x2400: | |
409 case 0x2600: /* 8 bit per pixel */ | |
410 codebook = (chunk_id == 0x2600 ? v1_codebook : v4_codebook); | |
411 cnum = chunk_size/4; | |
412 for(i = 0; i < cnum; i++) read_codebook(codebook+i, 1); | |
413 break; | |
414 | |
415 case 0x2100: | |
416 case 0x2300: | |
417 codebook = (chunk_id == 0x2300 ? v1_codebook : v4_codebook); | |
418 | |
419 ci = 0; | |
420 while(chunk_size > 0) | |
421 { | |
422 flag = get_long(); | |
423 chunk_size -= 4; | |
424 | |
425 for(i = 0; i < 32; i++) | |
426 { | |
427 if(flag & 0x80000000) | |
428 { | |
429 chunk_size -= 6; | |
430 read_codebook(codebook+ci, 0); | |
431 } | |
432 | |
433 ci++; | |
434 flag <<= 1; | |
435 } | |
436 } | |
437 while(chunk_size > 0) { skip_byte(); chunk_size--; } | |
438 break; | |
439 | |
440 case 0x2500: | |
441 case 0x2700: /* 8 bit per pixel */ | |
442 codebook = (chunk_id == 0x2700 ? v1_codebook : v4_codebook); | |
443 | |
444 ci = 0; | |
445 while(chunk_size > 0) | |
446 { | |
447 flag = get_long(); | |
448 chunk_size -= 4; | |
449 | |
450 for(i = 0; i < 32; i++) | |
451 { | |
452 if(flag & 0x80000000) | |
453 { | |
454 chunk_size -= 4; | |
455 read_codebook(codebook+ci, 1); | |
456 } | |
457 | |
458 ci++; | |
459 flag <<= 1; | |
460 } | |
461 } | |
462 while(chunk_size > 0) { skip_byte(); chunk_size--; } | |
463 break; | |
464 | |
465 /* -------------------- Frame -------------------- */ | |
466 case 0x3000: | |
467 while((chunk_size > 0) && (y < y_bottom)) | |
468 { | |
469 flag = get_long(); | |
470 chunk_size -= 4; | |
471 | |
472 for(i = 0; i < 32; i++) | |
473 { | |
474 if(y >= y_bottom) break; | |
475 if(flag & 0x80000000) /* 4 bytes per block */ | |
476 { | |
477 d0 = get_byte(); | |
478 d1 = get_byte(); | |
479 d2 = get_byte(); | |
480 d3 = get_byte(); | |
481 chunk_size -= 4; | |
482 cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3); | |
483 } | |
484 else /* 1 byte per block */ | |
485 { | |
486 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); | |
487 chunk_size--; | |
488 } | |
489 | |
490 x += 4; | |
491 if(x >= width) | |
492 { | |
493 x = 0; | |
494 y += 4; | |
495 } | |
496 flag <<= 1; | |
497 } | |
498 } | |
499 while(chunk_size > 0) { skip_byte(); chunk_size--; } | |
500 break; | |
501 | |
502 case 0x3100: | |
503 while((chunk_size > 0) && (y < y_bottom)) | |
504 { | |
505 /* ---- flag bits: 0 = SKIP, 10 = V1, 11 = V4 ---- */ | |
506 flag = (unsigned long)get_long(); | |
507 chunk_size -= 4; | |
508 mask = 0x80000000; | |
509 | |
510 while((mask) && (y < y_bottom)) | |
511 { | |
512 if(flag & mask) | |
513 { | |
514 if(mask == 1) | |
515 { | |
516 if(chunk_size < 0) break; | |
517 flag = (unsigned long)get_long(); | |
518 chunk_size -= 4; | |
519 mask = 0x80000000; | |
520 } | |
521 else mask >>= 1; | |
522 | |
523 if(flag & mask) /* V4 */ | |
524 { | |
525 d0 = get_byte(); | |
526 d1 = get_byte(); | |
527 d2 = get_byte(); | |
528 d3 = get_byte(); | |
529 chunk_size -= 4; | |
530 cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3); | |
531 } | |
532 else /* V1 */ | |
533 { | |
534 chunk_size--; | |
535 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); | |
536 } | |
537 } /* else SKIP */ | |
538 | |
539 mask >>= 1; | |
540 x += 4; | |
541 if(x >= width) | |
542 { | |
543 x = 0; | |
544 y += 4; | |
545 } | |
546 } | |
547 } | |
548 | |
549 while(chunk_size > 0) { skip_byte(); chunk_size--; } | |
550 break; | |
551 | |
552 case 0x3200: /* each byte is a V1 codebook */ | |
553 while((chunk_size > 0) && (y < y_bottom)) | |
554 { | |
555 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); | |
556 chunk_size--; | |
557 x += 4; | |
558 if(x >= width) | |
559 { | |
560 x = 0; | |
561 y += 4; | |
562 } | |
563 } | |
564 while(chunk_size > 0) { skip_byte(); chunk_size--; } | |
565 break; | |
566 | |
567 default: | |
568 printf("CVID: unknown chunk_id %08lx\n", chunk_id); | |
569 while(chunk_size > 0) { skip_byte(); chunk_size--; } | |
570 break; | |
571 } | |
572 } | |
573 } | |
574 | |
575 if(len != size) | |
576 { | |
577 if(len & 0x01) len++; /* AVIs tend to have a size mismatch */ | |
578 if(len != size) | |
579 { | |
580 long xlen; | |
581 skip_byte(); | |
582 xlen = get_byte() << 16; | |
583 xlen |= get_byte() << 8; | |
584 xlen |= get_byte(); /* Read Len */ | |
585 printf("CVID: END INFO chunk size %d cvid size1 %ld cvid size2 %ld\n", size, len, xlen); | |
586 } | |
587 } | |
588 } | |
589 |