Mercurial > mplayer.hg
comparison libmpcodecs/vd_huffyuv.c @ 5235:3e04fd1074d3
added HuffYUV support, courtesy of Roberto Togni <rtogni@bresciaonline.it>
author | melanson |
---|---|
date | Thu, 21 Mar 2002 01:21:49 +0000 |
parents | |
children | 9e80ac615570 |
comparison
equal
deleted
inserted
replaced
5234:781a155f76cf | 5235:3e04fd1074d3 |
---|---|
1 /* | |
2 * | |
3 * HuffYUV Decoder for Mplayer | |
4 * (c) 2002 Roberto Togni | |
5 * | |
6 * Fourcc: HFYU | |
7 * | |
8 * Original Win32 codec copyright: | |
9 * | |
10 *** Huffyuv v2.1.1, by Ben Rudiak-Gould. | |
11 *** http://www.math.berkeley.edu/~benrg/huffyuv.html | |
12 *** | |
13 *** This file is copyright 2000 Ben Rudiak-Gould, and distributed under | |
14 *** the terms of the GNU General Public License, v2 or later. See | |
15 *** http://www.gnu.org/copyleft/gpl.html. | |
16 * | |
17 */ | |
18 | |
19 #include <stdio.h> | |
20 #include <stdlib.h> | |
21 | |
22 #include "config.h" | |
23 #include "mp_msg.h" | |
24 | |
25 #include "vd_internal.h" | |
26 | |
27 | |
28 static vd_info_t info = { | |
29 "HuffYUV Video decoder", | |
30 "huffyuv", | |
31 VFM_HUFFYUV, | |
32 "Roberto Togni", | |
33 "Roberto Togni", | |
34 "native codec, original win32 by Ben Rudiak-Gould http://www.math.berkeley.edu/~benrg/huffyuv.html" | |
35 }; | |
36 | |
37 LIBVD_EXTERN(huffyuv) | |
38 | |
39 | |
40 /* | |
41 * Bitmap types | |
42 */ | |
43 #define BMPTYPE_YUV -1 | |
44 #define BMPTYPE_RGB -2 | |
45 #define BMPTYPE_RGBA -3 | |
46 | |
47 /* | |
48 * Compression methods | |
49 */ | |
50 #define METHOD_LEFT 0 | |
51 #define METHOD_GRAD 1 | |
52 #define METHOD_MEDIAN 2 | |
53 #define DECORR_FLAG 64 | |
54 #define METHOD_LEFT_DECORR (METHOD_LEFT | DECORR_FLAG) | |
55 #define METHOD_GRAD_DECORR (METHOD_GRAD | DECORR_FLAG) | |
56 #define METHOD_OLD -2 | |
57 | |
58 #define FOURCC_HFYU mmioFOURCC('H','F','Y','U') | |
59 | |
60 #define HUFFTABLE_CLASSIC_YUV ((unsigned char*) -1) | |
61 #define HUFFTABLE_CLASSIC_RGB ((unsigned char*) -2) | |
62 #define HUFFTABLE_CLASSIC_YUV_CHROMA ((unsigned char*) -3) | |
63 | |
64 | |
65 /* | |
66 * Huffman table | |
67 */ | |
68 typedef struct { | |
69 unsigned char* table_pointers[32]; | |
70 unsigned char table_data[129*25]; | |
71 } DecodeTable; | |
72 | |
73 | |
74 /* | |
75 * Decoder context | |
76 */ | |
77 typedef struct { | |
78 // Real image depth | |
79 int bitcount; | |
80 // Prediction method | |
81 int method; | |
82 // Bitmap color type | |
83 int bitmaptype; | |
84 // Huffman tables | |
85 unsigned char decode1_shift[256]; | |
86 unsigned char decode2_shift[256]; | |
87 unsigned char decode3_shift[256]; | |
88 DecodeTable decode1, decode2, decode3; | |
89 // Above line buffers | |
90 unsigned char *abovebuf1, *abovebuf2; | |
91 } huffyuv_context_t; | |
92 | |
93 | |
94 /* | |
95 * Classic Huffman tables | |
96 */ | |
97 unsigned char classic_shift_luma[] = { | |
98 34,36,35,69,135,232,9,16,10,24,11,23,12,16,13,10,14,8,15,8, | |
99 16,8,17,20,16,10,207,206,205,236,11,8,10,21,9,23,8,8,199,70, | |
100 69,68, 0 | |
101 }; | |
102 | |
103 unsigned char classic_shift_chroma[] = { | |
104 66,36,37,38,39,40,41,75,76,77,110,239,144,81,82,83,84,85,118,183, | |
105 56,57,88,89,56,89,154,57,58,57,26,141,57,56,58,57,58,57,184,119, | |
106 214,245,116,83,82,49,80,79,78,77,44,75,41,40,39,38,37,36,34, 0 | |
107 }; | |
108 | |
109 unsigned char classic_add_luma[256] = { | |
110 3, 9, 5, 12, 10, 35, 32, 29, 27, 50, 48, 45, 44, 41, 39, 37, | |
111 73, 70, 68, 65, 64, 61, 58, 56, 53, 50, 49, 46, 44, 41, 38, 36, | |
112 68, 65, 63, 61, 58, 55, 53, 51, 48, 46, 45, 43, 41, 39, 38, 36, | |
113 35, 33, 32, 30, 29, 27, 26, 25, 48, 47, 46, 44, 43, 41, 40, 39, | |
114 37, 36, 35, 34, 32, 31, 30, 28, 27, 26, 24, 23, 22, 20, 19, 37, | |
115 35, 34, 33, 31, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 29, | |
116 27, 26, 24, 22, 21, 19, 17, 16, 14, 26, 25, 23, 21, 19, 18, 16, | |
117 15, 27, 25, 23, 21, 19, 17, 16, 14, 26, 25, 23, 21, 18, 17, 14, | |
118 12, 17, 19, 13, 4, 9, 2, 11, 1, 7, 8, 0, 16, 3, 14, 6, | |
119 12, 10, 5, 15, 18, 11, 10, 13, 15, 16, 19, 20, 22, 24, 27, 15, | |
120 18, 20, 22, 24, 26, 14, 17, 20, 22, 24, 27, 15, 18, 20, 23, 25, | |
121 28, 16, 19, 22, 25, 28, 32, 36, 21, 25, 29, 33, 38, 42, 45, 49, | |
122 28, 31, 34, 37, 40, 42, 44, 47, 49, 50, 52, 54, 56, 57, 59, 60, | |
123 62, 64, 66, 67, 69, 35, 37, 39, 40, 42, 43, 45, 47, 48, 51, 52, | |
124 54, 55, 57, 59, 60, 62, 63, 66, 67, 69, 71, 72, 38, 40, 42, 43, | |
125 46, 47, 49, 51, 26, 28, 30, 31, 33, 34, 18, 19, 11, 13, 7, 8, | |
126 }; | |
127 | |
128 unsigned char classic_add_chroma[256] = { | |
129 3, 1, 2, 2, 2, 2, 3, 3, 7, 5, 7, 5, 8, 6, 11, 9, | |
130 7, 13, 11, 10, 9, 8, 7, 5, 9, 7, 6, 4, 7, 5, 8, 7, | |
131 11, 8, 13, 11, 19, 15, 22, 23, 20, 33, 32, 28, 27, 29, 51, 77, | |
132 43, 45, 76, 81, 46, 82, 75, 55, 56,144, 58, 80, 60, 74,147, 63, | |
133 143, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, | |
134 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 27, 30, 21, 22, | |
135 17, 14, 5, 6,100, 54, 47, 50, 51, 53,106,107,108,109,110,111, | |
136 112,113,114,115, 4,117,118, 92, 94,121,122, 3,124,103, 2, 1, | |
137 0,129,130,131,120,119,126,125,136,137,138,139,140,141,142,134, | |
138 135,132,133,104, 64,101, 62, 57,102, 95, 93, 59, 61, 28, 97, 96, | |
139 52, 49, 48, 29, 32, 25, 24, 46, 23, 98, 45, 44, 43, 20, 42, 41, | |
140 19, 18, 99, 40, 15, 39, 38, 16, 13, 12, 11, 37, 10, 9, 8, 36, | |
141 7,128,127,105,123,116, 35, 34, 33,145, 31, 79, 42,146, 78, 26, | |
142 83, 48, 49, 50, 44, 47, 26, 31, 30, 18, 17, 19, 21, 24, 25, 13, | |
143 14, 16, 17, 18, 20, 21, 12, 14, 15, 9, 10, 6, 9, 6, 5, 8, | |
144 6, 12, 8, 10, 7, 9, 6, 4, 6, 2, 2, 3, 3, 3, 3, 2, | |
145 }; | |
146 | |
147 | |
148 /* | |
149 * Internal function prototypes | |
150 */ | |
151 unsigned char* InitializeDecodeTable(unsigned char* hufftable, | |
152 unsigned char* shift, DecodeTable* decode_table); | |
153 unsigned char* InitializeShiftAddTables(unsigned char* hufftable, | |
154 unsigned char* shift, unsigned* add_shifted); | |
155 unsigned char* DecompressHuffmanTable(unsigned char* hufftable, | |
156 unsigned char* dst); | |
157 unsigned char huff_decompress(unsigned int* in, unsigned int *pos, | |
158 DecodeTable *decode_table, unsigned char *decode_shift); | |
159 | |
160 | |
161 | |
162 | |
163 // to set/get/query special features/parameters | |
164 static int control(sh_video_t *sh,int cmd,void* arg,...){ | |
165 return CONTROL_UNKNOWN; | |
166 } | |
167 | |
168 | |
169 /* | |
170 * | |
171 * Init HuffYUV decoder | |
172 * | |
173 */ | |
174 static int init(sh_video_t *sh) | |
175 { | |
176 int vo_ret; // Video output init ret value | |
177 huffyuv_context_t *hc; // Decoder context | |
178 unsigned char *hufftable; // Compressed huffman tables | |
179 BITMAPINFOHEADER *bih = sh->bih; | |
180 | |
181 if ((hc = malloc(sizeof(huffyuv_context_t))) == NULL) { | |
182 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for HuffYUV decoder context\n"); | |
183 return 0; | |
184 } | |
185 | |
186 sh->context = (void *)hc; | |
187 | |
188 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Allocating above line buffer\n"); | |
189 if ((hc->abovebuf1 = malloc(sizeof(char) * 4 * bih->biWidth)) == NULL) { | |
190 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for HuffYUV above buffer 1\n"); | |
191 return 0; | |
192 } | |
193 | |
194 if ((hc->abovebuf2 = malloc(sizeof(char) * 4 * bih->biWidth)) == NULL) { | |
195 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for HuffYUV above buffer 2\n"); | |
196 return 0; | |
197 } | |
198 | |
199 if (bih->biCompression != FOURCC_HFYU) { | |
200 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[HuffYUV] BITMAPHEADER fourcc != HFYU\n"); | |
201 return 0; | |
202 } | |
203 | |
204 /* Get bitcount */ | |
205 hc->bitcount = 0; | |
206 if (bih->biSize > sizeof(BITMAPINFOHEADER)+1) | |
207 hc->bitcount = *((char*)bih + sizeof(BITMAPINFOHEADER) + 1); | |
208 if (hc->bitcount == 0) | |
209 hc->bitcount = bih->biBitCount; | |
210 | |
211 /* Get bitmap type */ | |
212 switch (hc->bitcount & ~7) { | |
213 case 16: | |
214 hc->bitmaptype = BMPTYPE_YUV; // -1 | |
215 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Image type is YUV\n"); | |
216 break; | |
217 case 24: | |
218 hc->bitmaptype = BMPTYPE_RGB; // -2 | |
219 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Image type is RGB\n"); | |
220 break; | |
221 case 32: | |
222 hc->bitmaptype = BMPTYPE_RGBA; //-3 | |
223 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Image type is RGBA\n"); | |
224 break; | |
225 default: | |
226 hc->bitmaptype = 0; // ERR | |
227 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[HuffYUV] Image type is unknown\n"); | |
228 } | |
229 | |
230 /* Get method */ | |
231 switch (bih->biBitCount & 7) { | |
232 case 0: | |
233 if (bih->biSize > sizeof(BITMAPINFOHEADER)) { | |
234 hc->method = *((unsigned char*)bih + sizeof(BITMAPINFOHEADER)); | |
235 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method stored in extra data\n"); | |
236 } else | |
237 hc->method = METHOD_OLD; // Is it really needed? | |
238 break; | |
239 case 1: | |
240 hc->method = METHOD_LEFT; | |
241 break; | |
242 case 2: | |
243 hc->method = METHOD_LEFT_DECORR; | |
244 break; | |
245 case 3: | |
246 if (hc->bitmaptype == BMPTYPE_YUV) { | |
247 hc->method = METHOD_GRAD; | |
248 } else { | |
249 hc->method = METHOD_GRAD_DECORR; | |
250 } | |
251 break; | |
252 case 4: | |
253 hc->method = METHOD_MEDIAN; | |
254 break; | |
255 default: | |
256 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method: fallback to METHOD_OLD\n"); | |
257 hc->method = METHOD_OLD; | |
258 } | |
259 | |
260 /* Print method info */ | |
261 switch (hc->method) { | |
262 case METHOD_LEFT: | |
263 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method: Predict Left\n"); | |
264 break; | |
265 case METHOD_GRAD: | |
266 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method: Predict Gradient\n"); | |
267 break; | |
268 case METHOD_MEDIAN: | |
269 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method: Predict Median\n"); | |
270 break; | |
271 case METHOD_LEFT_DECORR: | |
272 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method: Predict Left with decorrelation\n"); | |
273 break; | |
274 case METHOD_GRAD_DECORR: | |
275 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method: Predict Gradient with decorrelation\n"); | |
276 break; | |
277 case METHOD_OLD: | |
278 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Method Old\n"); | |
279 break; | |
280 default: | |
281 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[HuffYUV] Method unknown\n"); | |
282 } | |
283 | |
284 /* Get compressed Huffman tables */ | |
285 if (bih->biSize == sizeof(BITMAPINFOHEADER) /*&& !(bih->biBitCount&7)*/) { | |
286 hufftable = (hc->bitmaptype == BMPTYPE_YUV) ? HUFFTABLE_CLASSIC_YUV : HUFFTABLE_CLASSIC_RGB; | |
287 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Using classic static Huffman tables\n"); | |
288 } else { | |
289 hufftable = (unsigned char*)bih + sizeof(BITMAPINFOHEADER) + ((bih->biBitCount&7) ? 0 : 4); | |
290 mp_msg(MSGT_DECVIDEO, MSGL_V, "[HuffYUV] Using Huffman tables stored in file\n"); | |
291 } | |
292 | |
293 /* Initialize decoder Huffman tables */ | |
294 hufftable = InitializeDecodeTable(hufftable, hc->decode1_shift, &(hc->decode1)); | |
295 hufftable = InitializeDecodeTable(hufftable, hc->decode2_shift, &(hc->decode2)); | |
296 InitializeDecodeTable(hufftable, hc->decode3_shift, &(hc->decode3)); | |
297 | |
298 /* | |
299 * Initialize video output device | |
300 */ | |
301 switch (hc->bitmaptype) { | |
302 case BMPTYPE_YUV: | |
303 vo_ret = mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YUY2); | |
304 break; | |
305 case BMPTYPE_RGB: | |
306 vo_ret = mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_BGR24); | |
307 break; | |
308 case BMPTYPE_RGBA: | |
309 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[HuffYUV] RGBA not supported yet.\n"); | |
310 return 0; | |
311 default: | |
312 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[HuffYUV] BUG! Unknown bitmaptype in vo config.\n"); | |
313 return 0; | |
314 } | |
315 | |
316 return vo_ret; | |
317 } | |
318 | |
319 | |
320 | |
321 | |
322 /* | |
323 * | |
324 * Uninit HuffYUV decoder | |
325 * | |
326 */ | |
327 static void uninit(sh_video_t *sh) | |
328 { | |
329 if (sh->context) { | |
330 if (((huffyuv_context_t*)&sh->context)->abovebuf1) | |
331 free(((huffyuv_context_t*)sh->context)->abovebuf1); | |
332 if (((huffyuv_context_t*)&sh->context)->abovebuf2) | |
333 free(((huffyuv_context_t*)sh->context)->abovebuf2); | |
334 free(sh->context); | |
335 } | |
336 } | |
337 | |
338 | |
339 | |
340 #define HUFF_DECOMPRESS_YUYV() \ | |
341 { \ | |
342 y1 = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode1), hc->decode1_shift); \ | |
343 u = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode2), hc->decode2_shift); \ | |
344 y2 = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode1), hc->decode1_shift); \ | |
345 v = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode3), hc->decode3_shift); \ | |
346 } | |
347 | |
348 | |
349 | |
350 #define HUFF_DECOMPRESS_RGB_DECORR() \ | |
351 { \ | |
352 g = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode2), hc->decode2_shift); \ | |
353 b = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode1), hc->decode1_shift); \ | |
354 r = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode3), hc->decode3_shift); \ | |
355 } | |
356 | |
357 | |
358 | |
359 #define HUFF_DECOMPRESS_RGB() \ | |
360 { \ | |
361 b = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode1), hc->decode1_shift); \ | |
362 g = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode2), hc->decode2_shift); \ | |
363 r = huff_decompress((unsigned int *)encoded, &pos, &(hc->decode3), hc->decode3_shift); \ | |
364 } | |
365 | |
366 | |
367 | |
368 #define MEDIAN(left, above, aboveleft) \ | |
369 { \ | |
370 if ((mi = (above)) > (left)) { \ | |
371 mx = mi; \ | |
372 mi = (left); \ | |
373 } else \ | |
374 mx = (left); \ | |
375 tmp = (above) + (left) - (aboveleft); \ | |
376 if (tmp < mi) \ | |
377 med = mi; \ | |
378 else if (tmp > mx) \ | |
379 med = mx; \ | |
380 else \ | |
381 med = tmp; \ | |
382 } | |
383 | |
384 | |
385 | |
386 #define YUV_STORE1ST_ABOVEBUF() \ | |
387 { \ | |
388 abovebuf[0] = outptr[0] = encoded[0]; \ | |
389 abovebuf[1] = left_u = outptr[1] = encoded[1]; \ | |
390 abovebuf[2] = left_y = outptr[2] = encoded[2]; \ | |
391 abovebuf[3] = left_v = outptr[3] = encoded[3]; \ | |
392 pixel_ptr = 4; \ | |
393 } | |
394 | |
395 | |
396 | |
397 #define YUV_STORE1ST() \ | |
398 { \ | |
399 outptr[0] = encoded[0]; \ | |
400 left_u = outptr[1] = encoded[1]; \ | |
401 left_y = outptr[2] = encoded[2]; \ | |
402 left_v = outptr[3] = encoded[3]; \ | |
403 pixel_ptr = 4; \ | |
404 } | |
405 | |
406 | |
407 | |
408 #define RGB_STORE1ST() \ | |
409 { \ | |
410 pixel_ptr = (height-1)*mpi->stride[0]; \ | |
411 left_b = outptr[pixel_ptr++] = encoded[1]; \ | |
412 left_g = outptr[pixel_ptr++] = encoded[2]; \ | |
413 left_r = outptr[pixel_ptr++] = encoded[3]; \ | |
414 pixel_ptr += bgr32; \ | |
415 } | |
416 | |
417 | |
418 | |
419 #define RGB_STORE1ST_ABOVEBUF() \ | |
420 { \ | |
421 pixel_ptr = (height-1)*mpi->stride[0]; \ | |
422 abovebuf[0] = left_b = outptr[pixel_ptr++] = encoded[1]; \ | |
423 abovebuf[1] = left_g = outptr[pixel_ptr++] = encoded[2]; \ | |
424 abovebuf[2] = left_r = outptr[pixel_ptr++] = encoded[3]; \ | |
425 pixel_ptr += bgr32; \ | |
426 } | |
427 | |
428 | |
429 | |
430 | |
431 #define YUV_PREDLEFT() \ | |
432 { \ | |
433 outptr[pixel_ptr++] = left_y += y1; \ | |
434 outptr[pixel_ptr++] = left_u += u; \ | |
435 outptr[pixel_ptr++] = left_y += y2; \ | |
436 outptr[pixel_ptr++] = left_v += v; \ | |
437 } | |
438 | |
439 | |
440 | |
441 #define YUV_PREDLEFT_BUF(buf, offs) \ | |
442 { \ | |
443 (buf)[(offs)] = outptr[pixel_ptr++] = left_y += y1; \ | |
444 (buf)[(offs)+1] = outptr[pixel_ptr++] = left_u += u; \ | |
445 (buf)[(offs)+2] = outptr[pixel_ptr++] = left_y += y2; \ | |
446 (buf)[(offs)+3] = outptr[pixel_ptr++] = left_v += v; \ | |
447 } | |
448 | |
449 | |
450 | |
451 #define YUV_PREDMED() \ | |
452 { \ | |
453 MEDIAN (left_y, abovebuf[col], abovebuf[col-2]); \ | |
454 curbuf[col] = outptr[pixel_ptr++] = left_y = med + y1; \ | |
455 MEDIAN (left_u, abovebuf[col+1], abovebuf[col+1-4]); \ | |
456 curbuf[col+1] = outptr[pixel_ptr++] = left_u = med + u; \ | |
457 MEDIAN (left_y, abovebuf[col+2], abovebuf[col+2-2]); \ | |
458 curbuf[col+2] = outptr[pixel_ptr++] = left_y = med + y2; \ | |
459 MEDIAN (left_v, abovebuf[col+3], abovebuf[col+3-4]); \ | |
460 curbuf[col+3] = outptr[pixel_ptr++] = left_v = med + v; \ | |
461 } | |
462 | |
463 | |
464 | |
465 #define RGB_PREDLEFT_DECORR() \ | |
466 { \ | |
467 outptr[pixel_ptr++] = left_b += b + g; \ | |
468 outptr[pixel_ptr++] = left_g += g; \ | |
469 outptr[pixel_ptr++] = left_r += r + g; \ | |
470 pixel_ptr += bgr32; \ | |
471 } | |
472 | |
473 | |
474 | |
475 #define RGB_PREDLEFT() \ | |
476 { \ | |
477 outptr[pixel_ptr++] = left_b += b; \ | |
478 outptr[pixel_ptr++] = left_g += g; \ | |
479 outptr[pixel_ptr++] = left_r += r; \ | |
480 pixel_ptr += bgr32; \ | |
481 } | |
482 | |
483 | |
484 | |
485 | |
486 /* | |
487 * | |
488 * Decode a HuffYUV frame | |
489 * | |
490 */ | |
491 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags) | |
492 { | |
493 mp_image_t* mpi; | |
494 int pixel_ptr; | |
495 unsigned char y1, y2, u, v, r, g, b, a; | |
496 unsigned char left_y, left_u, left_v, left_r, left_g, left_b; | |
497 unsigned char tmp, mi, mx, med; | |
498 unsigned char *swap; | |
499 int row, col; | |
500 unsigned int pos = 32; | |
501 unsigned char *encoded = (unsigned char *)data; | |
502 huffyuv_context_t *hc = (huffyuv_context_t *) sh->context; // Decoder context | |
503 unsigned char *abovebuf = hc->abovebuf1; | |
504 unsigned char *curbuf = hc->abovebuf2; | |
505 unsigned char *outptr; | |
506 int width = sh->disp_w; // Real image width | |
507 int height = sh->disp_h; // Real image height | |
508 int bgr32; | |
509 | |
510 // skipped frame | |
511 if(len <= 0) | |
512 return NULL; | |
513 | |
514 /* Do not accept stride for rgb, it gives me wrong output :-( */ | |
515 if (hc->bitmaptype == BMPTYPE_YUV) | |
516 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, sh->disp_w, sh->disp_h); | |
517 else | |
518 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, 0, sh->disp_w, sh->disp_h); | |
519 | |
520 if (!mpi) { | |
521 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate mpi image for huffyuv codec.\n"); | |
522 return NULL; | |
523 } | |
524 | |
525 outptr = mpi->planes[0]; // Output image pointer | |
526 | |
527 if (hc->bitmaptype == BMPTYPE_YUV) { | |
528 width >>= 1; // Each cycle stores two pixels | |
529 if (hc->method == METHOD_GRAD) { | |
530 /* | |
531 * YUV predict gradient | |
532 */ | |
533 /* Store 1st pixel */ | |
534 YUV_STORE1ST_ABOVEBUF(); | |
535 // Decompress 1st row (always stored with left prediction) | |
536 for (col = 1*4; col < width*4; col += 4) { | |
537 HUFF_DECOMPRESS_YUYV(); | |
538 YUV_PREDLEFT_BUF(abovebuf, col); | |
539 } | |
540 curbuf[width*4-1] = curbuf[width*4-2] = curbuf[width*4-3] = 0; | |
541 for (row = 1; row < height; row++) { | |
542 pixel_ptr = row * mpi->stride[0]; | |
543 HUFF_DECOMPRESS_YUYV(); | |
544 curbuf[0] = outptr[pixel_ptr++] = left_y += y1 + abovebuf[0] - curbuf[width*4-2]; | |
545 curbuf[1] = outptr[pixel_ptr++] = left_u += u + abovebuf[1] - curbuf[width*4+1-4]; | |
546 curbuf[2] = outptr[pixel_ptr++] = left_y += y2 + abovebuf[2] - abovebuf[0]; | |
547 curbuf[3] = outptr[pixel_ptr++] = left_v += v + abovebuf[3] - curbuf[width*4+3-4]; | |
548 for (col = 1*4; col < width*4; col += 4) { | |
549 HUFF_DECOMPRESS_YUYV(); | |
550 curbuf[col] = outptr[pixel_ptr++] = left_y += y1 + abovebuf[col]-abovebuf[col-2]; | |
551 curbuf[col+1] = outptr[pixel_ptr++] = left_u += u + abovebuf[col+1]-abovebuf[col+1-4]; | |
552 curbuf[col+2] = outptr[pixel_ptr++] = left_y += y2 + abovebuf[col+2]-abovebuf[col+2-2]; | |
553 curbuf[col+3] = outptr[pixel_ptr++] = left_v += v + abovebuf[col+3]-abovebuf[col+3-4]; | |
554 } | |
555 swap = abovebuf; | |
556 abovebuf = curbuf; | |
557 curbuf = swap; | |
558 } | |
559 } else if (hc->method == METHOD_MEDIAN) { | |
560 /* | |
561 * YUV predict median | |
562 */ | |
563 /* Store 1st pixel */ | |
564 YUV_STORE1ST_ABOVEBUF(); | |
565 // Decompress 1st row (always stored with left prediction) | |
566 for (col = 1*4; col < width*4; col += 4) { | |
567 HUFF_DECOMPRESS_YUYV(); | |
568 YUV_PREDLEFT_BUF (abovebuf, col); | |
569 } | |
570 // Decompress 1st two pixels of 2nd row | |
571 pixel_ptr = mpi->stride[0]; | |
572 HUFF_DECOMPRESS_YUYV(); | |
573 YUV_PREDLEFT_BUF (curbuf, 0); | |
574 HUFF_DECOMPRESS_YUYV(); | |
575 YUV_PREDLEFT_BUF (curbuf, 4); | |
576 // Complete 2nd row | |
577 for (col = 2*4; col < width*4; col += 4) { | |
578 HUFF_DECOMPRESS_YUYV(); | |
579 YUV_PREDMED(); | |
580 } | |
581 swap = abovebuf; | |
582 abovebuf = curbuf; | |
583 curbuf = swap; | |
584 for (row = 2; row < height; row++) { | |
585 pixel_ptr = row * mpi->stride[0]; | |
586 HUFF_DECOMPRESS_YUYV(); | |
587 MEDIAN (left_y, abovebuf[0], curbuf[width*4-2]); | |
588 curbuf[0] = outptr[pixel_ptr++] = left_y = med + y1; | |
589 MEDIAN (left_u, abovebuf[1], curbuf[width*4+1-4]); | |
590 curbuf[1] = outptr[pixel_ptr++] = left_u = med + u; | |
591 MEDIAN (left_y, abovebuf[2], abovebuf[0]); | |
592 curbuf[2] = outptr[pixel_ptr++] = left_y = med + y2; | |
593 MEDIAN (left_v, abovebuf[3], curbuf[width*4+3-4]); | |
594 curbuf[3] = outptr[pixel_ptr++] = left_v = med + v; | |
595 for (col = 1*4; col < width*4; col += 4) { | |
596 HUFF_DECOMPRESS_YUYV(); | |
597 YUV_PREDMED(); | |
598 } | |
599 swap = abovebuf; | |
600 abovebuf = curbuf; | |
601 curbuf = swap; | |
602 } | |
603 } else { | |
604 /* | |
605 * YUV predict left and predict old | |
606 */ | |
607 /* Store 1st pixel */ | |
608 YUV_STORE1ST(); | |
609 // Decompress 1st row (always stored with left prediction) | |
610 for (col = 1*4; col < width*4; col += 4) { | |
611 HUFF_DECOMPRESS_YUYV(); | |
612 YUV_PREDLEFT(); | |
613 } | |
614 for (row = 1; row < height; row++) { | |
615 pixel_ptr = row * mpi->stride[0]; | |
616 for (col = 0; col < width*4; col += 4) { | |
617 HUFF_DECOMPRESS_YUYV(); | |
618 YUV_PREDLEFT(); | |
619 } | |
620 } | |
621 } | |
622 } else { | |
623 bgr32 = (mpi->bpp) >> 5; // 1 if bpp = 32, 0 if bpp = 24 | |
624 if (hc->method == METHOD_LEFT_DECORR) { | |
625 /* | |
626 * RGB predict left with decorrelation | |
627 */ | |
628 /* Store 1st pixel */ | |
629 RGB_STORE1ST(); | |
630 // Decompress 1st row | |
631 for (col = 1; col < width; col ++) { | |
632 HUFF_DECOMPRESS_RGB_DECORR(); | |
633 RGB_PREDLEFT_DECORR(); | |
634 } | |
635 for (row = 1; row < height; row++) { | |
636 pixel_ptr = (height - row - 1) * mpi->stride[0]; | |
637 for (col = 0; col < width; col++) { | |
638 HUFF_DECOMPRESS_RGB_DECORR(); | |
639 RGB_PREDLEFT_DECORR(); | |
640 } | |
641 } | |
642 } else if (hc->method == METHOD_GRAD_DECORR) { | |
643 /* | |
644 * RGB predict gradient with decorrelation | |
645 */ | |
646 /* Store 1st pixel */ | |
647 RGB_STORE1ST_ABOVEBUF(); | |
648 // Decompress 1st row (always stored with left prediction) | |
649 for (col = 1*3; col < width*3; col += 3) { | |
650 HUFF_DECOMPRESS_RGB_DECORR(); | |
651 abovebuf[col] = outptr[pixel_ptr++] = left_b += b + g; | |
652 abovebuf[col+1] = outptr[pixel_ptr++] = left_g += g; | |
653 abovebuf[col+2] = outptr[pixel_ptr++] = left_r += r + g; | |
654 pixel_ptr += bgr32; | |
655 } | |
656 curbuf[width*3-1] = curbuf[width*3-2] = curbuf[width*3-3] = 0; | |
657 for (row = 1; row < height; row++) { | |
658 pixel_ptr = (height - row - 1) * mpi->stride[0]; | |
659 HUFF_DECOMPRESS_RGB_DECORR(); | |
660 curbuf[0] = outptr[pixel_ptr++] = left_b += b + g + abovebuf[0] - curbuf[width*3-3]; | |
661 curbuf[1] = outptr[pixel_ptr++] = left_g += g + abovebuf[1] - curbuf[width*3+1-3]; | |
662 curbuf[2] = outptr[pixel_ptr++] = left_r += r + g + abovebuf[2] - curbuf[width*3+2-3]; | |
663 pixel_ptr += bgr32; | |
664 for (col = 1*3; col < width*3; col += 3) { | |
665 HUFF_DECOMPRESS_RGB_DECORR(); | |
666 curbuf[col] = outptr[pixel_ptr++] = left_b += b + g + abovebuf[col]-abovebuf[col-3]; | |
667 curbuf[col+1] = outptr[pixel_ptr++] = left_g += g + abovebuf[col+1]-abovebuf[col+1-3]; | |
668 curbuf[col+2] = outptr[pixel_ptr++] = left_r += r + g + abovebuf[col+2]-abovebuf[col+2-3]; | |
669 pixel_ptr += bgr32; | |
670 } | |
671 swap = abovebuf; | |
672 abovebuf = curbuf; | |
673 curbuf = swap; | |
674 } | |
675 } else { | |
676 /* | |
677 * RGB predict left (no decorrelation) and predict old | |
678 */ | |
679 /* Store 1st pixel */ | |
680 RGB_STORE1ST(); | |
681 // Decompress 1st row | |
682 for (col = 1; col < width; col++) { | |
683 HUFF_DECOMPRESS_RGB(); | |
684 RGB_PREDLEFT(); | |
685 } | |
686 for (row = 1; row < height; row++) { | |
687 pixel_ptr = (height - row - 1) * mpi->stride[0]; | |
688 for (col = 0; col < width; col++) { | |
689 HUFF_DECOMPRESS_RGB(); | |
690 RGB_PREDLEFT(); | |
691 } | |
692 } | |
693 } | |
694 } | |
695 | |
696 return mpi; | |
697 } | |
698 | |
699 | |
700 | |
701 unsigned char* InitializeDecodeTable(unsigned char* hufftable, | |
702 unsigned char* shift, DecodeTable* decode_table) | |
703 { | |
704 unsigned int add_shifted[256]; | |
705 char code_lengths[256]; | |
706 char code_firstbits[256]; | |
707 char table_lengths[32]; | |
708 int all_zero_code=-1; | |
709 int i, j, k; | |
710 int firstbit, length, val; | |
711 unsigned char* p; | |
712 unsigned char * table; | |
713 | |
714 /* Initialize shift[] and add_shifted[] */ | |
715 hufftable = InitializeShiftAddTables(hufftable, shift, add_shifted); | |
716 | |
717 memset(table_lengths, -1, 32); | |
718 | |
719 /* Fill code_firstbits[], code_legths[] and table_lengths[] */ | |
720 for (i = 0; i < 256; ++i) { | |
721 if (add_shifted[i]) { | |
722 for (firstbit = 31; firstbit >= 0; firstbit--) { | |
723 if (add_shifted[i] & (1 << firstbit)) { | |
724 code_firstbits[i] = firstbit; | |
725 length = shift[i] - (32 - firstbit); | |
726 code_lengths[i] = length; | |
727 table_lengths[firstbit] = max(table_lengths[firstbit], length); | |
728 break; | |
729 } | |
730 } | |
731 } else { | |
732 all_zero_code = i; | |
733 } | |
734 } | |
735 | |
736 p = decode_table->table_data; | |
737 *p++ = 31; | |
738 *p++ = all_zero_code; | |
739 for (j = 0; j < 32; ++j) { | |
740 if (table_lengths[j] == -1) { | |
741 decode_table->table_pointers[j] = decode_table->table_data; | |
742 } else { | |
743 decode_table->table_pointers[j] = p; | |
744 *p++ = j - table_lengths[j]; | |
745 p += 1 << table_lengths[j]; | |
746 } | |
747 } | |
748 | |
749 for (k=0; k<256; ++k) { | |
750 if (add_shifted[k]) { | |
751 firstbit = code_firstbits[k]; | |
752 val = add_shifted[k] - (1 << firstbit); | |
753 table = decode_table->table_pointers[firstbit]; | |
754 memset(&table[1 + (val >> table[0])], k, | |
755 1 << (table_lengths[firstbit] - code_lengths[k])); | |
756 } | |
757 } | |
758 | |
759 return hufftable; | |
760 } | |
761 | |
762 | |
763 | |
764 unsigned char* InitializeShiftAddTables(unsigned char* hufftable, | |
765 unsigned char* shift, unsigned* add_shifted) | |
766 { | |
767 int i, j; | |
768 unsigned int bits; // must be 32bit unsigned | |
769 int min_already_processed; | |
770 int max_not_processed; | |
771 int bit; | |
772 | |
773 // special-case the old tables, since they don't fit the new rules | |
774 if (hufftable == HUFFTABLE_CLASSIC_YUV || hufftable == HUFFTABLE_CLASSIC_RGB) { | |
775 DecompressHuffmanTable(classic_shift_luma, shift); | |
776 for (i = 0; i < 256; ++i) | |
777 add_shifted[i] = classic_add_luma[i] << (32 - shift[i]); | |
778 return (hufftable == HUFFTABLE_CLASSIC_YUV) ? HUFFTABLE_CLASSIC_YUV_CHROMA : hufftable; | |
779 } else if (hufftable == HUFFTABLE_CLASSIC_YUV_CHROMA) { | |
780 DecompressHuffmanTable(classic_shift_chroma, shift); | |
781 for (i = 0; i < 256; ++i) | |
782 add_shifted[i] = classic_add_chroma[i] << (32 - shift[i]); | |
783 return hufftable; | |
784 } | |
785 | |
786 hufftable = DecompressHuffmanTable(hufftable, shift); | |
787 | |
788 // derive the actual bit patterns from the code lengths | |
789 min_already_processed = 32; | |
790 bits = 0; | |
791 do { | |
792 max_not_processed = 0; | |
793 for (i = 0; i < 256; ++i) { | |
794 if (shift[i] < min_already_processed && shift[i] > max_not_processed) | |
795 max_not_processed = shift[i]; | |
796 } | |
797 bit = 1 << (32 - max_not_processed); | |
798 // assert (!(bits & (bit - 1))); | |
799 for (j = 0; j < 256; ++j) { | |
800 if (shift[j] == max_not_processed) { | |
801 add_shifted[j] = bits; | |
802 bits += bit; | |
803 } | |
804 } | |
805 min_already_processed = max_not_processed; | |
806 } while (bits & 0xFFFFFFFF); | |
807 | |
808 return hufftable; | |
809 } | |
810 | |
811 | |
812 | |
813 unsigned char* DecompressHuffmanTable(unsigned char* hufftable, | |
814 unsigned char* dst) | |
815 { | |
816 int val; | |
817 int repeat; | |
818 int i = 0; | |
819 | |
820 do { | |
821 val = *hufftable & 31; | |
822 repeat = *hufftable++ >> 5; | |
823 if (!repeat) | |
824 repeat = *hufftable++; | |
825 while (repeat--) | |
826 dst[i++] = val; | |
827 } while (i < 256); | |
828 | |
829 return hufftable; | |
830 } | |
831 | |
832 | |
833 unsigned char huff_decompress(unsigned int* in, unsigned int *pos, DecodeTable *decode_table, | |
834 unsigned char *decode_shift) | |
835 { | |
836 unsigned int word = *pos >> 5; | |
837 unsigned int bit = *pos & 31; | |
838 unsigned int val = in[word]; | |
839 unsigned char outbyte; | |
840 unsigned char *tableptr; | |
841 int i; | |
842 | |
843 if (bit) | |
844 val = (val << bit) | (in[word + 1] >> (32 - bit)); | |
845 // figure out the appropriate lookup table based on the number of leading zeros | |
846 i = 31; | |
847 val |= 1; | |
848 while ((val & (1 << i--)) == 0); | |
849 val &= ~(1 << (i+1)); | |
850 tableptr = decode_table->table_pointers[i+1]; | |
851 val >>= *tableptr; | |
852 | |
853 outbyte = tableptr[val+1]; | |
854 *pos += decode_shift[outbyte]; | |
855 | |
856 return outbyte; | |
857 } |