Mercurial > mplayer.hg
comparison libmpcodecs/vd_lcl.c @ 7222:81f720e51821
added LCL decoder by Roberto Togni <r_togni@libero.it>, removed my old vd_zlib
author | alex |
---|---|
date | Sun, 01 Sep 2002 15:10:01 +0000 |
parents | |
children | 95740a8fc77f |
comparison
equal
deleted
inserted
replaced
7221:32fcb4422cbb | 7222:81f720e51821 |
---|---|
1 /* | |
2 * | |
3 * LCL (LossLess Codec Library) Decoder for Mplayer | |
4 * (c) 2002 Roberto Togni | |
5 * | |
6 * Fourcc: MSZH, ZLIB | |
7 * | |
8 * Win32 dll: | |
9 * Ver2.23 By Kenji Oshima 2000.09.20 | |
10 * avimszh.dll, avizlib.dll | |
11 * | |
12 * A description of the decoding algorithm can be found here: | |
13 * http://www.pcisys.net/~melanson/codecs | |
14 * | |
15 */ | |
16 | |
17 #include <stdio.h> | |
18 #include <stdlib.h> | |
19 | |
20 #include "config.h" | |
21 | |
22 #ifdef HAVE_ZLIB | |
23 #include <zlib.h> | |
24 #endif | |
25 | |
26 #include "mp_msg.h" | |
27 | |
28 #include "vd_internal.h" | |
29 | |
30 | |
31 static vd_info_t info = { | |
32 "LCL Video decoder", | |
33 "lcl", | |
34 "Roberto Togni", | |
35 "Roberto Togni", | |
36 "native codec" | |
37 }; | |
38 | |
39 LIBVD_EXTERN(lcl) | |
40 | |
41 | |
42 #define BMPTYPE_YUV 1 | |
43 #define BMPTYPE_RGB 2 | |
44 | |
45 #define IMGTYPE_YUV111 0 | |
46 #define IMGTYPE_YUV422 1 | |
47 #define IMGTYPE_RGB24 2 | |
48 #define IMGTYPE_YUV411 3 | |
49 #define IMGTYPE_YUV211 4 | |
50 #define IMGTYPE_YUV420 5 | |
51 | |
52 #define COMP_MSZH 0 | |
53 #define COMP_MSZH_NOCOMP 1 | |
54 #define COMP_ZLIB_HISPEED 1 | |
55 #define COMP_ZLIB_HICOMP 9 | |
56 #define COMP_ZLIB_NORMAL -1 | |
57 | |
58 #define FLAG_MULTITHREAD 1 | |
59 #define FLAG_NULLFRAME 2 | |
60 #define FLAG_PNGFILTER 4 | |
61 #define FLAGMASK_UNUSED 0xf8 | |
62 | |
63 #define CODEC_MSZH 1 | |
64 #define CODEC_ZLIB 3 | |
65 | |
66 #define FOURCC_MSZH mmioFOURCC('M','S','Z','H') | |
67 #define FOURCC_ZLIB mmioFOURCC('Z','L','I','B') | |
68 | |
69 /* | |
70 * Decoder context | |
71 */ | |
72 typedef struct { | |
73 // Image type | |
74 int imgtype; | |
75 // Compression type | |
76 int compression; | |
77 // Flags | |
78 int flags; | |
79 // Codec type | |
80 int codec; | |
81 // Decompressed data size | |
82 unsigned int decomp_size; | |
83 // Decompression buffer | |
84 unsigned char* decomp_buf; | |
85 #ifdef HAVE_ZLIB | |
86 z_stream zstream; | |
87 #endif | |
88 } lcl_context_t; | |
89 | |
90 | |
91 /* | |
92 * Internal function prototypes | |
93 */ | |
94 | |
95 | |
96 // to set/get/query special features/parameters | |
97 static int control(sh_video_t *sh,int cmd,void* arg,...) | |
98 { | |
99 switch(cmd) { | |
100 case VDCTRL_QUERY_FORMAT: | |
101 if (*((int*)arg) == IMGFMT_BGR24) | |
102 return CONTROL_TRUE; | |
103 else | |
104 return CONTROL_FALSE; | |
105 } | |
106 return CONTROL_UNKNOWN; | |
107 } | |
108 | |
109 | |
110 /* | |
111 * | |
112 * Init LCL decoder | |
113 * | |
114 */ | |
115 static int init(sh_video_t *sh) | |
116 { | |
117 int vo_ret; // Video output init ret value | |
118 int zret; // Zlib return code | |
119 lcl_context_t *hc; // Decoder context | |
120 BITMAPINFOHEADER *bih = sh->bih; | |
121 int basesize = bih->biWidth * bih->biHeight; | |
122 | |
123 if ((hc = malloc(sizeof(lcl_context_t))) == NULL) { | |
124 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for LCL decoder context.\n"); | |
125 return 0; | |
126 } | |
127 | |
128 sh->context = (void *)hc; | |
129 | |
130 #ifdef HAVE_ZLIB | |
131 // Needed if zlib unused or init aborted before inflateInit | |
132 memset(&(hc->zstream), 0, sizeof(z_stream)); | |
133 #endif | |
134 | |
135 if ((bih->biCompression != FOURCC_MSZH) && (bih->biCompression != FOURCC_ZLIB)) { | |
136 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] Unknown BITMAPHEADER fourcc.\n"); | |
137 return 0; | |
138 } | |
139 | |
140 if (bih->biSize < sizeof(BITMAPINFOHEADER) + 8) { | |
141 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BITMAPHEADER size too small.\n"); | |
142 return 0; | |
143 } | |
144 | |
145 /* Detect codec type */ | |
146 switch (hc->codec = *((char *)bih + sizeof(BITMAPINFOHEADER) + 7)) { | |
147 case CODEC_MSZH: | |
148 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Codec is MSZH.\n"); | |
149 break; | |
150 case CODEC_ZLIB: | |
151 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Codec is ZLIB.\n"); | |
152 break; | |
153 default: | |
154 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] Unknown codec id %d. Trusting fourcc.\n", hc->codec); | |
155 switch (bih->biCompression) { | |
156 case FOURCC_MSZH: | |
157 hc->codec = CODEC_MSZH; | |
158 break; | |
159 case FOURCC_ZLIB: | |
160 hc->codec = CODEC_ZLIB; | |
161 break; | |
162 default: | |
163 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] BUG! Unknown coded id and fourcc. Why am I here?.\n"); | |
164 return 0; | |
165 } | |
166 } | |
167 | |
168 | |
169 /* Detect image type */ | |
170 switch (hc->imgtype = *((char *)bih + sizeof(BITMAPINFOHEADER) + 4)) { | |
171 case IMGTYPE_YUV111: | |
172 hc->decomp_size = basesize * 3; | |
173 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Image type is YUV 1:1:1.\n"); | |
174 break; | |
175 case IMGTYPE_YUV422: | |
176 hc->decomp_size = basesize * 2; | |
177 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Image type is YUV 4:2:2.\n"); | |
178 break; | |
179 case IMGTYPE_RGB24: | |
180 hc->decomp_size = basesize * 3; | |
181 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Image type is RGB 24.\n"); | |
182 break; | |
183 case IMGTYPE_YUV411: | |
184 hc->decomp_size = basesize / 2 * 3; | |
185 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Image type is YUV 4:1:1.\n"); | |
186 break; | |
187 case IMGTYPE_YUV211: | |
188 hc->decomp_size = basesize * 2; | |
189 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Image type is YUV 2:1:1.\n"); | |
190 break; | |
191 case IMGTYPE_YUV420: | |
192 hc->decomp_size = basesize / 2 * 3; | |
193 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Image type is YUV 4:2:0.\n"); | |
194 break; | |
195 default: | |
196 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] Unsupported image format %d.\n", hc->imgtype); | |
197 return 0; | |
198 } | |
199 | |
200 /* Detect compression method */ | |
201 hc->compression = *((char *)bih + sizeof(BITMAPINFOHEADER) + 5); | |
202 switch (hc->codec) { | |
203 case CODEC_MSZH: | |
204 switch (hc->compression) { | |
205 case COMP_MSZH: | |
206 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Compression enabled.\n"); | |
207 break; | |
208 case COMP_MSZH_NOCOMP: | |
209 hc->decomp_size = 0; | |
210 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] No compression.\n"); | |
211 break; | |
212 default: | |
213 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] Unsupported compression format for MSZH (%d).\n", hc->compression); | |
214 return 0; | |
215 } | |
216 break; | |
217 case CODEC_ZLIB: | |
218 switch (hc->compression) { | |
219 case COMP_ZLIB_HISPEED: | |
220 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] High speed compression.\n"); | |
221 break; | |
222 case COMP_ZLIB_HICOMP: | |
223 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] High compression.\n"); | |
224 break; | |
225 case COMP_ZLIB_NORMAL: | |
226 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Normal compression.\n"); | |
227 break; | |
228 default: | |
229 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] Unsupported compression format for ZLIB (%d).\n", hc->compression); | |
230 return 0; | |
231 } | |
232 break; | |
233 default: | |
234 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BUG! Unknown codec in compression switch.\n"); | |
235 return 0; | |
236 } | |
237 | |
238 /* Allocate decompression buffer */ | |
239 /* 4*8 max oveflow space for mszh decomp algorithm */ | |
240 if (hc->decomp_size) { | |
241 if ((hc->decomp_buf = malloc(hc->decomp_size+4*8)) == NULL) { | |
242 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] Can't allocate decompression buffer.\n"); | |
243 return 0; | |
244 } | |
245 } | |
246 | |
247 /* Detect flags */ | |
248 hc->flags = *((char *)bih + sizeof(BITMAPINFOHEADER) + 6); | |
249 if (hc->flags & FLAG_MULTITHREAD) | |
250 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Multithread encoder flag set.\n"); | |
251 if (hc->flags & FLAG_NULLFRAME) | |
252 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] Nullframe insertion flag set.\n"); | |
253 if ((hc->codec == CODEC_ZLIB) && (hc->flags & FLAG_PNGFILTER)) | |
254 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "[LCL] PNG filter flag set.\n"); | |
255 if (hc->flags & FLAGMASK_UNUSED) | |
256 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] Unknown flag set (%d).\n", hc->flags); | |
257 | |
258 /* If needed init zlib */ | |
259 if (hc->codec == CODEC_ZLIB) { | |
260 #ifdef HAVE_ZLIB | |
261 hc->zstream.zalloc = Z_NULL; | |
262 hc->zstream.zfree = Z_NULL; | |
263 hc->zstream.opaque = Z_NULL; | |
264 zret = inflateInit(&(hc->zstream)); | |
265 if (zret != Z_OK) { | |
266 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] Inflate init error: %d\n", zret); | |
267 return 0; | |
268 } | |
269 #else | |
270 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] Zlib support not compiled.\n"); | |
271 return 0; | |
272 #endif | |
273 } | |
274 | |
275 /* | |
276 * Initialize video output device | |
277 */ | |
278 vo_ret = mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_BGR24); | |
279 | |
280 return vo_ret; | |
281 } | |
282 | |
283 | |
284 | |
285 | |
286 /* | |
287 * | |
288 * Uninit LCL decoder | |
289 * | |
290 */ | |
291 static void uninit(sh_video_t *sh) | |
292 { | |
293 lcl_context_t *hc = (lcl_context_t *) sh->context; // Decoder context | |
294 | |
295 if (sh->context) { | |
296 #ifdef HAVE_ZLIB | |
297 inflateEnd(&hc->zstream); | |
298 #endif | |
299 free(sh->context); | |
300 } | |
301 } | |
302 | |
303 | |
304 | |
305 inline unsigned char fix (int pix14) | |
306 { | |
307 int tmp; | |
308 | |
309 tmp = (pix14 + 0x80000) >> 20; | |
310 if (tmp < 0) | |
311 return 0; | |
312 if (tmp > 255) | |
313 return 255; | |
314 return tmp; | |
315 } | |
316 | |
317 | |
318 | |
319 inline unsigned char get_b (unsigned char yq, signed char bq) | |
320 { | |
321 return fix((yq << 20) + bq * 1858076); | |
322 } | |
323 | |
324 | |
325 | |
326 inline unsigned char get_g (unsigned char yq, signed char bq, signed char rq) | |
327 { | |
328 return fix((yq << 20) - bq * 360857 - rq * 748830); | |
329 } | |
330 | |
331 | |
332 | |
333 inline unsigned char get_r (unsigned char yq, signed char rq) | |
334 { | |
335 return fix((yq << 20) + rq * 1470103); | |
336 } | |
337 | |
338 | |
339 int mszh_decomp(unsigned char * srcptr, int srclen, unsigned char * destptr); | |
340 | |
341 /* | |
342 * | |
343 * Decode a frame | |
344 * | |
345 */ | |
346 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags) | |
347 { | |
348 mp_image_t* mpi; | |
349 int pixel_ptr; | |
350 int row, col; | |
351 unsigned char *encoded = (unsigned char *)data; | |
352 lcl_context_t *hc = (lcl_context_t *) sh->context; // Decoder context | |
353 unsigned char *outptr; | |
354 int width = sh->disp_w; // Real image width | |
355 int height = sh->disp_h; // Real image height | |
356 #ifdef HAVE_ZLIB | |
357 int zret; // Zlib return code | |
358 #endif | |
359 unsigned int mszh_dlen; | |
360 unsigned char yq, y1q, uq, vq; | |
361 int uqvq; | |
362 unsigned int mthread_inlen, mthread_outlen; | |
363 | |
364 // Skipped frame | |
365 if(len <= 0) | |
366 return NULL; | |
367 | |
368 /* Get output image buffer */ | |
369 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, 0, sh->disp_w, sh->disp_h); | |
370 if (!mpi) { | |
371 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate mpi image for lcl codec.\n"); | |
372 return NULL; | |
373 } | |
374 | |
375 outptr = mpi->planes[0]; // Output image pointer | |
376 | |
377 | |
378 /* Decompress frame */ | |
379 switch (hc->codec) { | |
380 case CODEC_MSZH: | |
381 switch (hc->compression) { | |
382 case COMP_MSZH: | |
383 if (hc->flags & FLAG_MULTITHREAD) { | |
384 mthread_inlen = *((unsigned int*)encoded); | |
385 mthread_outlen = *((unsigned int*)(encoded+4)); | |
386 mszh_dlen = mszh_decomp(encoded + 8, mthread_inlen, hc->decomp_buf); | |
387 if (mthread_outlen != mszh_dlen) { | |
388 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] MSZH: mthread1 decoded size differs (%d != %d)\n", | |
389 mthread_outlen, mszh_dlen); | |
390 } | |
391 mszh_dlen = mszh_decomp(encoded + 8 + mthread_inlen, len - mthread_inlen, | |
392 hc->decomp_buf + mthread_outlen); | |
393 if ((hc->decomp_size - mthread_outlen) != mszh_dlen) { | |
394 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] MSZH: mthread2 decoded size differs (%d != %d)\n", | |
395 hc->decomp_size - mthread_outlen, mszh_dlen); | |
396 } | |
397 encoded = hc->decomp_buf; | |
398 len = hc->decomp_size; | |
399 } else { | |
400 mszh_dlen = mszh_decomp(encoded, len, hc->decomp_buf); | |
401 if (hc->decomp_size != mszh_dlen) { | |
402 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] MSZH: decoded size differs (%d != %d)\n", | |
403 hc->decomp_size, mszh_dlen); | |
404 } | |
405 encoded = hc->decomp_buf; | |
406 len = mszh_dlen; | |
407 } | |
408 break; | |
409 case COMP_MSZH_NOCOMP: | |
410 break; | |
411 default: | |
412 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BUG! Unknown MSZH compression in frame decoder.\n"); | |
413 return 0; | |
414 } | |
415 break; | |
416 case CODEC_ZLIB: | |
417 switch (hc->compression) { | |
418 case COMP_ZLIB_HISPEED: | |
419 case COMP_ZLIB_HICOMP: | |
420 case COMP_ZLIB_NORMAL: | |
421 #ifdef HAVE_ZLIB | |
422 zret = inflateReset(&(hc->zstream)); | |
423 if (zret != Z_OK) { | |
424 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] ZLIB: inflate reset error: %d\n", zret); | |
425 return 0; | |
426 } | |
427 if (hc->flags & FLAG_MULTITHREAD) { | |
428 mthread_inlen = *((unsigned int*)encoded); | |
429 mthread_outlen = *((unsigned int*)(encoded+4)); | |
430 hc->zstream.next_in = encoded + 8; | |
431 hc->zstream.avail_in = mthread_inlen; | |
432 hc->zstream.next_out = hc->decomp_buf; | |
433 hc->zstream.avail_out = mthread_outlen; | |
434 zret = inflate(&(hc->zstream), Z_FINISH); | |
435 if ((zret != Z_OK) && (zret != Z_STREAM_END)) { | |
436 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] ZLIB: mthread1 inflate error: %d\n", zret); | |
437 return 0; | |
438 } | |
439 if (mthread_outlen != (unsigned int)(hc->zstream.total_out)) { | |
440 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] ZLIB: mthread1 decoded size differs (%d != %d)\n", | |
441 mthread_outlen, hc->zstream.total_out); | |
442 } | |
443 zret = inflateReset(&(hc->zstream)); | |
444 if (zret != Z_OK) { | |
445 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] ZLIB: mthread2 inflate reset error: %d\n", zret); | |
446 return 0; | |
447 } | |
448 hc->zstream.next_in = encoded + 8 + mthread_inlen; | |
449 hc->zstream.avail_in = len - mthread_inlen; | |
450 hc->zstream.next_out = hc->decomp_buf + mthread_outlen; | |
451 hc->zstream.avail_out = mthread_outlen; | |
452 zret = inflate(&(hc->zstream), Z_FINISH); | |
453 if ((zret != Z_OK) && (zret != Z_STREAM_END)) { | |
454 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] ZLIB: mthread2 inflate error: %d\n", zret); | |
455 return 0; | |
456 } | |
457 if ((hc->decomp_size - mthread_outlen) != (unsigned int)(hc->zstream.total_out)) { | |
458 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] ZLIB: mthread2 decoded size differs (%d != %d)\n", | |
459 hc->decomp_size - mthread_outlen, hc->zstream.total_out); | |
460 } | |
461 } else { | |
462 hc->zstream.next_in = data; | |
463 hc->zstream.avail_in = len; | |
464 hc->zstream.next_out = hc->decomp_buf; | |
465 hc->zstream.avail_out = hc->decomp_size; | |
466 zret = inflate(&(hc->zstream), Z_FINISH); | |
467 if ((zret != Z_OK) && (zret != Z_STREAM_END)) { | |
468 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] ZLIB: inflate error: %d\n", zret); | |
469 return 0; | |
470 } | |
471 if (hc->decomp_size != (unsigned int)(hc->zstream.total_out)) { | |
472 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[LCL] ZLIB: decoded size differs (%d != %d)\n", | |
473 hc->decomp_size, hc->zstream.total_out); | |
474 } | |
475 } | |
476 encoded = hc->decomp_buf; | |
477 len = hc->decomp_size;; | |
478 #else | |
479 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BUG! Zlib support not compiled in frame decoder.\n"); | |
480 return 0; | |
481 #endif | |
482 break; | |
483 default: | |
484 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BUG! Unknown ZLIB compression in frame decoder.\n"); | |
485 return 0; | |
486 } | |
487 break; | |
488 default: | |
489 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BUG! Unknown codec in frame decoder compression switch.\n"); | |
490 return 0; | |
491 } | |
492 | |
493 | |
494 /* Apply PNG filter */ | |
495 if ((hc->codec == CODEC_ZLIB) && (hc->flags & FLAG_PNGFILTER)) { | |
496 switch (hc->imgtype) { | |
497 case IMGTYPE_YUV111: | |
498 for (row = 0; row < height; row++) { | |
499 pixel_ptr = row * width * 3; | |
500 yq = encoded[pixel_ptr++]; | |
501 uqvq = encoded[pixel_ptr++] + (encoded[pixel_ptr++] << 8); | |
502 for (col = 1; col < width; col++) { | |
503 encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
504 uqvq -= (encoded[pixel_ptr+1] | (encoded[pixel_ptr+2]<<8)); | |
505 encoded[pixel_ptr+1] = (uqvq) & 0xff; | |
506 encoded[pixel_ptr+2] = ((uqvq)>>8) & 0xff; | |
507 pixel_ptr += 3; | |
508 } | |
509 } | |
510 break; | |
511 case IMGTYPE_RGB24: // No | |
512 for (row = 0; row < height; row++) { | |
513 pixel_ptr = row * width * 3; | |
514 yq = encoded[pixel_ptr++]; | |
515 uqvq = encoded[pixel_ptr++] + (encoded[pixel_ptr++] << 8); | |
516 for (col = 1; col < width; col++) { | |
517 encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
518 uqvq -= (encoded[pixel_ptr+1] | (encoded[pixel_ptr+2]<<8)); | |
519 encoded[pixel_ptr+1] = (uqvq) & 0xff; | |
520 encoded[pixel_ptr+2] = ((uqvq)>>8) & 0xff; | |
521 pixel_ptr += 3; | |
522 } | |
523 } | |
524 break; | |
525 case IMGTYPE_YUV422: | |
526 for (row = 0; row < height; row++) { | |
527 pixel_ptr = row * width * 2; | |
528 yq = uq = vq =0; | |
529 for (col = 0; col < width/4; col++) { | |
530 encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
531 encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
532 encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2]; | |
533 encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3]; | |
534 encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; | |
535 encoded[pixel_ptr+5] = uq -= encoded[pixel_ptr+5]; | |
536 encoded[pixel_ptr+6] = vq -= encoded[pixel_ptr+6]; | |
537 encoded[pixel_ptr+7] = vq -= encoded[pixel_ptr+7]; | |
538 pixel_ptr += 8; | |
539 } | |
540 } | |
541 break; | |
542 case IMGTYPE_YUV411: | |
543 for (row = 0; row < height; row++) { | |
544 pixel_ptr = row * width / 2 * 3; | |
545 yq = uq = vq =0; | |
546 for (col = 0; col < width/4; col++) { | |
547 encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
548 encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
549 encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2]; | |
550 encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3]; | |
551 encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; | |
552 encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5]; | |
553 pixel_ptr += 6; | |
554 } | |
555 } | |
556 break; | |
557 case IMGTYPE_YUV211: | |
558 for (row = 0; row < height; row++) { | |
559 pixel_ptr = row * width * 2; | |
560 yq = uq = vq =0; | |
561 for (col = 0; col < width/2; col++) { | |
562 encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
563 encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
564 encoded[pixel_ptr+2] = uq -= encoded[pixel_ptr+2]; | |
565 encoded[pixel_ptr+3] = vq -= encoded[pixel_ptr+3]; | |
566 pixel_ptr += 4; | |
567 } | |
568 } | |
569 break; | |
570 case IMGTYPE_YUV420: | |
571 for (row = 0; row < height/2; row++) { | |
572 pixel_ptr = row * width * 3; | |
573 yq = y1q = uq = vq =0; | |
574 for (col = 0; col < width/2; col++) { | |
575 encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; | |
576 encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; | |
577 encoded[pixel_ptr+2] = y1q -= encoded[pixel_ptr+2]; | |
578 encoded[pixel_ptr+3] = y1q -= encoded[pixel_ptr+3]; | |
579 encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; | |
580 encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5]; | |
581 pixel_ptr += 6; | |
582 } | |
583 } | |
584 break; | |
585 break; | |
586 default: | |
587 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BUG! Unknown imagetype in pngfilter switch.\n"); | |
588 return 0; | |
589 } | |
590 } | |
591 | |
592 /* Convert colorspace */ | |
593 switch (hc->imgtype) { | |
594 case IMGTYPE_YUV111: | |
595 for (row = height - 1; row >= 0; row--) { | |
596 pixel_ptr = row * mpi->stride[0]; | |
597 for (col = 0; col < width; col++) { | |
598 outptr[pixel_ptr++] = get_b(encoded[0], encoded[1]); | |
599 outptr[pixel_ptr++] = get_g(encoded[0], encoded[1], encoded[2]); | |
600 outptr[pixel_ptr++] = get_r(encoded[0], encoded[2]); | |
601 encoded += 3; | |
602 } | |
603 } | |
604 break; | |
605 case IMGTYPE_YUV422: | |
606 for (row = height - 1; row >= 0; row--) { | |
607 pixel_ptr = row * mpi->stride[0]; | |
608 for (col = 0; col < width/4; col++) { | |
609 outptr[pixel_ptr++] = get_b(encoded[0], encoded[4]); | |
610 outptr[pixel_ptr++] = get_g(encoded[0], encoded[4], encoded[6]); | |
611 outptr[pixel_ptr++] = get_r(encoded[0], encoded[6]); | |
612 outptr[pixel_ptr++] = get_b(encoded[1], encoded[4]); | |
613 outptr[pixel_ptr++] = get_g(encoded[1], encoded[4], encoded[6]); | |
614 outptr[pixel_ptr++] = get_r(encoded[1], encoded[6]); | |
615 outptr[pixel_ptr++] = get_b(encoded[2], encoded[5]); | |
616 outptr[pixel_ptr++] = get_g(encoded[2], encoded[5], encoded[7]); | |
617 outptr[pixel_ptr++] = get_r(encoded[2], encoded[7]); | |
618 outptr[pixel_ptr++] = get_b(encoded[3], encoded[5]); | |
619 outptr[pixel_ptr++] = get_g(encoded[3], encoded[5], encoded[7]); | |
620 outptr[pixel_ptr++] = get_r(encoded[3], encoded[7]); | |
621 encoded += 8; | |
622 } | |
623 } | |
624 break; | |
625 case IMGTYPE_RGB24: | |
626 for (row = height - 1; row >= 0; row--) { | |
627 pixel_ptr = row * mpi->stride[0]; | |
628 for (col = 0; col < width; col++) { | |
629 outptr[pixel_ptr++] = encoded[0]; | |
630 outptr[pixel_ptr++] = encoded[1]; | |
631 outptr[pixel_ptr++] = encoded[2]; | |
632 encoded += 3; | |
633 } | |
634 } | |
635 break; | |
636 case IMGTYPE_YUV411: | |
637 for (row = height - 1; row >= 0; row--) { | |
638 pixel_ptr = row * mpi->stride[0]; | |
639 for (col = 0; col < width/4; col++) { | |
640 outptr[pixel_ptr++] = get_b(encoded[0], encoded[4]); | |
641 outptr[pixel_ptr++] = get_g(encoded[0], encoded[4], encoded[5]); | |
642 outptr[pixel_ptr++] = get_r(encoded[0], encoded[5]); | |
643 outptr[pixel_ptr++] = get_b(encoded[1], encoded[4]); | |
644 outptr[pixel_ptr++] = get_g(encoded[1], encoded[4], encoded[5]); | |
645 outptr[pixel_ptr++] = get_r(encoded[1], encoded[5]); | |
646 outptr[pixel_ptr++] = get_b(encoded[2], encoded[4]); | |
647 outptr[pixel_ptr++] = get_g(encoded[2], encoded[4], encoded[5]); | |
648 outptr[pixel_ptr++] = get_r(encoded[2], encoded[5]); | |
649 outptr[pixel_ptr++] = get_b(encoded[3], encoded[4]); | |
650 outptr[pixel_ptr++] = get_g(encoded[3], encoded[4], encoded[5]); | |
651 outptr[pixel_ptr++] = get_r(encoded[3], encoded[5]); | |
652 encoded += 6; | |
653 } | |
654 } | |
655 break; | |
656 case IMGTYPE_YUV211: | |
657 for (row = height - 1; row >= 0; row--) { | |
658 pixel_ptr = row * mpi->stride[0]; | |
659 for (col = 0; col < width/2; col++) { | |
660 outptr[pixel_ptr++] = get_b(encoded[0], encoded[2]); | |
661 outptr[pixel_ptr++] = get_g(encoded[0], encoded[2], encoded[3]); | |
662 outptr[pixel_ptr++] = get_r(encoded[0], encoded[3]); | |
663 outptr[pixel_ptr++] = get_b(encoded[1], encoded[2]); | |
664 outptr[pixel_ptr++] = get_g(encoded[1], encoded[2], encoded[3]); | |
665 outptr[pixel_ptr++] = get_r(encoded[1], encoded[3]); | |
666 encoded += 4; | |
667 } | |
668 } | |
669 break; | |
670 case IMGTYPE_YUV420: | |
671 for (row = height / 2 - 1; row >= 0; row--) { | |
672 pixel_ptr = 2 * row * mpi->stride[0]; | |
673 for (col = 0; col < width/2; col++) { | |
674 outptr[pixel_ptr] = get_b(encoded[0], encoded[4]); | |
675 outptr[pixel_ptr+1] = get_g(encoded[0], encoded[4], encoded[5]); | |
676 outptr[pixel_ptr+2] = get_r(encoded[0], encoded[5]); | |
677 outptr[pixel_ptr+3] = get_b(encoded[1], encoded[4]); | |
678 outptr[pixel_ptr+4] = get_g(encoded[1], encoded[4], encoded[5]); | |
679 outptr[pixel_ptr+5] = get_r(encoded[1], encoded[5]); | |
680 outptr[pixel_ptr-mpi->stride[0]] = get_b(encoded[2], encoded[4]); | |
681 outptr[pixel_ptr-mpi->stride[0]+1] = get_g(encoded[2], encoded[4], encoded[5]); | |
682 outptr[pixel_ptr-mpi->stride[0]+2] = get_r(encoded[2], encoded[5]); | |
683 outptr[pixel_ptr-mpi->stride[0]+3] = get_b(encoded[3], encoded[4]); | |
684 outptr[pixel_ptr-mpi->stride[0]+4] = get_g(encoded[3], encoded[4], encoded[5]); | |
685 outptr[pixel_ptr-mpi->stride[0]+5] = get_r(encoded[3], encoded[5]); | |
686 pixel_ptr += 6; | |
687 encoded += 6; | |
688 } | |
689 } | |
690 break; | |
691 default: | |
692 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[LCL] BUG! Unknown imagetype in image decoder.\n"); | |
693 return 0; | |
694 } | |
695 | |
696 return mpi; | |
697 } | |
698 | |
699 | |
700 | |
701 int mszh_decomp(unsigned char * srcptr, int srclen, unsigned char * destptr) | |
702 { | |
703 unsigned char *destptr_bak = destptr; | |
704 unsigned char mask = 0; | |
705 unsigned char maskbit = 0; | |
706 unsigned int ofs, cnt; | |
707 | |
708 while (srclen > 0) { | |
709 if (maskbit == 0) { | |
710 mask = *(srcptr++); | |
711 maskbit = 8; | |
712 srclen--; | |
713 continue; | |
714 } | |
715 if ((mask & (1 << (--maskbit))) == 0) { | |
716 *(destptr++) = *(srcptr++); | |
717 *(destptr++) = *(srcptr++); | |
718 *(destptr++) = *(srcptr++); | |
719 *(destptr++) = *(srcptr++); | |
720 srclen -= 4; | |
721 } else { | |
722 ofs = *(srcptr++); | |
723 cnt = *(srcptr++); | |
724 ofs += cnt * 256;; | |
725 cnt = ((cnt >> 3) & 0x1f) + 1; | |
726 ofs &= 0x7ff; | |
727 srclen -= 2; | |
728 cnt *= 4; | |
729 for (; cnt > 0; cnt--) { | |
730 *(destptr) = *(destptr - ofs); | |
731 destptr++; | |
732 } | |
733 } | |
734 } | |
735 | |
736 return (destptr - destptr_bak); | |
737 } | |
738 |