• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/iff.c

Go to the documentation of this file.
00001 /*
00002  * IFF PBM/ILBM bitmap decoder
00003  * Copyright (c) 2010 Peter Ross <pross@xvid.org>
00004  * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
00005  *
00006  * This file is part of FFmpeg.
00007  *
00008  * FFmpeg is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * FFmpeg is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with FFmpeg; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00028 #include "libavutil/imgutils.h"
00029 #include "bytestream.h"
00030 #include "avcodec.h"
00031 #include "get_bits.h"
00032 
00033 // TODO: masking bits
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; // 1 if buffer and palette data already initialized, 0 otherwise
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 // 8 planes * 8-bit mask
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 // 32 planes * 4-bit mask * 4 lookup tables each
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 // Gray to RGB, required for palette table of grayscale images with bpp < 8
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     // If extradata is smaller than actually needed, fill the remaining with black.
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) { // EHB
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 { // Create gray-scale color palette for bps < 8
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;
00195 
00196     if (avctx->extradata_size < 2) {
00197         av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
00198         return AVERROR_INVALIDDATA;
00199     }
00200     palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
00201 
00202     if (avpkt) {
00203         int image_size;
00204         if (avpkt->size < 2)
00205             return AVERROR_INVALIDDATA;
00206         image_size = avpkt->size - AV_RB16(avpkt->data);
00207         buf = avpkt->data;
00208         buf_size = bytestream_get_be16(&buf);
00209         if (buf_size <= 1 || image_size <= 1) {
00210             av_log(avctx, AV_LOG_ERROR,
00211                    "Invalid image size received: %u -> image data offset: %d\n",
00212                    buf_size, image_size);
00213             return AVERROR_INVALIDDATA;
00214         }
00215     } else {
00216         buf = avctx->extradata;
00217         buf_size = bytestream_get_be16(&buf);
00218         if (buf_size <= 1 || palette_size < 0) {
00219             av_log(avctx, AV_LOG_ERROR,
00220                    "Invalid palette size received: %u -> palette data offset: %d\n",
00221                    buf_size, palette_size);
00222             return AVERROR_INVALIDDATA;
00223         }
00224     }
00225 
00226     if (buf_size > 8) {
00227         s->compression  = bytestream_get_byte(&buf);
00228         s->bpp          = bytestream_get_byte(&buf);
00229         s->ham          = bytestream_get_byte(&buf);
00230         s->flags        = bytestream_get_byte(&buf);
00231         s->transparency = bytestream_get_be16(&buf);
00232         s->masking      = bytestream_get_byte(&buf);
00233         if (s->masking == MASK_HAS_MASK) {
00234             if (s->bpp >= 8) {
00235                 avctx->pix_fmt = PIX_FMT_RGB32;
00236                 av_freep(&s->mask_buf);
00237                 av_freep(&s->mask_palbuf);
00238                 s->mask_buf = av_malloc((s->planesize * 32) + FF_INPUT_BUFFER_PADDING_SIZE);
00239                 if (!s->mask_buf)
00240                     return AVERROR(ENOMEM);
00241                 s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
00242                 if (!s->mask_palbuf) {
00243                     av_freep(&s->mask_buf);
00244                     return AVERROR(ENOMEM);
00245                 }
00246             }
00247             s->bpp++;
00248         } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) {
00249             av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
00250             return AVERROR_PATCHWELCOME;
00251         }
00252         if (!s->bpp || s->bpp > 32) {
00253             av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
00254             return AVERROR_INVALIDDATA;
00255         } else if (s->ham >= 8) {
00256             av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
00257             return AVERROR_INVALIDDATA;
00258         }
00259 
00260         av_freep(&s->ham_buf);
00261         av_freep(&s->ham_palbuf);
00262 
00263         if (s->ham) {
00264             int i, count = FFMIN(palette_size / 3, 1 << s->ham);
00265             int ham_count;
00266             const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
00267 
00268             s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
00269             if (!s->ham_buf)
00270                 return AVERROR(ENOMEM);
00271 
00272             ham_count = 8 * (1 << s->ham);
00273             s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
00274             if (!s->ham_palbuf) {
00275                 av_freep(&s->ham_buf);
00276                 return AVERROR(ENOMEM);
00277             }
00278 
00279             if (count) { // HAM with color palette attached
00280                 // prefill with black and palette and set HAM take direct value mask to zero
00281                 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
00282                 for (i=0; i < count; i++) {
00283                     s->ham_palbuf[i*2+1] = AV_RL24(palette + i*3);
00284                 }
00285                 count = 1 << s->ham;
00286             } else { // HAM with grayscale color palette
00287                 count = 1 << s->ham;
00288                 for (i=0; i < count; i++) {
00289                     s->ham_palbuf[i*2]   = 0; // take direct color value from palette
00290                     s->ham_palbuf[i*2+1] = av_le2ne32(gray2rgb((i * 255) >> s->ham));
00291                 }
00292             }
00293             for (i=0; i < count; i++) {
00294                 uint32_t tmp = i << (8 - s->ham);
00295                 tmp |= tmp >> s->ham;
00296                 s->ham_palbuf[(i+count)*2]     = 0x00FFFF; // just modify blue color component
00297                 s->ham_palbuf[(i+count*2)*2]   = 0xFFFF00; // just modify red color component
00298                 s->ham_palbuf[(i+count*3)*2]   = 0xFF00FF; // just modify green color component
00299                 s->ham_palbuf[(i+count)*2+1]   = tmp << 16;
00300                 s->ham_palbuf[(i+count*2)*2+1] = tmp;
00301                 s->ham_palbuf[(i+count*3)*2+1] = tmp << 8;
00302             }
00303             if (s->masking == MASK_HAS_MASK) {
00304                 for (i = 0; i < ham_count; i++)
00305                     s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
00306             }
00307         }
00308     }
00309 
00310     return 0;
00311 }
00312 
00313 static av_cold int decode_init(AVCodecContext *avctx)
00314 {
00315     IffContext *s = avctx->priv_data;
00316     int err;
00317 
00318     if (avctx->bits_per_coded_sample <= 8) {
00319         int palette_size;
00320 
00321         if (avctx->extradata_size >= 2)
00322             palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
00323         else
00324             palette_size = 0;
00325         avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
00326                          (avctx->extradata_size >= 2 && palette_size) ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
00327     } else if (avctx->bits_per_coded_sample <= 32) {
00328         avctx->pix_fmt = PIX_FMT_BGR32;
00329     } else {
00330         return AVERROR_INVALIDDATA;
00331     }
00332 
00333     if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
00334         return err;
00335     s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
00336     s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
00337     if (!s->planebuf)
00338         return AVERROR(ENOMEM);
00339 
00340     s->bpp = avctx->bits_per_coded_sample;
00341     avcodec_get_frame_defaults(&s->frame);
00342 
00343     if ((err = extract_header(avctx, NULL)) < 0)
00344         return err;
00345     s->frame.reference = 3;
00346 
00347     return 0;
00348 }
00349 
00357 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
00358 {
00359     const uint64_t *lut = plane8_lut[plane];
00360     do {
00361         uint64_t v = AV_RN64A(dst) | lut[*buf++];
00362         AV_WN64A(dst, v);
00363         dst += 8;
00364     } while (--buf_size);
00365 }
00366 
00374 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
00375 {
00376     const uint32_t *lut = plane32_lut[plane];
00377     do {
00378         unsigned mask = (*buf >> 2) & ~3;
00379         dst[0] |= lut[mask++];
00380         dst[1] |= lut[mask++];
00381         dst[2] |= lut[mask++];
00382         dst[3] |= lut[mask];
00383         mask = (*buf++ << 2) & 0x3F;
00384         dst[4] |= lut[mask++];
00385         dst[5] |= lut[mask++];
00386         dst[6] |= lut[mask++];
00387         dst[7] |= lut[mask];
00388         dst += 8;
00389     } while (--buf_size);
00390 }
00391 
00392 #define DECODE_HAM_PLANE32(x)       \
00393     first       = buf[x] << 1;      \
00394     second      = buf[(x)+1] << 1;  \
00395     delta      &= pal[first++];     \
00396     delta      |= pal[first];       \
00397     dst[x]      = delta;            \
00398     delta      &= pal[second++];    \
00399     delta      |= pal[second];      \
00400     dst[(x)+1]  = delta
00401 
00410 static void decode_ham_plane32(uint32_t *dst, const uint8_t  *buf,
00411                                const uint32_t *const pal, unsigned buf_size)
00412 {
00413     uint32_t delta = 0;
00414     do {
00415         uint32_t first, second;
00416         DECODE_HAM_PLANE32(0);
00417         DECODE_HAM_PLANE32(2);
00418         DECODE_HAM_PLANE32(4);
00419         DECODE_HAM_PLANE32(6);
00420         buf += 8;
00421         dst += 8;
00422     } while (--buf_size);
00423 }
00424 
00425 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
00426                          const uint32_t *const pal, unsigned width)
00427 {
00428     do {
00429         *dst++ = pal[*buf++];
00430     } while (--width);
00431 }
00432 
00442 static int decode_byterun(uint8_t *dst, int dst_size,
00443                           const uint8_t *buf, const uint8_t *const buf_end) {
00444     const uint8_t *const buf_start = buf;
00445     unsigned x;
00446     for (x = 0; x < dst_size && buf < buf_end;) {
00447         unsigned length;
00448         const int8_t value = *buf++;
00449         if (value >= 0) {
00450             length = value + 1;
00451             memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
00452             buf += length;
00453         } else if (value > -128) {
00454             length = -value + 1;
00455             memset(dst + x, *buf++, FFMIN(length, dst_size - x));
00456         } else { // noop
00457             continue;
00458         }
00459         x += length;
00460     }
00461     return buf - buf_start;
00462 }
00463 
00464 static int decode_frame_ilbm(AVCodecContext *avctx,
00465                             void *data, int *data_size,
00466                             AVPacket *avpkt)
00467 {
00468     IffContext *s = avctx->priv_data;
00469     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
00470     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
00471     const uint8_t *buf_end = buf+buf_size;
00472     int y, plane, res;
00473 
00474     if ((res = extract_header(avctx, avpkt)) < 0)
00475         return res;
00476 
00477     if (s->init) {
00478         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00479             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00480             return res;
00481         }
00482     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
00483         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00484         return res;
00485     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == PIX_FMT_PAL8) {
00486         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
00487             return res;
00488     }
00489     s->init = 1;
00490 
00491     if (avctx->codec_tag == MKTAG('A','C','B','M')) {
00492         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00493             memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
00494             for (plane = 0; plane < s->bpp; plane++) {
00495                 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
00496                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00497                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00498                     buf += s->planesize;
00499                 }
00500             }
00501         } else if (s->ham) { // HAM to PIX_FMT_BGR32
00502             memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
00503             for(y = 0; y < avctx->height; y++) {
00504                 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
00505                 memset(s->ham_buf, 0, s->planesize * 8);
00506                 for (plane = 0; plane < s->bpp; plane++) {
00507                     const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
00508                     if (start >= buf_end)
00509                         break;
00510                     decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
00511                 }
00512                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00513             }
00514         }
00515     } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
00516         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00517             for(y = 0; y < avctx->height; y++ ) {
00518                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00519                 memset(row, 0, avctx->width);
00520                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
00521                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00522                     buf += s->planesize;
00523                 }
00524             }
00525         } else if (s->ham) { // HAM to PIX_FMT_BGR32
00526             for (y = 0; y < avctx->height; y++) {
00527                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00528                 memset(s->ham_buf, 0, s->planesize * 8);
00529                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
00530                     decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
00531                     buf += s->planesize;
00532                 }
00533                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00534             }
00535         } else { // PIX_FMT_BGR32
00536             for(y = 0; y < avctx->height; y++ ) {
00537                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00538                 memset(row, 0, avctx->width << 2);
00539                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
00540                     decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00541                     buf += s->planesize;
00542                 }
00543             }
00544         }
00545     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
00546         for(y = 0; y < avctx->height; y++ ) {
00547             uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
00548             memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
00549             buf += avctx->width + (avctx->width % 2); // padding if odd
00550         }
00551     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
00552         for (y = 0; y < avctx->height; y++) {
00553             uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00554             memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
00555             buf += avctx->width + (avctx->width & 1); // padding if odd
00556             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
00557         }
00558     }
00559 
00560     *data_size = sizeof(AVFrame);
00561     *(AVFrame*)data = s->frame;
00562     return buf_size;
00563 }
00564 
00565 static int decode_frame_byterun1(AVCodecContext *avctx,
00566                             void *data, int *data_size,
00567                             AVPacket *avpkt)
00568 {
00569     IffContext *s = avctx->priv_data;
00570     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
00571     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
00572     const uint8_t *buf_end = buf+buf_size;
00573     int y, plane, res;
00574 
00575     if ((res = extract_header(avctx, avpkt)) < 0)
00576         return res;
00577     if (s->init) {
00578         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00579             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00580             return res;
00581         }
00582     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
00583         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00584         return res;
00585     } else if (avctx->pix_fmt == PIX_FMT_PAL8) {
00586         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
00587             return res;
00588     } else if (avctx->pix_fmt == PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
00589         if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
00590             return res;
00591     }
00592     s->init = 1;
00593 
00594     if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
00595         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00596             for(y = 0; y < avctx->height ; y++ ) {
00597                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00598                 memset(row, 0, avctx->width);
00599                 for (plane = 0; plane < s->bpp; plane++) {
00600                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00601                     decodeplane8(row, s->planebuf, s->planesize, plane);
00602                 }
00603             }
00604         } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to PIX_FMT_BGR32
00605             for (y = 0; y < avctx->height ; y++ ) {
00606                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00607                 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
00608                 for (plane = 0; plane < s->bpp; plane++) {
00609                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00610                     decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
00611                 }
00612                 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
00613             }
00614         } else if (s->ham) { // HAM to PIX_FMT_BGR32
00615             for (y = 0; y < avctx->height ; y++) {
00616                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00617                 memset(s->ham_buf, 0, s->planesize * 8);
00618                 for (plane = 0; plane < s->bpp; plane++) {
00619                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00620                     decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
00621                 }
00622                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
00623             }
00624         } else { //PIX_FMT_BGR32
00625             for(y = 0; y < avctx->height ; y++ ) {
00626                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00627                 memset(row, 0, avctx->width << 2);
00628                 for (plane = 0; plane < s->bpp; plane++) {
00629                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00630                     decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
00631                 }
00632             }
00633         }
00634     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
00635         for(y = 0; y < avctx->height ; y++ ) {
00636             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00637             buf += decode_byterun(row, avctx->width, buf, buf_end);
00638         }
00639     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
00640         for (y = 0; y < avctx->height ; y++) {
00641             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00642             buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
00643             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
00644         }
00645     }
00646 
00647     *data_size = sizeof(AVFrame);
00648     *(AVFrame*)data = s->frame;
00649     return buf_size;
00650 }
00651 
00652 static av_cold int decode_end(AVCodecContext *avctx)
00653 {
00654     IffContext *s = avctx->priv_data;
00655     if (s->frame.data[0])
00656         avctx->release_buffer(avctx, &s->frame);
00657     av_freep(&s->planebuf);
00658     av_freep(&s->ham_buf);
00659     av_freep(&s->ham_palbuf);
00660     return 0;
00661 }
00662 
00663 AVCodec ff_iff_ilbm_decoder = {
00664     .name           = "iff_ilbm",
00665     .type           = AVMEDIA_TYPE_VIDEO,
00666     .id             = CODEC_ID_IFF_ILBM,
00667     .priv_data_size = sizeof(IffContext),
00668     .init           = decode_init,
00669     .close          = decode_end,
00670     .decode         = decode_frame_ilbm,
00671     .capabilities   = CODEC_CAP_DR1,
00672     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
00673 };
00674 
00675 AVCodec ff_iff_byterun1_decoder = {
00676     .name           = "iff_byterun1",
00677     .type           = AVMEDIA_TYPE_VIDEO,
00678     .id             = CODEC_ID_IFF_BYTERUN1,
00679     .priv_data_size = sizeof(IffContext),
00680     .init           = decode_init,
00681     .close          = decode_end,
00682     .decode         = decode_frame_byterun1,
00683     .capabilities   = CODEC_CAP_DR1,
00684     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
00685 };
Generated on Fri Feb 1 2013 14:34:36 for FFmpeg by doxygen 1.7.1