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)
140 IffContext *s = avctx->priv_data;
142 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
143 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
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;
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);
154 for (i=0; i < count; i++) {
155 pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
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;
161 } else { // Create gray-scale color palette for bps < 8
162 count = 1 << avctx->bits_per_coded_sample;
164 for (i=0; i < count; i++) {
165 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
172 * Extracts the IFF extra context and updates internal
173 * decoder structures.
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
179 static int extract_header(AVCodecContext *const avctx,
180 const AVPacket *const avpkt) {
183 IffContext *s = avctx->priv_data;
184 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
189 return AVERROR_INVALIDDATA;
190 image_size = avpkt->size - AV_RB16(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;
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;
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;
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;
234 av_freep(&s->ham_buf);
235 av_freep(&s->ham_palbuf);
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);
242 return AVERROR(ENOMEM);
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);
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);
257 } else { // HAM with grayscale color palette
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));
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;
280 static av_cold int decode_init(AVCodecContext *avctx)
282 IffContext *s = avctx->priv_data;
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;
292 return AVERROR_INVALIDDATA;
295 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
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);
300 return AVERROR(ENOMEM);
302 s->bpp = avctx->bits_per_coded_sample;
303 avcodec_get_frame_defaults(&s->frame);
305 if ((err = extract_header(avctx, NULL)) < 0)
307 s->frame.reference = 3;
313 * Decode interleaved plane buffer up to 8bpp
314 * @param dst Destination buffer
315 * @param buf Source buffer
317 * @param plane plane number to decode as
319 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
321 const uint64_t *lut = plane8_lut[plane];
323 uint64_t v = AV_RN64A(dst) | lut[*buf++];
326 } while (--buf_size);
330 * Decode interleaved plane buffer up to 24bpp
331 * @param dst Destination buffer
332 * @param buf Source buffer
334 * @param plane plane number to decode as
336 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
338 const uint32_t *lut = plane32_lut[plane];
340 unsigned mask = (*buf >> 2) & ~3;
341 dst[0] |= lut[mask++];
342 dst[1] |= lut[mask++];
343 dst[2] |= lut[mask++];
345 mask = (*buf++ << 2) & 0x3F;
346 dst[4] |= lut[mask++];
347 dst[5] |= lut[mask++];
348 dst[6] |= lut[mask++];
351 } while (--buf_size);
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]; \
360 delta &= pal[second++]; \
361 delta |= pal[second]; \
365 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
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
372 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
373 const uint32_t *const pal, unsigned buf_size)
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);
384 } while (--buf_size);
388 * Decode one complete byterun1 encoded line.
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
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;
400 for (x = 0; x < dst_size && buf < buf_end;) {
402 const int8_t value = *buf++;
405 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
407 } else if (value > -128) {
409 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
415 return buf - buf_start;
418 static int decode_frame_ilbm(AVCodecContext *avctx,
419 void *data, int *data_size,
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;
428 if ((res = extract_header(avctx, avpkt)) < 0)
432 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
433 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
436 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
437 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
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)
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);
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)
464 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
466 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
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);
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);
487 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
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);
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
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);
514 *data_size = sizeof(AVFrame);
515 *(AVFrame*)data = s->frame;
519 static int decode_frame_byterun1(AVCodecContext *avctx,
520 void *data, int *data_size,
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;
529 if ((res = extract_header(avctx, avpkt)) < 0)
532 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
533 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
536 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
537 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
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)
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);
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);
563 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
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);
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);
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);
588 *data_size = sizeof(AVFrame);
589 *(AVFrame*)data = s->frame;
593 static av_cold int decode_end(AVCodecContext *avctx)
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);
604 AVCodec ff_iff_ilbm_decoder = {
606 .type = AVMEDIA_TYPE_VIDEO,
607 .id = CODEC_ID_IFF_ILBM,
608 .priv_data_size = sizeof(IffContext),
611 .decode = decode_frame_ilbm,
612 .capabilities = CODEC_CAP_DR1,
613 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
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),
623 .decode = decode_frame_byterun1,
624 .capabilities = CODEC_CAP_DR1,
625 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),