Mercurial > libavcodec.hg
annotate interplayvideo.c @ 10311:943b63f364ca libavcodec
Make sure all the bits are written to output in fax data decoder.
This fixes decoding TIFF images with fax compression and width being not
multiple of eight (and issue 1429).
author | kostya |
---|---|
date | Tue, 29 Sep 2009 05:55:14 +0000 |
parents | 5da84f0d0a55 |
children | 09227c145beb |
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 /** |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
7040
diff
changeset
|
23 * @file libavcodec/interplayvideo.c |
1468 | 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 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
41 #include "avcodec.h" |
5089 | 42 #include "bytestream.h" |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
43 #include "dsputil.h" |
9494
e09e4c095fdb
Simplify ipvideo_decode_opcodes by using get_bits, this might be slower
reimar
parents:
9493
diff
changeset
|
44 #define ALT_BITSTREAM_READER_LE |
e09e4c095fdb
Simplify ipvideo_decode_opcodes by using get_bits, this might be slower
reimar
parents:
9493
diff
changeset
|
45 #include "get_bits.h" |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
46 |
1468 | 47 #define PALETTE_COUNT 256 |
48 | |
49 /* debugging support */ | |
50 #define DEBUG_INTERPLAY 0 | |
51 #if DEBUG_INTERPLAY | |
2515 | 52 #define debug_interplay(x,...) av_log(NULL, AV_LOG_DEBUG, x, __VA_ARGS__) |
1468 | 53 #else |
54 static inline void debug_interplay(const char *format, ...) { } | |
55 #endif | |
56 | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
57 typedef struct IpvideoContext { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
58 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
59 AVCodecContext *avctx; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
60 DSPContext dsp; |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
61 AVFrame second_last_frame; |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
62 AVFrame last_frame; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
63 AVFrame current_frame; |
6218 | 64 const unsigned char *decoding_map; |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
65 int decoding_map_size; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
66 |
6218 | 67 const unsigned char *buf; |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
68 int size; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
69 |
6218 | 70 const unsigned char *stream_ptr; |
71 const unsigned char *stream_end; | |
1475 | 72 unsigned char *pixel_ptr; |
73 int line_inc; | |
74 int stride; | |
75 int upper_motion_limit_offset; | |
76 | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
77 } IpvideoContext; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
78 |
1468 | 79 #define CHECK_STREAM_PTR(n) \ |
9276
c80d14982fba
Change CHECK_STREAM_PTR macro to correctly handle the (extremely unlikely)
reimar
parents:
9275
diff
changeset
|
80 if (s->stream_end - s->stream_ptr < n) { \ |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
81 av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \ |
1475 | 82 s->stream_ptr + n, s->stream_end); \ |
1468 | 83 return -1; \ |
84 } | |
85 | |
9277
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
86 static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y) |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
87 { |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
88 int current_offset = s->pixel_ptr - s->current_frame.data[0]; |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
89 int motion_offset = current_offset + delta_y * s->stride + delta_x; |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
90 if (motion_offset < 0) { |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
91 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset); |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
92 return -1; |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
93 } else if (motion_offset > s->upper_motion_limit_offset) { |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
94 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n", |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
95 motion_offset, s->upper_motion_limit_offset); |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
96 return -1; |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
97 } |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
98 s->dsp.put_pixels_tab[1][0](s->pixel_ptr, src->data[0] + motion_offset, s->stride, 8); |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
99 return 0; |
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
100 } |
1475 | 101 |
102 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s) | |
1468 | 103 { |
9277
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
104 return copy_from(s, &s->last_frame, 0, 0); |
1468 | 105 } |
106 | |
1475 | 107 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
|
108 { |
9277
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
109 return copy_from(s, &s->second_last_frame, 0, 0); |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
110 } |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
111 |
1475 | 112 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s) |
1468 | 113 { |
114 unsigned char B; | |
115 int x, y; | |
116 | |
1475 | 117 /* copy block from 2 frames ago using a motion vector; need 1 more byte */ |
1468 | 118 CHECK_STREAM_PTR(1); |
1475 | 119 B = *s->stream_ptr++; |
1468 | 120 |
121 if (B < 56) { | |
122 x = 8 + (B % 7); | |
123 y = B / 7; | |
124 } else { | |
125 x = -14 + ((B - 56) % 29); | |
126 y = 8 + ((B - 56) / 29); | |
127 } | |
128 | |
129 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); | |
9277
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
130 return copy_from(s, &s->second_last_frame, x, y); |
1468 | 131 } |
132 | |
1475 | 133 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s) |
1468 | 134 { |
135 unsigned char B; | |
136 int x, y; | |
137 | |
138 /* copy 8x8 block from current frame from an up/left block */ | |
139 | |
140 /* need 1 more byte for motion */ | |
141 CHECK_STREAM_PTR(1); | |
1475 | 142 B = *s->stream_ptr++; |
1468 | 143 |
144 if (B < 56) { | |
145 x = -(8 + (B % 7)); | |
146 y = -(B / 7); | |
147 } else { | |
148 x = -(-14 + ((B - 56) % 29)); | |
149 y = -( 8 + ((B - 56) / 29)); | |
150 } | |
151 | |
152 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); | |
9277
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
153 return copy_from(s, &s->current_frame, x, y); |
1468 | 154 } |
155 | |
1475 | 156 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s) |
1468 | 157 { |
158 int x, y; | |
159 unsigned char B, BL, BH; | |
160 | |
161 /* copy a block from the previous frame; need 1 more byte */ | |
162 CHECK_STREAM_PTR(1); | |
163 | |
1475 | 164 B = *s->stream_ptr++; |
1468 | 165 BL = B & 0x0F; |
166 BH = (B >> 4) & 0x0F; | |
167 x = -8 + BL; | |
168 y = -8 + BH; | |
169 | |
170 debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); | |
9277
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
171 return copy_from(s, &s->last_frame, x, y); |
1468 | 172 } |
173 | |
1475 | 174 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s) |
1468 | 175 { |
176 signed char x, y; | |
177 | |
178 /* copy a block from the previous frame using an expanded range; | |
179 * need 2 more bytes */ | |
180 CHECK_STREAM_PTR(2); | |
181 | |
1475 | 182 x = *s->stream_ptr++; |
183 y = *s->stream_ptr++; | |
1468 | 184 |
185 debug_interplay (" motion bytes = %d, %d\n", x, y); | |
9277
b8e5b7edb2d5
Merge the 3 COPY_FROM_* macros with lots of duplicated code into a single
reimar
parents:
9276
diff
changeset
|
186 return copy_from(s, &s->last_frame, x, y); |
1468 | 187 } |
188 | |
1475 | 189 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s) |
1468 | 190 { |
191 /* mystery opcode? skip multiple blocks? */ | |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
192 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: Help! Mystery opcode 0x6 seen\n"); |
1468 | 193 |
194 /* report success */ | |
195 return 0; | |
196 } | |
197 | |
1475 | 198 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s) |
1468 | 199 { |
200 int x, y; | |
9298
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
201 unsigned char P[2]; |
1468 | 202 unsigned int flags; |
203 | |
204 /* 2-color encoding */ | |
205 CHECK_STREAM_PTR(2); | |
206 | |
9298
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
207 P[0] = *s->stream_ptr++; |
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
208 P[1] = *s->stream_ptr++; |
1468 | 209 |
9298
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
210 if (P[0] <= P[1]) { |
1468 | 211 |
212 /* need 8 more bytes from the stream */ | |
213 CHECK_STREAM_PTR(8); | |
214 | |
215 for (y = 0; y < 8; y++) { | |
9307
851ca5db8327
Avoid the last two uses of bitmasks in interplayvideo
reimar
parents:
9306
diff
changeset
|
216 flags = *s->stream_ptr++ | 0x100; |
9319 | 217 for (; flags != 1; flags >>= 1) |
9307
851ca5db8327
Avoid the last two uses of bitmasks in interplayvideo
reimar
parents:
9306
diff
changeset
|
218 *s->pixel_ptr++ = P[flags & 1]; |
1475 | 219 s->pixel_ptr += s->line_inc; |
1468 | 220 } |
221 | |
222 } else { | |
223 | |
224 /* need 2 more bytes from the stream */ | |
225 CHECK_STREAM_PTR(2); | |
226 | |
5089 | 227 flags = bytestream_get_le16(&s->stream_ptr); |
1468 | 228 for (y = 0; y < 8; y += 2) { |
9296
2129ee5b7e0d
Get rid of some pointless bitmask/shifter variables in interplayvideo.c
reimar
parents:
9277
diff
changeset
|
229 for (x = 0; x < 8; x += 2, flags >>= 1) { |
9299 | 230 s->pixel_ptr[x ] = |
231 s->pixel_ptr[x + 1 ] = | |
232 s->pixel_ptr[x + s->stride] = | |
233 s->pixel_ptr[x + 1 + s->stride] = P[flags & 1]; | |
1468 | 234 } |
1475 | 235 s->pixel_ptr += s->stride * 2; |
1468 | 236 } |
237 } | |
238 | |
239 /* report success */ | |
240 return 0; | |
241 } | |
242 | |
1475 | 243 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s) |
1468 | 244 { |
245 int x, y; | |
9312
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
246 unsigned char P[2]; |
1468 | 247 unsigned int flags = 0; |
248 | |
249 /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on | |
250 * either top and bottom or left and right halves */ | |
251 CHECK_STREAM_PTR(2); | |
252 | |
1475 | 253 P[0] = *s->stream_ptr++; |
254 P[1] = *s->stream_ptr++; | |
1468 | 255 |
256 if (P[0] <= P[1]) { | |
257 | |
9311
5d20b2610662
Fix a too small CHECK_STREAM_PTR value in interplayvideo.c
reimar
parents:
9307
diff
changeset
|
258 CHECK_STREAM_PTR(14); |
9312
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
259 s->stream_ptr -= 2; |
1468 | 260 |
9312
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
261 for (y = 0; y < 16; y++) { |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
262 // new values for each 4x4 block |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
263 if (!(y & 3)) { |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
264 P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++; |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
265 flags = bytestream_get_le16(&s->stream_ptr); |
1468 | 266 } |
267 | |
9319 | 268 for (x = 0; x < 4; x++, flags >>= 1) |
9312
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
269 *s->pixel_ptr++ = P[flags & 1]; |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
270 s->pixel_ptr += s->stride - 4; |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
271 // switch to right half |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
272 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4; |
1468 | 273 } |
274 | |
275 } else { | |
276 | |
277 /* need 10 more bytes */ | |
278 CHECK_STREAM_PTR(10); | |
279 | |
9306 | 280 if (s->stream_ptr[4] <= s->stream_ptr[5]) { |
1468 | 281 |
9312
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
282 flags = bytestream_get_le32(&s->stream_ptr); |
9300
6a1aacfa3043
Slightly simplify part of ipvideo_decode_block_opcode_0x8
reimar
parents:
9299
diff
changeset
|
283 |
1468 | 284 /* vertical split; left & right halves are 2-color encoded */ |
285 | |
9312
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
286 for (y = 0; y < 16; y++) { |
9319 | 287 for (x = 0; x < 4; x++, flags >>= 1) |
9312
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
288 *s->pixel_ptr++ = P[flags & 1]; |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
289 s->pixel_ptr += s->stride - 4; |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
290 // switch to right half |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
291 if (y == 7) { |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
292 s->pixel_ptr -= 8 * s->stride - 4; |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
293 P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++; |
601e91e470e7
Make ipvideo_decode_block_opcode_0x8 a lot simpler by decoding the pixels
reimar
parents:
9311
diff
changeset
|
294 flags = bytestream_get_le32(&s->stream_ptr); |
1468 | 295 } |
296 } | |
297 | |
298 } else { | |
299 | |
300 /* horizontal split; top & bottom halves are 2-color encoded */ | |
301 | |
302 for (y = 0; y < 8; y++) { | |
9300
6a1aacfa3043
Slightly simplify part of ipvideo_decode_block_opcode_0x8
reimar
parents:
9299
diff
changeset
|
303 if (y == 4) { |
6a1aacfa3043
Slightly simplify part of ipvideo_decode_block_opcode_0x8
reimar
parents:
9299
diff
changeset
|
304 P[0] = *s->stream_ptr++; |
6a1aacfa3043
Slightly simplify part of ipvideo_decode_block_opcode_0x8
reimar
parents:
9299
diff
changeset
|
305 P[1] = *s->stream_ptr++; |
1468 | 306 } |
9307
851ca5db8327
Avoid the last two uses of bitmasks in interplayvideo
reimar
parents:
9306
diff
changeset
|
307 flags = *s->stream_ptr++ | 0x100; |
1468 | 308 |
9319 | 309 for (; flags != 1; flags >>= 1) |
9307
851ca5db8327
Avoid the last two uses of bitmasks in interplayvideo
reimar
parents:
9306
diff
changeset
|
310 *s->pixel_ptr++ = P[flags & 1]; |
1475 | 311 s->pixel_ptr += s->line_inc; |
1468 | 312 } |
313 } | |
314 } | |
315 | |
316 /* report success */ | |
317 return 0; | |
318 } | |
319 | |
1475 | 320 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s) |
1468 | 321 { |
322 int x, y; | |
323 unsigned char P[4]; | |
324 | |
325 /* 4-color encoding */ | |
326 CHECK_STREAM_PTR(4); | |
327 | |
9273
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
328 memcpy(P, s->stream_ptr, 4); |
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
329 s->stream_ptr += 4; |
1468 | 330 |
9303
2ae6ab3fa3ba
Rearrange how the different cases are checked to reduce the number of
reimar
parents:
9302
diff
changeset
|
331 if (P[0] <= P[1]) { |
2ae6ab3fa3ba
Rearrange how the different cases are checked to reduce the number of
reimar
parents:
9302
diff
changeset
|
332 if (P[2] <= P[3]) { |
1468 | 333 |
9305 | 334 /* 1 of 4 colors for each pixel, need 16 more bytes */ |
335 CHECK_STREAM_PTR(16); | |
1468 | 336 |
9305 | 337 for (y = 0; y < 8; y++) { |
338 /* get the next set of 8 2-bit flags */ | |
339 int flags = bytestream_get_le16(&s->stream_ptr); | |
9319 | 340 for (x = 0; x < 8; x++, flags >>= 2) |
9305 | 341 *s->pixel_ptr++ = P[flags & 0x03]; |
342 s->pixel_ptr += s->line_inc; | |
1468 | 343 } |
344 | |
9303
2ae6ab3fa3ba
Rearrange how the different cases are checked to reduce the number of
reimar
parents:
9302
diff
changeset
|
345 } else { |
9305 | 346 uint32_t flags; |
1468 | 347 |
9305 | 348 /* 1 of 4 colors for each 2x2 block, need 4 more bytes */ |
349 CHECK_STREAM_PTR(4); | |
1468 | 350 |
9305 | 351 flags = bytestream_get_le32(&s->stream_ptr); |
1468 | 352 |
9305 | 353 for (y = 0; y < 8; y += 2) { |
354 for (x = 0; x < 8; x += 2, flags >>= 2) { | |
355 s->pixel_ptr[x ] = | |
356 s->pixel_ptr[x + 1 ] = | |
357 s->pixel_ptr[x + s->stride] = | |
358 s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03]; | |
359 } | |
360 s->pixel_ptr += s->stride * 2; | |
1468 | 361 } |
362 | |
9303
2ae6ab3fa3ba
Rearrange how the different cases are checked to reduce the number of
reimar
parents:
9302
diff
changeset
|
363 } |
2ae6ab3fa3ba
Rearrange how the different cases are checked to reduce the number of
reimar
parents:
9302
diff
changeset
|
364 } else { |
9302
0469949a5224
Avoid "reloading" code by using a 64 bit type for the flags and loading all at once.
reimar
parents:
9301
diff
changeset
|
365 uint64_t flags; |
1468 | 366 |
9304 | 367 /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */ |
1468 | 368 CHECK_STREAM_PTR(8); |
369 | |
9302
0469949a5224
Avoid "reloading" code by using a 64 bit type for the flags and loading all at once.
reimar
parents:
9301
diff
changeset
|
370 flags = bytestream_get_le64(&s->stream_ptr); |
9304 | 371 if (P[2] <= P[3]) { |
9305 | 372 for (y = 0; y < 8; y++) { |
373 for (x = 0; x < 8; x += 2, flags >>= 2) { | |
374 s->pixel_ptr[x ] = | |
375 s->pixel_ptr[x + 1] = P[flags & 0x03]; | |
376 } | |
377 s->pixel_ptr += s->stride; | |
1468 | 378 } |
9303
2ae6ab3fa3ba
Rearrange how the different cases are checked to reduce the number of
reimar
parents:
9302
diff
changeset
|
379 } else { |
9305 | 380 for (y = 0; y < 8; y += 2) { |
381 for (x = 0; x < 8; x++, flags >>= 2) { | |
382 s->pixel_ptr[x ] = | |
383 s->pixel_ptr[x + s->stride] = P[flags & 0x03]; | |
384 } | |
385 s->pixel_ptr += s->stride * 2; | |
1468 | 386 } |
9303
2ae6ab3fa3ba
Rearrange how the different cases are checked to reduce the number of
reimar
parents:
9302
diff
changeset
|
387 } |
1468 | 388 } |
389 | |
390 /* report success */ | |
391 return 0; | |
392 } | |
393 | |
1475 | 394 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s) |
1468 | 395 { |
396 int x, y; | |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
397 unsigned char P[4]; |
1468 | 398 int flags = 0; |
399 | |
400 /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on | |
401 * either top and bottom or left and right halves */ | |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
402 CHECK_STREAM_PTR(24); |
1468 | 403 |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
404 if (s->stream_ptr[0] <= s->stream_ptr[1]) { |
1468 | 405 |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
406 /* 4-color encoding for each quadrant; need 32 bytes */ |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
407 CHECK_STREAM_PTR(32); |
1468 | 408 |
9315
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
409 for (y = 0; y < 16; y++) { |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
410 // new values for each 4x4 block |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
411 if (!(y & 3)) { |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
412 memcpy(P, s->stream_ptr, 4); |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
413 s->stream_ptr += 4; |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
414 flags = bytestream_get_le32(&s->stream_ptr); |
1468 | 415 } |
416 | |
9319 | 417 for (x = 0; x < 4; x++, flags >>= 2) |
9315
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
418 *s->pixel_ptr++ = P[flags & 0x03]; |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
419 |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
420 s->pixel_ptr += s->stride - 4; |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
421 // switch to right half |
a476e5590725
Slightly simplify first part of ipvideo_decode_block_opcode_0xA,
reimar
parents:
9312
diff
changeset
|
422 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4; |
1468 | 423 } |
424 | |
425 } else { | |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
426 // vertical split? |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
427 int vert = s->stream_ptr[12] <= s->stream_ptr[13]; |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
428 uint64_t flags = 0; |
1468 | 429 |
430 /* 4-color encoding for either left and right or top and bottom | |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
431 * halves */ |
1468 | 432 |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
433 for (y = 0; y < 16; y++) { |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
434 // load values for each half |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
435 if (!(y & 7)) { |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
436 memcpy(P, s->stream_ptr, 4); |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
437 s->stream_ptr += 4; |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
438 flags = bytestream_get_le64(&s->stream_ptr); |
1468 | 439 } |
440 | |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
441 for (x = 0; x < 4; x++, flags >>= 2) |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
442 *s->pixel_ptr++ = P[flags & 0x03]; |
1468 | 443 |
9317
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
444 if (vert) { |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
445 s->pixel_ptr += s->stride - 4; |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
446 // switch to right half |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
447 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4; |
2c06c31c8664
One more simplification for ipvideo_decode_block_opcode_0xA
reimar
parents:
9315
diff
changeset
|
448 } else if (y & 1) s->pixel_ptr += s->line_inc; |
1468 | 449 } |
450 } | |
451 | |
452 /* report success */ | |
453 return 0; | |
454 } | |
455 | |
1475 | 456 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s) |
1468 | 457 { |
9273
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
458 int y; |
1468 | 459 |
460 /* 64-color encoding (each pixel in block is a different color) */ | |
461 CHECK_STREAM_PTR(64); | |
462 | |
463 for (y = 0; y < 8; y++) { | |
9273
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
464 memcpy(s->pixel_ptr, s->stream_ptr, 8); |
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
465 s->stream_ptr += 8; |
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
466 s->pixel_ptr += s->stride; |
1468 | 467 } |
468 | |
469 /* report success */ | |
470 return 0; | |
471 } | |
472 | |
1475 | 473 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s) |
1468 | 474 { |
475 int x, y; | |
476 | |
477 /* 16-color block encoding: each 2x2 block is a different color */ | |
478 CHECK_STREAM_PTR(16); | |
479 | |
480 for (y = 0; y < 8; y += 2) { | |
481 for (x = 0; x < 8; x += 2) { | |
9297 | 482 s->pixel_ptr[x ] = |
483 s->pixel_ptr[x + 1 ] = | |
484 s->pixel_ptr[x + s->stride] = | |
9301 | 485 s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++; |
1468 | 486 } |
1475 | 487 s->pixel_ptr += s->stride * 2; |
1468 | 488 } |
489 | |
490 /* report success */ | |
491 return 0; | |
492 } | |
493 | |
1475 | 494 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s) |
1468 | 495 { |
9273
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
496 int y; |
9322 | 497 unsigned char P[2]; |
1468 | 498 |
499 /* 4-color block encoding: each 4x4 block is a different color */ | |
500 CHECK_STREAM_PTR(4); | |
501 | |
9322 | 502 for (y = 0; y < 8; y++) { |
503 if (!(y & 3)) { | |
504 P[0] = *s->stream_ptr++; | |
505 P[1] = *s->stream_ptr++; | |
506 } | |
507 memset(s->pixel_ptr, P[0], 4); | |
508 memset(s->pixel_ptr + 4, P[1], 4); | |
9273
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
509 s->pixel_ptr += s->stride; |
1468 | 510 } |
511 | |
512 /* report success */ | |
513 return 0; | |
514 } | |
515 | |
1475 | 516 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s) |
1468 | 517 { |
9273
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
518 int y; |
1468 | 519 unsigned char pix; |
520 | |
521 /* 1-color encoding: the whole block is 1 solid color */ | |
522 CHECK_STREAM_PTR(1); | |
1475 | 523 pix = *s->stream_ptr++; |
1468 | 524 |
525 for (y = 0; y < 8; y++) { | |
9273
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
526 memset(s->pixel_ptr, pix, 8); |
42c63846b321
Replace many tiny loops in the interplayvideo decoder by memset, memcpy
reimar
parents:
9272
diff
changeset
|
527 s->pixel_ptr += s->stride; |
1468 | 528 } |
529 | |
530 /* report success */ | |
531 return 0; | |
532 } | |
533 | |
1475 | 534 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s) |
1468 | 535 { |
536 int x, y; | |
9298
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
537 unsigned char sample[2]; |
1468 | 538 |
539 /* dithered encoding */ | |
540 CHECK_STREAM_PTR(2); | |
9298
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
541 sample[0] = *s->stream_ptr++; |
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
542 sample[1] = *s->stream_ptr++; |
1468 | 543 |
544 for (y = 0; y < 8; y++) { | |
545 for (x = 0; x < 8; x += 2) { | |
9298
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
546 *s->pixel_ptr++ = sample[ y & 1 ]; |
9698f0d03ed9
Avoid code duplication by using ?: and array indexing instead of if..else
reimar
parents:
9297
diff
changeset
|
547 *s->pixel_ptr++ = sample[!(y & 1)]; |
1468 | 548 } |
1475 | 549 s->pixel_ptr += s->line_inc; |
1468 | 550 } |
551 | |
552 /* report success */ | |
553 return 0; | |
554 } | |
555 | |
9272
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
556 static int (* const ipvideo_decode_block[])(IpvideoContext *s) = { |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
557 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
558 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
559 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
560 ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
561 ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
562 ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
563 ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
564 ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF, |
bb2fa003a336
Make ipvideo_decode_block array constant, compile-time initialized instead
reimar
parents:
9127
diff
changeset
|
565 }; |
1468 | 566 |
567 static void ipvideo_decode_opcodes(IpvideoContext *s) | |
568 { | |
569 int x, y; | |
570 unsigned char opcode; | |
571 int ret; | |
572 static int frame = 0; | |
9494
e09e4c095fdb
Simplify ipvideo_decode_opcodes by using get_bits, this might be slower
reimar
parents:
9493
diff
changeset
|
573 GetBitContext gb; |
1468 | 574 |
575 debug_interplay("------------------ frame %d\n", frame); | |
576 frame++; | |
577 | |
578 /* 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
|
579 memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4); |
1468 | 580 |
1475 | 581 s->stride = s->current_frame.linesize[0]; |
582 s->stream_ptr = s->buf + 14; /* data starts 14 bytes in */ | |
583 s->stream_end = s->buf + s->size; | |
584 s->line_inc = s->stride - 8; | |
585 s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride | |
586 + s->avctx->width - 8; | |
1468 | 587 |
9494
e09e4c095fdb
Simplify ipvideo_decode_opcodes by using get_bits, this might be slower
reimar
parents:
9493
diff
changeset
|
588 init_get_bits(&gb, s->decoding_map, s->decoding_map_size * 8); |
1475 | 589 for (y = 0; y < (s->stride * s->avctx->height); y += s->stride * 8) { |
590 for (x = y; x < y + s->avctx->width; x += 8) { | |
9494
e09e4c095fdb
Simplify ipvideo_decode_opcodes by using get_bits, this might be slower
reimar
parents:
9493
diff
changeset
|
591 opcode = get_bits(&gb, 4); |
1468 | 592 |
1475 | 593 debug_interplay(" block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n", |
594 x - y, y / s->stride, opcode, s->stream_ptr); | |
1468 | 595 |
1475 | 596 s->pixel_ptr = s->current_frame.data[0] + x; |
597 ret = ipvideo_decode_block[opcode](s); | |
598 if (ret != 0) { | |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
599 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n", |
1475 | 600 frame, x - y, y / s->stride); |
601 return; | |
1468 | 602 } |
603 } | |
604 } | |
9275
67cf9d31724c
Simplify check for leftover bytes after decoding for interplayvideo.
reimar
parents:
9274
diff
changeset
|
605 if (s->stream_end - s->stream_ptr > 1) { |
2962 | 606 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n", |
1475 | 607 s->stream_end - s->stream_ptr); |
608 } | |
1468 | 609 } |
610 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6483
diff
changeset
|
611 static av_cold int ipvideo_decode_init(AVCodecContext *avctx) |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
612 { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
613 IpvideoContext *s = avctx->priv_data; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
614 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
615 s->avctx = avctx; |
1468 | 616 |
1585
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1545
diff
changeset
|
617 if (s->avctx->palctrl == NULL) { |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
618 av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.\n"); |
1468 | 619 return -1; |
620 } | |
621 | |
622 avctx->pix_fmt = PIX_FMT_PAL8; | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
623 dsputil_init(&s->dsp, avctx); |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
624 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
625 /* 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
|
626 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2); |
1468 | 627 |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
628 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
|
629 s->second_last_frame.data[0] = NULL; |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
630 |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
631 return 0; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
632 } |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
633 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
634 static int ipvideo_decode_frame(AVCodecContext *avctx, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
635 void *data, int *data_size, |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9322
diff
changeset
|
636 AVPacket *avpkt) |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
637 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9322
diff
changeset
|
638 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9322
diff
changeset
|
639 int buf_size = avpkt->size; |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
640 IpvideoContext *s = avctx->priv_data; |
1585
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1545
diff
changeset
|
641 AVPaletteControl *palette_control = avctx->palctrl; |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
642 |
1770 | 643 /* compressed buffer needs to be large enough to at least hold an entire |
644 * decoding map */ | |
645 if (buf_size < s->decoding_map_size) | |
646 return buf_size; | |
647 | |
1468 | 648 s->decoding_map = buf; |
649 s->buf = buf + s->decoding_map_size; | |
650 s->size = buf_size - s->decoding_map_size; | |
651 | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
652 s->current_frame.reference = 3; |
1468 | 653 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
|
654 av_log(avctx, AV_LOG_ERROR, " Interplay Video: get_buffer() failed\n"); |
1468 | 655 return -1; |
656 } | |
657 | |
658 ipvideo_decode_opcodes(s); | |
659 | |
1585
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1545
diff
changeset
|
660 if (palette_control->palette_changed) { |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1545
diff
changeset
|
661 palette_control->palette_changed = 0; |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1545
diff
changeset
|
662 s->current_frame.palette_has_changed = 1; |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1545
diff
changeset
|
663 } |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1545
diff
changeset
|
664 |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
665 *data_size = sizeof(AVFrame); |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
666 *(AVFrame*)data = s->current_frame; |
1468 | 667 |
668 /* shuffle frames */ | |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
669 if (s->second_last_frame.data[0]) |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
670 avctx->release_buffer(avctx, &s->second_last_frame); |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
671 s->second_last_frame = s->last_frame; |
1468 | 672 s->last_frame = s->current_frame; |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
673 s->current_frame.data[0] = NULL; /* catch any access attempts */ |
1468 | 674 |
675 /* report that the buffer was completely consumed */ | |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
676 return buf_size; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
677 } |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
678 |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6483
diff
changeset
|
679 static av_cold int ipvideo_decode_end(AVCodecContext *avctx) |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
680 { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
681 IpvideoContext *s = avctx->priv_data; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
682 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
683 /* release the last frame */ |
1474
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
684 if (s->last_frame.data[0]) |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
685 avctx->release_buffer(avctx, &s->last_frame); |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
686 if (s->second_last_frame.data[0]) |
94c7f7c23dd9
video looks beautiful now, many thanks to Alexander Belyakov
tmmm
parents:
1473
diff
changeset
|
687 avctx->release_buffer(avctx, &s->second_last_frame); |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
688 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
689 return 0; |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
690 } |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
691 |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
692 AVCodec interplay_video_decoder = { |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
693 "interplayvideo", |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
694 CODEC_TYPE_VIDEO, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
695 CODEC_ID_INTERPLAY_VIDEO, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
696 sizeof(IpvideoContext), |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
697 ipvideo_decode_init, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
698 NULL, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
699 ipvideo_decode_end, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
700 ipvideo_decode_frame, |
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
701 CODEC_CAP_DR1, |
9083
bf274494b66e
Change a bunch of codec long_names to be more consistent and descriptive.
diego
parents:
8718
diff
changeset
|
702 .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"), |
1439
a4d00b1f0271
initial commit for Id RoQ and Interplay MVE multimedia subsystems
tmmm
parents:
diff
changeset
|
703 }; |