• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • 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 Libav.
00007  *
00008  * Libav 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  * Libav 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 Libav; 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 typedef struct {
00034     AVFrame frame;
00035     int planesize;
00036     uint8_t * planebuf;
00037     int init; // 1 if buffer and palette data already initialized, 0 otherwise
00038 } IffContext;
00039 
00040 #define LUT8_PART(plane, v)                             \
00041     AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane,  \
00042     AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane,  \
00043     AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane,  \
00044     AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane,  \
00045     AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane,  \
00046     AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane,  \
00047     AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane,  \
00048     AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane,  \
00049     AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane,  \
00050     AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane,  \
00051     AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane,  \
00052     AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane,  \
00053     AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane,  \
00054     AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane,  \
00055     AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane,  \
00056     AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
00057 
00058 #define LUT8(plane) {                           \
00059     LUT8_PART(plane, 0x0000000),                \
00060     LUT8_PART(plane, 0x1000000),                \
00061     LUT8_PART(plane, 0x0010000),                \
00062     LUT8_PART(plane, 0x1010000),                \
00063     LUT8_PART(plane, 0x0000100),                \
00064     LUT8_PART(plane, 0x1000100),                \
00065     LUT8_PART(plane, 0x0010100),                \
00066     LUT8_PART(plane, 0x1010100),                \
00067     LUT8_PART(plane, 0x0000001),                \
00068     LUT8_PART(plane, 0x1000001),                \
00069     LUT8_PART(plane, 0x0010001),                \
00070     LUT8_PART(plane, 0x1010001),                \
00071     LUT8_PART(plane, 0x0000101),                \
00072     LUT8_PART(plane, 0x1000101),                \
00073     LUT8_PART(plane, 0x0010101),                \
00074     LUT8_PART(plane, 0x1010101),                \
00075 }
00076 
00077 // 8 planes * 8-bit mask
00078 static const uint64_t plane8_lut[8][256] = {
00079     LUT8(0), LUT8(1), LUT8(2), LUT8(3),
00080     LUT8(4), LUT8(5), LUT8(6), LUT8(7),
00081 };
00082 
00083 #define LUT32(plane) {                                \
00084              0,          0,          0,          0,   \
00085              0,          0,          0, 1 << plane,   \
00086              0,          0, 1 << plane,          0,   \
00087              0,          0, 1 << plane, 1 << plane,   \
00088              0, 1 << plane,          0,          0,   \
00089              0, 1 << plane,          0, 1 << plane,   \
00090              0, 1 << plane, 1 << plane,          0,   \
00091              0, 1 << plane, 1 << plane, 1 << plane,   \
00092     1 << plane,          0,          0,          0,   \
00093     1 << plane,          0,          0, 1 << plane,   \
00094     1 << plane,          0, 1 << plane,          0,   \
00095     1 << plane,          0, 1 << plane, 1 << plane,   \
00096     1 << plane, 1 << plane,          0,          0,   \
00097     1 << plane, 1 << plane,          0, 1 << plane,   \
00098     1 << plane, 1 << plane, 1 << plane,          0,   \
00099     1 << plane, 1 << plane, 1 << plane, 1 << plane,   \
00100 }
00101 
00102 // 32 planes * 4-bit mask * 4 lookup tables each
00103 static const uint32_t plane32_lut[32][16*4] = {
00104     LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
00105     LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
00106     LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
00107     LUT32(12), LUT32(13), LUT32(14), LUT32(15),
00108     LUT32(16), LUT32(17), LUT32(18), LUT32(19),
00109     LUT32(20), LUT32(21), LUT32(22), LUT32(23),
00110     LUT32(24), LUT32(25), LUT32(26), LUT32(27),
00111     LUT32(28), LUT32(29), LUT32(30), LUT32(31),
00112 };
00113 
00114 // Gray to RGB, required for palette table of grayscale images with bpp < 8
00115 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
00116     return x << 16 | x << 8 | x;
00117 }
00118 
00122 static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
00123 {
00124     int count, i;
00125 
00126     if (avctx->bits_per_coded_sample > 8) {
00127         av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
00128         return AVERROR_INVALIDDATA;
00129     }
00130 
00131     count = 1 << avctx->bits_per_coded_sample;
00132     // If extradata is smaller than actually needed, fill the remaining with black.
00133     count = FFMIN(avctx->extradata_size / 3, count);
00134     if (count) {
00135         for (i=0; i < count; i++) {
00136             pal[i] = 0xFF000000 | AV_RB24( avctx->extradata + i*3 );
00137         }
00138     } else { // Create gray-scale color palette for bps < 8
00139         count = 1 << avctx->bits_per_coded_sample;
00140 
00141         for (i=0; i < count; i++) {
00142             pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
00143         }
00144     }
00145     return 0;
00146 }
00147 
00148 static av_cold int decode_init(AVCodecContext *avctx)
00149 {
00150     IffContext *s = avctx->priv_data;
00151     int err;
00152 
00153     if (avctx->bits_per_coded_sample <= 8) {
00154         avctx->pix_fmt = (avctx->bits_per_coded_sample < 8 ||
00155                           avctx->extradata_size) ? PIX_FMT_PAL8
00156                                                  : PIX_FMT_GRAY8;
00157     } else if (avctx->bits_per_coded_sample <= 32) {
00158         avctx->pix_fmt = PIX_FMT_BGR32;
00159     } else {
00160         return AVERROR_INVALIDDATA;
00161     }
00162 
00163     if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
00164         return err;
00165     s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
00166     s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
00167     if (!s->planebuf)
00168         return AVERROR(ENOMEM);
00169 
00170     s->frame.reference = 1;
00171 
00172     return 0;
00173 }
00174 
00182 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
00183 {
00184     const uint64_t *lut = plane8_lut[plane];
00185     do {
00186         uint64_t v = AV_RN64A(dst) | lut[*buf++];
00187         AV_WN64A(dst, v);
00188         dst += 8;
00189     } while (--buf_size);
00190 }
00191 
00199 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
00200 {
00201     const uint32_t *lut = plane32_lut[plane];
00202     do {
00203         unsigned mask = (*buf >> 2) & ~3;
00204         dst[0] |= lut[mask++];
00205         dst[1] |= lut[mask++];
00206         dst[2] |= lut[mask++];
00207         dst[3] |= lut[mask];
00208         mask = (*buf++ << 2) & 0x3F;
00209         dst[4] |= lut[mask++];
00210         dst[5] |= lut[mask++];
00211         dst[6] |= lut[mask++];
00212         dst[7] |= lut[mask];
00213         dst += 8;
00214     } while (--buf_size);
00215 }
00216 
00226 static int decode_byterun(uint8_t *dst, int dst_size,
00227                           const uint8_t *buf, const uint8_t *const buf_end) {
00228     const uint8_t *const buf_start = buf;
00229     unsigned x;
00230     for (x = 0; x < dst_size && buf < buf_end;) {
00231         unsigned length;
00232         const int8_t value = *buf++;
00233         if (value >= 0) {
00234             length = value + 1;
00235             memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
00236             buf += length;
00237         } else if (value > -128) {
00238             length = -value + 1;
00239             memset(dst + x, *buf++, FFMIN(length, dst_size - x));
00240         } else { // noop
00241             continue;
00242         }
00243         x += length;
00244     }
00245     return buf - buf_start;
00246 }
00247 
00248 static int decode_frame_ilbm(AVCodecContext *avctx,
00249                             void *data, int *data_size,
00250                             AVPacket *avpkt)
00251 {
00252     IffContext *s = avctx->priv_data;
00253     const uint8_t *buf = avpkt->data;
00254     int buf_size = avpkt->size;
00255     const uint8_t *buf_end = buf+buf_size;
00256     int y, plane, res;
00257 
00258     if (s->init) {
00259         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00260             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00261             return res;
00262         }
00263     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
00264         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00265         return res;
00266     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
00267         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
00268             return res;
00269     }
00270     s->init = 1;
00271 
00272     if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
00273         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00274             for(y = 0; y < avctx->height; y++ ) {
00275                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00276                 memset(row, 0, avctx->width);
00277                 for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) {
00278                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00279                     buf += s->planesize;
00280                 }
00281             }
00282         } else { // PIX_FMT_BGR32
00283             for(y = 0; y < avctx->height; y++ ) {
00284                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00285                 memset(row, 0, avctx->width << 2);
00286                 for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) {
00287                     decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
00288                     buf += s->planesize;
00289                 }
00290             }
00291         }
00292     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
00293         for(y = 0; y < avctx->height; y++ ) {
00294             uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
00295             memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
00296             buf += avctx->width + (avctx->width % 2); // padding if odd
00297         }
00298     }
00299 
00300     *data_size = sizeof(AVFrame);
00301     *(AVFrame*)data = s->frame;
00302     return buf_size;
00303 }
00304 
00305 static int decode_frame_byterun1(AVCodecContext *avctx,
00306                             void *data, int *data_size,
00307                             AVPacket *avpkt)
00308 {
00309     IffContext *s = avctx->priv_data;
00310     const uint8_t *buf = avpkt->data;
00311     int buf_size = avpkt->size;
00312     const uint8_t *buf_end = buf+buf_size;
00313     int y, plane, res;
00314 
00315     if (s->init) {
00316         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00317             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00318             return res;
00319         }
00320     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
00321         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00322         return res;
00323     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
00324         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
00325             return res;
00326     }
00327     s->init = 1;
00328 
00329     if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
00330         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
00331             for(y = 0; y < avctx->height ; y++ ) {
00332                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
00333                 memset(row, 0, avctx->width);
00334                 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
00335                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00336                     decodeplane8(row, s->planebuf, s->planesize, plane);
00337                 }
00338             }
00339         } else { //PIX_FMT_BGR32
00340             for(y = 0; y < avctx->height ; y++ ) {
00341                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00342                 memset(row, 0, avctx->width << 2);
00343                 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
00344                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
00345                     decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
00346                 }
00347             }
00348         }
00349     } else {
00350         for(y = 0; y < avctx->height ; y++ ) {
00351             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
00352             buf += decode_byterun(row, avctx->width, buf, buf_end);
00353         }
00354     }
00355 
00356     *data_size = sizeof(AVFrame);
00357     *(AVFrame*)data = s->frame;
00358     return buf_size;
00359 }
00360 
00361 static av_cold int decode_end(AVCodecContext *avctx)
00362 {
00363     IffContext *s = avctx->priv_data;
00364     if (s->frame.data[0])
00365         avctx->release_buffer(avctx, &s->frame);
00366     av_freep(&s->planebuf);
00367     return 0;
00368 }
00369 
00370 AVCodec ff_iff_ilbm_decoder = {
00371     .name           = "iff_ilbm",
00372     .type           = AVMEDIA_TYPE_VIDEO,
00373     .id             = CODEC_ID_IFF_ILBM,
00374     .priv_data_size = sizeof(IffContext),
00375     .init           = decode_init,
00376     .close          = decode_end,
00377     .decode         = decode_frame_ilbm,
00378     .capabilities   = CODEC_CAP_DR1,
00379     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
00380 };
00381 
00382 AVCodec ff_iff_byterun1_decoder = {
00383     .name           = "iff_byterun1",
00384     .type           = AVMEDIA_TYPE_VIDEO,
00385     .id             = CODEC_ID_IFF_BYTERUN1,
00386     .priv_data_size = sizeof(IffContext),
00387     .init           = decode_init,
00388     .close          = decode_end,
00389     .decode         = decode_frame_byterun1,
00390     .capabilities   = CODEC_CAP_DR1,
00391     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
00392 };
Generated on Thu Jul 11 2013 15:38:19 for Libav by doxygen 1.7.1