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