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