Mercurial > libavcodec.hg
annotate targa.c @ 9896:bbefbca72722 libavcodec
Drop code that attempts to decode frames that are prefixed by junk.
Too often it ends up decoding random data into noise without detecting
it (for example after seeking of some MP3 data with oddly often occurring
startcode emulation).
Fixes issue1154.
| author | michael |
|---|---|
| date | Tue, 30 Jun 2009 03:57:27 +0000 |
| parents | 8f56bd47d2c8 |
| children | 266bf83f634d |
| rev | line source |
|---|---|
| 3986 | 1 /* |
| 2 * Targa (.tga) image decoder | |
| 3 * Copyright (c) 2006 Konstantin Shishkov | |
| 4 * | |
| 5 * This file is part of FFmpeg. | |
| 6 * | |
| 7 * FFmpeg is free software; you can redistribute it and/or | |
| 8 * modify it under the terms of the GNU Lesser General Public | |
| 9 * License as published by the Free Software Foundation; either | |
| 10 * version 2.1 of the License, or (at your option) any later version. | |
| 11 * | |
| 12 * FFmpeg is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 * Lesser General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU Lesser General Public | |
| 18 * License along with FFmpeg; if not, write to the Free Software | |
| 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 */ | |
|
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7040
diff
changeset
|
21 |
|
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7040
diff
changeset
|
22 #include "libavutil/intreadwrite.h" |
| 3986 | 23 #include "avcodec.h" |
| 24 | |
| 25 enum TargaCompr{ | |
| 26 TGA_NODATA = 0, // no image data | |
| 27 TGA_PAL = 1, // palettized | |
| 28 TGA_RGB = 2, // true-color | |
| 29 TGA_BW = 3, // black & white or grayscale | |
| 30 TGA_RLE = 8, // flag pointing that data is RLE-coded | |
| 31 }; | |
| 32 | |
| 33 typedef struct TargaContext { | |
| 34 AVFrame picture; | |
| 35 | |
| 36 int width, height; | |
| 37 int bpp; | |
| 38 int color_type; | |
| 39 int compression_type; | |
| 40 } TargaContext; | |
| 41 | |
| 6281 | 42 static void targa_decode_rle(AVCodecContext *avctx, TargaContext *s, const uint8_t *src, uint8_t *dst, int w, int h, int stride, int bpp) |
| 3986 | 43 { |
| 44 int i, x, y; | |
| 45 int depth = (bpp + 1) >> 3; | |
| 46 int type, count; | |
| 47 int diff; | |
| 48 | |
| 49 diff = stride - w * depth; | |
| 50 x = y = 0; | |
| 51 while(y < h){ | |
| 52 type = *src++; | |
| 53 count = (type & 0x7F) + 1; | |
| 54 type &= 0x80; | |
| 55 if((x + count > w) && (x + count + 1 > (h - y) * w)){ | |
| 56 av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count); | |
| 57 return; | |
| 58 } | |
| 59 for(i = 0; i < count; i++){ | |
| 60 switch(depth){ | |
| 61 case 1: | |
| 62 *dst = *src; | |
| 63 break; | |
| 64 case 2: | |
| 4364 | 65 *((uint16_t*)dst) = AV_RL16(src); |
| 3986 | 66 break; |
| 67 case 3: | |
| 68 dst[0] = src[0]; | |
| 69 dst[1] = src[1]; | |
| 70 dst[2] = src[2]; | |
| 71 break; | |
| 4132 | 72 case 4: |
| 4364 | 73 *((uint32_t*)dst) = AV_RL32(src); |
| 4132 | 74 break; |
| 3986 | 75 } |
| 76 dst += depth; | |
| 77 if(!type) | |
| 78 src += depth; | |
| 79 | |
| 80 x++; | |
| 81 if(x == w){ | |
| 82 x = 0; | |
| 83 y++; | |
| 84 dst += diff; | |
| 85 } | |
| 86 } | |
| 87 if(type) | |
| 88 src += depth; | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 static int decode_frame(AVCodecContext *avctx, | |
| 93 void *data, int *data_size, | |
|
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8573
diff
changeset
|
94 AVPacket *avpkt) |
| 3986 | 95 { |
|
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8573
diff
changeset
|
96 const uint8_t *buf = avpkt->data; |
|
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8573
diff
changeset
|
97 int buf_size = avpkt->size; |
| 3986 | 98 TargaContext * const s = avctx->priv_data; |
| 99 AVFrame *picture = data; | |
| 100 AVFrame * const p= (AVFrame*)&s->picture; | |
| 101 uint8_t *dst; | |
| 102 int stride; | |
| 103 int idlen, pal, compr, x, y, w, h, bpp, flags; | |
| 104 int first_clr, colors, csize; | |
| 105 | |
| 106 /* parse image header */ | |
| 107 idlen = *buf++; | |
| 108 pal = *buf++; | |
| 109 compr = *buf++; | |
| 4364 | 110 first_clr = AV_RL16(buf); buf += 2; |
| 111 colors = AV_RL16(buf); buf += 2; | |
| 3986 | 112 csize = *buf++; |
| 4364 | 113 x = AV_RL16(buf); buf += 2; |
| 114 y = AV_RL16(buf); buf += 2; | |
| 115 w = AV_RL16(buf); buf += 2; | |
| 116 h = AV_RL16(buf); buf += 2; | |
| 3986 | 117 bpp = *buf++; |
| 118 flags = *buf++; | |
| 119 //skip identifier if any | |
| 120 buf += idlen; | |
| 121 s->bpp = bpp; | |
| 122 s->width = w; | |
| 123 s->height = h; | |
| 124 switch(s->bpp){ | |
| 125 case 8: | |
| 126 avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? PIX_FMT_GRAY8 : PIX_FMT_PAL8; | |
| 127 break; | |
| 128 case 15: | |
| 129 avctx->pix_fmt = PIX_FMT_RGB555; | |
| 130 break; | |
| 131 case 16: | |
| 132 avctx->pix_fmt = PIX_FMT_RGB555; | |
| 133 break; | |
| 134 case 24: | |
| 135 avctx->pix_fmt = PIX_FMT_BGR24; | |
| 136 break; | |
| 4132 | 137 case 32: |
|
4494
ce643a22f049
Replace deprecated PIX_FMT names by the newer variants.
diego
parents:
4364
diff
changeset
|
138 avctx->pix_fmt = PIX_FMT_RGB32; |
| 4132 | 139 break; |
| 3986 | 140 default: |
| 4128 | 141 av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", s->bpp); |
| 3986 | 142 return -1; |
| 143 } | |
| 144 | |
| 145 if(s->picture.data[0]) | |
| 146 avctx->release_buffer(avctx, &s->picture); | |
| 147 | |
| 148 if(avcodec_check_dimensions(avctx, w, h)) | |
| 149 return -1; | |
| 150 if(w != avctx->width || h != avctx->height) | |
| 151 avcodec_set_dimensions(avctx, w, h); | |
| 152 if(avctx->get_buffer(avctx, p) < 0){ | |
| 153 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
| 154 return -1; | |
| 155 } | |
| 156 if(flags & 0x20){ | |
| 157 dst = p->data[0]; | |
| 158 stride = p->linesize[0]; | |
| 159 }else{ //image is upside-down | |
| 160 dst = p->data[0] + p->linesize[0] * (h - 1); | |
| 161 stride = -p->linesize[0]; | |
| 162 } | |
| 163 | |
| 164 if(avctx->pix_fmt == PIX_FMT_PAL8 && avctx->palctrl){ | |
| 165 memcpy(p->data[1], avctx->palctrl->palette, AVPALETTE_SIZE); | |
| 166 if(avctx->palctrl->palette_changed){ | |
| 167 p->palette_has_changed = 1; | |
| 168 avctx->palctrl->palette_changed = 0; | |
| 169 } | |
| 170 } | |
| 171 if(colors){ | |
| 172 if((colors + first_clr) > 256){ | |
| 173 av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr); | |
| 174 return -1; | |
| 175 } | |
| 176 if(csize != 24){ | |
| 177 av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize); | |
| 178 return -1; | |
| 179 } | |
| 180 if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway | |
| 181 buf += colors * ((csize + 1) >> 3); | |
| 182 else{ | |
| 183 int r, g, b, t; | |
| 184 int32_t *pal = ((int32_t*)p->data[1]) + first_clr; | |
| 185 for(t = 0; t < colors; t++){ | |
| 186 r = *buf++; | |
| 187 g = *buf++; | |
| 188 b = *buf++; | |
| 189 *pal++ = (b << 16) | (g << 8) | r; | |
| 190 } | |
| 191 p->palette_has_changed = 1; | |
| 192 avctx->palctrl->palette_changed = 0; | |
| 193 } | |
| 194 } | |
| 195 if((compr & (~TGA_RLE)) == TGA_NODATA) | |
| 196 memset(p->data[0], 0, p->linesize[0] * s->height); | |
| 197 else{ | |
| 198 if(compr & TGA_RLE) | |
| 199 targa_decode_rle(avctx, s, buf, dst, avctx->width, avctx->height, stride, bpp); | |
| 200 else{ | |
| 201 for(y = 0; y < s->height; y++){ | |
| 202 #ifdef WORDS_BIGENDIAN | |
| 203 if((s->bpp + 1) >> 3 == 2){ | |
| 204 uint16_t *dst16 = (uint16_t*)dst; | |
| 205 for(x = 0; x < s->width; x++) | |
| 4364 | 206 dst16[x] = AV_RL16(buf + x * 2); |
| 4132 | 207 }else if((s->bpp + 1) >> 3 == 4){ |
| 208 uint32_t *dst32 = (uint32_t*)dst; | |
| 209 for(x = 0; x < s->width; x++) | |
| 4364 | 210 dst32[x] = AV_RL32(buf + x * 4); |
| 3986 | 211 }else |
| 212 #endif | |
| 213 memcpy(dst, buf, s->width * ((s->bpp + 1) >> 3)); | |
| 214 | |
| 215 dst += stride; | |
| 216 buf += s->width * ((s->bpp + 1) >> 3); | |
| 217 } | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 *picture= *(AVFrame*)&s->picture; | |
| 222 *data_size = sizeof(AVPicture); | |
| 223 | |
| 224 return buf_size; | |
| 225 } | |
| 226 | |
|
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6281
diff
changeset
|
227 static av_cold int targa_init(AVCodecContext *avctx){ |
| 3986 | 228 TargaContext *s = avctx->priv_data; |
| 229 | |
| 230 avcodec_get_frame_defaults((AVFrame*)&s->picture); | |
| 231 avctx->coded_frame= (AVFrame*)&s->picture; | |
| 232 | |
| 233 return 0; | |
| 234 } | |
| 235 | |
|
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6281
diff
changeset
|
236 static av_cold int targa_end(AVCodecContext *avctx){ |
| 3986 | 237 TargaContext *s = avctx->priv_data; |
| 238 | |
| 239 if(s->picture.data[0]) | |
| 240 avctx->release_buffer(avctx, &s->picture); | |
| 241 | |
| 242 return 0; | |
| 243 } | |
| 244 | |
| 245 AVCodec targa_decoder = { | |
| 246 "targa", | |
| 247 CODEC_TYPE_VIDEO, | |
| 248 CODEC_ID_TARGA, | |
| 249 sizeof(TargaContext), | |
| 250 targa_init, | |
| 251 NULL, | |
| 252 targa_end, | |
| 253 decode_frame, | |
|
9810
8f56bd47d2c8
targa image decoder uses get_buffer, set CODEC_CAP_DR1
bcoudurier
parents:
9553
diff
changeset
|
254 CODEC_CAP_DR1, |
| 6722 | 255 NULL, |
|
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6722
diff
changeset
|
256 .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), |
| 3986 | 257 }; |
