]> git.sesse.net Git - ffmpeg/blob - libavcodec/iff.c
iff: fix invalid reads (ticket 689)
[ffmpeg] / libavcodec / iff.c
1 /*
2  * IFF PBM/ILBM bitmap decoder
3  * Copyright (c) 2010 Peter Ross <pross@xvid.org>
4  * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 /**
24  * @file
25  * IFF PBM/ILBM bitmap decoder
26  */
27
28 #include "libavutil/imgutils.h"
29 #include "bytestream.h"
30 #include "avcodec.h"
31 #include "get_bits.h"
32
33 // TODO: masking bits
34 typedef enum {
35     MASK_NONE,
36     MASK_HAS_MASK,
37     MASK_HAS_TRANSPARENT_COLOR,
38     MASK_LASSO
39 } mask_type;
40
41 typedef struct {
42     AVFrame frame;
43     int planesize;
44     uint8_t * planebuf;
45     uint8_t * ham_buf;      ///< temporary buffer for planar to chunky conversation
46     uint32_t *ham_palbuf;   ///< HAM decode table
47     unsigned  compression;  ///< delta compression method used
48     unsigned  bpp;          ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
49     unsigned  ham;          ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
50     unsigned  flags;        ///< 1 for EHB, 0 is no extra half darkening
51     unsigned  transparency; ///< TODO: transparency color index in palette
52     unsigned  masking;      ///< TODO: masking method used
53     int init; // 1 if buffer and palette data already initialized, 0 otherwise
54 } IffContext;
55
56 #define LUT8_PART(plane, v)                             \
57     AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane,  \
58     AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane,  \
59     AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane,  \
60     AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane,  \
61     AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane,  \
62     AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane,  \
63     AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane,  \
64     AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane,  \
65     AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane,  \
66     AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane,  \
67     AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane,  \
68     AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane,  \
69     AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane,  \
70     AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane,  \
71     AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane,  \
72     AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
73
74 #define LUT8(plane) {                           \
75     LUT8_PART(plane, 0x0000000),                \
76     LUT8_PART(plane, 0x1000000),                \
77     LUT8_PART(plane, 0x0010000),                \
78     LUT8_PART(plane, 0x1010000),                \
79     LUT8_PART(plane, 0x0000100),                \
80     LUT8_PART(plane, 0x1000100),                \
81     LUT8_PART(plane, 0x0010100),                \
82     LUT8_PART(plane, 0x1010100),                \
83     LUT8_PART(plane, 0x0000001),                \
84     LUT8_PART(plane, 0x1000001),                \
85     LUT8_PART(plane, 0x0010001),                \
86     LUT8_PART(plane, 0x1010001),                \
87     LUT8_PART(plane, 0x0000101),                \
88     LUT8_PART(plane, 0x1000101),                \
89     LUT8_PART(plane, 0x0010101),                \
90     LUT8_PART(plane, 0x1010101),                \
91 }
92
93 // 8 planes * 8-bit mask
94 static const uint64_t plane8_lut[8][256] = {
95     LUT8(0), LUT8(1), LUT8(2), LUT8(3),
96     LUT8(4), LUT8(5), LUT8(6), LUT8(7),
97 };
98
99 #define LUT32(plane) {                                \
100              0,          0,          0,          0,   \
101              0,          0,          0, 1 << plane,   \
102              0,          0, 1 << plane,          0,   \
103              0,          0, 1 << plane, 1 << plane,   \
104              0, 1 << plane,          0,          0,   \
105              0, 1 << plane,          0, 1 << plane,   \
106              0, 1 << plane, 1 << plane,          0,   \
107              0, 1 << plane, 1 << plane, 1 << plane,   \
108     1 << plane,          0,          0,          0,   \
109     1 << plane,          0,          0, 1 << plane,   \
110     1 << plane,          0, 1 << plane,          0,   \
111     1 << plane,          0, 1 << plane, 1 << plane,   \
112     1 << plane, 1 << plane,          0,          0,   \
113     1 << plane, 1 << plane,          0, 1 << plane,   \
114     1 << plane, 1 << plane, 1 << plane,          0,   \
115     1 << plane, 1 << plane, 1 << plane, 1 << plane,   \
116 }
117
118 // 32 planes * 4-bit mask * 4 lookup tables each
119 static const uint32_t plane32_lut[32][16*4] = {
120     LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
121     LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
122     LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
123     LUT32(12), LUT32(13), LUT32(14), LUT32(15),
124     LUT32(16), LUT32(17), LUT32(18), LUT32(19),
125     LUT32(20), LUT32(21), LUT32(22), LUT32(23),
126     LUT32(24), LUT32(25), LUT32(26), LUT32(27),
127     LUT32(28), LUT32(29), LUT32(30), LUT32(31),
128 };
129
130 // Gray to RGB, required for palette table of grayscale images with bpp < 8
131 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
132     return x << 16 | x << 8 | x;
133 }
134
135 /**
136  * Convert CMAP buffer (stored in extradata) to lavc palette format
137  */
138 static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
139 {
140     int count, i;
141     const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
142     int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
143
144     if (avctx->bits_per_coded_sample > 8) {
145         av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
146         return AVERROR_INVALIDDATA;
147     }
148
149     count = 1 << avctx->bits_per_coded_sample;
150     // If extradata is smaller than actually needed, fill the remaining with black.
151     count = FFMIN(palette_size / 3, count);
152     if (count) {
153         for (i=0; i < count; i++) {
154             pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
155         }
156     } else { // Create gray-scale color palette for bps < 8
157         count = 1 << avctx->bits_per_coded_sample;
158
159         for (i=0; i < count; i++) {
160             pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
161         }
162     }
163     return 0;
164 }
165
166 /**
167  * Extracts the IFF extra context and updates internal
168  * decoder structures.
169  *
170  * @param avctx the AVCodecContext where to extract extra context to
171  * @param avpkt the AVPacket to extract extra context from or NULL to use avctx
172  * @return 0 in case of success, a negative error code otherwise
173  */
174 static int extract_header(AVCodecContext *const avctx,
175                           const AVPacket *const avpkt) {
176     const uint8_t *buf;
177     unsigned buf_size;
178     IffContext *s = avctx->priv_data;
179     int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
180
181     if (avpkt) {
182         int image_size;
183         if (avpkt->size < 2)
184             return AVERROR_INVALIDDATA;
185         image_size = avpkt->size - AV_RB16(avpkt->data);
186         buf = avpkt->data;
187         buf_size = bytestream_get_be16(&buf);
188         if (buf_size <= 1 || image_size <= 1) {
189             av_log(avctx, AV_LOG_ERROR,
190                    "Invalid image size received: %u -> image data offset: %d\n",
191                    buf_size, image_size);
192             return AVERROR_INVALIDDATA;
193         }
194     } else {
195         if (avctx->extradata_size < 2)
196             return AVERROR_INVALIDDATA;
197         buf = avctx->extradata;
198         buf_size = bytestream_get_be16(&buf);
199         if (buf_size <= 1 || palette_size < 0) {
200             av_log(avctx, AV_LOG_ERROR,
201                    "Invalid palette size received: %u -> palette data offset: %d\n",
202                    buf_size, palette_size);
203             return AVERROR_INVALIDDATA;
204         }
205     }
206
207     if (buf_size > 8) {
208         s->compression  = bytestream_get_byte(&buf);
209         s->bpp          = bytestream_get_byte(&buf);
210         s->ham          = bytestream_get_byte(&buf);
211         s->flags        = bytestream_get_byte(&buf);
212         s->transparency = bytestream_get_be16(&buf);
213         s->masking      = bytestream_get_byte(&buf);
214         if (s->masking == MASK_HAS_TRANSPARENT_COLOR) {
215             av_log(avctx, AV_LOG_ERROR, "Transparency not supported\n");
216             return AVERROR_PATCHWELCOME;
217         } else if (s->masking != MASK_NONE) {
218             av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
219             return AVERROR_PATCHWELCOME;
220         }
221         if (!s->bpp || s->bpp > 32) {
222             av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
223             return AVERROR_INVALIDDATA;
224         } else if (s->ham >= 8) {
225             av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
226             return AVERROR_INVALIDDATA;
227         }
228
229         av_freep(&s->ham_buf);
230         av_freep(&s->ham_palbuf);
231
232         if (s->ham) {
233             int i, count = FFMIN(palette_size / 3, 1 << s->ham);
234             const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
235             s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
236             if (!s->ham_buf)
237                 return AVERROR(ENOMEM);
238
239             s->ham_palbuf = av_malloc((8 * (1 << s->ham) * sizeof (uint32_t)) + FF_INPUT_BUFFER_PADDING_SIZE);
240             if (!s->ham_palbuf) {
241                 av_freep(&s->ham_buf);
242                 return AVERROR(ENOMEM);
243             }
244
245             if (count) { // HAM with color palette attached
246                 // prefill with black and palette and set HAM take direct value mask to zero
247                 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
248                 for (i=0; i < count; i++) {
249                     s->ham_palbuf[i*2+1] = AV_RL24(palette + i*3);
250                 }
251                 count = 1 << s->ham;
252             } else { // HAM with grayscale color palette
253                 count = 1 << s->ham;
254                 for (i=0; i < count; i++) {
255                     s->ham_palbuf[i*2]   = 0; // take direct color value from palette
256                     s->ham_palbuf[i*2+1] = av_le2ne32(gray2rgb((i * 255) >> s->ham));
257                 }
258             }
259             for (i=0; i < count; i++) {
260                 uint32_t tmp = i << (8 - s->ham);
261                 tmp |= tmp >> s->ham;
262                 s->ham_palbuf[(i+count)*2]     = 0x00FFFF; // just modify blue color component
263                 s->ham_palbuf[(i+count*2)*2]   = 0xFFFF00; // just modify red color component
264                 s->ham_palbuf[(i+count*3)*2]   = 0xFF00FF; // just modify green color component
265                 s->ham_palbuf[(i+count)*2+1]   = tmp << 16;
266                 s->ham_palbuf[(i+count*2)*2+1] = tmp;
267                 s->ham_palbuf[(i+count*3)*2+1] = tmp << 8;
268             }
269         } else if (s->flags & 1) { // EHB (ExtraHalfBrite) color palette
270             av_log(avctx, AV_LOG_ERROR, "ExtraHalfBrite (EHB) mode not supported\n");
271             return AVERROR_PATCHWELCOME;
272         }
273     }
274
275     return 0;
276 }
277
278 static av_cold int decode_init(AVCodecContext *avctx)
279 {
280     IffContext *s = avctx->priv_data;
281     int err;
282
283     if (avctx->bits_per_coded_sample <= 8) {
284         int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
285         avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
286                          (avctx->extradata_size >= 2 && palette_size) ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
287     } else if (avctx->bits_per_coded_sample <= 32) {
288         avctx->pix_fmt = PIX_FMT_BGR32;
289     } else {
290         return AVERROR_INVALIDDATA;
291     }
292
293     if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
294         return err;
295     s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
296     s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
297     if (!s->planebuf)
298         return AVERROR(ENOMEM);
299
300     s->bpp = avctx->bits_per_coded_sample;
301     avcodec_get_frame_defaults(&s->frame);
302
303     if ((err = extract_header(avctx, NULL)) < 0)
304         return err;
305     s->frame.reference = 3;
306
307     return 0;
308 }
309
310 /**
311  * Decode interleaved plane buffer up to 8bpp
312  * @param dst Destination buffer
313  * @param buf Source buffer
314  * @param buf_size
315  * @param plane plane number to decode as
316  */
317 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
318 {
319     const uint64_t *lut = plane8_lut[plane];
320     do {
321         uint64_t v = AV_RN64A(dst) | lut[*buf++];
322         AV_WN64A(dst, v);
323         dst += 8;
324     } while (--buf_size);
325 }
326
327 /**
328  * Decode interleaved plane buffer up to 24bpp
329  * @param dst Destination buffer
330  * @param buf Source buffer
331  * @param buf_size
332  * @param plane plane number to decode as
333  */
334 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
335 {
336     const uint32_t *lut = plane32_lut[plane];
337     do {
338         unsigned mask = (*buf >> 2) & ~3;
339         dst[0] |= lut[mask++];
340         dst[1] |= lut[mask++];
341         dst[2] |= lut[mask++];
342         dst[3] |= lut[mask];
343         mask = (*buf++ << 2) & 0x3F;
344         dst[4] |= lut[mask++];
345         dst[5] |= lut[mask++];
346         dst[6] |= lut[mask++];
347         dst[7] |= lut[mask];
348         dst += 8;
349     } while (--buf_size);
350 }
351
352 #define DECODE_HAM_PLANE32(x)       \
353     first       = buf[x] << 1;      \
354     second      = buf[(x)+1] << 1;  \
355     delta      &= pal[first++];     \
356     delta      |= pal[first];       \
357     dst[x]      = delta;            \
358     delta      &= pal[second++];    \
359     delta      |= pal[second];      \
360     dst[(x)+1]  = delta
361
362 /**
363  * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
364  *
365  * @param dst the destination 24bpp buffer
366  * @param buf the source 8bpp chunky buffer
367  * @param pal the HAM decode table
368  * @param buf_size the plane size in bytes
369  */
370 static void decode_ham_plane32(uint32_t *dst, const uint8_t  *buf,
371                                const uint32_t *const pal, unsigned buf_size)
372 {
373     uint32_t delta = 0;
374     do {
375         uint32_t first, second;
376         DECODE_HAM_PLANE32(0);
377         DECODE_HAM_PLANE32(2);
378         DECODE_HAM_PLANE32(4);
379         DECODE_HAM_PLANE32(6);
380         buf += 8;
381         dst += 8;
382     } while (--buf_size);
383 }
384
385 /**
386  * Decode one complete byterun1 encoded line.
387  *
388  * @param dst the destination buffer where to store decompressed bitstream
389  * @param dst_size the destination plane size in bytes
390  * @param buf the source byterun1 compressed bitstream
391  * @param buf_end the EOF of source byterun1 compressed bitstream
392  * @return number of consumed bytes in byterun1 compressed bitstream
393 */
394 static int decode_byterun(uint8_t *dst, int dst_size,
395                           const uint8_t *buf, const uint8_t *const buf_end) {
396     const uint8_t *const buf_start = buf;
397     unsigned x;
398     for (x = 0; x < dst_size && buf < buf_end;) {
399         unsigned length;
400         const int8_t value = *buf++;
401         if (value >= 0) {
402             length = value + 1;
403             memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
404             buf += length;
405         } else if (value > -128) {
406             length = -value + 1;
407             memset(dst + x, *buf++, FFMIN(length, dst_size - x));
408         } else { // noop
409             continue;
410         }
411         x += length;
412     }
413     return buf - buf_start;
414 }
415
416 static int decode_frame_ilbm(AVCodecContext *avctx,
417                             void *data, int *data_size,
418                             AVPacket *avpkt)
419 {
420     IffContext *s = avctx->priv_data;
421     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
422     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
423     const uint8_t *buf_end = buf+buf_size;
424     int y, plane, res;
425
426     if ((res = extract_header(avctx, avpkt)) < 0)
427         return res;
428
429     if (s->init) {
430         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
431             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
432             return res;
433         }
434     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
435         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
436         return res;
437     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
438         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
439             return res;
440     }
441     s->init = 1;
442
443     if (avctx->codec_tag == MKTAG('A','C','B','M')) {
444         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
445             memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
446             for (plane = 0; plane < s->bpp; plane++) {
447                 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
448                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
449                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
450                     buf += s->planesize;
451                 }
452             }
453         }
454     } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
455         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
456             for(y = 0; y < avctx->height; y++ ) {
457                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
458                 memset(row, 0, avctx->width);
459                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
460                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
461                     buf += s->planesize;
462                 }
463             }
464         } else if (s->ham) { // HAM to PIX_FMT_BGR32
465             for (y = 0; y < avctx->height; y++) {
466                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
467                 memset(s->ham_buf, 0, s->planesize * 8);
468                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
469                     decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
470                     buf += s->planesize;
471                 }
472                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
473             }
474         } else { // PIX_FMT_BGR32
475             for(y = 0; y < avctx->height; y++ ) {
476                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
477                 memset(row, 0, avctx->width << 2);
478                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
479                     decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
480                     buf += s->planesize;
481                 }
482             }
483         }
484     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
485         for(y = 0; y < avctx->height; y++ ) {
486             uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
487             memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
488             buf += avctx->width + (avctx->width % 2); // padding if odd
489         }
490     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
491         for (y = 0; y < avctx->height; y++) {
492             uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
493             memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
494             buf += avctx->width + (avctx->width & 1); // padding if odd
495             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
496         }
497     }
498
499     *data_size = sizeof(AVFrame);
500     *(AVFrame*)data = s->frame;
501     return buf_size;
502 }
503
504 static int decode_frame_byterun1(AVCodecContext *avctx,
505                             void *data, int *data_size,
506                             AVPacket *avpkt)
507 {
508     IffContext *s = avctx->priv_data;
509     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
510     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
511     const uint8_t *buf_end = buf+buf_size;
512     int y, plane, res;
513
514     if ((res = extract_header(avctx, avpkt)) < 0)
515         return res;
516     if (s->init) {
517         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
518             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
519             return res;
520         }
521     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
522         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
523         return res;
524     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
525         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
526             return res;
527     }
528     s->init = 1;
529
530     if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
531         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
532             for(y = 0; y < avctx->height ; y++ ) {
533                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
534                 memset(row, 0, avctx->width);
535                 for (plane = 0; plane < s->bpp; plane++) {
536                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
537                     decodeplane8(row, s->planebuf, s->planesize, plane);
538                 }
539             }
540         } else if (s->ham) { // HAM to PIX_FMT_BGR32
541             for (y = 0; y < avctx->height ; y++) {
542                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
543                 memset(s->ham_buf, 0, s->planesize * 8);
544                 for (plane = 0; plane < s->bpp; plane++) {
545                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
546                     decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
547                 }
548                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
549             }
550         } else { //PIX_FMT_BGR32
551             for(y = 0; y < avctx->height ; y++ ) {
552                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
553                 memset(row, 0, avctx->width << 2);
554                 for (plane = 0; plane < s->bpp; plane++) {
555                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
556                     decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
557                 }
558             }
559         }
560     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
561         for(y = 0; y < avctx->height ; y++ ) {
562             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
563             buf += decode_byterun(row, avctx->width, buf, buf_end);
564         }
565     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
566         for (y = 0; y < avctx->height ; y++) {
567             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
568             buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
569             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
570         }
571     }
572
573     *data_size = sizeof(AVFrame);
574     *(AVFrame*)data = s->frame;
575     return buf_size;
576 }
577
578 static av_cold int decode_end(AVCodecContext *avctx)
579 {
580     IffContext *s = avctx->priv_data;
581     if (s->frame.data[0])
582         avctx->release_buffer(avctx, &s->frame);
583     av_freep(&s->planebuf);
584     av_freep(&s->ham_buf);
585     av_freep(&s->ham_palbuf);
586     return 0;
587 }
588
589 AVCodec ff_iff_ilbm_decoder = {
590     .name           = "iff_ilbm",
591     .type           = AVMEDIA_TYPE_VIDEO,
592     .id             = CODEC_ID_IFF_ILBM,
593     .priv_data_size = sizeof(IffContext),
594     .init           = decode_init,
595     .close          = decode_end,
596     .decode         = decode_frame_ilbm,
597     .capabilities   = CODEC_CAP_DR1,
598     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
599 };
600
601 AVCodec ff_iff_byterun1_decoder = {
602     .name           = "iff_byterun1",
603     .type           = AVMEDIA_TYPE_VIDEO,
604     .id             = CODEC_ID_IFF_BYTERUN1,
605     .priv_data_size = sizeof(IffContext),
606     .init           = decode_init,
607     .close          = decode_end,
608     .decode         = decode_frame_byterun1,
609     .capabilities   = CODEC_CAP_DR1,
610     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
611 };