]> git.sesse.net Git - ffmpeg/blob - libavcodec/iff.c
Merge remote-tracking branch 'qatar/master'
[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     IffContext *s = avctx->priv_data;
141     int count, i;
142     const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
143     int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
144
145     if (avctx->bits_per_coded_sample > 8) {
146         av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
147         return AVERROR_INVALIDDATA;
148     }
149
150     count = 1 << avctx->bits_per_coded_sample;
151     // If extradata is smaller than actually needed, fill the remaining with black.
152     count = FFMIN(palette_size / 3, count);
153     if (count) {
154         for (i=0; i < count; i++) {
155             pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
156         }
157         if (s->flags && count >= 32) { // EHB
158             for (i = 0; i < 32; i++)
159                 pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1;
160         }
161     } else { // Create gray-scale color palette for bps < 8
162         count = 1 << avctx->bits_per_coded_sample;
163
164         for (i=0; i < count; i++) {
165             pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
166         }
167     }
168     return 0;
169 }
170
171 /**
172  * Extracts the IFF extra context and updates internal
173  * decoder structures.
174  *
175  * @param avctx the AVCodecContext where to extract extra context to
176  * @param avpkt the AVPacket to extract extra context from or NULL to use avctx
177  * @return 0 in case of success, a negative error code otherwise
178  */
179 static int extract_header(AVCodecContext *const avctx,
180                           const AVPacket *const avpkt) {
181     const uint8_t *buf;
182     unsigned buf_size;
183     IffContext *s = avctx->priv_data;
184     int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
185
186     if (avpkt) {
187         int image_size;
188         if (avpkt->size < 2)
189             return AVERROR_INVALIDDATA;
190         image_size = avpkt->size - AV_RB16(avpkt->data);
191         buf = avpkt->data;
192         buf_size = bytestream_get_be16(&buf);
193         if (buf_size <= 1 || image_size <= 1) {
194             av_log(avctx, AV_LOG_ERROR,
195                    "Invalid image size received: %u -> image data offset: %d\n",
196                    buf_size, image_size);
197             return AVERROR_INVALIDDATA;
198         }
199     } else {
200         if (avctx->extradata_size < 2)
201             return AVERROR_INVALIDDATA;
202         buf = avctx->extradata;
203         buf_size = bytestream_get_be16(&buf);
204         if (buf_size <= 1 || palette_size < 0) {
205             av_log(avctx, AV_LOG_ERROR,
206                    "Invalid palette size received: %u -> palette data offset: %d\n",
207                    buf_size, palette_size);
208             return AVERROR_INVALIDDATA;
209         }
210     }
211
212     if (buf_size > 8) {
213         s->compression  = bytestream_get_byte(&buf);
214         s->bpp          = bytestream_get_byte(&buf);
215         s->ham          = bytestream_get_byte(&buf);
216         s->flags        = bytestream_get_byte(&buf);
217         s->transparency = bytestream_get_be16(&buf);
218         s->masking      = bytestream_get_byte(&buf);
219         if (s->masking == MASK_HAS_TRANSPARENT_COLOR) {
220             av_log(avctx, AV_LOG_ERROR, "Transparency not supported\n");
221             return AVERROR_PATCHWELCOME;
222         } else if (s->masking != MASK_NONE) {
223             av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
224             return AVERROR_PATCHWELCOME;
225         }
226         if (!s->bpp || s->bpp > 32) {
227             av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
228             return AVERROR_INVALIDDATA;
229         } else if (s->ham >= 8) {
230             av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
231             return AVERROR_INVALIDDATA;
232         }
233
234         av_freep(&s->ham_buf);
235         av_freep(&s->ham_palbuf);
236
237         if (s->ham) {
238             int i, count = FFMIN(palette_size / 3, 1 << s->ham);
239             const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
240             s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
241             if (!s->ham_buf)
242                 return AVERROR(ENOMEM);
243
244             s->ham_palbuf = av_malloc((8 * (1 << s->ham) * sizeof (uint32_t)) + FF_INPUT_BUFFER_PADDING_SIZE);
245             if (!s->ham_palbuf) {
246                 av_freep(&s->ham_buf);
247                 return AVERROR(ENOMEM);
248             }
249
250             if (count) { // HAM with color palette attached
251                 // prefill with black and palette and set HAM take direct value mask to zero
252                 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
253                 for (i=0; i < count; i++) {
254                     s->ham_palbuf[i*2+1] = AV_RL24(palette + i*3);
255                 }
256                 count = 1 << s->ham;
257             } else { // HAM with grayscale color palette
258                 count = 1 << s->ham;
259                 for (i=0; i < count; i++) {
260                     s->ham_palbuf[i*2]   = 0; // take direct color value from palette
261                     s->ham_palbuf[i*2+1] = av_le2ne32(gray2rgb((i * 255) >> s->ham));
262                 }
263             }
264             for (i=0; i < count; i++) {
265                 uint32_t tmp = i << (8 - s->ham);
266                 tmp |= tmp >> s->ham;
267                 s->ham_palbuf[(i+count)*2]     = 0x00FFFF; // just modify blue color component
268                 s->ham_palbuf[(i+count*2)*2]   = 0xFFFF00; // just modify red color component
269                 s->ham_palbuf[(i+count*3)*2]   = 0xFF00FF; // just modify green color component
270                 s->ham_palbuf[(i+count)*2+1]   = tmp << 16;
271                 s->ham_palbuf[(i+count*2)*2+1] = tmp;
272                 s->ham_palbuf[(i+count*3)*2+1] = tmp << 8;
273             }
274         }
275     }
276
277     return 0;
278 }
279
280 static av_cold int decode_init(AVCodecContext *avctx)
281 {
282     IffContext *s = avctx->priv_data;
283     int err;
284
285     if (avctx->bits_per_coded_sample <= 8) {
286         int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
287         avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
288                          (avctx->extradata_size >= 2 && palette_size) ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
289     } else if (avctx->bits_per_coded_sample <= 32) {
290         avctx->pix_fmt = PIX_FMT_BGR32;
291     } else {
292         return AVERROR_INVALIDDATA;
293     }
294
295     if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
296         return err;
297     s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
298     s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
299     if (!s->planebuf)
300         return AVERROR(ENOMEM);
301
302     s->bpp = avctx->bits_per_coded_sample;
303     avcodec_get_frame_defaults(&s->frame);
304
305     if ((err = extract_header(avctx, NULL)) < 0)
306         return err;
307     s->frame.reference = 3;
308
309     return 0;
310 }
311
312 /**
313  * Decode interleaved plane buffer up to 8bpp
314  * @param dst Destination buffer
315  * @param buf Source buffer
316  * @param buf_size
317  * @param plane plane number to decode as
318  */
319 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
320 {
321     const uint64_t *lut = plane8_lut[plane];
322     do {
323         uint64_t v = AV_RN64A(dst) | lut[*buf++];
324         AV_WN64A(dst, v);
325         dst += 8;
326     } while (--buf_size);
327 }
328
329 /**
330  * Decode interleaved plane buffer up to 24bpp
331  * @param dst Destination buffer
332  * @param buf Source buffer
333  * @param buf_size
334  * @param plane plane number to decode as
335  */
336 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
337 {
338     const uint32_t *lut = plane32_lut[plane];
339     do {
340         unsigned mask = (*buf >> 2) & ~3;
341         dst[0] |= lut[mask++];
342         dst[1] |= lut[mask++];
343         dst[2] |= lut[mask++];
344         dst[3] |= lut[mask];
345         mask = (*buf++ << 2) & 0x3F;
346         dst[4] |= lut[mask++];
347         dst[5] |= lut[mask++];
348         dst[6] |= lut[mask++];
349         dst[7] |= lut[mask];
350         dst += 8;
351     } while (--buf_size);
352 }
353
354 #define DECODE_HAM_PLANE32(x)       \
355     first       = buf[x] << 1;      \
356     second      = buf[(x)+1] << 1;  \
357     delta      &= pal[first++];     \
358     delta      |= pal[first];       \
359     dst[x]      = delta;            \
360     delta      &= pal[second++];    \
361     delta      |= pal[second];      \
362     dst[(x)+1]  = delta
363
364 /**
365  * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
366  *
367  * @param dst the destination 24bpp buffer
368  * @param buf the source 8bpp chunky buffer
369  * @param pal the HAM decode table
370  * @param buf_size the plane size in bytes
371  */
372 static void decode_ham_plane32(uint32_t *dst, const uint8_t  *buf,
373                                const uint32_t *const pal, unsigned buf_size)
374 {
375     uint32_t delta = 0;
376     do {
377         uint32_t first, second;
378         DECODE_HAM_PLANE32(0);
379         DECODE_HAM_PLANE32(2);
380         DECODE_HAM_PLANE32(4);
381         DECODE_HAM_PLANE32(6);
382         buf += 8;
383         dst += 8;
384     } while (--buf_size);
385 }
386
387 /**
388  * Decode one complete byterun1 encoded line.
389  *
390  * @param dst the destination buffer where to store decompressed bitstream
391  * @param dst_size the destination plane size in bytes
392  * @param buf the source byterun1 compressed bitstream
393  * @param buf_end the EOF of source byterun1 compressed bitstream
394  * @return number of consumed bytes in byterun1 compressed bitstream
395 */
396 static int decode_byterun(uint8_t *dst, int dst_size,
397                           const uint8_t *buf, const uint8_t *const buf_end) {
398     const uint8_t *const buf_start = buf;
399     unsigned x;
400     for (x = 0; x < dst_size && buf < buf_end;) {
401         unsigned length;
402         const int8_t value = *buf++;
403         if (value >= 0) {
404             length = value + 1;
405             memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
406             buf += length;
407         } else if (value > -128) {
408             length = -value + 1;
409             memset(dst + x, *buf++, FFMIN(length, dst_size - x));
410         } else { // noop
411             continue;
412         }
413         x += length;
414     }
415     return buf - buf_start;
416 }
417
418 static int decode_frame_ilbm(AVCodecContext *avctx,
419                             void *data, int *data_size,
420                             AVPacket *avpkt)
421 {
422     IffContext *s = avctx->priv_data;
423     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
424     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
425     const uint8_t *buf_end = buf+buf_size;
426     int y, plane, res;
427
428     if ((res = extract_header(avctx, avpkt)) < 0)
429         return res;
430
431     if (s->init) {
432         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
433             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
434             return res;
435         }
436     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
437         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
438         return res;
439     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
440         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
441             return res;
442     }
443     s->init = 1;
444
445     if (avctx->codec_tag == MKTAG('A','C','B','M')) {
446         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
447             memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
448             for (plane = 0; plane < s->bpp; plane++) {
449                 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
450                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
451                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
452                     buf += s->planesize;
453                 }
454             }
455         } else if (s->ham) { // HAM to PIX_FMT_BGR32
456             memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
457             for(y = 0; y < avctx->height; y++) {
458                 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
459                 memset(s->ham_buf, 0, s->planesize * 8);
460                 for (plane = 0; plane < s->bpp; plane++) {
461                     const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
462                     if (start >= buf_end)
463                         break;
464                     decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
465                 }
466                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
467             }
468         }
469     } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
470         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
471             for(y = 0; y < avctx->height; y++ ) {
472                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
473                 memset(row, 0, avctx->width);
474                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
475                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
476                     buf += s->planesize;
477                 }
478             }
479         } else if (s->ham) { // 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                 memset(s->ham_buf, 0, s->planesize * 8);
483                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
484                     decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
485                     buf += s->planesize;
486                 }
487                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
488             }
489         } else { // PIX_FMT_BGR32
490             for(y = 0; y < avctx->height; y++ ) {
491                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
492                 memset(row, 0, avctx->width << 2);
493                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
494                     decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
495                     buf += s->planesize;
496                 }
497             }
498         }
499     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
500         for(y = 0; y < avctx->height; y++ ) {
501             uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
502             memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
503             buf += avctx->width + (avctx->width % 2); // padding if odd
504         }
505     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
506         for (y = 0; y < avctx->height; y++) {
507             uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
508             memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
509             buf += avctx->width + (avctx->width & 1); // padding if odd
510             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
511         }
512     }
513
514     *data_size = sizeof(AVFrame);
515     *(AVFrame*)data = s->frame;
516     return buf_size;
517 }
518
519 static int decode_frame_byterun1(AVCodecContext *avctx,
520                             void *data, int *data_size,
521                             AVPacket *avpkt)
522 {
523     IffContext *s = avctx->priv_data;
524     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
525     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
526     const uint8_t *buf_end = buf+buf_size;
527     int y, plane, res;
528
529     if ((res = extract_header(avctx, avpkt)) < 0)
530         return res;
531     if (s->init) {
532         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
533             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
534             return res;
535         }
536     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
537         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
538         return res;
539     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
540         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
541             return res;
542     }
543     s->init = 1;
544
545     if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
546         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
547             for(y = 0; y < avctx->height ; y++ ) {
548                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
549                 memset(row, 0, avctx->width);
550                 for (plane = 0; plane < s->bpp; plane++) {
551                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
552                     decodeplane8(row, s->planebuf, s->planesize, plane);
553                 }
554             }
555         } else if (s->ham) { // HAM to PIX_FMT_BGR32
556             for (y = 0; y < avctx->height ; y++) {
557                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
558                 memset(s->ham_buf, 0, s->planesize * 8);
559                 for (plane = 0; plane < s->bpp; plane++) {
560                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
561                     decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
562                 }
563                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
564             }
565         } else { //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                 memset(row, 0, avctx->width << 2);
569                 for (plane = 0; plane < s->bpp; plane++) {
570                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
571                     decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
572                 }
573             }
574         }
575     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
576         for(y = 0; y < avctx->height ; y++ ) {
577             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
578             buf += decode_byterun(row, avctx->width, buf, buf_end);
579         }
580     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
581         for (y = 0; y < avctx->height ; y++) {
582             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
583             buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
584             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
585         }
586     }
587
588     *data_size = sizeof(AVFrame);
589     *(AVFrame*)data = s->frame;
590     return buf_size;
591 }
592
593 static av_cold int decode_end(AVCodecContext *avctx)
594 {
595     IffContext *s = avctx->priv_data;
596     if (s->frame.data[0])
597         avctx->release_buffer(avctx, &s->frame);
598     av_freep(&s->planebuf);
599     av_freep(&s->ham_buf);
600     av_freep(&s->ham_palbuf);
601     return 0;
602 }
603
604 AVCodec ff_iff_ilbm_decoder = {
605     .name           = "iff_ilbm",
606     .type           = AVMEDIA_TYPE_VIDEO,
607     .id             = CODEC_ID_IFF_ILBM,
608     .priv_data_size = sizeof(IffContext),
609     .init           = decode_init,
610     .close          = decode_end,
611     .decode         = decode_frame_ilbm,
612     .capabilities   = CODEC_CAP_DR1,
613     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
614 };
615
616 AVCodec ff_iff_byterun1_decoder = {
617     .name           = "iff_byterun1",
618     .type           = AVMEDIA_TYPE_VIDEO,
619     .id             = CODEC_ID_IFF_BYTERUN1,
620     .priv_data_size = sizeof(IffContext),
621     .init           = decode_init,
622     .close          = decode_end,
623     .decode         = decode_frame_byterun1,
624     .capabilities   = CODEC_CAP_DR1,
625     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
626 };