]> git.sesse.net Git - ffmpeg/blob - libavcodec/iff.c
Merge remote-tracking branch 'cus/stable'
[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 = 1;
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('I','L','B','M')) { // interleaved
444         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
445             for(y = 0; y < avctx->height; y++ ) {
446                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
447                 memset(row, 0, avctx->width);
448                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
449                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
450                     buf += s->planesize;
451                 }
452             }
453         } else if (s->ham) { // HAM to PIX_FMT_BGR32
454             for (y = 0; y < avctx->height; y++) {
455                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
456                 memset(s->ham_buf, 0, avctx->width);
457                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
458                     decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
459                     buf += s->planesize;
460                 }
461                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
462             }
463         } else { // PIX_FMT_BGR32
464             for(y = 0; y < avctx->height; y++ ) {
465                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
466                 memset(row, 0, avctx->width << 2);
467                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
468                     decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
469                     buf += s->planesize;
470                 }
471             }
472         }
473     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
474         for(y = 0; y < avctx->height; y++ ) {
475             uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
476             memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
477             buf += avctx->width + (avctx->width % 2); // padding if odd
478         }
479     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
480         for (y = 0; y < avctx->height; y++) {
481             uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
482             memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
483             buf += avctx->width + (avctx->width & 1); // padding if odd
484             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
485         }
486     }
487
488     *data_size = sizeof(AVFrame);
489     *(AVFrame*)data = s->frame;
490     return buf_size;
491 }
492
493 static int decode_frame_byterun1(AVCodecContext *avctx,
494                             void *data, int *data_size,
495                             AVPacket *avpkt)
496 {
497     IffContext *s = avctx->priv_data;
498     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
499     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
500     const uint8_t *buf_end = buf+buf_size;
501     int y, plane, res;
502
503     if ((res = extract_header(avctx, avpkt)) < 0)
504         return res;
505     if (s->init) {
506         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
507             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
508             return res;
509         }
510     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
511         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
512         return res;
513     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
514         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
515             return res;
516     }
517     s->init = 1;
518
519     if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
520         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
521             for(y = 0; y < avctx->height ; y++ ) {
522                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
523                 memset(row, 0, avctx->width);
524                 for (plane = 0; plane < s->bpp; plane++) {
525                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
526                     decodeplane8(row, s->planebuf, s->planesize, plane);
527                 }
528             }
529         } else if (s->ham) { // HAM to PIX_FMT_BGR32
530             for (y = 0; y < avctx->height ; y++) {
531                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
532                 memset(s->ham_buf, 0, avctx->width);
533                 for (plane = 0; plane < s->bpp; plane++) {
534                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
535                     decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
536                 }
537                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
538             }
539         } else { //PIX_FMT_BGR32
540             for(y = 0; y < avctx->height ; y++ ) {
541                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
542                 memset(row, 0, avctx->width << 2);
543                 for (plane = 0; plane < s->bpp; plane++) {
544                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
545                     decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
546                 }
547             }
548         }
549     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
550         for(y = 0; y < avctx->height ; y++ ) {
551             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
552             buf += decode_byterun(row, avctx->width, buf, buf_end);
553         }
554     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
555         for (y = 0; y < avctx->height ; y++) {
556             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
557             buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
558             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
559         }
560     }
561
562     *data_size = sizeof(AVFrame);
563     *(AVFrame*)data = s->frame;
564     return buf_size;
565 }
566
567 static av_cold int decode_end(AVCodecContext *avctx)
568 {
569     IffContext *s = avctx->priv_data;
570     if (s->frame.data[0])
571         avctx->release_buffer(avctx, &s->frame);
572     av_freep(&s->planebuf);
573     av_freep(&s->ham_buf);
574     av_freep(&s->ham_palbuf);
575     return 0;
576 }
577
578 AVCodec ff_iff_ilbm_decoder = {
579     .name           = "iff_ilbm",
580     .type           = AVMEDIA_TYPE_VIDEO,
581     .id             = CODEC_ID_IFF_ILBM,
582     .priv_data_size = sizeof(IffContext),
583     .init           = decode_init,
584     .close          = decode_end,
585     .decode         = decode_frame_ilbm,
586     .capabilities   = CODEC_CAP_DR1,
587     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
588 };
589
590 AVCodec ff_iff_byterun1_decoder = {
591     .name           = "iff_byterun1",
592     .type           = AVMEDIA_TYPE_VIDEO,
593     .id             = CODEC_ID_IFF_BYTERUN1,
594     .priv_data_size = sizeof(IffContext),
595     .init           = decode_init,
596     .close          = decode_end,
597     .decode         = decode_frame_byterun1,
598     .capabilities   = CODEC_CAP_DR1,
599     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
600 };