Mercurial > libavcodec.hg
annotate interplayvideo.c @ 1539:14d01ccc0081 libavcodec
picture buffer cleanup, this fixes a assertion failure (if assertion checking was manualy enabled for utils.c) and a memleak at least
author | michael |
---|---|
date | Thu, 16 Oct 2003 00:21:54 +0000 |
parents | 26eb7678cb46 |
children | b340e83b8d0d |
rev | line source |
---|---|
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
1 /* |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
2 * Interplay MVE Video Decoder |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
3 * Copyright (C) 2003 the ffmpeg project |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
4 * |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
5 * This library is free software; you can redistribute it and/or |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
6 * modify it under the terms of the GNU Lesser General Public |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
7 * License as published by the Free Software Foundation; either |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
8 * version 2 of the License, or (at your option) any later version. |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
9 * |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
10 * This library is distributed in the hope that it will be useful, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
13 * Lesser General Public License for more details. |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
14 * |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
15 * You should have received a copy of the GNU Lesser General Public |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
16 * License along with this library; if not, write to the Free Software |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
18 * |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
19 */ |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
20 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
21 /** |
1468 | 22 * @file interplayvideo.c |
23 * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net) | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
24 * For more information about the Interplay MVE format, visit: |
1468 | 25 * http://www.pcisys.net/~melanson/codecs/interplay-mve.txt |
26 * This code is written in such a way that the identifiers match up | |
27 * with the encoding descriptions in the document. | |
28 * | |
29 * This decoder presently only supports a PAL8 output colorspace. | |
30 * | |
31 * An Interplay video frame consists of 2 parts: The decoding map and | |
32 * the video data. A demuxer must load these 2 parts together in a single | |
33 * buffer before sending it through the stream to this decoder. | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
34 */ |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
35 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
36 #include <stdio.h> |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
37 #include <stdlib.h> |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
38 #include <string.h> |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
39 #include <unistd.h> |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
40 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
41 #include "common.h" |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
42 #include "avcodec.h" |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
43 #include "dsputil.h" |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
44 |
1468 | 45 #define PALETTE_COUNT 256 |
46 | |
47 /* debugging support */ | |
48 #define DEBUG_INTERPLAY 0 | |
49 #if DEBUG_INTERPLAY | |
50 #define debug_interplay printf | |
51 #else | |
52 static inline void debug_interplay(const char *format, ...) { } | |
53 #endif | |
54 | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
55 typedef struct IpvideoContext { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
56 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
57 AVCodecContext *avctx; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
58 DSPContext dsp; |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
59 AVFrame second_last_frame; |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
60 AVFrame last_frame; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
61 AVFrame current_frame; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
62 unsigned char *decoding_map; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
63 int decoding_map_size; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
64 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
65 unsigned char *buf; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
66 int size; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
67 |
1468 | 68 unsigned char palette[PALETTE_COUNT * 4]; |
69 | |
1475 | 70 unsigned char *stream_ptr; |
71 unsigned char *stream_end; | |
72 unsigned char *pixel_ptr; | |
73 int line_inc; | |
74 int stride; | |
75 int upper_motion_limit_offset; | |
76 | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
77 } IpvideoContext; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
78 |
1468 | 79 #define CHECK_STREAM_PTR(n) \ |
1475 | 80 if ((s->stream_ptr + n) > s->stream_end) { \ |
1468 | 81 printf ("Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \ |
1475 | 82 s->stream_ptr + n, s->stream_end); \ |
1468 | 83 return -1; \ |
84 } | |
85 | |
86 static void ipvideo_new_palette(IpvideoContext *s, unsigned char *palette) { | |
87 | |
88 int i; | |
89 unsigned char r, g, b; | |
90 unsigned int *palette32; | |
91 | |
1475 | 92 palette32 = (unsigned int *)s->palette; |
93 for (i = 0; i < PALETTE_COUNT; i++) { | |
94 r = *palette++; | |
95 g = *palette++; | |
96 b = *palette++; | |
97 palette32[i] = (r << 16) | (g << 8) | (b); | |
1468 | 98 } |
99 } | |
100 | |
1475 | 101 #define COPY_FROM_CURRENT() \ |
102 motion_offset = current_offset; \ | |
103 motion_offset += y * s->stride; \ | |
104 motion_offset += x; \ | |
105 if (motion_offset < 0) { \ | |
106 printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \ | |
107 return -1; \ | |
108 } else if (motion_offset > s->upper_motion_limit_offset) { \ | |
109 printf (" Interplay video: motion offset above limit (%d >= %d)\n", \ | |
110 motion_offset, s->upper_motion_limit_offset); \ | |
111 return -1; \ | |
112 } \ | |
113 s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \ | |
114 s->current_frame.data[0] + motion_offset, s->stride, 8); | |
1468 | 115 |
1475 | 116 #define COPY_FROM_PREVIOUS() \ |
117 motion_offset = current_offset; \ | |
118 motion_offset += y * s->stride; \ | |
119 motion_offset += x; \ | |
120 if (motion_offset < 0) { \ | |
121 printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \ | |
122 return -1; \ | |
123 } else if (motion_offset > s->upper_motion_limit_offset) { \ | |
124 printf (" Interplay video: motion offset above limit (%d >= %d)\n", \ | |
125 motion_offset, s->upper_motion_limit_offset); \ | |
126 return -1; \ | |
127 } \ | |
128 s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \ | |
129 s->last_frame.data[0] + motion_offset, s->stride, 8); | |
130 | |
131 #define COPY_FROM_SECOND_LAST() \ | |
132 motion_offset = current_offset; \ | |
133 motion_offset += y * s->stride; \ | |
134 motion_offset += x; \ | |
135 if (motion_offset < 0) { \ | |
136 printf (" Interplay video: motion offset < 0 (%d)\n", motion_offset); \ | |
137 return -1; \ | |
138 } else if (motion_offset > s->upper_motion_limit_offset) { \ | |
139 printf (" Interplay video: motion offset above limit (%d >= %d)\n", \ | |
140 motion_offset, s->upper_motion_limit_offset); \ | |
141 return -1; \ | |
142 } \ | |
143 s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \ | |
144 s->second_last_frame.data[0] + motion_offset, s->stride, 8); | |
145 | |
146 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s) | |
1468 | 147 { |
148 int x, y; | |
1475 | 149 int motion_offset; |
150 int current_offset = s->pixel_ptr - s->current_frame.data[0]; | |
1468 | 151 |
1475 | 152 /* copy a block from the previous frame */ |
153 x = y = 0; | |
154 COPY_FROM_PREVIOUS(); | |
1468 | 155 |
156 /* report success */ | |
157 return 0; | |
158 } | |
159 | |
1475 | 160 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s) |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
161 { |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
162 int x, y; |
1475 | 163 int motion_offset; |
164 int current_offset = s->pixel_ptr - s->current_frame.data[0]; | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
165 |
1475 | 166 /* copy block from 2 frames ago */ |
167 x = y = 0; | |
168 COPY_FROM_SECOND_LAST(); | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
169 |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
170 /* report success */ |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
171 return 0; |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
172 } |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
173 |
1475 | 174 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s) |
1468 | 175 { |
176 unsigned char B; | |
177 int x, y; | |
178 int motion_offset; | |
1475 | 179 int current_offset = s->pixel_ptr - s->current_frame.data[0]; |
1468 | 180 |
1475 | 181 /* copy block from 2 frames ago using a motion vector; need 1 more byte */ |
1468 | 182 CHECK_STREAM_PTR(1); |
1475 | 183 B = *s->stream_ptr++; |
1468 | 184 |
185 if (B < 56) { | |
186 x = 8 + (B % 7); | |
187 y = B / 7; | |
188 } else { | |
189 x = -14 + ((B - 56) % 29); | |
190 y = 8 + ((B - 56) / 29); | |
191 } | |
192 | |
193 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
194 COPY_FROM_SECOND_LAST(); |
1468 | 195 |
196 /* report success */ | |
197 return 0; | |
198 } | |
199 | |
1475 | 200 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s) |
1468 | 201 { |
202 unsigned char B; | |
203 int x, y; | |
204 int motion_offset; | |
1475 | 205 int current_offset = s->pixel_ptr - s->current_frame.data[0]; |
1468 | 206 |
207 /* copy 8x8 block from current frame from an up/left block */ | |
208 | |
209 /* need 1 more byte for motion */ | |
210 CHECK_STREAM_PTR(1); | |
1475 | 211 B = *s->stream_ptr++; |
1468 | 212 |
213 if (B < 56) { | |
214 x = -(8 + (B % 7)); | |
215 y = -(B / 7); | |
216 } else { | |
217 x = -(-14 + ((B - 56) % 29)); | |
218 y = -( 8 + ((B - 56) / 29)); | |
219 } | |
220 | |
221 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); | |
222 COPY_FROM_CURRENT(); | |
223 | |
224 /* report success */ | |
225 return 0; | |
226 } | |
227 | |
1475 | 228 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s) |
1468 | 229 { |
230 int x, y; | |
231 unsigned char B, BL, BH; | |
232 int motion_offset; | |
1475 | 233 int current_offset = s->pixel_ptr - s->current_frame.data[0]; |
1468 | 234 |
235 /* copy a block from the previous frame; need 1 more byte */ | |
236 CHECK_STREAM_PTR(1); | |
237 | |
1475 | 238 B = *s->stream_ptr++; |
1468 | 239 BL = B & 0x0F; |
240 BH = (B >> 4) & 0x0F; | |
241 x = -8 + BL; | |
242 y = -8 + BH; | |
243 | |
244 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); | |
245 COPY_FROM_PREVIOUS(); | |
246 | |
247 /* report success */ | |
248 return 0; | |
249 } | |
250 | |
1475 | 251 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s) |
1468 | 252 { |
253 signed char x, y; | |
254 int motion_offset; | |
1475 | 255 int current_offset = s->pixel_ptr - s->current_frame.data[0]; |
1468 | 256 |
257 /* copy a block from the previous frame using an expanded range; | |
258 * need 2 more bytes */ | |
259 CHECK_STREAM_PTR(2); | |
260 | |
1475 | 261 x = *s->stream_ptr++; |
262 y = *s->stream_ptr++; | |
1468 | 263 |
264 debug_interplay (" motion bytes = %d, %d\n", x, y); | |
265 COPY_FROM_PREVIOUS(); | |
266 | |
267 /* report success */ | |
268 return 0; | |
269 } | |
270 | |
1475 | 271 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s) |
1468 | 272 { |
273 /* mystery opcode? skip multiple blocks? */ | |
274 printf (" Interplay video: Help! Mystery opcode 0x6 seen\n"); | |
275 | |
276 /* report success */ | |
277 return 0; | |
278 } | |
279 | |
1475 | 280 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s) |
1468 | 281 { |
282 int x, y; | |
283 unsigned char P0, P1; | |
284 unsigned char B[8]; | |
285 unsigned int flags; | |
286 int bitmask; | |
287 | |
288 /* 2-color encoding */ | |
289 CHECK_STREAM_PTR(2); | |
290 | |
1475 | 291 P0 = *s->stream_ptr++; |
292 P1 = *s->stream_ptr++; | |
1468 | 293 |
294 if (P0 <= P1) { | |
295 | |
296 /* need 8 more bytes from the stream */ | |
297 CHECK_STREAM_PTR(8); | |
298 for (y = 0; y < 8; y++) | |
1475 | 299 B[y] = *s->stream_ptr++; |
1468 | 300 |
301 for (y = 0; y < 8; y++) { | |
302 flags = B[y]; | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
303 for (x = 0x01; x <= 0x80; x <<= 1) { |
1468 | 304 if (flags & x) |
1475 | 305 *s->pixel_ptr++ = P1; |
1468 | 306 else |
1475 | 307 *s->pixel_ptr++ = P0; |
1468 | 308 } |
1475 | 309 s->pixel_ptr += s->line_inc; |
1468 | 310 } |
311 | |
312 } else { | |
313 | |
314 /* need 2 more bytes from the stream */ | |
315 CHECK_STREAM_PTR(2); | |
1475 | 316 B[0] = *s->stream_ptr++; |
317 B[1] = *s->stream_ptr++; | |
1468 | 318 |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
319 flags = (B[1] << 8) | B[0]; |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
320 bitmask = 0x0001; |
1468 | 321 for (y = 0; y < 8; y += 2) { |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
322 for (x = 0; x < 8; x += 2, bitmask <<= 1) { |
1468 | 323 if (flags & bitmask) { |
1475 | 324 *(s->pixel_ptr + x) = P1; |
325 *(s->pixel_ptr + x + 1) = P1; | |
326 *(s->pixel_ptr + s->stride + x) = P1; | |
327 *(s->pixel_ptr + s->stride + x + 1) = P1; | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
328 } else { |
1475 | 329 *(s->pixel_ptr + x) = P0; |
330 *(s->pixel_ptr + x + 1) = P0; | |
331 *(s->pixel_ptr + s->stride + x) = P0; | |
332 *(s->pixel_ptr + s->stride + x + 1) = P0; | |
1468 | 333 } |
334 } | |
1475 | 335 s->pixel_ptr += s->stride * 2; |
1468 | 336 } |
337 } | |
338 | |
339 /* report success */ | |
340 return 0; | |
341 } | |
342 | |
1475 | 343 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s) |
1468 | 344 { |
345 int x, y; | |
346 unsigned char P[8]; | |
347 unsigned char B[8]; | |
348 unsigned int flags = 0; | |
349 unsigned int bitmask = 0; | |
350 unsigned char P0 = 0, P1 = 0; | |
351 int lower_half = 0; | |
352 | |
353 /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on | |
354 * either top and bottom or left and right halves */ | |
355 CHECK_STREAM_PTR(2); | |
356 | |
1475 | 357 P[0] = *s->stream_ptr++; |
358 P[1] = *s->stream_ptr++; | |
1468 | 359 |
360 if (P[0] <= P[1]) { | |
361 | |
362 /* need 12 more bytes */ | |
363 CHECK_STREAM_PTR(12); | |
1475 | 364 B[0] = *s->stream_ptr++; B[1] = *s->stream_ptr++; |
365 P[2] = *s->stream_ptr++; P[3] = *s->stream_ptr++; | |
366 B[2] = *s->stream_ptr++; B[3] = *s->stream_ptr++; | |
367 P[4] = *s->stream_ptr++; P[5] = *s->stream_ptr++; | |
368 B[4] = *s->stream_ptr++; B[5] = *s->stream_ptr++; | |
369 P[6] = *s->stream_ptr++; P[7] = *s->stream_ptr++; | |
370 B[6] = *s->stream_ptr++; B[7] = *s->stream_ptr++; | |
1468 | 371 |
372 for (y = 0; y < 8; y++) { | |
373 | |
374 /* time to reload flags? */ | |
375 if (y == 0) { | |
376 flags = | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
377 ((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
378 ((B[0] & 0x0F) ) | ((B[4] & 0x0F) << 4) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
379 ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
380 ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20); |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
381 bitmask = 0x00000001; |
1468 | 382 lower_half = 0; /* still on top half */ |
383 } else if (y == 4) { | |
384 flags = | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
385 ((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
386 ((B[2] & 0x0F) ) | ((B[6] & 0x0F) << 4) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
387 ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
388 ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20); |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
389 bitmask = 0x00000001; |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
390 lower_half = 2; |
1468 | 391 } |
392 | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
393 for (x = 0; x < 8; x++, bitmask <<= 1) { |
1468 | 394 /* get the pixel values ready for this quadrant */ |
395 if (x == 0) { | |
396 P0 = P[lower_half + 0]; | |
397 P1 = P[lower_half + 1]; | |
398 } else if (x == 4) { | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
399 P0 = P[lower_half + 4]; |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
400 P1 = P[lower_half + 5]; |
1468 | 401 } |
402 | |
403 if (flags & bitmask) | |
1475 | 404 *s->pixel_ptr++ = P1; |
1468 | 405 else |
1475 | 406 *s->pixel_ptr++ = P0; |
1468 | 407 } |
1475 | 408 s->pixel_ptr += s->line_inc; |
1468 | 409 } |
410 | |
411 } else { | |
412 | |
413 /* need 10 more bytes */ | |
414 CHECK_STREAM_PTR(10); | |
1475 | 415 B[0] = *s->stream_ptr++; B[1] = *s->stream_ptr++; |
416 B[2] = *s->stream_ptr++; B[3] = *s->stream_ptr++; | |
417 P[2] = *s->stream_ptr++; P[3] = *s->stream_ptr++; | |
418 B[4] = *s->stream_ptr++; B[5] = *s->stream_ptr++; | |
419 B[6] = *s->stream_ptr++; B[7] = *s->stream_ptr++; | |
1468 | 420 |
421 if (P[2] <= P[3]) { | |
422 | |
423 /* vertical split; left & right halves are 2-color encoded */ | |
424 | |
425 for (y = 0; y < 8; y++) { | |
426 | |
427 /* time to reload flags? */ | |
428 if (y == 0) { | |
429 flags = | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
430 ((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
431 ((B[0] & 0x0F) ) | ((B[4] & 0x0F) << 4) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
432 ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
433 ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20); |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
434 bitmask = 0x00000001; |
1468 | 435 } else if (y == 4) { |
436 flags = | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
437 ((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
438 ((B[2] & 0x0F) ) | ((B[6] & 0x0F) << 4) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
439 ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) | |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
440 ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20); |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
441 bitmask = 0x00000001; |
1468 | 442 } |
443 | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
444 for (x = 0; x < 8; x++, bitmask <<= 1) { |
1468 | 445 /* get the pixel values ready for this half */ |
446 if (x == 0) { | |
447 P0 = P[0]; | |
448 P1 = P[1]; | |
449 } else if (x == 4) { | |
450 P0 = P[2]; | |
451 P1 = P[3]; | |
452 } | |
453 | |
454 if (flags & bitmask) | |
1475 | 455 *s->pixel_ptr++ = P1; |
1468 | 456 else |
1475 | 457 *s->pixel_ptr++ = P0; |
1468 | 458 } |
1475 | 459 s->pixel_ptr += s->line_inc; |
1468 | 460 } |
461 | |
462 } else { | |
463 | |
464 /* horizontal split; top & bottom halves are 2-color encoded */ | |
465 | |
466 for (y = 0; y < 8; y++) { | |
467 | |
468 flags = B[y]; | |
469 if (y == 0) { | |
470 P0 = P[0]; | |
471 P1 = P[1]; | |
472 } else if (y == 4) { | |
473 P0 = P[2]; | |
474 P1 = P[3]; | |
475 } | |
476 | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
477 for (bitmask = 0x01; bitmask <= 0x80; bitmask <<= 1) { |
1468 | 478 |
479 if (flags & bitmask) | |
1475 | 480 *s->pixel_ptr++ = P1; |
1468 | 481 else |
1475 | 482 *s->pixel_ptr++ = P0; |
1468 | 483 } |
1475 | 484 s->pixel_ptr += s->line_inc; |
1468 | 485 } |
486 } | |
487 } | |
488 | |
489 /* report success */ | |
490 return 0; | |
491 } | |
492 | |
1475 | 493 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s) |
1468 | 494 { |
495 int x, y; | |
496 unsigned char P[4]; | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
497 unsigned char B[4]; |
1468 | 498 unsigned int flags = 0; |
499 int shifter = 0; | |
500 unsigned char pix; | |
501 | |
502 /* 4-color encoding */ | |
503 CHECK_STREAM_PTR(4); | |
504 | |
505 for (y = 0; y < 4; y++) | |
1475 | 506 P[y] = *s->stream_ptr++; |
1468 | 507 |
508 if ((P[0] <= P[1]) && (P[2] <= P[3])) { | |
509 | |
510 /* 1 of 4 colors for each pixel, need 16 more bytes */ | |
511 CHECK_STREAM_PTR(16); | |
512 | |
513 for (y = 0; y < 8; y++) { | |
514 /* get the next set of 8 2-bit flags */ | |
1475 | 515 flags = (s->stream_ptr[1] << 8) | s->stream_ptr[0]; |
516 s->stream_ptr += 2; | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
517 for (x = 0, shifter = 0; x < 8; x++, shifter += 2) { |
1475 | 518 *s->pixel_ptr++ = P[(flags >> shifter) & 0x03]; |
1468 | 519 } |
1475 | 520 s->pixel_ptr += s->line_inc; |
1468 | 521 } |
522 | |
523 } else if ((P[0] <= P[1]) && (P[2] > P[3])) { | |
524 | |
525 /* 1 of 4 colors for each 2x2 block, need 4 more bytes */ | |
526 CHECK_STREAM_PTR(4); | |
527 | |
1475 | 528 B[0] = *s->stream_ptr++; |
529 B[1] = *s->stream_ptr++; | |
530 B[2] = *s->stream_ptr++; | |
531 B[3] = *s->stream_ptr++; | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
532 flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0]; |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
533 shifter = 0; |
1468 | 534 |
535 for (y = 0; y < 8; y += 2) { | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
536 for (x = 0; x < 8; x += 2, shifter += 2) { |
1468 | 537 pix = P[(flags >> shifter) & 0x03]; |
1475 | 538 *(s->pixel_ptr + x) = pix; |
539 *(s->pixel_ptr + x + 1) = pix; | |
540 *(s->pixel_ptr + s->stride + x) = pix; | |
541 *(s->pixel_ptr + s->stride + x + 1) = pix; | |
1468 | 542 } |
1475 | 543 s->pixel_ptr += s->stride * 2; |
1468 | 544 } |
545 | |
546 } else if ((P[0] > P[1]) && (P[2] <= P[3])) { | |
547 | |
548 /* 1 of 4 colors for each 2x1 block, need 8 more bytes */ | |
549 CHECK_STREAM_PTR(8); | |
550 | |
551 for (y = 0; y < 8; y++) { | |
552 /* time to reload flags? */ | |
553 if ((y == 0) || (y == 4)) { | |
1475 | 554 B[0] = *s->stream_ptr++; |
555 B[1] = *s->stream_ptr++; | |
556 B[2] = *s->stream_ptr++; | |
557 B[3] = *s->stream_ptr++; | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
558 flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0]; |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
559 shifter = 0; |
1468 | 560 } |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
561 for (x = 0; x < 8; x += 2, shifter += 2) { |
1468 | 562 pix = P[(flags >> shifter) & 0x03]; |
1475 | 563 *(s->pixel_ptr + x) = pix; |
564 *(s->pixel_ptr + x + 1) = pix; | |
1468 | 565 } |
1475 | 566 s->pixel_ptr += s->stride; |
1468 | 567 } |
568 | |
569 } else { | |
570 | |
571 /* 1 of 4 colors for each 1x2 block, need 8 more bytes */ | |
572 CHECK_STREAM_PTR(8); | |
573 | |
574 for (y = 0; y < 8; y += 2) { | |
575 /* time to reload flags? */ | |
576 if ((y == 0) || (y == 4)) { | |
1475 | 577 B[0] = *s->stream_ptr++; |
578 B[1] = *s->stream_ptr++; | |
579 B[2] = *s->stream_ptr++; | |
580 B[3] = *s->stream_ptr++; | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
581 flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0]; |
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
582 shifter = 0; |
1468 | 583 } |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
584 for (x = 0; x < 8; x++, shifter += 2) { |
1468 | 585 pix = P[(flags >> shifter) & 0x03]; |
1475 | 586 *(s->pixel_ptr + x) = pix; |
587 *(s->pixel_ptr + s->stride + x) = pix; | |
1468 | 588 } |
1475 | 589 s->pixel_ptr += s->stride * 2; |
1468 | 590 } |
591 } | |
592 | |
593 /* report success */ | |
594 return 0; | |
595 } | |
596 | |
1475 | 597 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s) |
1468 | 598 { |
599 int x, y; | |
600 unsigned char P[16]; | |
601 unsigned char B[16]; | |
602 int flags = 0; | |
603 int shifter = 0; | |
604 int index; | |
605 int split; | |
606 int lower_half; | |
607 | |
608 /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on | |
609 * either top and bottom or left and right halves */ | |
610 CHECK_STREAM_PTR(4); | |
611 | |
612 for (y = 0; y < 4; y++) | |
1475 | 613 P[y] = *s->stream_ptr++; |
1468 | 614 |
615 if (P[0] <= P[1]) { | |
616 | |
617 /* 4-color encoding for each quadrant; need 28 more bytes */ | |
618 CHECK_STREAM_PTR(28); | |
619 | |
620 for (y = 0; y < 4; y++) | |
1475 | 621 B[y] = *s->stream_ptr++; |
1468 | 622 for (y = 4; y < 16; y += 4) { |
623 for (x = y; x < y + 4; x++) | |
1475 | 624 P[x] = *s->stream_ptr++; |
1468 | 625 for (x = y; x < y + 4; x++) |
1475 | 626 B[x] = *s->stream_ptr++; |
1468 | 627 } |
628 | |
629 for (y = 0; y < 8; y++) { | |
630 | |
631 lower_half = (y >= 4) ? 4 : 0; | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
632 flags = (B[y + 8] << 8) | B[y]; |
1468 | 633 |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
634 for (x = 0, shifter = 0; x < 8; x++, shifter += 2) { |
1468 | 635 split = (x >= 4) ? 8 : 0; |
636 index = split + lower_half + ((flags >> shifter) & 0x03); | |
1475 | 637 *s->pixel_ptr++ = P[index]; |
1468 | 638 } |
639 | |
1475 | 640 s->pixel_ptr += s->line_inc; |
1468 | 641 } |
642 | |
643 } else { | |
644 | |
645 /* 4-color encoding for either left and right or top and bottom | |
646 * halves; need 20 more bytes */ | |
647 CHECK_STREAM_PTR(20); | |
648 | |
649 for (y = 0; y < 8; y++) | |
1475 | 650 B[y] = *s->stream_ptr++; |
1468 | 651 for (y = 4; y < 8; y++) |
1475 | 652 P[y] = *s->stream_ptr++; |
1468 | 653 for (y = 8; y < 16; y++) |
1475 | 654 B[y] = *s->stream_ptr++; |
1468 | 655 |
656 if (P[4] <= P[5]) { | |
657 | |
658 /* block is divided into left and right halves */ | |
659 for (y = 0; y < 8; y++) { | |
660 | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
661 flags = (B[y + 8] << 8) | B[y]; |
1468 | 662 split = 0; |
663 | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
664 for (x = 0, shifter = 0; x < 8; x++, shifter += 2) { |
1468 | 665 if (x == 4) |
666 split = 4; | |
1475 | 667 *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)]; |
1468 | 668 } |
669 | |
1475 | 670 s->pixel_ptr += s->line_inc; |
1468 | 671 } |
672 | |
673 } else { | |
674 | |
675 /* block is divided into top and bottom halves */ | |
676 split = 0; | |
677 for (y = 0; y < 8; y++) { | |
678 | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
679 flags = (B[y * 2 + 1] << 8) | B[y * 2]; |
1468 | 680 if (y == 4) |
681 split = 4; | |
682 | |
1473
873100cd2108
wrong, wrong, wrong...coded bits are read in the opposite direction
tmmm
parents:
1468
diff
changeset
|
683 for (x = 0, shifter = 0; x < 8; x++, shifter += 2) |
1475 | 684 *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)]; |
1468 | 685 |
1475 | 686 s->pixel_ptr += s->line_inc; |
1468 | 687 } |
688 } | |
689 } | |
690 | |
691 /* report success */ | |
692 return 0; | |
693 } | |
694 | |
1475 | 695 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s) |
1468 | 696 { |
697 int x, y; | |
698 | |
699 /* 64-color encoding (each pixel in block is a different color) */ | |
700 CHECK_STREAM_PTR(64); | |
701 | |
702 for (y = 0; y < 8; y++) { | |
703 for (x = 0; x < 8; x++) { | |
1475 | 704 *s->pixel_ptr++ = *s->stream_ptr++; |
1468 | 705 } |
1475 | 706 s->pixel_ptr += s->line_inc; |
1468 | 707 } |
708 | |
709 /* report success */ | |
710 return 0; | |
711 } | |
712 | |
1475 | 713 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s) |
1468 | 714 { |
715 int x, y; | |
716 unsigned char pix; | |
717 | |
718 /* 16-color block encoding: each 2x2 block is a different color */ | |
719 CHECK_STREAM_PTR(16); | |
720 | |
721 for (y = 0; y < 8; y += 2) { | |
722 for (x = 0; x < 8; x += 2) { | |
1475 | 723 pix = *s->stream_ptr++; |
724 *(s->pixel_ptr + x) = pix; | |
725 *(s->pixel_ptr + x + 1) = pix; | |
726 *(s->pixel_ptr + s->stride + x) = pix; | |
727 *(s->pixel_ptr + s->stride + x + 1) = pix; | |
1468 | 728 } |
1475 | 729 s->pixel_ptr += s->stride * 2; |
1468 | 730 } |
731 | |
732 /* report success */ | |
733 return 0; | |
734 } | |
735 | |
1475 | 736 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s) |
1468 | 737 { |
738 int x, y; | |
739 unsigned char P[4]; | |
740 unsigned char index = 0; | |
741 | |
742 /* 4-color block encoding: each 4x4 block is a different color */ | |
743 CHECK_STREAM_PTR(4); | |
744 | |
745 for (y = 0; y < 4; y++) | |
1475 | 746 P[y] = *s->stream_ptr++; |
1468 | 747 |
748 for (y = 0; y < 8; y++) { | |
749 if (y < 4) | |
750 index = 0; | |
751 else | |
752 index = 2; | |
753 | |
754 for (x = 0; x < 8; x++) { | |
755 if (x == 4) | |
756 index++; | |
1475 | 757 *s->pixel_ptr++ = P[index]; |
1468 | 758 } |
1475 | 759 s->pixel_ptr += s->line_inc; |
1468 | 760 } |
761 | |
762 /* report success */ | |
763 return 0; | |
764 } | |
765 | |
1475 | 766 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s) |
1468 | 767 { |
768 int x, y; | |
769 unsigned char pix; | |
770 | |
771 /* 1-color encoding: the whole block is 1 solid color */ | |
772 CHECK_STREAM_PTR(1); | |
1475 | 773 pix = *s->stream_ptr++; |
1468 | 774 |
775 for (y = 0; y < 8; y++) { | |
776 for (x = 0; x < 8; x++) { | |
1475 | 777 *s->pixel_ptr++ = pix; |
1468 | 778 } |
1475 | 779 s->pixel_ptr += s->line_inc; |
1468 | 780 } |
781 | |
782 /* report success */ | |
783 return 0; | |
784 } | |
785 | |
1475 | 786 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s) |
1468 | 787 { |
788 int x, y; | |
789 unsigned char sample0, sample1; | |
790 | |
791 /* dithered encoding */ | |
792 CHECK_STREAM_PTR(2); | |
1475 | 793 sample0 = *s->stream_ptr++; |
794 sample1 = *s->stream_ptr++; | |
1468 | 795 |
796 for (y = 0; y < 8; y++) { | |
797 for (x = 0; x < 8; x += 2) { | |
798 if (y & 1) { | |
1475 | 799 *s->pixel_ptr++ = sample1; |
800 *s->pixel_ptr++ = sample0; | |
1468 | 801 } else { |
1475 | 802 *s->pixel_ptr++ = sample0; |
803 *s->pixel_ptr++ = sample1; | |
1468 | 804 } |
805 } | |
1475 | 806 s->pixel_ptr += s->line_inc; |
1468 | 807 } |
808 | |
809 /* report success */ | |
810 return 0; | |
811 } | |
812 | |
1475 | 813 static int (*ipvideo_decode_block[16])(IpvideoContext *s); |
1468 | 814 |
815 static void ipvideo_decode_opcodes(IpvideoContext *s) | |
816 { | |
817 int x, y; | |
818 int index = 0; | |
819 unsigned char opcode; | |
820 int ret; | |
821 int code_counts[16]; | |
822 static int frame = 0; | |
823 | |
824 debug_interplay("------------------ frame %d\n", frame); | |
825 frame++; | |
826 | |
827 for (x = 0; x < 16; x++) | |
828 code_counts[x] = 0; | |
829 | |
830 /* this is PAL8, so make the palette available */ | |
1475 | 831 memcpy(s->current_frame.data[1], s->palette, PALETTE_COUNT * 4); |
1468 | 832 |
1475 | 833 s->stride = s->current_frame.linesize[0]; |
834 s->stream_ptr = s->buf + 14; /* data starts 14 bytes in */ | |
835 s->stream_end = s->buf + s->size; | |
836 s->line_inc = s->stride - 8; | |
837 s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride | |
838 + s->avctx->width - 8; | |
839 s->dsp = s->dsp; | |
1468 | 840 |
1475 | 841 for (y = 0; y < (s->stride * s->avctx->height); y += s->stride * 8) { |
842 for (x = y; x < y + s->avctx->width; x += 8) { | |
843 /* bottom nibble first, then top nibble (which makes it | |
844 * hard to use a GetBitcontext) */ | |
845 if (index & 1) | |
846 opcode = s->decoding_map[index >> 1] >> 4; | |
847 else | |
848 opcode = s->decoding_map[index >> 1] & 0xF; | |
849 index++; | |
1468 | 850 |
1475 | 851 debug_interplay(" block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n", |
852 x - y, y / s->stride, opcode, s->stream_ptr); | |
853 code_counts[opcode]++; | |
1468 | 854 |
1475 | 855 s->pixel_ptr = s->current_frame.data[0] + x; |
856 ret = ipvideo_decode_block[opcode](s); | |
857 if (ret != 0) { | |
858 printf(" Interplay video: decode problem on frame %d, @ block (%d, %d)\n", | |
859 frame, x - y, y / s->stride); | |
860 return; | |
1468 | 861 } |
862 } | |
863 } | |
1475 | 864 if ((s->stream_ptr != s->stream_end) && |
865 (s->stream_ptr + 1 != s->stream_end)) { | |
866 printf (" Interplay video: decode finished with %d bytes left over\n", | |
867 s->stream_end - s->stream_ptr); | |
868 } | |
1468 | 869 } |
870 | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
871 static int ipvideo_decode_init(AVCodecContext *avctx) |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
872 { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
873 IpvideoContext *s = avctx->priv_data; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
874 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
875 s->avctx = avctx; |
1468 | 876 |
877 if (s->avctx->extradata_size != sizeof(AVPaletteControl)) { | |
878 printf (" Interplay video: expected extradata_size of %d\n", | |
879 sizeof(AVPaletteControl)); | |
880 return -1; | |
881 } | |
882 | |
883 avctx->pix_fmt = PIX_FMT_PAL8; | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
884 avctx->has_b_frames = 0; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
885 dsputil_init(&s->dsp, avctx); |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
886 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
887 /* decoding map contains 4 bits of information per 8x8 block */ |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
888 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2); |
1468 | 889 |
890 /* assign block decode functions */ | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
891 ipvideo_decode_block[0x0] = ipvideo_decode_block_opcode_0x0; |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
892 ipvideo_decode_block[0x1] = ipvideo_decode_block_opcode_0x1; |
1468 | 893 ipvideo_decode_block[0x2] = ipvideo_decode_block_opcode_0x2; |
894 ipvideo_decode_block[0x3] = ipvideo_decode_block_opcode_0x3; | |
895 ipvideo_decode_block[0x4] = ipvideo_decode_block_opcode_0x4; | |
896 ipvideo_decode_block[0x5] = ipvideo_decode_block_opcode_0x5; | |
897 ipvideo_decode_block[0x6] = ipvideo_decode_block_opcode_0x6; | |
898 ipvideo_decode_block[0x7] = ipvideo_decode_block_opcode_0x7; | |
899 ipvideo_decode_block[0x8] = ipvideo_decode_block_opcode_0x8; | |
900 ipvideo_decode_block[0x9] = ipvideo_decode_block_opcode_0x9; | |
901 ipvideo_decode_block[0xA] = ipvideo_decode_block_opcode_0xA; | |
902 ipvideo_decode_block[0xB] = ipvideo_decode_block_opcode_0xB; | |
903 ipvideo_decode_block[0xC] = ipvideo_decode_block_opcode_0xC; | |
904 ipvideo_decode_block[0xD] = ipvideo_decode_block_opcode_0xD; | |
905 ipvideo_decode_block[0xE] = ipvideo_decode_block_opcode_0xE; | |
906 ipvideo_decode_block[0xF] = ipvideo_decode_block_opcode_0xF; | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
907 |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
908 s->current_frame.data[0] = s->last_frame.data[0] = |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
909 s->second_last_frame.data[0] = NULL; |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
910 |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
911 return 0; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
912 } |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
913 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
914 static int ipvideo_decode_frame(AVCodecContext *avctx, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
915 void *data, int *data_size, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
916 uint8_t *buf, int buf_size) |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
917 { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
918 IpvideoContext *s = avctx->priv_data; |
1468 | 919 AVPaletteControl *palette_control = (AVPaletteControl *)avctx->extradata; |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
920 |
1468 | 921 if (palette_control->palette_changed) { |
922 /* load the new palette and reset the palette control */ | |
923 ipvideo_new_palette(s, palette_control->palette); | |
924 palette_control->palette_changed = 0; | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
925 } |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
926 |
1468 | 927 s->decoding_map = buf; |
928 s->buf = buf + s->decoding_map_size; | |
929 s->size = buf_size - s->decoding_map_size; | |
930 | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
931 s->current_frame.reference = 3; |
1468 | 932 if (avctx->get_buffer(avctx, &s->current_frame)) { |
933 printf (" Interplay Video: get_buffer() failed\n"); | |
934 return -1; | |
935 } | |
936 | |
937 ipvideo_decode_opcodes(s); | |
938 | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
939 *data_size = sizeof(AVFrame); |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
940 *(AVFrame*)data = s->current_frame; |
1468 | 941 |
942 /* shuffle frames */ | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
943 if (s->second_last_frame.data[0]) |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
944 avctx->release_buffer(avctx, &s->second_last_frame); |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
945 s->second_last_frame = s->last_frame; |
1468 | 946 s->last_frame = s->current_frame; |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
947 s->current_frame.data[0] = NULL; /* catch any access attempts */ |
1468 | 948 |
949 /* report that the buffer was completely consumed */ | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
950 return buf_size; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
951 } |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
952 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
953 static int ipvideo_decode_end(AVCodecContext *avctx) |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
954 { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
955 IpvideoContext *s = avctx->priv_data; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
956 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
957 /* release the last frame */ |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
958 if (s->last_frame.data[0]) |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
959 avctx->release_buffer(avctx, &s->last_frame); |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
960 if (s->second_last_frame.data[0]) |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
961 avctx->release_buffer(avctx, &s->second_last_frame); |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
962 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
963 return 0; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
964 } |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
965 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
966 AVCodec interplay_video_decoder = { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
967 "interplayvideo", |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
968 CODEC_TYPE_VIDEO, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
969 CODEC_ID_INTERPLAY_VIDEO, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
970 sizeof(IpvideoContext), |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
971 ipvideo_decode_init, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
972 NULL, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
973 ipvideo_decode_end, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
974 ipvideo_decode_frame, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
975 CODEC_CAP_DR1, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
976 }; |