Mercurial > mplayer.hg
annotate fli.c @ 3600:3094e7b6a15b
pre-cache fixed
author | arpi |
---|---|
date | Wed, 19 Dec 2001 02:16:43 +0000 |
parents | 21c7b77b3e83 |
children | 7fb817c9060b |
rev | line source |
---|---|
3155 | 1 /* |
2 FLI Decoder for MPlayer | |
3 | |
4 (C) 2001 Mike Melanson | |
3185 | 5 |
6 32bpp support (c) alex | |
3155 | 7 */ |
8 | |
3509
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
9 #include "config.h" |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
10 #include "bswap.h" |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
11 |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
12 #define LE_16(x) (le2me_16(*(unsigned short *)(x))) |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
13 #define LE_32(x) (le2me_32(*(unsigned int *)(x))) |
3155 | 14 |
15 #define FLI_256_COLOR 4 | |
16 #define FLI_DELTA 7 | |
17 #define FLI_COLOR 11 | |
18 #define FLI_LC 12 | |
19 #define FLI_BLACK 13 | |
20 #define FLI_BRUN 15 | |
21 #define FLI_COPY 16 | |
22 #define FLI_MINI 18 | |
23 | |
24 // 256 RGB entries; 25% of these bytes will be unused, but it's faster | |
25 // to index 4-byte entries | |
26 static unsigned char palette[256 * 4]; | |
27 | |
28 void AVI_Decode_Fli( | |
29 unsigned char *encoded, | |
30 int encoded_size, | |
31 unsigned char *decoded, | |
32 int width, | |
33 int height, | |
34 int bytes_per_pixel) | |
35 { | |
36 int stream_ptr = 0; | |
37 int pixel_ptr; | |
38 int palette_ptr1; | |
39 int palette_ptr2; | |
40 | |
41 unsigned int frame_size; | |
42 int num_chunks; | |
43 | |
44 unsigned int chunk_size; | |
45 int chunk_type; | |
46 | |
47 int i, j; | |
48 | |
49 int color_packets; | |
50 int color_changes; | |
51 int color_scale; | |
52 | |
53 int lines; | |
54 int compressed_lines; | |
55 int starting_line; | |
56 signed short line_packets; | |
57 int y_ptr; | |
58 int line_inc; | |
59 signed char byte_run; | |
60 | |
61 frame_size = LE_32(&encoded[stream_ptr]); | |
62 stream_ptr += 6; // skip the magic number | |
63 num_chunks = LE_16(&encoded[stream_ptr]); | |
64 stream_ptr += 10; // skip padding | |
65 | |
66 // iterate through the chunks | |
67 frame_size -= 16; | |
68 while ((frame_size > 0) && (num_chunks > 0)) | |
69 { | |
70 chunk_size = LE_32(&encoded[stream_ptr]); | |
71 stream_ptr += 4; | |
72 chunk_type = LE_16(&encoded[stream_ptr]); | |
73 stream_ptr += 2; | |
74 | |
75 switch (chunk_type) | |
76 { | |
77 case FLI_256_COLOR: | |
78 case FLI_COLOR: | |
79 if (chunk_type == FLI_COLOR) | |
80 color_scale = 4; | |
81 else | |
82 color_scale = 1; | |
83 // set up the palette | |
84 color_packets = LE_16(&encoded[stream_ptr]); | |
85 stream_ptr += 2; | |
86 palette_ptr1 = 0; | |
87 for (i = 0; i < color_packets; i++) | |
88 { | |
89 // first byte is how many colors to skip | |
90 palette_ptr1 += (encoded[stream_ptr++] * 4); | |
91 // next byte indicates how many entries to change | |
92 color_changes = encoded[stream_ptr++]; | |
93 // if there are 0 color changes, there are actually 256 | |
94 if (color_changes == 0) | |
95 color_changes = 256; | |
96 for (j = 0; j < color_changes; j++) | |
97 { | |
98 palette[palette_ptr1++] = encoded[stream_ptr + 2] * color_scale; | |
99 palette[palette_ptr1++] = encoded[stream_ptr + 1] * color_scale; | |
100 palette[palette_ptr1++] = encoded[stream_ptr + 0] * color_scale; | |
101 palette_ptr1++; | |
102 stream_ptr += 3; | |
103 } | |
104 } | |
3509
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
105 // it seems that a color packet has to be an even number of bytes |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
106 // so account for a pad byte |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
107 if (stream_ptr & 0x01) |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
108 stream_ptr++; |
3155 | 109 break; |
110 | |
111 case FLI_DELTA: | |
112 line_inc = width * bytes_per_pixel; | |
113 y_ptr = 0; | |
114 compressed_lines = LE_16(&encoded[stream_ptr]); | |
115 stream_ptr += 2; | |
116 while (compressed_lines > 0) | |
117 { | |
118 line_packets = LE_16(&encoded[stream_ptr]); | |
119 stream_ptr += 2; | |
120 if (line_packets < 0) | |
121 { | |
122 line_packets = -line_packets; | |
123 y_ptr += (line_packets * line_inc); | |
124 } | |
125 else | |
126 { | |
127 pixel_ptr = y_ptr; | |
128 for (i = 0; i < line_packets; i++) | |
129 { | |
130 // account for the skip bytes | |
3185 | 131 pixel_ptr += encoded[stream_ptr++] * bytes_per_pixel; |
3155 | 132 byte_run = encoded[stream_ptr++]; |
133 if (byte_run < 0) | |
134 { | |
135 byte_run = -byte_run; | |
136 palette_ptr1 = encoded[stream_ptr++] * 4; | |
137 palette_ptr2 = encoded[stream_ptr++] * 4; | |
138 for (j = 0; j < byte_run; j++) | |
139 { | |
140 decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; | |
141 decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; | |
142 decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; | |
3185 | 143 if (bytes_per_pixel == 4) /* 32bpp */ |
144 pixel_ptr++; | |
3155 | 145 |
146 decoded[pixel_ptr++] = palette[palette_ptr2 + 0]; | |
147 decoded[pixel_ptr++] = palette[palette_ptr2 + 1]; | |
148 decoded[pixel_ptr++] = palette[palette_ptr2 + 2]; | |
3185 | 149 if (bytes_per_pixel == 4) /* 32bpp */ |
150 pixel_ptr++; | |
3155 | 151 } |
152 } | |
153 else | |
154 { | |
155 for (j = 0; j < byte_run * 2; j++) | |
156 { | |
157 palette_ptr1 = encoded[stream_ptr++] * 4; | |
158 decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; | |
159 decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; | |
160 decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; | |
3185 | 161 if (bytes_per_pixel == 4) /* 32bpp */ |
162 pixel_ptr++; | |
3155 | 163 } |
164 } | |
165 } | |
166 y_ptr += line_inc; | |
167 compressed_lines--; | |
168 } | |
169 } | |
170 break; | |
171 | |
172 case FLI_LC: | |
173 // line compressed | |
174 line_inc = width * bytes_per_pixel; | |
175 starting_line = LE_16(&encoded[stream_ptr]); | |
176 stream_ptr += 2; | |
177 y_ptr = starting_line * line_inc; | |
178 | |
179 compressed_lines = LE_16(&encoded[stream_ptr]); | |
180 stream_ptr += 2; | |
181 while (compressed_lines > 0) | |
182 { | |
183 pixel_ptr = y_ptr; | |
184 line_packets = encoded[stream_ptr++]; | |
185 if (line_packets > 0) | |
186 { | |
187 for (i = 0; i < line_packets; i++) | |
188 { | |
189 // account for the skip bytes | |
3185 | 190 pixel_ptr += encoded[stream_ptr++] * bytes_per_pixel; |
3155 | 191 byte_run = encoded[stream_ptr++]; |
192 if (byte_run > 0) | |
193 { | |
194 for (j = 0; j < byte_run; j++) | |
195 { | |
196 palette_ptr1 = encoded[stream_ptr++] * 4; | |
197 decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; | |
198 decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; | |
199 decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; | |
3185 | 200 if (bytes_per_pixel == 4) /* 32bpp */ |
201 pixel_ptr++; | |
3155 | 202 } |
203 } | |
204 else | |
205 { | |
206 byte_run = -byte_run; | |
207 palette_ptr1 = encoded[stream_ptr++] * 4; | |
208 for (j = 0; j < byte_run; j++) | |
209 { | |
210 decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; | |
211 decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; | |
212 decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; | |
3185 | 213 if (bytes_per_pixel == 4) /* 32bpp */ |
214 pixel_ptr++; | |
3155 | 215 } |
216 } | |
217 } | |
218 } | |
219 | |
220 y_ptr += line_inc; | |
221 compressed_lines--; | |
222 } | |
223 break; | |
224 | |
225 case FLI_BLACK: | |
226 // set the whole frame to color 0 (which is usually black) | |
3185 | 227 for (pixel_ptr = 0; pixel_ptr < (width * height * bytes_per_pixel); pixel_ptr++) |
3155 | 228 { |
229 decoded[pixel_ptr++] = palette[0]; | |
230 decoded[pixel_ptr++] = palette[1]; | |
231 decoded[pixel_ptr++] = palette[2]; | |
3185 | 232 if (bytes_per_pixel == 4) /* 32bpp */ |
233 pixel_ptr++; | |
3155 | 234 } |
235 break; | |
236 | |
237 case FLI_BRUN: | |
238 // byte run compression | |
239 line_inc = width * bytes_per_pixel; | |
240 y_ptr = 0; | |
241 for (lines = 0; lines < height; lines++) | |
242 { | |
243 pixel_ptr = y_ptr; | |
244 line_packets = encoded[stream_ptr++]; | |
245 for (i = 0; i < line_packets; i++) | |
246 { | |
247 byte_run = encoded[stream_ptr++]; | |
248 if (byte_run > 0) | |
249 { | |
250 palette_ptr1 = encoded[stream_ptr++] * 4; | |
251 for (j = 0; j < byte_run; j++) | |
252 { | |
253 decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; | |
254 decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; | |
255 decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; | |
3185 | 256 if (bytes_per_pixel == 4) /* 32bpp */ |
257 pixel_ptr++; | |
3155 | 258 } |
259 } | |
260 else // copy bytes if byte_run < 0 | |
261 { | |
262 byte_run = -byte_run; | |
263 for (j = 0; j < byte_run; j++) | |
264 { | |
265 palette_ptr1 = encoded[stream_ptr++] * 4; | |
266 decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; | |
267 decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; | |
268 decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; | |
3185 | 269 if (bytes_per_pixel == 4) /* 32bpp */ |
270 pixel_ptr++; | |
3155 | 271 } |
272 } | |
273 } | |
274 | |
275 y_ptr += line_inc; | |
276 } | |
277 break; | |
278 | |
279 case FLI_COPY: | |
3509
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
280 // copy the chunk (uncompressed frame) |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
281 for (pixel_ptr = 0; pixel_ptr < chunk_size - 6; pixel_ptr++) |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
282 { |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
283 palette_ptr1 = encoded[stream_ptr++] * 4; |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
284 decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
285 decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
286 decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
287 if (bytes_per_pixel == 4) /* 32bpp */ |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
288 pixel_ptr++; |
21c7b77b3e83
fixed endian-ness for FLI and MS Video 1 decoders; fixed padding bug in
melanson
parents:
3185
diff
changeset
|
289 } |
3155 | 290 break; |
291 | |
292 case FLI_MINI: | |
293 // sort of a thumbnail? disregard this chunk... | |
294 stream_ptr += chunk_size - 6; | |
295 break; | |
296 | |
297 default: | |
298 printf ("FLI: Unrecognized chunk type: %d\n", chunk_type); | |
299 break; | |
300 } | |
301 | |
302 frame_size -= chunk_size; | |
303 num_chunks--; | |
304 } | |
305 } |