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