00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00028 #include "libavutil/imgutils.h"
00029 #include "bytestream.h"
00030 #include "avcodec.h"
00031 #include "get_bits.h"
00032
00033
00034 typedef enum {
00035 MASK_NONE,
00036 MASK_HAS_MASK,
00037 MASK_HAS_TRANSPARENT_COLOR,
00038 MASK_LASSO
00039 } mask_type;
00040
00041 typedef struct {
00042 AVFrame frame;
00043 int planesize;
00044 uint8_t * planebuf;
00045 uint8_t * ham_buf;
00046 uint32_t *ham_palbuf;
00047 uint32_t *mask_buf;
00048 uint32_t *mask_palbuf;
00049 unsigned compression;
00050 unsigned bpp;
00051 unsigned ham;
00052 unsigned flags;
00053 unsigned transparency;
00054 unsigned masking;
00055 int init;
00056 } IffContext;
00057
00058 #define LUT8_PART(plane, v) \
00059 AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \
00060 AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \
00061 AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \
00062 AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \
00063 AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \
00064 AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \
00065 AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \
00066 AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \
00067 AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \
00068 AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \
00069 AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \
00070 AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \
00071 AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \
00072 AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \
00073 AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \
00074 AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
00075
00076 #define LUT8(plane) { \
00077 LUT8_PART(plane, 0x0000000), \
00078 LUT8_PART(plane, 0x1000000), \
00079 LUT8_PART(plane, 0x0010000), \
00080 LUT8_PART(plane, 0x1010000), \
00081 LUT8_PART(plane, 0x0000100), \
00082 LUT8_PART(plane, 0x1000100), \
00083 LUT8_PART(plane, 0x0010100), \
00084 LUT8_PART(plane, 0x1010100), \
00085 LUT8_PART(plane, 0x0000001), \
00086 LUT8_PART(plane, 0x1000001), \
00087 LUT8_PART(plane, 0x0010001), \
00088 LUT8_PART(plane, 0x1010001), \
00089 LUT8_PART(plane, 0x0000101), \
00090 LUT8_PART(plane, 0x1000101), \
00091 LUT8_PART(plane, 0x0010101), \
00092 LUT8_PART(plane, 0x1010101), \
00093 }
00094
00095
00096 static const uint64_t plane8_lut[8][256] = {
00097 LUT8(0), LUT8(1), LUT8(2), LUT8(3),
00098 LUT8(4), LUT8(5), LUT8(6), LUT8(7),
00099 };
00100
00101 #define LUT32(plane) { \
00102 0, 0, 0, 0, \
00103 0, 0, 0, 1 << plane, \
00104 0, 0, 1 << plane, 0, \
00105 0, 0, 1 << plane, 1 << plane, \
00106 0, 1 << plane, 0, 0, \
00107 0, 1 << plane, 0, 1 << plane, \
00108 0, 1 << plane, 1 << plane, 0, \
00109 0, 1 << plane, 1 << plane, 1 << plane, \
00110 1 << plane, 0, 0, 0, \
00111 1 << plane, 0, 0, 1 << plane, \
00112 1 << plane, 0, 1 << plane, 0, \
00113 1 << plane, 0, 1 << plane, 1 << plane, \
00114 1 << plane, 1 << plane, 0, 0, \
00115 1 << plane, 1 << plane, 0, 1 << plane, \
00116 1 << plane, 1 << plane, 1 << plane, 0, \
00117 1 << plane, 1 << plane, 1 << plane, 1 << plane, \
00118 }
00119
00120
00121 static const uint32_t plane32_lut[32][16*4] = {
00122 LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
00123 LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
00124 LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
00125 LUT32(12), LUT32(13), LUT32(14), LUT32(15),
00126 LUT32(16), LUT32(17), LUT32(18), LUT32(19),
00127 LUT32(20), LUT32(21), LUT32(22), LUT32(23),
00128 LUT32(24), LUT32(25), LUT32(26), LUT32(27),
00129 LUT32(28), LUT32(29), LUT32(30), LUT32(31),
00130 };
00131
00132
00133 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
00134 return x << 16 | x << 8 | x;
00135 }
00136
00140 static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
00141 {
00142 IffContext *s = avctx->priv_data;
00143 int count, i;
00144 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
00145 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
00146
00147 if (avctx->bits_per_coded_sample > 8) {
00148 av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
00149 return AVERROR_INVALIDDATA;
00150 }
00151
00152 count = 1 << avctx->bits_per_coded_sample;
00153
00154 count = FFMIN(palette_size / 3, count);
00155 if (count) {
00156 for (i=0; i < count; i++) {
00157 pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
00158 }
00159 if (s->flags && count >= 32) {
00160 for (i = 0; i < 32; i++)
00161 pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1;
00162 count = FFMAX(count, 64);
00163 }
00164 } else {
00165 count = 1 << avctx->bits_per_coded_sample;
00166
00167 for (i=0; i < count; i++) {
00168 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
00169 }
00170 }
00171 if (s->masking == MASK_HAS_MASK) {
00172 memcpy(pal + (1 << avctx->bits_per_coded_sample), pal, count * 4);
00173 for (i = 0; i < count; i++)
00174 pal[i] &= 0xFFFFFF;
00175 } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR &&
00176 s->transparency < 1 << avctx->bits_per_coded_sample)
00177 pal[s->transparency] &= 0xFFFFFF;
00178 return 0;
00179 }
00180
00189 static int extract_header(AVCodecContext *const avctx,
00190 const AVPacket *const avpkt) {
00191 const uint8_t *buf;
00192 unsigned buf_size;
00193 IffContext *s = avctx->priv_data;
00194 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
00195
00196 if (avpkt) {
00197 int image_size;
00198 if (avpkt->size < 2)
00199 return AVERROR_INVALIDDATA;
00200 image_size = avpkt->size - AV_RB16(avpkt->data);
00201 buf = avpkt->data;
00202 buf_size = bytestream_get_be16(&buf);
00203 if (buf_size <= 1 || image_size <= 1) {
00204 av_log(avctx, AV_LOG_ERROR,
00205 "Invalid image size received: %u -> image data offset: %d\n",
00206 buf_size, image_size);
00207 return AVERROR_INVALIDDATA;
00208 }
00209 } else {
00210 if (avctx->extradata_size < 2)
00211 return AVERROR_INVALIDDATA;
00212 buf = avctx->extradata;
00213 buf_size = bytestream_get_be16(&buf);
00214 if (buf_size <= 1 || palette_size < 0) {
00215 av_log(avctx, AV_LOG_ERROR,
00216 "Invalid palette size received: %u -> palette data offset: %d\n",
00217 buf_size, palette_size);
00218 return AVERROR_INVALIDDATA;
00219 }
00220 }
00221
00222 if (buf_size > 8) {
00223 s->compression = bytestream_get_byte(&buf);
00224 s->bpp = bytestream_get_byte(&buf);
00225 s->ham = bytestream_get_byte(&buf);
00226 s->flags = bytestream_get_byte(&buf);
00227 s->transparency = bytestream_get_be16(&buf);
00228 s->masking = bytestream_get_byte(&buf);
00229 if (s->masking == MASK_HAS_MASK) {
00230 if (s->bpp >= 8) {
00231 avctx->pix_fmt = PIX_FMT_RGB32;
00232 av_freep(&s->mask_buf);
00233 av_freep(&s->mask_palbuf);
00234 s->mask_buf = av_malloc((s->planesize * 32) + FF_INPUT_BUFFER_PADDING_SIZE);
00235 if (!s->mask_buf)
00236 return AVERROR(ENOMEM);
00237 s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
00238 if (!s->mask_palbuf) {
00239 av_freep(&s->mask_buf);
00240 return AVERROR(ENOMEM);
00241 }
00242 }
00243 s->bpp++;
00244 } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) {
00245 av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
00246 return AVERROR_PATCHWELCOME;
00247 }
00248 if (!s->bpp || s->bpp > 32) {
00249 av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
00250 return AVERROR_INVALIDDATA;
00251 } else if (s->ham >= 8) {
00252 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
00253 return AVERROR_INVALIDDATA;
00254 }
00255
00256 av_freep(&s->ham_buf);
00257 av_freep(&s->ham_palbuf);
00258
00259 if (s->ham) {
00260 int i, count = FFMIN(palette_size / 3, 1 << s->ham);
00261 int ham_count;
00262 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
00263
00264 s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
00265 if (!s->ham_buf)
00266 return AVERROR(ENOMEM);
00267
00268 ham_count = 8 * (1 << s->ham);
00269 s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
00270 if (!s->ham_palbuf) {
00271 av_freep(&s->ham_buf);
00272 return AVERROR(ENOMEM);
00273 }
00274
00275 if (count) {
00276
00277 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
00278 for (i=0; i < count; i++) {
00279 s->ham_palbuf[i*2+1] = AV_RL24(palette + i*3);
00280 }
00281 count = 1 << s->ham;
00282 } else {
00283 count = 1 << s->ham;
00284 for (i=0; i < count; i++) {
00285 s->ham_palbuf[i*2] = 0;
00286 s->ham_palbuf[i*2+1] = av_le2ne32(gray2rgb((i * 255) >> s->ham));
00287 }
00288 }
00289 for (i=0; i < count; i++) {
00290 uint32_t tmp = i << (8 - s->ham);
00291 tmp |= tmp >> s->ham;
00292 s->ham_palbuf[(i+count)*2] = 0x00FFFF;
00293 s->ham_palbuf[(i+count*2)*2] = 0xFFFF00;
00294 s->ham_palbuf[(i+count*3)*2] = 0xFF00FF;
00295 s->ham_palbuf[(i+count)*2+1] = tmp << 16;
00296 s->ham_palbuf[(i+count*2)*2+1] = tmp;
00297 s->ham_palbuf[(i+count*3)*2+1] = tmp << 8;
00298 }
00299 if (s->masking == MASK_HAS_MASK) {
00300 for (i = 0; i < ham_count; i++)
00301 s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
00302 }
00303 }
00304 }
00305
00306 return 0;
00307 }
00308
00309 static av_cold int decode_init(AVCodecContext *avctx)
00310 {
00311 IffContext *s = avctx->priv_data;
00312 int err;
00313
00314 if (avctx->bits_per_coded_sample <= 8) {
00315 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
00316 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
00317 (avctx->extradata_size >= 2 && palette_size) ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
00318 } else if (avctx->bits_per_coded_sample <= 32) {
00319 if (avctx->codec_tag != MKTAG('D','E','E','P'))
00320 avctx->pix_fmt = PIX_FMT_BGR32;
00321 } else {
00322 return AVERROR_INVALIDDATA;
00323 }
00324
00325 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
00326 return err;
00327 s->planesize = FFALIGN(avctx->width, 16) >> 3;
00328 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
00329 if (!s->planebuf)
00330 return AVERROR(ENOMEM);
00331
00332 s->bpp = avctx->bits_per_coded_sample;
00333 avcodec_get_frame_defaults(&s->frame);
00334
00335 if ((err = extract_header(avctx, NULL)) < 0)
00336 return err;
00337 s->frame.reference = 3;
00338
00339 return 0;
00340 }
00341
00349 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
00350 {
00351 const uint64_t *lut = plane8_lut[plane];
00352 do {
00353 uint64_t v = AV_RN64A(dst) | lut[*buf++];
00354 AV_WN64A(dst, v);
00355 dst += 8;
00356 } while (--buf_size);
00357 }
00358
00366 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
00367 {
00368 const uint32_t *lut = plane32_lut[plane];
00369 do {
00370 unsigned mask = (*buf >> 2) & ~3;
00371 dst[0] |= lut[mask++];
00372 dst[1] |= lut[mask++];
00373 dst[2] |= lut[mask++];
00374 dst[3] |= lut[mask];
00375 mask = (*buf++ << 2) & 0x3F;
00376 dst[4] |= lut[mask++];
00377 dst[5] |= lut[mask++];
00378 dst[6] |= lut[mask++];
00379 dst[7] |= lut[mask];
00380 dst += 8;
00381 } while (--buf_size);
00382 }
00383
00384 #define DECODE_HAM_PLANE32(x) \
00385 first = buf[x] << 1; \
00386 second = buf[(x)+1] << 1; \
00387 delta &= pal[first++]; \
00388 delta |= pal[first]; \
00389 dst[x] = delta; \
00390 delta &= pal[second++]; \
00391 delta |= pal[second]; \
00392 dst[(x)+1] = delta
00393
00402 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
00403 const uint32_t *const pal, unsigned buf_size)
00404 {
00405 uint32_t delta = 0;
00406 do {
00407 uint32_t first, second;
00408 DECODE_HAM_PLANE32(0);
00409 DECODE_HAM_PLANE32(2);
00410 DECODE_HAM_PLANE32(4);
00411 DECODE_HAM_PLANE32(6);
00412 buf += 8;
00413 dst += 8;
00414 } while (--buf_size);
00415 }
00416
00417 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
00418 const uint32_t *const pal, unsigned width)
00419 {
00420 do {
00421 *dst++ = pal[*buf++];
00422 } while (--width);
00423 }
00424
00434 static int decode_byterun(uint8_t *dst, int dst_size,
00435 const uint8_t *buf, const uint8_t *const buf_end) {
00436 const uint8_t *const buf_start = buf;
00437 unsigned x;
00438 for (x = 0; x < dst_size && buf < buf_end;) {
00439 unsigned length;
00440 const int8_t value = *buf++;
00441 if (value >= 0) {
00442 length = value + 1;
00443 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
00444 buf += length;
00445 } else if (value > -128) {
00446 length = -value + 1;
00447 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
00448 } else {
00449 continue;
00450 }
00451 x += length;
00452 }
00453 return buf - buf_start;
00454 }
00455
00456 static int decode_frame_ilbm(AVCodecContext *avctx,
00457 void *data, int *data_size,
00458 AVPacket *avpkt)
00459 {
00460 IffContext *s = avctx->priv_data;
00461 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
00462 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
00463 const uint8_t *buf_end = buf+buf_size;
00464 int y, plane, res;
00465
00466 if ((res = extract_header(avctx, avpkt)) < 0)
00467 return res;
00468
00469 if (s->init) {
00470 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00471 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00472 return res;
00473 }
00474 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
00475 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00476 return res;
00477 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == PIX_FMT_PAL8) {
00478 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
00479 return res;
00480 }
00481 s->init = 1;
00482
00483 if (avctx->codec_tag == MKTAG('A','C','B','M')) {
00484 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00485 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
00486 for (plane = 0; plane < s->bpp; plane++) {
00487 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
00488 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00489 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00490 buf += s->planesize;
00491 }
00492 }
00493 } else if (s->ham) {
00494 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
00495 for(y = 0; y < avctx->height; y++) {
00496 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
00497 memset(s->ham_buf, 0, s->planesize * 8);
00498 for (plane = 0; plane < s->bpp; plane++) {
00499 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
00500 if (start >= buf_end)
00501 break;
00502 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
00503 }
00504 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00505 }
00506 }
00507 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) {
00508 int raw_width = avctx->width * (av_get_bits_per_pixel(&av_pix_fmt_descriptors[avctx->pix_fmt]) >> 3);
00509 int x;
00510 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
00511 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
00512 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
00513 buf += raw_width;
00514 if (avctx->pix_fmt == PIX_FMT_BGR32) {
00515 for(x = 0; x < avctx->width; x++)
00516 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
00517 }
00518 }
00519 } else if (avctx->codec_tag == MKTAG('I','L','B','M')) {
00520 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00521 for(y = 0; y < avctx->height; y++ ) {
00522 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00523 memset(row, 0, avctx->width);
00524 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
00525 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00526 buf += s->planesize;
00527 }
00528 }
00529 } else if (s->ham) {
00530 for (y = 0; y < avctx->height; y++) {
00531 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00532 memset(s->ham_buf, 0, s->planesize * 8);
00533 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
00534 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
00535 buf += s->planesize;
00536 }
00537 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00538 }
00539 } else {
00540 for(y = 0; y < avctx->height; y++ ) {
00541 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00542 memset(row, 0, avctx->width << 2);
00543 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
00544 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00545 buf += s->planesize;
00546 }
00547 }
00548 }
00549 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) {
00550 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00551 for(y = 0; y < avctx->height; y++ ) {
00552 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
00553 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
00554 buf += avctx->width + (avctx->width % 2);
00555 }
00556 } else if (s->ham) {
00557 for (y = 0; y < avctx->height; y++) {
00558 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00559 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
00560 buf += avctx->width + (avctx->width & 1);
00561 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00562 }
00563 } else {
00564 av_log_ask_for_sample(avctx, "unsupported bpp\n");
00565 return AVERROR_INVALIDDATA;
00566 }
00567 }
00568
00569 *data_size = sizeof(AVFrame);
00570 *(AVFrame*)data = s->frame;
00571 return buf_size;
00572 }
00573
00574 static int decode_frame_byterun1(AVCodecContext *avctx,
00575 void *data, int *data_size,
00576 AVPacket *avpkt)
00577 {
00578 IffContext *s = avctx->priv_data;
00579 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
00580 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
00581 const uint8_t *buf_end = buf+buf_size;
00582 int y, plane, res;
00583
00584 if ((res = extract_header(avctx, avpkt)) < 0)
00585 return res;
00586 if (s->init) {
00587 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00588 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00589 return res;
00590 }
00591 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
00592 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00593 return res;
00594 } else if (avctx->pix_fmt == PIX_FMT_PAL8) {
00595 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
00596 return res;
00597 } else if (avctx->pix_fmt == PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
00598 if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
00599 return res;
00600 }
00601 s->init = 1;
00602
00603 if (avctx->codec_tag == MKTAG('I','L','B','M')) {
00604 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00605 for(y = 0; y < avctx->height ; y++ ) {
00606 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00607 memset(row, 0, avctx->width);
00608 for (plane = 0; plane < s->bpp; plane++) {
00609 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00610 decodeplane8(row, s->planebuf, s->planesize, plane);
00611 }
00612 }
00613 } else if (avctx->bits_per_coded_sample <= 8) {
00614 for (y = 0; y < avctx->height ; y++ ) {
00615 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00616 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
00617 for (plane = 0; plane < s->bpp; plane++) {
00618 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00619 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
00620 }
00621 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
00622 }
00623 } else if (s->ham) {
00624 for (y = 0; y < avctx->height ; y++) {
00625 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00626 memset(s->ham_buf, 0, s->planesize * 8);
00627 for (plane = 0; plane < s->bpp; plane++) {
00628 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00629 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
00630 }
00631 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00632 }
00633 } else {
00634 for(y = 0; y < avctx->height ; y++ ) {
00635 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00636 memset(row, 0, avctx->width << 2);
00637 for (plane = 0; plane < s->bpp; plane++) {
00638 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00639 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
00640 }
00641 }
00642 }
00643 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) {
00644 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00645 for(y = 0; y < avctx->height ; y++ ) {
00646 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00647 buf += decode_byterun(row, avctx->width, buf, buf_end);
00648 }
00649 } else if (s->ham) {
00650 for (y = 0; y < avctx->height ; y++) {
00651 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00652 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
00653 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00654 }
00655 } else {
00656 av_log_ask_for_sample(avctx, "unsupported bpp\n");
00657 return AVERROR_INVALIDDATA;
00658 }
00659 }
00660
00661 *data_size = sizeof(AVFrame);
00662 *(AVFrame*)data = s->frame;
00663 return buf_size;
00664 }
00665
00666 static av_cold int decode_end(AVCodecContext *avctx)
00667 {
00668 IffContext *s = avctx->priv_data;
00669 if (s->frame.data[0])
00670 avctx->release_buffer(avctx, &s->frame);
00671 av_freep(&s->planebuf);
00672 av_freep(&s->ham_buf);
00673 av_freep(&s->ham_palbuf);
00674 return 0;
00675 }
00676
00677 AVCodec ff_iff_ilbm_decoder = {
00678 .name = "iff_ilbm",
00679 .type = AVMEDIA_TYPE_VIDEO,
00680 .id = CODEC_ID_IFF_ILBM,
00681 .priv_data_size = sizeof(IffContext),
00682 .init = decode_init,
00683 .close = decode_end,
00684 .decode = decode_frame_ilbm,
00685 .capabilities = CODEC_CAP_DR1,
00686 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
00687 };
00688
00689 AVCodec ff_iff_byterun1_decoder = {
00690 .name = "iff_byterun1",
00691 .type = AVMEDIA_TYPE_VIDEO,
00692 .id = CODEC_ID_IFF_BYTERUN1,
00693 .priv_data_size = sizeof(IffContext),
00694 .init = decode_init,
00695 .close = decode_end,
00696 .decode = decode_frame_byterun1,
00697 .capabilities = CODEC_CAP_DR1,
00698 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
00699 };