1/* 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> 5 * 6 * This file is part of FFmpeg. 7 * 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. 12 * 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. 17 * 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 21 */ 22 23/** 24 * @file 25 * IFF PBM/ILBM bitmap decoder 26 */ 27 28#include "bytestream.h" 29#include "avcodec.h" 30#include "get_bits.h" 31#include "iff.h" 32 33typedef struct { 34 AVFrame frame; 35 int planesize; 36 uint8_t * planebuf; 37} IffContext; 38 39/** 40 * Convert CMAP buffer (stored in extradata) to lavc palette format 41 */ 42int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal) 43{ 44 int count, i; 45 46 if (avctx->bits_per_coded_sample > 8) { 47 av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n"); 48 return AVERROR_INVALIDDATA; 49 } 50 51 count = 1 << avctx->bits_per_coded_sample; 52 if (avctx->extradata_size < count * 3) { 53 av_log(avctx, AV_LOG_ERROR, "palette data underflow\n"); 54 return AVERROR_INVALIDDATA; 55 } 56 for (i=0; i < count; i++) { 57 pal[i] = 0xFF000000 | AV_RB24( avctx->extradata + i*3 ); 58 } 59 return 0; 60} 61 62static av_cold int decode_init(AVCodecContext *avctx) 63{ 64 IffContext *s = avctx->priv_data; 65 int err; 66 67 if (avctx->bits_per_coded_sample <= 8) { 68 avctx->pix_fmt = PIX_FMT_PAL8; 69 } else if (avctx->bits_per_coded_sample <= 32) { 70 avctx->pix_fmt = PIX_FMT_BGR32; 71 } else { 72 return AVERROR_INVALIDDATA; 73 } 74 75 s->planesize = avctx->width >> 3; 76 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE); 77 if (!s->planebuf) 78 return AVERROR(ENOMEM); 79 80 s->frame.reference = 1; 81 if ((err = avctx->get_buffer(avctx, &s->frame) < 0)) { 82 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 83 return err; 84 } 85 86 return avctx->bits_per_coded_sample <= 8 ? 87 ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1]) : 0; 88} 89 90/** 91 * Decode interleaved plane buffer up to 8bpp 92 * @param dst Destination buffer 93 * @param buf Source buffer 94 * @param buf_size 95 * @param bps bits_per_coded_sample (must be <= 8) 96 * @param plane plane number to decode as 97 */ 98static void decodeplane8(uint8_t *dst, const uint8_t *const buf, int buf_size, int bps, int plane) 99{ 100 GetBitContext gb; 101 int i; 102 const int b = (buf_size * 8) + bps - 1; 103 init_get_bits(&gb, buf, buf_size * 8); 104 for(i = 0; i < b; i++) { 105 dst[i] |= get_bits1(&gb) << plane; 106 } 107} 108 109/** 110 * Decode interleaved plane buffer up to 24bpp 111 * @param dst Destination buffer 112 * @param buf Source buffer 113 * @param buf_size 114 * @param bps bits_per_coded_sample 115 * @param plane plane number to decode as 116 */ 117static void decodeplane32(uint32_t *dst, const uint8_t *const buf, int buf_size, int bps, int plane) 118{ 119 GetBitContext gb; 120 int i; 121 const int b = (buf_size * 8) + bps - 1; 122 init_get_bits(&gb, buf, buf_size * 8); 123 for(i = 0; i < b; i++) { 124 dst[i] |= get_bits1(&gb) << plane; 125 } 126} 127 128static int decode_frame_ilbm(AVCodecContext *avctx, 129 void *data, int *data_size, 130 AVPacket *avpkt) 131{ 132 IffContext *s = avctx->priv_data; 133 const uint8_t *buf = avpkt->data; 134 int buf_size = avpkt->size; 135 const uint8_t *buf_end = buf+buf_size; 136 int y, plane; 137 138 if (avctx->reget_buffer(avctx, &s->frame) < 0){ 139 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 140 return -1; 141 } 142 143 if (avctx->pix_fmt == PIX_FMT_PAL8) { 144 for(y = 0; y < avctx->height; y++ ) { 145 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ]; 146 memset(row, 0, avctx->width); 147 for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) { 148 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), avctx->bits_per_coded_sample, plane); 149 buf += s->planesize; 150 } 151 } 152 } else { // PIX_FMT_BGR32 153 for(y = 0; y < avctx->height; y++ ) { 154 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]]; 155 memset(row, 0, avctx->width << 2); 156 for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) { 157 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), avctx->bits_per_coded_sample, plane); 158 buf += s->planesize; 159 } 160 } 161 } 162 163 *data_size = sizeof(AVFrame); 164 *(AVFrame*)data = s->frame; 165 return buf_size; 166} 167 168static int decode_frame_byterun1(AVCodecContext *avctx, 169 void *data, int *data_size, 170 AVPacket *avpkt) 171{ 172 IffContext *s = avctx->priv_data; 173 const uint8_t *buf = avpkt->data; 174 int buf_size = avpkt->size; 175 const uint8_t *buf_end = buf+buf_size; 176 int y, plane, x; 177 178 if (avctx->reget_buffer(avctx, &s->frame) < 0){ 179 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 180 return -1; 181 } 182 183 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved 184 if (avctx->pix_fmt == PIX_FMT_PAL8) { 185 for(y = 0; y < avctx->height ; y++ ) { 186 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ]; 187 memset(row, 0, avctx->width); 188 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) { 189 for(x = 0; x < s->planesize && buf < buf_end; ) { 190 int8_t value = *buf++; 191 unsigned length; 192 if (value >= 0) { 193 length = value + 1; 194 memcpy(s->planebuf + x, buf, FFMIN3(length, s->planesize - x, buf_end - buf)); 195 buf += length; 196 } else if (value > -128) { 197 length = -value + 1; 198 memset(s->planebuf + x, *buf++, FFMIN(length, s->planesize - x)); 199 } else { //noop 200 continue; 201 } 202 x += length; 203 } 204 decodeplane8(row, s->planebuf, s->planesize, avctx->bits_per_coded_sample, plane); 205 } 206 } 207 } else { //PIX_FMT_BGR32 208 for(y = 0; y < avctx->height ; y++ ) { 209 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]]; 210 memset(row, 0, avctx->width << 2); 211 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) { 212 for(x = 0; x < s->planesize && buf < buf_end; ) { 213 int8_t value = *buf++; 214 unsigned length; 215 if (value >= 0) { 216 length = value + 1; 217 memcpy(s->planebuf + x, buf, FFMIN3(length, s->planesize - x, buf_end - buf)); 218 buf += length; 219 } else if (value > -128) { 220 length = -value + 1; 221 memset(s->planebuf + x, *buf++, FFMIN(length, s->planesize - x)); 222 } else { // noop 223 continue; 224 } 225 x += length; 226 } 227 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, avctx->bits_per_coded_sample, plane); 228 } 229 } 230 } 231 } else { 232 for(y = 0; y < avctx->height ; y++ ) { 233 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]]; 234 for(x = 0; x < avctx->width && buf < buf_end; ) { 235 int8_t value = *buf++; 236 unsigned length; 237 if (value >= 0) { 238 length = value + 1; 239 memcpy(row + x, buf, FFMIN3(length, buf_end - buf, avctx->width - x)); 240 buf += length; 241 } else if (value > -128) { 242 length = -value + 1; 243 memset(row + x, *buf++, FFMIN(length, avctx->width - x)); 244 } else { //noop 245 continue; 246 } 247 x += length; 248 } 249 } 250 } 251 252 *data_size = sizeof(AVFrame); 253 *(AVFrame*)data = s->frame; 254 return buf_size; 255} 256 257static av_cold int decode_end(AVCodecContext *avctx) 258{ 259 IffContext *s = avctx->priv_data; 260 if (s->frame.data[0]) 261 avctx->release_buffer(avctx, &s->frame); 262 av_freep(&s->planebuf); 263 return 0; 264} 265 266AVCodec iff_ilbm_decoder = { 267 "iff_ilbm", 268 AVMEDIA_TYPE_VIDEO, 269 CODEC_ID_IFF_ILBM, 270 sizeof(IffContext), 271 decode_init, 272 NULL, 273 decode_end, 274 decode_frame_ilbm, 275 CODEC_CAP_DR1, 276 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"), 277}; 278 279AVCodec iff_byterun1_decoder = { 280 "iff_byterun1", 281 AVMEDIA_TYPE_VIDEO, 282 CODEC_ID_IFF_BYTERUN1, 283 sizeof(IffContext), 284 decode_init, 285 NULL, 286 decode_end, 287 decode_frame_byterun1, 288 CODEC_CAP_DR1, 289 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"), 290}; 291