FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/iff.c
Date: 2024-07-17 14:05:47
Exec Total Coverage
Lines: 136 1090 12.5%
Functions: 8 28 28.6%
Branches: 73 820 8.9%

Line Branch Exec Source
1 /*
2 * IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN bitmap decoder
3 * Copyright (c) 2010 Peter Ross <pross@xvid.org>
4 * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
5 * Copyright (c) 2016 Paul B Mahol
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /**
25 * @file
26 * IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN bitmap decoder
27 */
28
29 #include <stdint.h>
30
31 #include "libavutil/imgutils.h"
32 #include "libavutil/mem.h"
33
34 #include "bytestream.h"
35 #include "avcodec.h"
36 #include "codec_internal.h"
37 #include "decode.h"
38
39 // TODO: masking bits
40 typedef enum {
41 MASK_NONE,
42 MASK_HAS_MASK,
43 MASK_HAS_TRANSPARENT_COLOR,
44 MASK_LASSO
45 } mask_type;
46
47 typedef struct IffContext {
48 int planesize;
49 uint8_t * planebuf;
50 uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation
51 uint32_t *ham_palbuf; ///< HAM decode table
52 uint32_t *mask_buf; ///< temporary buffer for palette indices
53 uint32_t *mask_palbuf; ///< masking palette table
54 unsigned compression; ///< delta compression method used
55 unsigned is_short; ///< short compression method used
56 unsigned is_interlaced;///< video is interlaced
57 unsigned is_brush; ///< video is in ANBR format
58 unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
59 unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
60 unsigned flags; ///< 1 for EHB, 0 is no extra half darkening
61 unsigned transparency; ///< TODO: transparency color index in palette
62 unsigned masking; ///< TODO: masking method used
63 int init; // 1 if buffer and palette data already initialized, 0 otherwise
64 int16_t tvdc[16]; ///< TVDC lookup table
65 uint8_t *video[2];
66 unsigned video_size;
67 uint32_t *pal;
68 } IffContext;
69
70 #define LUT8_PART(plane, v) \
71 AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \
72 AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \
73 AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \
74 AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \
75 AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \
76 AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \
77 AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \
78 AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \
79 AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \
80 AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \
81 AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \
82 AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \
83 AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \
84 AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \
85 AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \
86 AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
87
88 #define LUT8(plane) { \
89 LUT8_PART(plane, 0x0000000), \
90 LUT8_PART(plane, 0x1000000), \
91 LUT8_PART(plane, 0x0010000), \
92 LUT8_PART(plane, 0x1010000), \
93 LUT8_PART(plane, 0x0000100), \
94 LUT8_PART(plane, 0x1000100), \
95 LUT8_PART(plane, 0x0010100), \
96 LUT8_PART(plane, 0x1010100), \
97 LUT8_PART(plane, 0x0000001), \
98 LUT8_PART(plane, 0x1000001), \
99 LUT8_PART(plane, 0x0010001), \
100 LUT8_PART(plane, 0x1010001), \
101 LUT8_PART(plane, 0x0000101), \
102 LUT8_PART(plane, 0x1000101), \
103 LUT8_PART(plane, 0x0010101), \
104 LUT8_PART(plane, 0x1010101), \
105 }
106
107 // 8 planes * 8-bit mask
108 static const uint64_t plane8_lut[8][256] = {
109 LUT8(0), LUT8(1), LUT8(2), LUT8(3),
110 LUT8(4), LUT8(5), LUT8(6), LUT8(7),
111 };
112
113 #define LUT32(plane) { \
114 0, 0, 0, 0, \
115 0, 0, 0, 1U << plane, \
116 0, 0, 1U << plane, 0, \
117 0, 0, 1U << plane, 1U << plane, \
118 0, 1U << plane, 0, 0, \
119 0, 1U << plane, 0, 1U << plane, \
120 0, 1U << plane, 1U << plane, 0, \
121 0, 1U << plane, 1U << plane, 1U << plane, \
122 1U << plane, 0, 0, 0, \
123 1U << plane, 0, 0, 1U << plane, \
124 1U << plane, 0, 1U << plane, 0, \
125 1U << plane, 0, 1U << plane, 1U << plane, \
126 1U << plane, 1U << plane, 0, 0, \
127 1U << plane, 1U << plane, 0, 1U << plane, \
128 1U << plane, 1U << plane, 1U << plane, 0, \
129 1U << plane, 1U << plane, 1U << plane, 1U << plane, \
130 }
131
132 // 32 planes * 4-bit mask * 4 lookup tables each
133 static const uint32_t plane32_lut[32][16*4] = {
134 LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
135 LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
136 LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
137 LUT32(12), LUT32(13), LUT32(14), LUT32(15),
138 LUT32(16), LUT32(17), LUT32(18), LUT32(19),
139 LUT32(20), LUT32(21), LUT32(22), LUT32(23),
140 LUT32(24), LUT32(25), LUT32(26), LUT32(27),
141 LUT32(28), LUT32(29), LUT32(30), LUT32(31),
142 };
143
144 // Gray to RGB, required for palette table of grayscale images with bpp < 8
145 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
146 return x << 16 | x << 8 | x;
147 }
148
149 /**
150 * Convert CMAP buffer (stored in extradata) to lavc palette format
151 */
152 2 static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
153 {
154 2 IffContext *s = avctx->priv_data;
155 unsigned count, i;
156 2 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
157 /* extract_header() already checked that the RHS is >= 0. */
158 2 unsigned palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
159
160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (avctx->bits_per_coded_sample > 8) {
161 av_log(avctx, AV_LOG_ERROR, "bits_per_coded_sample > 8 not supported\n");
162 return AVERROR_INVALIDDATA;
163 }
164
165 2 count = 1 << avctx->bits_per_coded_sample;
166 // If extradata is smaller than actually needed, fill the remaining with black.
167 2 count = FFMIN(palette_size / 3, count);
168
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (count) {
169
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 2 times.
514 for (i = 0; i < count; i++)
170 512 pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
171
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (s->flags && count >= 32) { // EHB
172 for (i = 0; i < 32; i++)
173 pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1;
174 count = FFMAX(count, 64);
175 }
176 } else { // Create gray-scale color palette for bps < 8
177 count = 1 << avctx->bits_per_coded_sample;
178
179 for (i = 0; i < count; i++)
180 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
181 }
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (s->masking == MASK_HAS_MASK) {
183 if ((1 << avctx->bits_per_coded_sample) < count) {
184 avpriv_request_sample(avctx, "overlapping mask");
185 return AVERROR_PATCHWELCOME;
186 }
187 memcpy(pal + (1 << avctx->bits_per_coded_sample), pal, count * 4);
188 for (i = 0; i < count; i++)
189 pal[i] &= 0xFFFFFF;
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR &&
191 s->transparency < 1 << avctx->bits_per_coded_sample)
192 pal[s->transparency] &= 0xFFFFFF;
193 2 return 0;
194 }
195
196 /**
197 * Extracts the IFF extra context and updates internal
198 * decoder structures.
199 *
200 * @param avctx the AVCodecContext where to extract extra context to
201 * @return >= 0 in case of success, a negative error code otherwise
202 */
203 4 static int extract_header(AVCodecContext *const avctx,
204 const uint8_t *const extradata, int extradata_size)
205 {
206 4 IffContext *s = avctx->priv_data;
207 4 const uint8_t *buf = extradata;
208 4 unsigned buf_size = 0;
209 int palette_size;
210
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (extradata_size < 2) {
212 av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
213 return AVERROR_INVALIDDATA;
214 }
215 4 palette_size = extradata_size - AV_RB16(extradata);
216
217 4 buf_size = bytestream_get_be16(&buf);
218
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (buf_size <= 1 || palette_size < 0) {
219 av_log(avctx, AV_LOG_ERROR,
220 "Invalid palette size received: %u -> palette data offset: %d\n",
221 buf_size, palette_size);
222 return AVERROR_INVALIDDATA;
223 }
224
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (buf_size < 41)
226 return 0;
227
228 4 s->compression = bytestream_get_byte(&buf);
229 4 s->bpp = bytestream_get_byte(&buf);
230 4 s->ham = bytestream_get_byte(&buf);
231 4 s->flags = bytestream_get_byte(&buf);
232 4 s->transparency = bytestream_get_be16(&buf);
233 4 s->masking = bytestream_get_byte(&buf);
234
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4 times.
68 for (int i = 0; i < 16; i++)
235 64 s->tvdc[i] = bytestream_get_be16(&buf);
236
237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->ham) {
238 if (s->bpp > 8) {
239 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
240 return AVERROR_INVALIDDATA;
241 } else if (s->ham != (s->bpp > 6 ? 6 : 4)) {
242 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u, BPP: %u\n", s->ham, s->bpp);
243 return AVERROR_INVALIDDATA;
244 }
245 }
246
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->masking == MASK_HAS_MASK) {
248 if (s->bpp >= 8 && !s->ham) {
249 avctx->pix_fmt = AV_PIX_FMT_RGB32;
250 if (s->bpp > 16) {
251 av_log(avctx, AV_LOG_ERROR, "bpp %d too large for palette\n", s->bpp);
252 return AVERROR(ENOMEM);
253 }
254 s->mask_buf = av_malloc((s->planesize * 32) + AV_INPUT_BUFFER_PADDING_SIZE);
255 if (!s->mask_buf)
256 return AVERROR(ENOMEM);
257 s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + AV_INPUT_BUFFER_PADDING_SIZE);
258 if (!s->mask_palbuf)
259 return AVERROR(ENOMEM);
260 }
261 s->bpp++;
262
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) {
263 av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
264 return AVERROR_PATCHWELCOME;
265 }
266
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!s->bpp || s->bpp > 32) {
267 av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
268 return AVERROR_INVALIDDATA;
269 }
270
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (s->video_size && s->planesize * s->bpp * avctx->height > s->video_size)
271 return AVERROR_INVALIDDATA;
272
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->ham) {
274 int count = FFMIN(palette_size / 3, 1 << s->ham);
275 int ham_count;
276 const uint8_t *const palette = extradata + AV_RB16(extradata);
277 int extra_space = 1;
278
279 if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ') && s->ham == 4)
280 extra_space = 4;
281
282 s->ham_buf = av_malloc((s->planesize * 8) + AV_INPUT_BUFFER_PADDING_SIZE);
283 if (!s->ham_buf)
284 return AVERROR(ENOMEM);
285
286 ham_count = 8 * (1 << s->ham);
287 s->ham_palbuf = av_malloc(extra_space * (ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + AV_INPUT_BUFFER_PADDING_SIZE);
288 if (!s->ham_palbuf)
289 return AVERROR(ENOMEM);
290
291 if (count) { // HAM with color palette attached
292 // prefill with black and palette and set HAM take direct value mask to zero
293 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
294 for (int i = 0; i < count; i++) {
295 s->ham_palbuf[i*2+1] = 0xFF000000 | AV_RL24(palette + i*3);
296 }
297 count = 1 << s->ham;
298 } else { // HAM with grayscale color palette
299 count = 1 << s->ham;
300 for (int i = 0; i < count; i++) {
301 s->ham_palbuf[i*2] = 0xFF000000; // take direct color value from palette
302 s->ham_palbuf[i*2+1] = 0xFF000000 | av_le2ne32(gray2rgb((i * 255) >> s->ham));
303 }
304 }
305 for (int i = 0; i < count; i++) {
306 uint32_t tmp = i << (8 - s->ham);
307 tmp |= tmp >> s->ham;
308 s->ham_palbuf[(i+count)*2] = 0xFF00FFFF; // just modify blue color component
309 s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00; // just modify red color component
310 s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF; // just modify green color component
311 s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16;
312 s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp;
313 s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8;
314 }
315 if (s->masking == MASK_HAS_MASK) {
316 for (int i = 0; i < ham_count; i++)
317 s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
318 }
319 }
320
321 4 return 0;
322 }
323
324 4 static av_cold int decode_end(AVCodecContext *avctx)
325 {
326 4 IffContext *s = avctx->priv_data;
327 4 av_freep(&s->planebuf);
328 4 av_freep(&s->ham_buf);
329 4 av_freep(&s->ham_palbuf);
330 4 av_freep(&s->mask_buf);
331 4 av_freep(&s->mask_palbuf);
332 4 av_freep(&s->video[0]);
333 4 av_freep(&s->video[1]);
334 4 av_freep(&s->pal);
335 4 return 0;
336 }
337
338 4 static av_cold int decode_init(AVCodecContext *avctx)
339 {
340 4 IffContext *s = avctx->priv_data;
341 int err;
342
343
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (avctx->bits_per_coded_sample <= 8) {
344 int palette_size;
345
346
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (avctx->extradata_size >= 2)
347 4 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
348 else
349 palette_size = 0;
350 4 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
351
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 (avctx->extradata_size >= 2 && palette_size) ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8;
352 } else if (avctx->bits_per_coded_sample <= 32) {
353 if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8')) {
354 avctx->pix_fmt = AV_PIX_FMT_RGB32;
355 } else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N')) {
356 avctx->pix_fmt = AV_PIX_FMT_RGB444;
357 } else if (avctx->codec_tag != MKTAG('D', 'E', 'E', 'P')) {
358 if (avctx->bits_per_coded_sample == 24) {
359 avctx->pix_fmt = AV_PIX_FMT_0BGR32;
360 } else if (avctx->bits_per_coded_sample == 32) {
361 avctx->pix_fmt = AV_PIX_FMT_BGR32;
362 } else {
363 avpriv_request_sample(avctx, "unknown bits_per_coded_sample");
364 return AVERROR_PATCHWELCOME;
365 }
366 }
367 } else {
368 return AVERROR_INVALIDDATA;
369 }
370
371
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
372 return err;
373 4 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
374 4 s->planebuf = av_malloc(s->planesize * avctx->height + AV_INPUT_BUFFER_PADDING_SIZE);
375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->planebuf)
376 return AVERROR(ENOMEM);
377
378 4 s->bpp = avctx->bits_per_coded_sample;
379
380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
381 s->video_size = FFALIGN(avctx->width, 2) * avctx->height * s->bpp;
382 if (!s->video_size)
383 return AVERROR_INVALIDDATA;
384 s->video[0] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp);
385 s->video[1] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp);
386 s->pal = av_calloc(256, sizeof(*s->pal));
387 if (!s->video[0] || !s->video[1] || !s->pal)
388 return AVERROR(ENOMEM);
389 }
390
391 4 err = extract_header(avctx, avctx->extradata, avctx->extradata_size);
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
393 return err;
394
395 4 return 0;
396 }
397
398 /**
399 * Decode interleaved plane buffer up to 8bpp
400 * @param dst Destination buffer
401 * @param buf Source buffer
402 * @param buf_size
403 * @param plane plane number to decode as
404 */
405 1920 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
406 {
407 const uint64_t *lut;
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1920 times.
1920 if (plane >= 8) {
409 av_log(NULL, AV_LOG_WARNING, "Ignoring extra planes beyond 8\n");
410 return;
411 }
412 1920 lut = plane8_lut[plane];
413 do {
414 76800 uint64_t v = AV_RN64A(dst) | lut[*buf++];
415 76800 AV_WN64A(dst, v);
416 76800 dst += 8;
417
2/2
✓ Branch 0 taken 74880 times.
✓ Branch 1 taken 1920 times.
76800 } while (--buf_size);
418 }
419
420 /**
421 * Decode interleaved plane buffer up to 24bpp
422 * @param dst Destination buffer
423 * @param buf Source buffer
424 * @param buf_size
425 * @param plane plane number to decode as
426 */
427 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
428 {
429 const uint32_t *lut = plane32_lut[plane];
430 do {
431 unsigned mask = (*buf >> 2) & ~3;
432 dst[0] |= lut[mask++];
433 dst[1] |= lut[mask++];
434 dst[2] |= lut[mask++];
435 dst[3] |= lut[mask];
436 mask = (*buf++ << 2) & 0x3F;
437 dst[4] |= lut[mask++];
438 dst[5] |= lut[mask++];
439 dst[6] |= lut[mask++];
440 dst[7] |= lut[mask];
441 dst += 8;
442 } while (--buf_size);
443 }
444
445 #define DECODE_HAM_PLANE32(x) \
446 first = buf[x] << 1; \
447 second = buf[(x)+1] << 1; \
448 delta &= pal[first++]; \
449 delta |= pal[first]; \
450 dst[x] = delta; \
451 delta &= pal[second++]; \
452 delta |= pal[second]; \
453 dst[(x)+1] = delta
454
455 /**
456 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
457 *
458 * @param dst the destination 24bpp buffer
459 * @param buf the source 8bpp chunky buffer
460 * @param pal the HAM decode table
461 * @param buf_size the plane size in bytes
462 */
463 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
464 const uint32_t *const pal, unsigned buf_size)
465 {
466 uint32_t delta = pal[1]; /* first palette entry */
467 do {
468 uint32_t first, second;
469 DECODE_HAM_PLANE32(0);
470 DECODE_HAM_PLANE32(2);
471 DECODE_HAM_PLANE32(4);
472 DECODE_HAM_PLANE32(6);
473 buf += 8;
474 dst += 8;
475 } while (--buf_size);
476 }
477
478 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
479 const uint32_t *const pal, unsigned width)
480 {
481 do {
482 *dst++ = pal[*buf++];
483 } while (--width);
484 }
485
486 /**
487 * Decode one complete byterun1 encoded line.
488 *
489 * @param dst the destination buffer where to store decompressed bitstream
490 * @param dst_size the destination plane size in bytes
491 * @param buf the source byterun1 compressed bitstream
492 * @param buf_end the EOF of source byterun1 compressed bitstream
493 * @return number of consumed bytes in byterun1 compressed bitstream
494 */
495 240 static int decode_byterun(uint8_t *dst, int dst_size,
496 GetByteContext *gb)
497 {
498 unsigned x;
499
3/4
✓ Branch 0 taken 10125 times.
✓ Branch 1 taken 240 times.
✓ Branch 3 taken 10125 times.
✗ Branch 4 not taken.
10365 for (x = 0; x < dst_size && bytestream2_get_bytes_left(gb) > 0;) {
500 unsigned length;
501 10125 const int8_t value = bytestream2_get_byte(gb);
502
2/2
✓ Branch 0 taken 4486 times.
✓ Branch 1 taken 5639 times.
10125 if (value >= 0) {
503
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4486 times.
4486 length = FFMIN3(value + 1, dst_size - x, bytestream2_get_bytes_left(gb));
504 4486 bytestream2_get_buffer(gb, dst + x, length);
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4486 times.
4486 if (length < value + 1)
506 bytestream2_skip(gb, value + 1 - length);
507
1/2
✓ Branch 0 taken 5639 times.
✗ Branch 1 not taken.
5639 } else if (value > -128) {
508 5639 length = FFMIN(-value + 1, dst_size - x);
509 5639 memset(dst + x, bytestream2_get_byte(gb), length);
510 } else { // noop
511 continue;
512 }
513 10125 x += length;
514 }
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (x < dst_size) {
516 av_log(NULL, AV_LOG_WARNING, "decode_byterun ended before plane size\n");
517 memset(dst+x, 0, dst_size - x);
518 }
519 240 return bytestream2_tell(gb);
520 }
521
522 static int decode_byterun2(uint8_t *dst, int height, int line_size,
523 GetByteContext *gb)
524 {
525 GetByteContext cmds;
526 int count;
527 int i, y_pos = 0, x_pos = 0;
528
529 if (bytestream2_get_be32(gb) != MKBETAG('V', 'D', 'A', 'T'))
530 return 0;
531
532 bytestream2_skip(gb, 4);
533 count = bytestream2_get_be16(gb) - 2;
534 if (count < 0 || bytestream2_get_bytes_left(gb) < count)
535 return 0;
536
537 bytestream2_init(&cmds, gb->buffer, count);
538 bytestream2_skip(gb, count);
539
540 for (i = 0; i < count && x_pos < line_size; i++) {
541 int8_t cmd = bytestream2_get_byte(&cmds);
542 int l, r;
543
544 if (cmd == 0) {
545 l = bytestream2_get_be16(gb);
546 while (l-- > 0 && x_pos < line_size) {
547 dst[x_pos + y_pos * line_size ] = bytestream2_get_byte(gb);
548 dst[x_pos + y_pos++ * line_size + 1] = bytestream2_get_byte(gb);
549 if (y_pos >= height) {
550 y_pos = 0;
551 x_pos += 2;
552 }
553 }
554 } else if (cmd < 0) {
555 l = -cmd;
556 while (l-- > 0 && x_pos < line_size) {
557 dst[x_pos + y_pos * line_size ] = bytestream2_get_byte(gb);
558 dst[x_pos + y_pos++ * line_size + 1] = bytestream2_get_byte(gb);
559 if (y_pos >= height) {
560 y_pos = 0;
561 x_pos += 2;
562 }
563 }
564 } else if (cmd == 1) {
565 l = bytestream2_get_be16(gb);
566 r = bytestream2_get_be16(gb);
567 while (l-- > 0 && x_pos < line_size) {
568 dst[x_pos + y_pos * line_size ] = r >> 8;
569 dst[x_pos + y_pos++ * line_size + 1] = r & 0xFF;
570 if (y_pos >= height) {
571 y_pos = 0;
572 x_pos += 2;
573 }
574 }
575 } else {
576 l = cmd;
577 r = bytestream2_get_be16(gb);
578 while (l-- > 0 && x_pos < line_size) {
579 dst[x_pos + y_pos * line_size ] = r >> 8;
580 dst[x_pos + y_pos++ * line_size + 1] = r & 0xFF;
581 if (y_pos >= height) {
582 y_pos = 0;
583 x_pos += 2;
584 }
585 }
586 }
587 }
588
589 return bytestream2_tell(gb);
590 }
591
592 #define DECODE_RGBX_COMMON(type) \
593 if (!length) { \
594 length = bytestream2_get_byte(gb); \
595 if (!length) { \
596 length = bytestream2_get_be16(gb); \
597 if (!length) \
598 return; \
599 } \
600 } \
601 for (i = 0; i < length; i++) { \
602 *(type *)(dst + y*linesize + x * sizeof(type)) = pixel; \
603 x += 1; \
604 if (x >= width) { \
605 y += 1; \
606 if (y >= height) \
607 return; \
608 x = 0; \
609 } \
610 }
611
612 /**
613 * Decode RGB8 buffer
614 * @param[out] dst Destination buffer
615 * @param width Width of destination buffer (pixels)
616 * @param height Height of destination buffer (pixels)
617 * @param linesize Line size of destination buffer (bytes)
618 */
619 static void decode_rgb8(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize)
620 {
621 int x = 0, y = 0, i, length;
622 while (bytestream2_get_bytes_left(gb) >= 4) {
623 uint32_t pixel = 0xFF000000 | bytestream2_get_be24(gb);
624 length = bytestream2_get_byte(gb) & 0x7F;
625 DECODE_RGBX_COMMON(uint32_t)
626 }
627 }
628
629 /**
630 * Decode RGBN buffer
631 * @param[out] dst Destination buffer
632 * @param width Width of destination buffer (pixels)
633 * @param height Height of destination buffer (pixels)
634 * @param linesize Line size of destination buffer (bytes)
635 */
636 static void decode_rgbn(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize)
637 {
638 int x = 0, y = 0, i, length;
639 while (bytestream2_get_bytes_left(gb) >= 2) {
640 uint32_t pixel = bytestream2_get_be16u(gb);
641 length = pixel & 0x7;
642 pixel >>= 4;
643 DECODE_RGBX_COMMON(uint16_t)
644 }
645 }
646
647 /**
648 * Decode DEEP RLE 32-bit buffer
649 * @param[out] dst Destination buffer
650 * @param[in] src Source buffer
651 * @param src_size Source buffer size (bytes)
652 * @param width Width of destination buffer (pixels)
653 * @param height Height of destination buffer (pixels)
654 * @param linesize Line size of destination buffer (bytes)
655 */
656 static void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize)
657 {
658 const uint8_t *src_end = src + src_size;
659 int x = 0, y = 0, i;
660 while (src_end - src >= 5) {
661 int opcode;
662 opcode = *(int8_t *)src++;
663 if (opcode >= 0) {
664 int size = opcode + 1;
665 for (i = 0; i < size; i++) {
666 int length = FFMIN(size - i, width - x);
667 if (src_end - src < length * 4)
668 return;
669 memcpy(dst + y*linesize + x * 4, src, length * 4);
670 src += length * 4;
671 x += length;
672 i += length;
673 if (x >= width) {
674 x = 0;
675 y += 1;
676 if (y >= height)
677 return;
678 }
679 }
680 } else {
681 int size = -opcode + 1;
682 uint32_t pixel = AV_RN32(src);
683 for (i = 0; i < size; i++) {
684 *(uint32_t *)(dst + y*linesize + x * 4) = pixel;
685 x += 1;
686 if (x >= width) {
687 x = 0;
688 y += 1;
689 if (y >= height)
690 return;
691 }
692 }
693 src += 4;
694 }
695 }
696 }
697
698 /**
699 * Decode DEEP TVDC 32-bit buffer
700 * @param[out] dst Destination buffer
701 * @param[in] src Source buffer
702 * @param src_size Source buffer size (bytes)
703 * @param width Width of destination buffer (pixels)
704 * @param height Height of destination buffer (pixels)
705 * @param linesize Line size of destination buffer (bytes)
706 * @param[int] tvdc TVDC lookup table
707 */
708 static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize, const int16_t *tvdc)
709 {
710 int x = 0, y = 0, plane = 0;
711 int8_t pixel = 0;
712 int i, j;
713
714 for (i = 0; i < src_size * 2;) {
715 #define GETNIBBLE ((i & 1) ? (src[i>>1] & 0xF) : (src[i>>1] >> 4))
716 int d = tvdc[GETNIBBLE];
717 i++;
718 if (d) {
719 pixel += d;
720 dst[y * linesize + x*4 + plane] = pixel;
721 x++;
722 } else {
723 if (i >= src_size * 2)
724 return;
725 d = GETNIBBLE + 1;
726 i++;
727 d = FFMIN(d, width - x);
728 for (j = 0; j < d; j++) {
729 dst[y * linesize + x*4 + plane] = pixel;
730 x++;
731 }
732 }
733 if (x >= width) {
734 plane++;
735 if (plane >= 4) {
736 y++;
737 if (y >= height)
738 return;
739 plane = 0;
740 }
741 x = 0;
742 pixel = 0;
743 i = (i + 1) & ~1;
744 }
745 }
746 }
747
748 static void decode_short_horizontal_delta(uint8_t *dst,
749 const uint8_t *buf, const uint8_t *buf_end,
750 int w, int bpp, int dst_size)
751 {
752 int planepitch = FFALIGN(w, 16) >> 3;
753 int pitch = planepitch * bpp;
754 GetByteContext ptrs, gb;
755 PutByteContext pb;
756 unsigned ofssrc, pos;
757 int i, k;
758
759 bytestream2_init(&ptrs, buf, buf_end - buf);
760 bytestream2_init_writer(&pb, dst, dst_size);
761
762 for (k = 0; k < bpp; k++) {
763 ofssrc = bytestream2_get_be32(&ptrs);
764 pos = 0;
765
766 if (!ofssrc)
767 continue;
768
769 if (ofssrc >= buf_end - buf)
770 continue;
771
772 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
773 while (bytestream2_peek_be16(&gb) != 0xFFFF && bytestream2_get_bytes_left(&gb) > 3) {
774 int16_t offset = bytestream2_get_be16(&gb);
775 unsigned noffset;
776
777 if (offset >= 0) {
778 unsigned data = bytestream2_get_be16(&gb);
779
780 pos += offset * 2;
781 noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch;
782 bytestream2_seek_p(&pb, noffset, SEEK_SET);
783 bytestream2_put_be16(&pb, data);
784 } else {
785 uint16_t count = bytestream2_get_be16(&gb);
786
787 pos += 2 * -(offset + 2);
788 for (i = 0; i < count; i++) {
789 uint16_t data = bytestream2_get_be16(&gb);
790
791 pos += 2;
792 noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch;
793 bytestream2_seek_p(&pb, noffset, SEEK_SET);
794 bytestream2_put_be16(&pb, data);
795 }
796 }
797 }
798 }
799 }
800
801 static void decode_byte_vertical_delta(uint8_t *dst,
802 const uint8_t *buf, const uint8_t *buf_end,
803 int w, int xor, int bpp, int dst_size)
804 {
805 int ncolumns = ((w + 15) / 16) * 2;
806 int dstpitch = ncolumns * bpp;
807 unsigned ofsdst, ofssrc, opcode, x;
808 GetByteContext ptrs, gb;
809 PutByteContext pb;
810 int i, j, k;
811
812 bytestream2_init(&ptrs, buf, buf_end - buf);
813 bytestream2_init_writer(&pb, dst, dst_size);
814
815 for (k = 0; k < bpp; k++) {
816 ofssrc = bytestream2_get_be32(&ptrs);
817
818 if (!ofssrc)
819 continue;
820
821 if (ofssrc >= buf_end - buf)
822 continue;
823
824 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
825 for (j = 0; j < ncolumns; j++) {
826 ofsdst = j + k * ncolumns;
827
828 i = bytestream2_get_byte(&gb);
829 while (i > 0) {
830 opcode = bytestream2_get_byte(&gb);
831
832 if (opcode == 0) {
833 opcode = bytestream2_get_byte(&gb);
834 x = bytestream2_get_byte(&gb);
835
836 while (opcode) {
837 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
838 if (xor && ofsdst < dst_size) {
839 bytestream2_put_byte(&pb, dst[ofsdst] ^ x);
840 } else {
841 bytestream2_put_byte(&pb, x);
842 }
843 ofsdst += dstpitch;
844 opcode--;
845 }
846 } else if (opcode < 0x80) {
847 ofsdst += opcode * dstpitch;
848 } else {
849 opcode &= 0x7f;
850
851 while (opcode) {
852 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
853 if (xor && ofsdst < dst_size) {
854 bytestream2_put_byte(&pb, dst[ofsdst] ^ bytestream2_get_byte(&gb));
855 } else {
856 bytestream2_put_byte(&pb, bytestream2_get_byte(&gb));
857 }
858 ofsdst += dstpitch;
859 opcode--;
860 }
861 }
862 i--;
863 }
864 }
865 }
866 }
867
868 static void decode_delta_j(uint8_t *dst,
869 const uint8_t *buf, const uint8_t *buf_end,
870 int w, int h, int bpp, int dst_size)
871 {
872 int32_t pitch;
873 uint8_t *ptr;
874 uint32_t type, flag, cols, groups, rows, bytes;
875 uint32_t offset;
876 int planepitch_byte = (w + 7) / 8;
877 int planepitch = ((w + 15) / 16) * 2;
878 int kludge_j, b, g, r, d;
879 GetByteContext gb;
880
881 pitch = planepitch * bpp;
882 kludge_j = w < 320 ? (320 - w) / 8 / 2 : 0;
883
884 bytestream2_init(&gb, buf, buf_end - buf);
885
886 while (bytestream2_get_bytes_left(&gb) >= 2) {
887 type = bytestream2_get_be16(&gb);
888
889 switch (type) {
890 case 0:
891 return;
892 case 1:
893 flag = bytestream2_get_be16(&gb);
894 cols = bytestream2_get_be16(&gb);
895 groups = bytestream2_get_be16(&gb);
896
897 for (g = 0; g < groups; g++) {
898 offset = bytestream2_get_be16(&gb);
899
900 if (cols * bpp == 0 || bytestream2_get_bytes_left(&gb) < cols * bpp) {
901 av_log(NULL, AV_LOG_ERROR, "cols*bpp is invalid (%"PRId32"*%d)", cols, bpp);
902 return;
903 }
904
905 if (kludge_j)
906 offset = ((offset / (320 / 8)) * pitch) + (offset % (320 / 8)) - kludge_j;
907 else
908 offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte);
909
910 for (b = 0; b < cols; b++) {
911 for (d = 0; d < bpp; d++) {
912 uint8_t value = bytestream2_get_byte(&gb);
913
914 if (offset >= dst_size)
915 return;
916 ptr = dst + offset;
917
918 if (flag)
919 ptr[0] ^= value;
920 else
921 ptr[0] = value;
922
923 offset += planepitch;
924 }
925 }
926 if ((cols * bpp) & 1)
927 bytestream2_skip(&gb, 1);
928 }
929 break;
930 case 2:
931 flag = bytestream2_get_be16(&gb);
932 rows = bytestream2_get_be16(&gb);
933 bytes = bytestream2_get_be16(&gb);
934 groups = bytestream2_get_be16(&gb);
935
936 for (g = 0; g < groups; g++) {
937 offset = bytestream2_get_be16(&gb);
938
939 if (kludge_j)
940 offset = ((offset / (320 / 8)) * pitch) + (offset % (320/ 8)) - kludge_j;
941 else
942 offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte);
943
944 for (r = 0; r < rows; r++) {
945 for (d = 0; d < bpp; d++) {
946 unsigned noffset = offset + (r * pitch) + d * planepitch;
947
948 if (!bytes || bytestream2_get_bytes_left(&gb) < bytes) {
949 av_log(NULL, AV_LOG_ERROR, "bytes %"PRId32" is invalid", bytes);
950 return;
951 }
952
953 for (b = 0; b < bytes; b++) {
954 uint8_t value = bytestream2_get_byte(&gb);
955
956 if (noffset >= dst_size)
957 return;
958 ptr = dst + noffset;
959
960 if (flag)
961 ptr[0] ^= value;
962 else
963 ptr[0] = value;
964
965 noffset++;
966 }
967 }
968 }
969 if ((rows * bytes * bpp) & 1)
970 bytestream2_skip(&gb, 1);
971 }
972 break;
973 default:
974 return;
975 }
976 }
977 }
978
979 static void decode_short_vertical_delta(uint8_t *dst,
980 const uint8_t *buf, const uint8_t *buf_end,
981 int w, int bpp, int dst_size)
982 {
983 int ncolumns = (w + 15) >> 4;
984 int dstpitch = ncolumns * bpp * 2;
985 unsigned ofsdst, ofssrc, ofsdata, opcode, x;
986 GetByteContext ptrs, gb, dptrs, dgb;
987 PutByteContext pb;
988 int i, j, k;
989
990 if (buf_end - buf <= 64)
991 return;
992
993 bytestream2_init(&ptrs, buf, buf_end - buf);
994 bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32);
995 bytestream2_init_writer(&pb, dst, dst_size);
996
997 for (k = 0; k < bpp; k++) {
998 ofssrc = bytestream2_get_be32(&ptrs);
999 ofsdata = bytestream2_get_be32(&dptrs);
1000
1001 if (!ofssrc)
1002 continue;
1003
1004 if (ofssrc >= buf_end - buf)
1005 return;
1006
1007 if (ofsdata >= buf_end - buf)
1008 return;
1009
1010 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
1011 bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata));
1012 for (j = 0; j < ncolumns; j++) {
1013 ofsdst = (j + k * ncolumns) * 2;
1014
1015 i = bytestream2_get_byte(&gb);
1016 while (i > 0) {
1017 opcode = bytestream2_get_byte(&gb);
1018
1019 if (opcode == 0) {
1020 opcode = bytestream2_get_byte(&gb);
1021 x = bytestream2_get_be16(&dgb);
1022
1023 while (opcode) {
1024 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1025 bytestream2_put_be16(&pb, x);
1026 ofsdst += dstpitch;
1027 opcode--;
1028 }
1029 } else if (opcode < 0x80) {
1030 ofsdst += opcode * dstpitch;
1031 } else {
1032 opcode &= 0x7f;
1033
1034 while (opcode) {
1035 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1036 bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb));
1037 ofsdst += dstpitch;
1038 opcode--;
1039 }
1040 }
1041 i--;
1042 }
1043 }
1044 }
1045 }
1046
1047 static void decode_long_vertical_delta(uint8_t *dst,
1048 const uint8_t *buf, const uint8_t *buf_end,
1049 int w, int bpp, int dst_size)
1050 {
1051 int ncolumns = (w + 31) >> 5;
1052 int dstpitch = ((w + 15) / 16 * 2) * bpp;
1053 unsigned ofsdst, ofssrc, ofsdata, opcode, x;
1054 GetByteContext ptrs, gb, dptrs, dgb;
1055 PutByteContext pb;
1056 int i, j, k, h;
1057
1058 if (buf_end - buf <= 64)
1059 return;
1060
1061 h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0;
1062 bytestream2_init(&ptrs, buf, buf_end - buf);
1063 bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32);
1064 bytestream2_init_writer(&pb, dst, dst_size);
1065
1066 for (k = 0; k < bpp; k++) {
1067 ofssrc = bytestream2_get_be32(&ptrs);
1068 ofsdata = bytestream2_get_be32(&dptrs);
1069
1070 if (!ofssrc)
1071 continue;
1072
1073 if (ofssrc >= buf_end - buf)
1074 return;
1075
1076 if (ofsdata >= buf_end - buf)
1077 return;
1078
1079 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
1080 bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata));
1081 for (j = 0; j < ncolumns; j++) {
1082 ofsdst = (j + k * ncolumns) * 4 - h * (2 * k);
1083
1084 i = bytestream2_get_byte(&gb);
1085 while (i > 0) {
1086 opcode = bytestream2_get_byte(&gb);
1087
1088 if (opcode == 0) {
1089 opcode = bytestream2_get_byte(&gb);
1090 if (h && (j == (ncolumns - 1))) {
1091 x = bytestream2_get_be16(&dgb);
1092 bytestream2_skip(&dgb, 2);
1093 } else {
1094 x = bytestream2_get_be32(&dgb);
1095 }
1096
1097 if (ofsdst + (opcode - 1LL) * dstpitch > bytestream2_size_p(&pb))
1098 return;
1099
1100 while (opcode) {
1101 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1102 if (h && (j == (ncolumns - 1))) {
1103 bytestream2_put_be16(&pb, x);
1104 } else {
1105 bytestream2_put_be32(&pb, x);
1106 }
1107 ofsdst += dstpitch;
1108 opcode--;
1109 }
1110 } else if (opcode < 0x80) {
1111 ofsdst += opcode * dstpitch;
1112 } else {
1113 opcode &= 0x7f;
1114
1115 while (opcode) {
1116 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1117 if (h && (j == (ncolumns - 1))) {
1118 bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb));
1119 bytestream2_skip(&dgb, 2);
1120 } else {
1121 bytestream2_put_be32(&pb, bytestream2_get_be32(&dgb));
1122 }
1123 ofsdst += dstpitch;
1124 opcode--;
1125 }
1126 }
1127 i--;
1128 }
1129 }
1130 }
1131 }
1132
1133 static void decode_short_vertical_delta2(uint8_t *dst,
1134 const uint8_t *buf, const uint8_t *buf_end,
1135 int w, int bpp, int dst_size)
1136 {
1137 int ncolumns = (w + 15) >> 4;
1138 int dstpitch = ncolumns * bpp * 2;
1139 unsigned ofsdst, ofssrc, opcode, x;
1140 GetByteContext ptrs, gb;
1141 PutByteContext pb;
1142 int i, j, k;
1143
1144 bytestream2_init(&ptrs, buf, buf_end - buf);
1145 bytestream2_init_writer(&pb, dst, dst_size);
1146
1147 for (k = 0; k < bpp; k++) {
1148 ofssrc = bytestream2_get_be32(&ptrs);
1149
1150 if (!ofssrc)
1151 continue;
1152
1153 if (ofssrc >= buf_end - buf)
1154 continue;
1155
1156 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
1157 for (j = 0; j < ncolumns; j++) {
1158 ofsdst = (j + k * ncolumns) * 2;
1159
1160 i = bytestream2_get_be16(&gb);
1161 while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) {
1162 opcode = bytestream2_get_be16(&gb);
1163
1164 if (opcode == 0) {
1165 opcode = bytestream2_get_be16(&gb);
1166 x = bytestream2_get_be16(&gb);
1167
1168 while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) {
1169 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1170 bytestream2_put_be16(&pb, x);
1171 ofsdst += dstpitch;
1172 opcode--;
1173 }
1174 } else if (opcode < 0x8000) {
1175 ofsdst += opcode * dstpitch;
1176 } else {
1177 opcode &= 0x7fff;
1178
1179 while (opcode && bytestream2_get_bytes_left(&gb) > 1 &&
1180 bytestream2_get_bytes_left_p(&pb) > 1) {
1181 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1182 bytestream2_put_be16(&pb, bytestream2_get_be16(&gb));
1183 ofsdst += dstpitch;
1184 opcode--;
1185 }
1186 }
1187 i--;
1188 }
1189 }
1190 }
1191 }
1192
1193 static void decode_long_vertical_delta2(uint8_t *dst,
1194 const uint8_t *buf, const uint8_t *buf_end,
1195 int w, int bpp, int dst_size)
1196 {
1197 int ncolumns = (w + 31) >> 5;
1198 int dstpitch = ((w + 15) / 16 * 2) * bpp;
1199 unsigned ofsdst, ofssrc, opcode, x;
1200 unsigned skip = 0x80000000, mask = skip - 1;
1201 GetByteContext ptrs, gb;
1202 PutByteContext pb;
1203 int i, j, k, h;
1204
1205 h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0;
1206 bytestream2_init(&ptrs, buf, buf_end - buf);
1207 bytestream2_init_writer(&pb, dst, dst_size);
1208
1209 for (k = 0; k < bpp; k++) {
1210 ofssrc = bytestream2_get_be32(&ptrs);
1211
1212 if (!ofssrc)
1213 continue;
1214
1215 if (ofssrc >= buf_end - buf)
1216 continue;
1217
1218 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
1219 for (j = 0; j < ncolumns; j++) {
1220 ofsdst = (j + k * ncolumns) * 4 - h * (2 * k);
1221
1222 if (h && (j == (ncolumns - 1))) {
1223 skip = 0x8000;
1224 mask = skip - 1;
1225 }
1226
1227 i = bytestream2_get_be32(&gb);
1228 while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) {
1229 opcode = bytestream2_get_be32(&gb);
1230
1231 if (opcode == 0) {
1232 if (h && (j == ncolumns - 1)) {
1233 opcode = bytestream2_get_be16(&gb);
1234 x = bytestream2_get_be16(&gb);
1235 } else {
1236 opcode = bytestream2_get_be32(&gb);
1237 x = bytestream2_get_be32(&gb);
1238 }
1239
1240 if (ofsdst + (opcode - 1LL) * dstpitch > bytestream2_size_p(&pb))
1241 return;
1242
1243 while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) {
1244 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1245 if (h && (j == ncolumns - 1))
1246 bytestream2_put_be16(&pb, x);
1247 else
1248 bytestream2_put_be32(&pb, x);
1249 ofsdst += dstpitch;
1250 opcode--;
1251 }
1252 } else if (opcode < skip) {
1253 ofsdst += opcode * dstpitch;
1254 } else {
1255 opcode &= mask;
1256
1257 while (opcode && bytestream2_get_bytes_left(&gb) > 1 &&
1258 bytestream2_get_bytes_left_p(&pb) > 1) {
1259 bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
1260 if (h && (j == ncolumns - 1)) {
1261 bytestream2_put_be16(&pb, bytestream2_get_be16(&gb));
1262 } else {
1263 bytestream2_put_be32(&pb, bytestream2_get_be32(&gb));
1264 }
1265 ofsdst += dstpitch;
1266 opcode--;
1267 }
1268 }
1269 i--;
1270 }
1271 }
1272 }
1273 }
1274
1275 static void decode_delta_d(uint8_t *dst,
1276 const uint8_t *buf, const uint8_t *buf_end,
1277 int w, int flag, int bpp, int dst_size)
1278 {
1279 int planepitch = FFALIGN(w, 16) >> 3;
1280 int pitch = planepitch * bpp;
1281 int planepitch_byte = (w + 7) / 8;
1282 unsigned entries, ofssrc;
1283 GetByteContext gb, ptrs;
1284 PutByteContext pb;
1285 int k;
1286
1287 if (buf_end - buf <= 4 * bpp)
1288 return;
1289
1290 bytestream2_init_writer(&pb, dst, dst_size);
1291 bytestream2_init(&ptrs, buf, bpp * 4);
1292
1293 for (k = 0; k < bpp; k++) {
1294 ofssrc = bytestream2_get_be32(&ptrs);
1295
1296 if (!ofssrc)
1297 continue;
1298
1299 if (ofssrc >= buf_end - buf)
1300 continue;
1301
1302 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
1303
1304 entries = bytestream2_get_be32(&gb);
1305 if (entries * 8LL > bytestream2_get_bytes_left(&gb))
1306 return;
1307
1308 while (entries && bytestream2_get_bytes_left(&gb) >= 8) {
1309 int32_t opcode = bytestream2_get_be32(&gb);
1310 unsigned offset = bytestream2_get_be32(&gb);
1311
1312 bytestream2_seek_p(&pb, (offset / planepitch_byte) * pitch + (offset % planepitch_byte) + k * planepitch, SEEK_SET);
1313 if (opcode >= 0) {
1314 uint32_t x = bytestream2_get_be32(&gb);
1315 if (opcode && 4 + (opcode - 1LL) * pitch > bytestream2_get_bytes_left_p(&pb))
1316 continue;
1317 while (opcode && bytestream2_get_bytes_left_p(&pb) > 0) {
1318 bytestream2_put_be32(&pb, x);
1319 bytestream2_skip_p(&pb, pitch - 4);
1320 opcode--;
1321 }
1322 } else {
1323 while (opcode && bytestream2_get_bytes_left(&gb) > 0) {
1324 bytestream2_put_be32(&pb, bytestream2_get_be32(&gb));
1325 bytestream2_skip_p(&pb, pitch - 4);
1326 opcode++;
1327 }
1328 }
1329 entries--;
1330 }
1331 }
1332 }
1333
1334 static void decode_delta_e(uint8_t *dst,
1335 const uint8_t *buf, const uint8_t *buf_end,
1336 int w, int flag, int bpp, int dst_size)
1337 {
1338 int planepitch = FFALIGN(w, 16) >> 3;
1339 int pitch = planepitch * bpp;
1340 int planepitch_byte = (w + 7) / 8;
1341 unsigned entries, ofssrc;
1342 GetByteContext gb, ptrs;
1343 PutByteContext pb;
1344 int k;
1345
1346 if (buf_end - buf <= 4 * bpp)
1347 return;
1348
1349 bytestream2_init_writer(&pb, dst, dst_size);
1350 bytestream2_init(&ptrs, buf, bpp * 4);
1351
1352 for (k = 0; k < bpp; k++) {
1353 ofssrc = bytestream2_get_be32(&ptrs);
1354
1355 if (!ofssrc)
1356 continue;
1357
1358 if (ofssrc >= buf_end - buf)
1359 continue;
1360
1361 bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
1362
1363 entries = bytestream2_get_be16(&gb);
1364 while (entries && bytestream2_get_bytes_left(&gb) >= 6) {
1365 int16_t opcode = bytestream2_get_be16(&gb);
1366 unsigned offset = bytestream2_get_be32(&gb);
1367
1368 bytestream2_seek_p(&pb, (offset / planepitch_byte) * pitch + (offset % planepitch_byte) + k * planepitch, SEEK_SET);
1369 if (opcode >= 0) {
1370 uint16_t x = bytestream2_get_be16(&gb);
1371 while (opcode && bytestream2_get_bytes_left_p(&pb) > 0) {
1372 bytestream2_put_be16(&pb, x);
1373 bytestream2_skip_p(&pb, pitch - 2);
1374 opcode--;
1375 }
1376 } else {
1377 opcode = -opcode;
1378 while (opcode && bytestream2_get_bytes_left(&gb) > 0) {
1379 bytestream2_put_be16(&pb, bytestream2_get_be16(&gb));
1380 bytestream2_skip_p(&pb, pitch - 2);
1381 opcode--;
1382 }
1383 }
1384 entries--;
1385 }
1386 }
1387 }
1388
1389 static void decode_delta_l(uint8_t *dst,
1390 const uint8_t *buf, const uint8_t *buf_end,
1391 int w, int flag, int bpp, int dst_size)
1392 {
1393 GetByteContext off0, off1, dgb, ogb;
1394 PutByteContext pb;
1395 unsigned poff0, poff1;
1396 int i, k, dstpitch;
1397 int planepitch_byte = (w + 7) / 8;
1398 int planepitch = ((w + 15) / 16) * 2;
1399 int pitch = planepitch * bpp;
1400 int count = 0;
1401
1402 if (buf_end - buf <= 64)
1403 return;
1404
1405 bytestream2_init(&off0, buf, buf_end - buf);
1406 bytestream2_init(&off1, buf + 32, buf_end - (buf + 32));
1407 bytestream2_init_writer(&pb, dst, dst_size);
1408
1409 dstpitch = flag ? (((w + 7) / 8) * bpp): 2;
1410
1411 for (k = 0; k < bpp; k++) {
1412 poff0 = bytestream2_get_be32(&off0);
1413 poff1 = bytestream2_get_be32(&off1);
1414
1415 if (!poff0)
1416 continue;
1417
1418 if (2LL * poff0 >= buf_end - buf)
1419 return;
1420
1421 if (2LL * poff1 >= buf_end - buf)
1422 return;
1423
1424 bytestream2_init(&dgb, buf + 2 * poff0, buf_end - (buf + 2 * poff0));
1425 bytestream2_init(&ogb, buf + 2 * poff1, buf_end - (buf + 2 * poff1));
1426
1427 while (bytestream2_peek_be16(&ogb) != 0xFFFF && bytestream2_get_bytes_left(&ogb) >= 4) {
1428 uint32_t offset = bytestream2_get_be16(&ogb);
1429 int16_t cnt = bytestream2_get_be16(&ogb);
1430 uint16_t data;
1431
1432 if (count > dst_size)
1433 break;
1434 offset = ((2 * offset) / planepitch_byte) * pitch + ((2 * offset) % planepitch_byte) + k * planepitch;
1435 if (cnt < 0) {
1436 if (bytestream2_get_bytes_left(&dgb) < 2)
1437 break;
1438 bytestream2_seek_p(&pb, offset, SEEK_SET);
1439 cnt = -cnt;
1440 data = bytestream2_get_be16(&dgb);
1441 count += cnt;
1442 for (i = 0; i < cnt; i++) {
1443 bytestream2_put_be16(&pb, data);
1444 bytestream2_skip_p(&pb, dstpitch - 2);
1445 }
1446 } else {
1447 if (bytestream2_get_bytes_left(&dgb) < 2*cnt)
1448 break;
1449 bytestream2_seek_p(&pb, offset, SEEK_SET);
1450 count += cnt;
1451 for (i = 0; i < cnt; i++) {
1452 data = bytestream2_get_be16(&dgb);
1453 bytestream2_put_be16(&pb, data);
1454 bytestream2_skip_p(&pb, dstpitch - 2);
1455 }
1456 }
1457 }
1458 }
1459 }
1460
1461 static int unsupported(AVCodecContext *avctx)
1462 {
1463 IffContext *s = avctx->priv_data;
1464 avpriv_request_sample(avctx, "bitmap (compression 0x%0x, bpp %i, ham %i, interlaced %i)", s->compression, s->bpp, s->ham, s->is_interlaced);
1465 return AVERROR_INVALIDDATA;
1466 }
1467
1468 2 static int parse_packet_header(AVCodecContext *const avctx,
1469 GetByteContext *gb)
1470 {
1471 2 IffContext *s = avctx->priv_data;
1472
1473
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (avctx->codec_tag != MKTAG('A', 'N', 'I', 'M'))
1474 2 return 0;
1475
1476 bytestream2_skip(gb, 4);
1477 while (bytestream2_get_bytes_left(gb) >= 1) {
1478 uint32_t chunk_id = bytestream2_get_le32(gb);
1479 uint64_t data_size = bytestream2_get_be32(gb);
1480
1481 if (chunk_id == MKTAG('B', 'M', 'H', 'D')) {
1482 bytestream2_skip(gb, data_size + (data_size & 1));
1483 } else if (chunk_id == MKTAG('A', 'N', 'H', 'D')) {
1484 unsigned extra;
1485 if (data_size < 40)
1486 return AVERROR_INVALIDDATA;
1487
1488 s->compression = (bytestream2_get_byte(gb) << 8) | (s->compression & 0xFF);
1489 bytestream2_skip(gb, 19);
1490 extra = bytestream2_get_be32(gb);
1491 s->is_short = !(extra & 1);
1492 s->is_brush = extra == 2;
1493 s->is_interlaced = !!(extra & 0x40);
1494 data_size -= 24;
1495 bytestream2_skip(gb, data_size + (data_size & 1));
1496 } else if (chunk_id == MKTAG('D', 'L', 'T', 'A') ||
1497 chunk_id == MKTAG('B', 'O', 'D', 'Y')) {
1498 if (chunk_id == MKTAG('B','O','D','Y'))
1499 s->compression &= 0xFF;
1500 break;
1501 } else if (chunk_id == MKTAG('C', 'M', 'A', 'P')) {
1502 int count = data_size / 3;
1503 uint32_t *pal = s->pal;
1504
1505 if (count > 256)
1506 return AVERROR_INVALIDDATA;
1507 if (s->ham) {
1508 for (int i = 0; i < count; i++)
1509 pal[i] = 0xFF000000 | bytestream2_get_le24(gb);
1510 } else {
1511 for (int i = 0; i < count; i++)
1512 pal[i] = 0xFF000000 | bytestream2_get_be24(gb);
1513 }
1514 bytestream2_skip(gb, data_size & 1);
1515 } else {
1516 bytestream2_skip(gb, data_size + (data_size&1));
1517 }
1518 }
1519
1520 return 0;
1521 }
1522
1523 2 static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
1524 int *got_frame, AVPacket *avpkt)
1525 {
1526 2 IffContext *s = avctx->priv_data;
1527 2 const uint8_t *buf = avpkt->data;
1528 2 int buf_size = avpkt->size;
1529 2 const uint8_t *buf_end = buf + buf_size;
1530 int y, plane, res;
1531 2 GetByteContext gb0, *const gb = &gb0;
1532 const AVPixFmtDescriptor *desc;
1533
1534 2 bytestream2_init(gb, avpkt->data, avpkt->size);
1535
1536
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((res = parse_packet_header(avctx, gb)) < 0)
1537 return res;
1538
1539
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((res = ff_get_buffer(avctx, frame, 0)) < 0)
1540 return res;
1541
1542 2 buf += bytestream2_tell(gb);
1543 2 buf_size -= bytestream2_tell(gb);
1544 2 desc = av_pix_fmt_desc_get(avctx->pix_fmt);
1545
1546
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 if (!s->init && avctx->bits_per_coded_sample <= 8 - (s->masking == MASK_HAS_MASK) &&
1547
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 avctx->pix_fmt == AV_PIX_FMT_PAL8) {
1548
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((res = cmap_read_palette(avctx, (uint32_t *)frame->data[1])) < 0)
1549 return res;
1550 } else if (!s->init && avctx->bits_per_coded_sample <= 8 &&
1551 avctx->pix_fmt == AV_PIX_FMT_RGB32) {
1552 if ((res = cmap_read_palette(avctx, s->mask_palbuf)) < 0)
1553 return res;
1554 }
1555 2 s->init = 1;
1556
1557
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (s->compression <= 0xff && (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))) {
1558 if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
1559 memcpy(s->pal, frame->data[1], 256 * 4);
1560 }
1561
1562
2/14
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
2 switch (s->compression) {
1563 1 case 0x0:
1564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (avctx->codec_tag == MKTAG('A', 'C', 'B', 'M')) {
1565 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
1566 memset(frame->data[0], 0, avctx->height * frame->linesize[0]);
1567 for (plane = 0; plane < s->bpp; plane++) {
1568 for (y = 0; y < avctx->height && buf < buf_end; y++) {
1569 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1570 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
1571 buf += s->planesize;
1572 }
1573 }
1574 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
1575 memset(frame->data[0], 0, avctx->height * frame->linesize[0]);
1576 for (y = 0; y < avctx->height; y++) {
1577 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1578 memset(s->ham_buf, 0, s->planesize * 8);
1579 for (plane = 0; plane < s->bpp; plane++) {
1580 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
1581 if (start >= buf_end)
1582 break;
1583 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
1584 }
1585 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
1586 }
1587 } else
1588 return unsupported(avctx);
1589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) {
1590 int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3);
1591 int x;
1592 for (y = 0; y < avctx->height && buf < buf_end; y++) {
1593 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1594 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
1595 buf += raw_width;
1596 if (avctx->pix_fmt == AV_PIX_FMT_BGR32) {
1597 for (x = 0; x < avctx->width; x++)
1598 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
1599 }
1600 }
1601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved
1602 avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
1603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))
1604 memcpy(s->video[0], buf, FFMIN(buf_end - buf, s->video_size));
1605
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
1606
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 1 times.
241 for (y = 0; y < avctx->height; y++) {
1607 240 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1608 240 memset(row, 0, avctx->width);
1609
3/4
✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 240 times.
✓ Branch 2 taken 1920 times.
✗ Branch 3 not taken.
2160 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
1610 1920 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
1611 1920 buf += s->planesize;
1612 }
1613 }
1614 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
1615 for (y = 0; y < avctx->height; y++) {
1616 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1617 memset(s->ham_buf, 0, s->planesize * 8);
1618 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
1619 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
1620 buf += s->planesize;
1621 }
1622 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
1623 }
1624 } else { // AV_PIX_FMT_BGR32
1625 for (y = 0; y < avctx->height; y++) {
1626 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1627 memset(row, 0, avctx->width << 2);
1628 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
1629 decodeplane32((uint32_t *)row, buf,
1630 FFMIN(s->planesize, buf_end - buf), plane);
1631 buf += s->planesize;
1632 }
1633 }
1634 }
1635 } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM
1636 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
1637 for (y = 0; y < avctx->height && buf_end > buf; y++) {
1638 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1639 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
1640 buf += avctx->width + (avctx->width % 2); // padding if odd
1641 }
1642 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
1643 for (y = 0; y < avctx->height && buf_end > buf; y++) {
1644 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1645 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
1646 buf += avctx->width + (avctx->width & 1); // padding if odd
1647 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
1648 }
1649 } else
1650 return unsupported(avctx);
1651 } else {
1652 return unsupported(avctx);
1653 }
1654 1 break;
1655 1 case 0x1:
1656
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved
1657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
1658 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
1659 uint8_t *video = s->video[0];
1660
1661 for (y = 0; y < avctx->height; y++) {
1662 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1663 memset(row, 0, avctx->width);
1664 for (plane = 0; plane < s->bpp; plane++) {
1665 decode_byterun(s->planebuf, s->planesize, gb);
1666 if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
1667 memcpy(video, s->planebuf, s->planesize);
1668 video += s->planesize;
1669 }
1670 decodeplane8(row, s->planebuf, s->planesize, plane);
1671 }
1672 }
1673 } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32
1674 for (y = 0; y < avctx->height; y++) {
1675 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1676 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
1677 for (plane = 0; plane < s->bpp; plane++) {
1678 decode_byterun(s->planebuf, s->planesize, gb);
1679 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
1680 }
1681 lookup_pal_indicies((uint32_t *)row, s->mask_buf, s->mask_palbuf, avctx->width);
1682 }
1683 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
1684 uint8_t *video = s->video[0];
1685 for (y = 0; y < avctx->height; y++) {
1686 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1687 memset(s->ham_buf, 0, s->planesize * 8);
1688 for (plane = 0; plane < s->bpp; plane++) {
1689 decode_byterun(s->planebuf, s->planesize, gb);
1690 if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
1691 memcpy(video, s->planebuf, s->planesize);
1692 video += s->planesize;
1693 }
1694 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
1695 }
1696 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
1697 }
1698 } else { // AV_PIX_FMT_BGR32
1699 for (y = 0; y < avctx->height; y++) {
1700 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1701 memset(row, 0, avctx->width << 2);
1702 for (plane = 0; plane < s->bpp; plane++) {
1703 decode_byterun(s->planebuf, s->planesize, gb);
1704 decodeplane32((uint32_t *)row, s->planebuf, s->planesize, plane);
1705 }
1706 }
1707 }
1708
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM
1709
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
1710
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 1 times.
241 for (y = 0; y < avctx->height; y++) {
1711 240 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1712 240 decode_byterun(row, avctx->width, gb);
1713 }
1714 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
1715 for (y = 0; y < avctx->height; y++) {
1716 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1717 decode_byterun(s->ham_buf, avctx->width, gb);
1718 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
1719 }
1720 } else
1721 return unsupported(avctx);
1722 } else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { // IFF-DEEP
1723 if (av_get_bits_per_pixel(desc) == 32)
1724 decode_deep_rle32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0]);
1725 else
1726 return unsupported(avctx);
1727 } else if (avctx->codec_tag == MKTAG('A', 'C', 'B', 'M')) {
1728 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
1729 memset(frame->data[0], 0, avctx->height * frame->linesize[0]);
1730 for (plane = 0; plane < s->bpp; plane++) {
1731 for (y = 0; y < avctx->height && buf < buf_end; y++) {
1732 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1733 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
1734 buf += s->planesize;
1735 }
1736 }
1737 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
1738 memset(frame->data[0], 0, avctx->height * frame->linesize[0]);
1739 for (y = 0; y < avctx->height; y++) {
1740 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1741 memset(s->ham_buf, 0, s->planesize * 8);
1742 for (plane = 0; plane < s->bpp; plane++) {
1743 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
1744 if (start >= buf_end)
1745 break;
1746 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
1747 }
1748 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
1749 }
1750 } else {
1751 return unsupported(avctx);
1752 }
1753 } else {
1754 return unsupported(avctx);
1755 }
1756 1 break;
1757 case 0x2:
1758 if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
1759 for (plane = 0; plane < s->bpp; plane++) {
1760 decode_byterun2(s->planebuf, avctx->height, s->planesize, gb);
1761 for (y = 0; y < avctx->height; y++) {
1762 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1763 decodeplane8(row, s->planebuf + s->planesize * y, s->planesize, plane);
1764 }
1765 }
1766 } else {
1767 return unsupported(avctx);
1768 }
1769 break;
1770 case 0x4:
1771 if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8') && avctx->pix_fmt == AV_PIX_FMT_RGB32)
1772 decode_rgb8(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]);
1773 else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N') && avctx->pix_fmt == AV_PIX_FMT_RGB444)
1774 decode_rgbn(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]);
1775 else
1776 return unsupported(avctx);
1777 break;
1778 case 0x5:
1779 if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) {
1780 if (av_get_bits_per_pixel(desc) == 32)
1781 decode_deep_tvdc32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0], s->tvdc);
1782 else
1783 return unsupported(avctx);
1784 } else
1785 return unsupported(avctx);
1786 break;
1787 case 0x300:
1788 case 0x301:
1789 decode_short_horizontal_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
1790 break;
1791 case 0x500:
1792 case 0x501:
1793 decode_byte_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->is_brush, s->bpp, s->video_size);
1794 break;
1795 case 0x700:
1796 case 0x701:
1797 if (s->is_short)
1798 decode_short_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
1799 else
1800 decode_long_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
1801 break;
1802 case 0x800:
1803 case 0x801:
1804 if (s->is_short)
1805 decode_short_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
1806 else
1807 decode_long_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
1808 break;
1809 case 0x4a00:
1810 case 0x4a01:
1811 decode_delta_j(s->video[0], buf, buf_end, avctx->width, avctx->height, s->bpp, s->video_size);
1812 break;
1813 case 0x6400:
1814 case 0x6401:
1815 if (s->is_interlaced)
1816 return unsupported(avctx);
1817 decode_delta_d(s->video[0], buf, buf_end, avctx->width, s->is_interlaced, s->bpp, s->video_size);
1818 break;
1819 case 0x6500:
1820 case 0x6501:
1821 if (s->is_interlaced)
1822 return unsupported(avctx);
1823 decode_delta_e(s->video[0], buf, buf_end, avctx->width, s->is_interlaced, s->bpp, s->video_size);
1824 break;
1825 case 0x6c00:
1826 case 0x6c01:
1827 decode_delta_l(s->video[0], buf, buf_end, avctx->width, s->is_short, s->bpp, s->video_size);
1828 break;
1829 default:
1830 return unsupported(avctx);
1831 }
1832
1833
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (s->compression <= 0xff && (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))) {
1834 memcpy(s->video[1], s->video[0], s->video_size);
1835 }
1836
1837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (s->compression > 0xff) {
1838 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
1839 buf = s->video[0];
1840 for (y = 0; y < avctx->height; y++) {
1841 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1842 memset(row, 0, avctx->width);
1843 for (plane = 0; plane < s->bpp; plane++) {
1844 decodeplane8(row, buf, s->planesize, plane);
1845 buf += s->planesize;
1846 }
1847 }
1848 if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
1849 memcpy(frame->data[1], s->pal, 256 * 4);
1850 } else if (s->ham) {
1851 int i, count = 1 << s->ham;
1852
1853 buf = s->video[0];
1854 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof(uint32_t));
1855 for (i = 0; i < count; i++) {
1856 s->ham_palbuf[i*2+1] = s->pal[i];
1857 }
1858 for (i = 0; i < count; i++) {
1859 uint32_t tmp = i << (8 - s->ham);
1860 tmp |= tmp >> s->ham;
1861 s->ham_palbuf[(i+count)*2] = 0xFF00FFFF;
1862 s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00;
1863 s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF;
1864 s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16;
1865 s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp;
1866 s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8;
1867 }
1868 if (s->masking == MASK_HAS_MASK) {
1869 for (i = 0; i < 8 * (1 << s->ham); i++)
1870 s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
1871 }
1872 for (y = 0; y < avctx->height; y++) {
1873 uint8_t *row = &frame->data[0][y * frame->linesize[0]];
1874 memset(s->ham_buf, 0, s->planesize * 8);
1875 for (plane = 0; plane < s->bpp; plane++) {
1876 decodeplane8(s->ham_buf, buf, s->planesize, plane);
1877 buf += s->planesize;
1878 }
1879 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
1880 }
1881 } else {
1882 return unsupported(avctx);
1883 }
1884
1885 if (!s->is_brush) {
1886 FFSWAP(uint8_t *, s->video[0], s->video[1]);
1887 }
1888 }
1889
1890
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (avpkt->flags & AV_PKT_FLAG_KEY) {
1891 2 frame->flags |= AV_FRAME_FLAG_KEY;
1892 2 frame->pict_type = AV_PICTURE_TYPE_I;
1893 } else {
1894 frame->flags &= ~AV_FRAME_FLAG_KEY;
1895 frame->pict_type = AV_PICTURE_TYPE_P;
1896 }
1897
1898 2 *got_frame = 1;
1899
1900 2 return buf_size;
1901 }
1902
1903 const FFCodec ff_iff_ilbm_decoder = {
1904 .p.name = "iff",
1905 CODEC_LONG_NAME("IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN"),
1906 .p.type = AVMEDIA_TYPE_VIDEO,
1907 .p.id = AV_CODEC_ID_IFF_ILBM,
1908 .priv_data_size = sizeof(IffContext),
1909 .init = decode_init,
1910 .close = decode_end,
1911 FF_CODEC_DECODE_CB(decode_frame),
1912 .p.capabilities = AV_CODEC_CAP_DR1,
1913 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1914 };
1915