FFmpeg coverage


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