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