FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/iff.c
Date: 2026-09-26 14:26:21
Exec Total Coverage
Lines: 142 1090 13.0%
Functions: 8 28 28.6%
Branches: 81 820 9.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 5 static int extract_header(AVCodecContext *const avctx,
204 const uint8_t *const extradata, int extradata_size)
205 {
206 5 IffContext *s = avctx->priv_data;
207 5 const uint8_t *buf = extradata;
208 5 unsigned buf_size = 0;
209 int palette_size;
210
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (extradata_size < 2) {
212 ✗ av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
213 ✗ return AVERROR_INVALIDDATA;
214 }
215 5 palette_size = extradata_size - AV_RB16(extradata);
216
217 5 buf_size = bytestream_get_be16(&buf);
218
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 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 5 times.
5 if (buf_size < 41)
226 ✗ return 0;
227
228 5 s->compression = bytestream_get_byte(&buf);
229 5 s->bpp = bytestream_get_byte(&buf);
230 5 s->ham = bytestream_get_byte(&buf);
231 5 s->flags = bytestream_get_byte(&buf);
232 5 s->transparency = bytestream_get_be16(&buf);
233 5 s->masking = bytestream_get_byte(&buf);
234
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 5 times.
85 for (int i = 0; i < 16; i++)
235 80 s->tvdc[i] = bytestream_get_be16(&buf);
236
237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 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 5 times.
5 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 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 } 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 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 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
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
5 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 5 times.
5 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_mallocz((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 5 return 0;
322 }
323
324 5 static av_cold int decode_end(AVCodecContext *avctx)
325 {
326 5 IffContext *s = avctx->priv_data;
327 5 av_freep(&s->planebuf);
328 5 av_freep(&s->ham_buf);
329 5 av_freep(&s->ham_palbuf);
330 5 av_freep(&s->mask_buf);
331 5 av_freep(&s->mask_palbuf);
332 5 av_freep(&s->video[0]);
333 5 av_freep(&s->video[1]);
334 5 av_freep(&s->pal);
335 5 return 0;
336 }
337
338 5 static av_cold int decode_init(AVCodecContext *avctx)
339 {
340 5 IffContext *s = avctx->priv_data;
341 int err;
342
343
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (avctx->bits_per_coded_sample <= 8) {
344 int palette_size;
345
346
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (avctx->extradata_size >= 2)
347 5 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
348 else
349 ✗ palette_size = 0;
350 5 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
351
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
5 (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 5 times.
5 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
372 ✗ return err;
373 5 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
374 5 s->planebuf = av_malloc(s->planesize * avctx->height + AV_INPUT_BUFFER_PADDING_SIZE);
375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!s->planebuf)
376 ✗ return AVERROR(ENOMEM);
377
378 5 s->bpp = avctx->bits_per_coded_sample;
379
380
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
381 1 s->video_size = FFALIGN(avctx->width, 2) * avctx->height * s->bpp;
382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!s->video_size)
383 ✗ return AVERROR_INVALIDDATA;
384 1 s->video[0] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp);
385 1 s->video[1] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp);
386 1 s->pal = av_calloc(256, sizeof(*s->pal));
387
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (!s->video[0] || !s->video[1] || !s->pal)
388 ✗ return AVERROR(ENOMEM);
389 }
390
391 5 err = extract_header(avctx, avctx->extradata, avctx->extradata_size);
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (err < 0)
393 ✗ return err;
394
395 5 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