Mercurial > libavcodec.hg
annotate interplayvideo.c @ 1545:b340e83b8d0d libavcodec
gcc->C99 and warning fixes patch by (Dan Christiansen <danchr at daimi dot au dot dk>)
| author | michael |
|---|---|
| date | Sun, 19 Oct 2003 21:05:41 +0000 |
| parents | 26eb7678cb46 |
| children | 6b224ca24033 |
| 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", | |
|
1545
b340e83b8d0d
gcc->C99 and warning fixes patch by (Dan Christiansen <danchr at daimi dot au dot dk>)
michael
parents:
1475
diff
changeset
|
879 (int)sizeof(AVPaletteControl)); |
| 1468 | 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 }; |
