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>
6 * This file is part of FFmpeg.
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.
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.
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
25 * IFF PBM/ILBM bitmap decoder
28 #include "libavutil/imgutils.h"
29 #include "bytestream.h"
37 MASK_HAS_TRANSPARENT_COLOR,
42 * Gets the actual extra data after video preperties which contains
43 * the raw CMAP palette data beyond the IFF extra context.
45 * @param avctx the AVCodecContext where to extract raw palette data from
46 * @return pointer to raw CMAP palette data
48 static av_always_inline uint8_t *get_palette_data(const AVCodecContext *const avctx) {
49 return avctx->extradata + AV_RB16(avctx->extradata);
53 * Gets the size of CMAP palette data beyond the IFF extra context.
54 * Please note that any value < 2 of IFF extra context or
55 * raw extradata < 0 is considered as illegal extradata.
57 * @param avctx the AVCodecContext where to extract palette data size from
58 * @return size of raw palette data in bytes
60 static av_always_inline int get_palette_size(const AVCodecContext *const avctx) {
61 return avctx->extradata_size - AV_RB16(avctx->extradata);
65 * Gets the actual raw image data after video properties which
66 * contains the raw image data beyond the IFF extra context.
68 * @param avpkt the AVPacket where to extract raw image data from
69 * @return pointer to raw image data
71 static av_always_inline uint8_t *get_image_data(const AVPacket *const avpkt) {
72 return avpkt->data + AV_RB16(avpkt->data);
76 * Gets the size of raw image data beyond the IFF extra context.
77 * Please note that any value < 2 of either IFF extra context
78 * or raw image data is considered as an illegal packet.
80 * @param avpkt the AVPacket where to extract image data size from
81 * @return size of raw image data in bytes
83 static av_always_inline int get_image_size(const AVPacket *const avpkt) {
84 return avpkt->size - AV_RB16(avpkt->data);
91 uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation
92 uint32_t *ham_palbuf; ///< HAM decode table
93 unsigned compression; ///< delta compression method used
94 unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
95 unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
96 unsigned flags; ///< 1 for EHB, 0 is no extra half darkening
97 unsigned transparency; ///< TODO: transparency color index in palette
98 unsigned masking; ///< TODO: masking method used
99 int init; // 1 if buffer and palette data already initialized, 0 otherwise
102 #define LUT8_PART(plane, v) \
103 AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \
104 AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \
105 AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \
106 AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \
107 AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \
108 AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \
109 AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \
110 AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \
111 AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \
112 AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \
113 AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \
114 AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \
115 AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \
116 AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \
117 AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \
118 AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
120 #define LUT8(plane) { \
121 LUT8_PART(plane, 0x0000000), \
122 LUT8_PART(plane, 0x1000000), \
123 LUT8_PART(plane, 0x0010000), \
124 LUT8_PART(plane, 0x1010000), \
125 LUT8_PART(plane, 0x0000100), \
126 LUT8_PART(plane, 0x1000100), \
127 LUT8_PART(plane, 0x0010100), \
128 LUT8_PART(plane, 0x1010100), \
129 LUT8_PART(plane, 0x0000001), \
130 LUT8_PART(plane, 0x1000001), \
131 LUT8_PART(plane, 0x0010001), \
132 LUT8_PART(plane, 0x1010001), \
133 LUT8_PART(plane, 0x0000101), \
134 LUT8_PART(plane, 0x1000101), \
135 LUT8_PART(plane, 0x0010101), \
136 LUT8_PART(plane, 0x1010101), \
139 // 8 planes * 8-bit mask
140 static const uint64_t plane8_lut[8][256] = {
141 LUT8(0), LUT8(1), LUT8(2), LUT8(3),
142 LUT8(4), LUT8(5), LUT8(6), LUT8(7),
145 #define LUT32(plane) { \
147 0, 0, 0, 1 << plane, \
148 0, 0, 1 << plane, 0, \
149 0, 0, 1 << plane, 1 << plane, \
150 0, 1 << plane, 0, 0, \
151 0, 1 << plane, 0, 1 << plane, \
152 0, 1 << plane, 1 << plane, 0, \
153 0, 1 << plane, 1 << plane, 1 << plane, \
154 1 << plane, 0, 0, 0, \
155 1 << plane, 0, 0, 1 << plane, \
156 1 << plane, 0, 1 << plane, 0, \
157 1 << plane, 0, 1 << plane, 1 << plane, \
158 1 << plane, 1 << plane, 0, 0, \
159 1 << plane, 1 << plane, 0, 1 << plane, \
160 1 << plane, 1 << plane, 1 << plane, 0, \
161 1 << plane, 1 << plane, 1 << plane, 1 << plane, \
164 // 32 planes * 4-bit mask * 4 lookup tables each
165 static const uint32_t plane32_lut[32][16*4] = {
166 LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
167 LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
168 LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
169 LUT32(12), LUT32(13), LUT32(14), LUT32(15),
170 LUT32(16), LUT32(17), LUT32(18), LUT32(19),
171 LUT32(20), LUT32(21), LUT32(22), LUT32(23),
172 LUT32(24), LUT32(25), LUT32(26), LUT32(27),
173 LUT32(28), LUT32(29), LUT32(30), LUT32(31),
176 // Gray to RGB, required for palette table of grayscale images with bpp < 8
177 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
178 return x << 16 | x << 8 | x;
182 * Convert CMAP buffer (stored in extradata) to lavc palette format
184 static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
187 const uint8_t *const extradata = get_palette_data(avctx);
189 if (avctx->bits_per_coded_sample > 8) {
190 av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
191 return AVERROR_INVALIDDATA;
194 count = 1 << avctx->bits_per_coded_sample;
195 // If extradata is smaller than actually needed, fill the remaining with black.
196 count = FFMIN(get_palette_size(avctx) / 3, count);
198 for (i=0; i < count; i++) {
199 pal[i] = 0xFF000000 | AV_RB24(extradata + i*3);
201 } else { // Create gray-scale color palette for bps < 8
202 count = 1 << avctx->bits_per_coded_sample;
204 for (i=0; i < count; i++) {
205 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
212 * Extracts the IFF extra context and updates internal
213 * decoder structures.
215 * @param avctx the AVCodecContext where to extract extra context to
216 * @param avpkt the AVPacket to extract extra context from or NULL to use avctx
217 * @return 0 in case of success, a negative error code otherwise
219 static int extract_header(AVCodecContext *const avctx,
220 const AVPacket *const avpkt) {
223 IffContext *s = avctx->priv_data;
226 return AVERROR_INVALIDDATA;
228 buf_size = bytestream_get_be16(&buf);
229 if (buf_size <= 1 || get_image_size(avpkt) <= 1) {
230 av_log(avctx, AV_LOG_ERROR,
231 "Invalid image size received: %u -> image data offset: %d\n",
232 buf_size, get_image_size(avpkt));
233 return AVERROR_INVALIDDATA;
236 if (avctx->extradata_size < 2)
237 return AVERROR_INVALIDDATA;
238 buf = avctx->extradata;
239 buf_size = bytestream_get_be16(&buf);
240 if (buf_size <= 1 || get_palette_size(avctx) < 0) {
241 av_log(avctx, AV_LOG_ERROR,
242 "Invalid palette size received: %u -> palette data offset: %d\n",
243 buf_size, get_palette_size(avctx));
244 return AVERROR_INVALIDDATA;
249 s->compression = bytestream_get_byte(&buf);
250 s->bpp = bytestream_get_byte(&buf);
251 s->ham = bytestream_get_byte(&buf);
252 s->flags = bytestream_get_byte(&buf);
253 s->transparency = bytestream_get_be16(&buf);
254 s->masking = bytestream_get_byte(&buf);
255 if (s->masking == MASK_HAS_TRANSPARENT_COLOR) {
256 av_log(avctx, AV_LOG_ERROR, "Transparency not supported\n");
257 return AVERROR_PATCHWELCOME;
258 } else if (s->masking != MASK_NONE) {
259 av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
260 return AVERROR_PATCHWELCOME;
262 if (!s->bpp || s->bpp > 32) {
263 av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
264 return AVERROR_INVALIDDATA;
265 } else if (s->ham >= 8) {
266 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
267 return AVERROR_INVALIDDATA;
270 av_freep(&s->ham_buf);
271 av_freep(&s->ham_palbuf);
274 int i, count = FFMIN(get_palette_size(avctx) / 3, 1 << s->ham);
275 const uint8_t *const extradata = get_palette_data(avctx);
276 s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
278 return AVERROR(ENOMEM);
280 s->ham_palbuf = av_malloc((8 * (1 << s->ham) * sizeof (uint32_t)) + FF_INPUT_BUFFER_PADDING_SIZE);
281 if (!s->ham_palbuf) {
282 av_freep(&s->ham_buf);
283 return AVERROR(ENOMEM);
286 if (count) { // HAM with color palette attached
287 // prefill with black and palette and set HAM take direct value mask to zero
288 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
289 for (i=0; i < count; i++) {
290 s->ham_palbuf[i*2+1] = AV_RL24(extradata + i*3);
293 } else { // HAM with grayscale color palette
295 for (i=0; i < count; i++) {
296 s->ham_palbuf[i*2] = 0; // take direct color value from palette
297 s->ham_palbuf[i*2+1] = av_le2ne32(gray2rgb((i * 255) >> s->ham));
300 for (i=0; i < count; i++) {
301 uint32_t tmp = i << (8 - s->ham);
302 tmp |= tmp >> s->ham;
303 s->ham_palbuf[(i+count)*2] = 0x00FFFF; // just modify blue color component
304 s->ham_palbuf[(i+count*2)*2] = 0xFFFF00; // just modify red color component
305 s->ham_palbuf[(i+count*3)*2] = 0xFF00FF; // just modify green color component
306 s->ham_palbuf[(i+count)*2+1] = tmp << 16;
307 s->ham_palbuf[(i+count*2)*2+1] = tmp;
308 s->ham_palbuf[(i+count*3)*2+1] = tmp << 8;
310 } else if (s->flags & 1) { // EHB (ExtraHalfBrite) color palette
311 av_log(avctx, AV_LOG_ERROR, "ExtraHalfBrite (EHB) mode not supported\n");
312 return AVERROR_PATCHWELCOME;
319 static av_cold int decode_init(AVCodecContext *avctx)
321 IffContext *s = avctx->priv_data;
324 if (avctx->bits_per_coded_sample <= 8) {
325 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
326 (avctx->extradata_size >= 2 && get_palette_size(avctx)) ? PIX_FMT_PAL8
328 } else if (avctx->bits_per_coded_sample <= 32) {
329 avctx->pix_fmt = PIX_FMT_BGR32;
331 return AVERROR_INVALIDDATA;
334 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
336 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
337 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
339 return AVERROR(ENOMEM);
341 s->bpp = avctx->bits_per_coded_sample;
343 if ((err = extract_header(avctx, NULL)) < 0)
345 s->frame.reference = 1;
351 * Decode interleaved plane buffer up to 8bpp
352 * @param dst Destination buffer
353 * @param buf Source buffer
355 * @param plane plane number to decode as
357 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
359 const uint64_t *lut = plane8_lut[plane];
361 uint64_t v = AV_RN64A(dst) | lut[*buf++];
364 } while (--buf_size);
368 * Decode interleaved plane buffer up to 24bpp
369 * @param dst Destination buffer
370 * @param buf Source buffer
372 * @param plane plane number to decode as
374 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
376 const uint32_t *lut = plane32_lut[plane];
378 unsigned mask = (*buf >> 2) & ~3;
379 dst[0] |= lut[mask++];
380 dst[1] |= lut[mask++];
381 dst[2] |= lut[mask++];
383 mask = (*buf++ << 2) & 0x3F;
384 dst[4] |= lut[mask++];
385 dst[5] |= lut[mask++];
386 dst[6] |= lut[mask++];
389 } while (--buf_size);
392 #define DECODE_HAM_PLANE32(x) \
393 first = buf[x] << 1; \
394 second = buf[(x)+1] << 1; \
395 delta &= pal[first++]; \
396 delta |= pal[first]; \
398 delta &= pal[second++]; \
399 delta |= pal[second]; \
403 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
405 * @param dst the destination 24bpp buffer
406 * @param buf the source 8bpp chunky buffer
407 * @param pal the HAM decode table
408 * @param buf_size the plane size in bytes
410 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
411 const uint32_t *const pal, unsigned buf_size)
415 uint32_t first, second;
416 DECODE_HAM_PLANE32(0);
417 DECODE_HAM_PLANE32(2);
418 DECODE_HAM_PLANE32(4);
419 DECODE_HAM_PLANE32(6);
422 } while (--buf_size);
426 * Decode one complete byterun1 encoded line.
428 * @param dst the destination buffer where to store decompressed bitstream
429 * @param dst_size the destination plane size in bytes
430 * @param buf the source byterun1 compressed bitstream
431 * @param buf_end the EOF of source byterun1 compressed bitstream
432 * @return number of consumed bytes in byterun1 compressed bitstream
434 static int decode_byterun(uint8_t *dst, int dst_size,
435 const uint8_t *buf, const uint8_t *const buf_end) {
436 const uint8_t *const buf_start = buf;
438 for (x = 0; x < dst_size && buf < buf_end;) {
440 const int8_t value = *buf++;
443 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
445 } else if (value > -128) {
447 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
453 return buf - buf_start;
456 static int decode_frame_ilbm(AVCodecContext *avctx,
457 void *data, int *data_size,
460 IffContext *s = avctx->priv_data;
461 const uint8_t *buf = avpkt->size >= 2 ? get_image_data(avpkt) : NULL;
462 const int buf_size = avpkt->size >= 2 ? get_image_size(avpkt) : 0;
463 const uint8_t *buf_end = buf+buf_size;
466 if ((res = extract_header(avctx, avpkt)) < 0)
470 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
471 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
474 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
475 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
477 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
478 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
483 if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
484 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
485 for(y = 0; y < avctx->height; y++ ) {
486 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
487 memset(row, 0, avctx->width);
488 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
489 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
493 } else if (s->ham) { // HAM to PIX_FMT_BGR32
494 for (y = 0; y < avctx->height; y++) {
495 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
496 memset(s->ham_buf, 0, avctx->width);
497 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
498 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
501 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
503 } else { // 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 memset(row, 0, avctx->width << 2);
507 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
508 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
513 } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
514 for(y = 0; y < avctx->height; y++ ) {
515 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
516 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
517 buf += avctx->width + (avctx->width % 2); // padding if odd
519 } else { // IFF-PBM: HAM to PIX_FMT_BGR32
520 for (y = 0; y < avctx->height; y++) {
521 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
522 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
523 buf += avctx->width + (avctx->width & 1); // padding if odd
524 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
528 *data_size = sizeof(AVFrame);
529 *(AVFrame*)data = s->frame;
533 static int decode_frame_byterun1(AVCodecContext *avctx,
534 void *data, int *data_size,
537 IffContext *s = avctx->priv_data;
538 const uint8_t *buf = avpkt->size >= 2 ? get_image_data(avpkt) : NULL;
539 const int buf_size = avpkt->size >= 2 ? get_image_size(avpkt) : 0;
540 const uint8_t *buf_end = buf+buf_size;
543 if ((res = extract_header(avctx, avpkt)) < 0)
546 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
547 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
550 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
551 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
553 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
554 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
559 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
560 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
561 for(y = 0; y < avctx->height ; y++ ) {
562 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
563 memset(row, 0, avctx->width);
564 for (plane = 0; plane < s->bpp; plane++) {
565 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
566 decodeplane8(row, s->planebuf, s->planesize, plane);
569 } else if (s->ham) { // HAM to PIX_FMT_BGR32
570 for (y = 0; y < avctx->height ; y++) {
571 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
572 memset(s->ham_buf, 0, avctx->width);
573 for (plane = 0; plane < s->bpp; plane++) {
574 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
575 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
577 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
579 } else { //PIX_FMT_BGR32
580 for(y = 0; y < avctx->height ; y++ ) {
581 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
582 memset(row, 0, avctx->width << 2);
583 for (plane = 0; plane < s->bpp; plane++) {
584 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
585 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
589 } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
590 for(y = 0; y < avctx->height ; y++ ) {
591 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
592 buf += decode_byterun(row, avctx->width, buf, buf_end);
594 } else { // IFF-PBM: HAM to PIX_FMT_BGR32
595 for (y = 0; y < avctx->height ; y++) {
596 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
597 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
598 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
602 *data_size = sizeof(AVFrame);
603 *(AVFrame*)data = s->frame;
607 static av_cold int decode_end(AVCodecContext *avctx)
609 IffContext *s = avctx->priv_data;
610 if (s->frame.data[0])
611 avctx->release_buffer(avctx, &s->frame);
612 av_freep(&s->planebuf);
613 av_freep(&s->ham_buf);
614 av_freep(&s->ham_palbuf);
618 AVCodec ff_iff_ilbm_decoder = {
628 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
631 AVCodec ff_iff_byterun1_decoder = {
634 CODEC_ID_IFF_BYTERUN1,
639 decode_frame_byterun1,
641 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),