annotate ffmpeg/libavcodec/targa.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Targa (.tga) image decoder
yading@10 3 * Copyright (c) 2006 Konstantin Shishkov
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 #include "libavutil/intreadwrite.h"
yading@10 23 #include "libavutil/imgutils.h"
yading@10 24 #include "avcodec.h"
yading@10 25 #include "bytestream.h"
yading@10 26 #include "internal.h"
yading@10 27 #include "targa.h"
yading@10 28
yading@10 29 typedef struct TargaContext {
yading@10 30 GetByteContext gb;
yading@10 31 } TargaContext;
yading@10 32
yading@10 33 static uint8_t *advance_line(uint8_t *start, uint8_t *line,
yading@10 34 int stride, int *y, int h, int interleave)
yading@10 35 {
yading@10 36 *y += interleave;
yading@10 37
yading@10 38 if (*y < h) {
yading@10 39 return line + interleave * stride;
yading@10 40 } else {
yading@10 41 *y = (*y + 1) & (interleave - 1);
yading@10 42 if (*y && *y < h) {
yading@10 43 return start + *y * stride;
yading@10 44 } else {
yading@10 45 return NULL;
yading@10 46 }
yading@10 47 }
yading@10 48 }
yading@10 49
yading@10 50 static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s,
yading@10 51 uint8_t *start, int w, int h, int stride,
yading@10 52 int bpp, int interleave)
yading@10 53 {
yading@10 54 int x, y;
yading@10 55 int depth = (bpp + 1) >> 3;
yading@10 56 int type, count;
yading@10 57 uint8_t *line = start;
yading@10 58 uint8_t *dst = line;
yading@10 59
yading@10 60 x = y = count = 0;
yading@10 61 while (dst) {
yading@10 62 if (bytestream2_get_bytes_left(&s->gb) <= 0) {
yading@10 63 av_log(avctx, AV_LOG_ERROR,
yading@10 64 "Ran ouf of data before end-of-image\n");
yading@10 65 return AVERROR_INVALIDDATA;
yading@10 66 }
yading@10 67 type = bytestream2_get_byteu(&s->gb);
yading@10 68 count = (type & 0x7F) + 1;
yading@10 69 type &= 0x80;
yading@10 70 if (!type) {
yading@10 71 do {
yading@10 72 int n = FFMIN(count, w - x);
yading@10 73 bytestream2_get_buffer(&s->gb, dst, n * depth);
yading@10 74 count -= n;
yading@10 75 dst += n * depth;
yading@10 76 x += n;
yading@10 77 if (x == w) {
yading@10 78 x = 0;
yading@10 79 dst = line = advance_line(start, line, stride, &y, h, interleave);
yading@10 80 }
yading@10 81 } while (dst && count > 0);
yading@10 82 } else {
yading@10 83 uint8_t tmp[4];
yading@10 84 bytestream2_get_buffer(&s->gb, tmp, depth);
yading@10 85 do {
yading@10 86 int n = FFMIN(count, w - x);
yading@10 87 count -= n;
yading@10 88 x += n;
yading@10 89 do {
yading@10 90 memcpy(dst, tmp, depth);
yading@10 91 dst += depth;
yading@10 92 } while (--n);
yading@10 93 if (x == w) {
yading@10 94 x = 0;
yading@10 95 dst = line = advance_line(start, line, stride, &y, h, interleave);
yading@10 96 }
yading@10 97 } while (dst && count > 0);
yading@10 98 }
yading@10 99 }
yading@10 100
yading@10 101 if (count) {
yading@10 102 av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds\n");
yading@10 103 return AVERROR_INVALIDDATA;
yading@10 104 }
yading@10 105
yading@10 106 return 0;
yading@10 107 }
yading@10 108
yading@10 109 static int decode_frame(AVCodecContext *avctx,
yading@10 110 void *data, int *got_frame,
yading@10 111 AVPacket *avpkt)
yading@10 112 {
yading@10 113 TargaContext * const s = avctx->priv_data;
yading@10 114 AVFrame * const p = data;
yading@10 115 uint8_t *dst;
yading@10 116 int stride;
yading@10 117 int idlen, pal, compr, y, w, h, bpp, flags, ret;
yading@10 118 int first_clr, colors, csize;
yading@10 119 int interleave;
yading@10 120
yading@10 121 bytestream2_init(&s->gb, avpkt->data, avpkt->size);
yading@10 122
yading@10 123 /* parse image header */
yading@10 124 idlen = bytestream2_get_byte(&s->gb);
yading@10 125 pal = bytestream2_get_byte(&s->gb);
yading@10 126 compr = bytestream2_get_byte(&s->gb);
yading@10 127 first_clr = bytestream2_get_le16(&s->gb);
yading@10 128 colors = bytestream2_get_le16(&s->gb);
yading@10 129 csize = bytestream2_get_byte(&s->gb);
yading@10 130 bytestream2_skip(&s->gb, 4); /* 2: x, 2: y */
yading@10 131 w = bytestream2_get_le16(&s->gb);
yading@10 132 h = bytestream2_get_le16(&s->gb);
yading@10 133 bpp = bytestream2_get_byte(&s->gb);
yading@10 134
yading@10 135 if (bytestream2_get_bytes_left(&s->gb) <= idlen) {
yading@10 136 av_log(avctx, AV_LOG_ERROR,
yading@10 137 "Not enough data to read header\n");
yading@10 138 return AVERROR_INVALIDDATA;
yading@10 139 }
yading@10 140
yading@10 141 flags = bytestream2_get_byte(&s->gb);
yading@10 142
yading@10 143 if (!pal && (first_clr || colors || csize)) {
yading@10 144 av_log(avctx, AV_LOG_WARNING, "File without colormap has colormap information set.\n");
yading@10 145 // specification says we should ignore those value in this case
yading@10 146 first_clr = colors = csize = 0;
yading@10 147 }
yading@10 148
yading@10 149 // skip identifier if any
yading@10 150 bytestream2_skip(&s->gb, idlen);
yading@10 151
yading@10 152 switch (bpp) {
yading@10 153 case 8:
yading@10 154 avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? AV_PIX_FMT_GRAY8 : AV_PIX_FMT_PAL8;
yading@10 155 break;
yading@10 156 case 15:
yading@10 157 case 16:
yading@10 158 avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
yading@10 159 break;
yading@10 160 case 24:
yading@10 161 avctx->pix_fmt = AV_PIX_FMT_BGR24;
yading@10 162 break;
yading@10 163 case 32:
yading@10 164 avctx->pix_fmt = AV_PIX_FMT_BGRA;
yading@10 165 break;
yading@10 166 default:
yading@10 167 av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", bpp);
yading@10 168 return AVERROR_INVALIDDATA;
yading@10 169 }
yading@10 170
yading@10 171 if (colors && (colors + first_clr) > 256) {
yading@10 172 av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
yading@10 173 return AVERROR_INVALIDDATA;
yading@10 174 }
yading@10 175
yading@10 176 if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
yading@10 177 return ret;
yading@10 178 if (w != avctx->width || h != avctx->height)
yading@10 179 avcodec_set_dimensions(avctx, w, h);
yading@10 180 if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
yading@10 181 return ret;
yading@10 182
yading@10 183 if (flags & TGA_TOPTOBOTTOM) {
yading@10 184 dst = p->data[0];
yading@10 185 stride = p->linesize[0];
yading@10 186 } else { //image is upside-down
yading@10 187 dst = p->data[0] + p->linesize[0] * (h - 1);
yading@10 188 stride = -p->linesize[0];
yading@10 189 }
yading@10 190
yading@10 191 interleave = flags & TGA_INTERLEAVE2 ? 2 :
yading@10 192 flags & TGA_INTERLEAVE4 ? 4 : 1;
yading@10 193
yading@10 194 if (colors) {
yading@10 195 int pal_size, pal_sample_size;
yading@10 196
yading@10 197 switch (csize) {
yading@10 198 case 32: pal_sample_size = 4; break;
yading@10 199 case 24: pal_sample_size = 3; break;
yading@10 200 case 16:
yading@10 201 case 15: pal_sample_size = 2; break;
yading@10 202 default:
yading@10 203 av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);
yading@10 204 return AVERROR_INVALIDDATA;
yading@10 205 }
yading@10 206 pal_size = colors * pal_sample_size;
yading@10 207 if (avctx->pix_fmt != AV_PIX_FMT_PAL8) //should not occur but skip palette anyway
yading@10 208 bytestream2_skip(&s->gb, pal_size);
yading@10 209 else {
yading@10 210 int t;
yading@10 211 uint32_t *pal = ((uint32_t *)p->data[1]) + first_clr;
yading@10 212
yading@10 213 if (bytestream2_get_bytes_left(&s->gb) < pal_size) {
yading@10 214 av_log(avctx, AV_LOG_ERROR,
yading@10 215 "Not enough data to read palette\n");
yading@10 216 return AVERROR_INVALIDDATA;
yading@10 217 }
yading@10 218 switch (pal_sample_size) {
yading@10 219 case 4:
yading@10 220 for (t = 0; t < colors; t++)
yading@10 221 *pal++ = bytestream2_get_le32u(&s->gb);
yading@10 222 break;
yading@10 223 case 3:
yading@10 224 /* RGB24 */
yading@10 225 for (t = 0; t < colors; t++)
yading@10 226 *pal++ = (0xffU<<24) | bytestream2_get_le24u(&s->gb);
yading@10 227 break;
yading@10 228 case 2:
yading@10 229 /* RGB555 */
yading@10 230 for (t = 0; t < colors; t++) {
yading@10 231 uint32_t v = bytestream2_get_le16u(&s->gb);
yading@10 232 v = ((v & 0x7C00) << 9) |
yading@10 233 ((v & 0x03E0) << 6) |
yading@10 234 ((v & 0x001F) << 3);
yading@10 235 /* left bit replication */
yading@10 236 v |= (v & 0xE0E0E0U) >> 5;
yading@10 237 *pal++ = (0xffU<<24) | v;
yading@10 238 }
yading@10 239 break;
yading@10 240 }
yading@10 241 p->palette_has_changed = 1;
yading@10 242 }
yading@10 243 }
yading@10 244
yading@10 245 if ((compr & (~TGA_RLE)) == TGA_NODATA) {
yading@10 246 memset(p->data[0], 0, p->linesize[0] * h);
yading@10 247 } else {
yading@10 248 if (compr & TGA_RLE) {
yading@10 249 int res = targa_decode_rle(avctx, s, dst, w, h, stride, bpp, interleave);
yading@10 250 if (res < 0)
yading@10 251 return res;
yading@10 252 } else {
yading@10 253 size_t img_size = w * ((bpp + 1) >> 3);
yading@10 254 uint8_t *line;
yading@10 255 if (bytestream2_get_bytes_left(&s->gb) < img_size * h) {
yading@10 256 av_log(avctx, AV_LOG_ERROR,
yading@10 257 "Not enough data available for image\n");
yading@10 258 return AVERROR_INVALIDDATA;
yading@10 259 }
yading@10 260
yading@10 261 line = dst;
yading@10 262 y = 0;
yading@10 263 do {
yading@10 264 bytestream2_get_buffer(&s->gb, line, img_size);
yading@10 265 line = advance_line(dst, line, stride, &y, h, interleave);
yading@10 266 } while (line);
yading@10 267 }
yading@10 268 }
yading@10 269
yading@10 270 if (flags & TGA_RIGHTTOLEFT) { // right-to-left, needs horizontal flip
yading@10 271 int x;
yading@10 272 for (y = 0; y < h; y++) {
yading@10 273 void *line = &p->data[0][y * p->linesize[0]];
yading@10 274 for (x = 0; x < w >> 1; x++) {
yading@10 275 switch (bpp) {
yading@10 276 case 32:
yading@10 277 FFSWAP(uint32_t, ((uint32_t *)line)[x], ((uint32_t *)line)[w - x - 1]);
yading@10 278 break;
yading@10 279 case 24:
yading@10 280 FFSWAP(uint8_t, ((uint8_t *)line)[3 * x ], ((uint8_t *)line)[3 * w - 3 * x - 3]);
yading@10 281 FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 1], ((uint8_t *)line)[3 * w - 3 * x - 2]);
yading@10 282 FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 2], ((uint8_t *)line)[3 * w - 3 * x - 1]);
yading@10 283 break;
yading@10 284 case 16:
yading@10 285 FFSWAP(uint16_t, ((uint16_t *)line)[x], ((uint16_t *)line)[w - x - 1]);
yading@10 286 break;
yading@10 287 case 8:
yading@10 288 FFSWAP(uint8_t, ((uint8_t *)line)[x], ((uint8_t *)line)[w - x - 1]);
yading@10 289 }
yading@10 290 }
yading@10 291 }
yading@10 292 }
yading@10 293
yading@10 294 *got_frame = 1;
yading@10 295
yading@10 296 return avpkt->size;
yading@10 297 }
yading@10 298
yading@10 299 AVCodec ff_targa_decoder = {
yading@10 300 .name = "targa",
yading@10 301 .type = AVMEDIA_TYPE_VIDEO,
yading@10 302 .id = AV_CODEC_ID_TARGA,
yading@10 303 .priv_data_size = sizeof(TargaContext),
yading@10 304 .decode = decode_frame,
yading@10 305 .capabilities = CODEC_CAP_DR1,
yading@10 306 .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"),
yading@10 307 };