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,
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
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
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), \
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),
99 #define LUT32(plane) { \
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, \
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),
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;
136 * Convert CMAP buffer (stored in extradata) to lavc palette format
138 static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
141 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
142 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
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;
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);
153 for (i=0; i < count; i++) {
154 pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
156 } else { // Create gray-scale color palette for bps < 8
157 count = 1 << avctx->bits_per_coded_sample;
159 for (i=0; i < count; i++) {
160 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
167 * Extracts the IFF extra context and updates internal
168 * decoder structures.
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
174 static int extract_header(AVCodecContext *const avctx,
175 const AVPacket *const avpkt) {
178 IffContext *s = avctx->priv_data;
179 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
184 return AVERROR_INVALIDDATA;
185 image_size = avpkt->size - AV_RB16(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;
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;
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;
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;
229 av_freep(&s->ham_buf);
230 av_freep(&s->ham_palbuf);
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);
237 return AVERROR(ENOMEM);
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);
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);
252 } else { // HAM with grayscale color palette
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));
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;
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;
278 static av_cold int decode_init(AVCodecContext *avctx)
280 IffContext *s = avctx->priv_data;
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;
290 return AVERROR_INVALIDDATA;
293 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
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);
298 return AVERROR(ENOMEM);
300 s->bpp = avctx->bits_per_coded_sample;
301 avcodec_get_frame_defaults(&s->frame);
303 if ((err = extract_header(avctx, NULL)) < 0)
305 s->frame.reference = 3;
311 * Decode interleaved plane buffer up to 8bpp
312 * @param dst Destination buffer
313 * @param buf Source buffer
315 * @param plane plane number to decode as
317 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
319 const uint64_t *lut = plane8_lut[plane];
321 uint64_t v = AV_RN64A(dst) | lut[*buf++];
324 } while (--buf_size);
328 * Decode interleaved plane buffer up to 24bpp
329 * @param dst Destination buffer
330 * @param buf Source buffer
332 * @param plane plane number to decode as
334 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
336 const uint32_t *lut = plane32_lut[plane];
338 unsigned mask = (*buf >> 2) & ~3;
339 dst[0] |= lut[mask++];
340 dst[1] |= lut[mask++];
341 dst[2] |= lut[mask++];
343 mask = (*buf++ << 2) & 0x3F;
344 dst[4] |= lut[mask++];
345 dst[5] |= lut[mask++];
346 dst[6] |= lut[mask++];
349 } while (--buf_size);
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]; \
358 delta &= pal[second++]; \
359 delta |= pal[second]; \
363 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
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
370 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
371 const uint32_t *const pal, unsigned buf_size)
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);
382 } while (--buf_size);
386 * Decode one complete byterun1 encoded line.
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
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;
398 for (x = 0; x < dst_size && buf < buf_end;) {
400 const int8_t value = *buf++;
403 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
405 } else if (value > -128) {
407 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
413 return buf - buf_start;
416 static int decode_frame_ilbm(AVCodecContext *avctx,
417 void *data, int *data_size,
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;
426 if ((res = extract_header(avctx, avpkt)) < 0)
430 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
431 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
434 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
435 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
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)
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);
454 } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
455 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
456 for(y = 0; y < avctx->height; y++ ) {
457 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
458 memset(row, 0, avctx->width);
459 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
460 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
464 } else if (s->ham) { // HAM to PIX_FMT_BGR32
465 for (y = 0; y < avctx->height; y++) {
466 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
467 memset(s->ham_buf, 0, s->planesize * 8);
468 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
469 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
472 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
474 } else { // PIX_FMT_BGR32
475 for(y = 0; y < avctx->height; y++ ) {
476 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
477 memset(row, 0, avctx->width << 2);
478 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
479 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
484 } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
485 for(y = 0; y < avctx->height; y++ ) {
486 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
487 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
488 buf += avctx->width + (avctx->width % 2); // padding if odd
490 } else { // IFF-PBM: HAM to PIX_FMT_BGR32
491 for (y = 0; y < avctx->height; y++) {
492 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
493 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
494 buf += avctx->width + (avctx->width & 1); // padding if odd
495 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
499 *data_size = sizeof(AVFrame);
500 *(AVFrame*)data = s->frame;
504 static int decode_frame_byterun1(AVCodecContext *avctx,
505 void *data, int *data_size,
508 IffContext *s = avctx->priv_data;
509 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
510 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
511 const uint8_t *buf_end = buf+buf_size;
514 if ((res = extract_header(avctx, avpkt)) < 0)
517 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
518 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
521 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
522 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
524 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
525 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
530 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
531 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
532 for(y = 0; y < avctx->height ; y++ ) {
533 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
534 memset(row, 0, avctx->width);
535 for (plane = 0; plane < s->bpp; plane++) {
536 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
537 decodeplane8(row, s->planebuf, s->planesize, plane);
540 } else if (s->ham) { // HAM to PIX_FMT_BGR32
541 for (y = 0; y < avctx->height ; y++) {
542 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
543 memset(s->ham_buf, 0, s->planesize * 8);
544 for (plane = 0; plane < s->bpp; plane++) {
545 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
546 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
548 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
550 } else { //PIX_FMT_BGR32
551 for(y = 0; y < avctx->height ; y++ ) {
552 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
553 memset(row, 0, avctx->width << 2);
554 for (plane = 0; plane < s->bpp; plane++) {
555 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
556 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
560 } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
561 for(y = 0; y < avctx->height ; y++ ) {
562 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
563 buf += decode_byterun(row, avctx->width, buf, buf_end);
565 } else { // IFF-PBM: HAM to PIX_FMT_BGR32
566 for (y = 0; y < avctx->height ; y++) {
567 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
568 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
569 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
573 *data_size = sizeof(AVFrame);
574 *(AVFrame*)data = s->frame;
578 static av_cold int decode_end(AVCodecContext *avctx)
580 IffContext *s = avctx->priv_data;
581 if (s->frame.data[0])
582 avctx->release_buffer(avctx, &s->frame);
583 av_freep(&s->planebuf);
584 av_freep(&s->ham_buf);
585 av_freep(&s->ham_palbuf);
589 AVCodec ff_iff_ilbm_decoder = {
591 .type = AVMEDIA_TYPE_VIDEO,
592 .id = CODEC_ID_IFF_ILBM,
593 .priv_data_size = sizeof(IffContext),
596 .decode = decode_frame_ilbm,
597 .capabilities = CODEC_CAP_DR1,
598 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
601 AVCodec ff_iff_byterun1_decoder = {
602 .name = "iff_byterun1",
603 .type = AVMEDIA_TYPE_VIDEO,
604 .id = CODEC_ID_IFF_BYTERUN1,
605 .priv_data_size = sizeof(IffContext),
608 .decode = decode_frame_byterun1,
609 .capabilities = CODEC_CAP_DR1,
610 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),