00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intreadwrite.h"
00023 #include "libavutil/imgutils.h"
00024 #include "avcodec.h"
00025 #include "bytestream.h"
00026 #include "targa.h"
00027
00028 typedef struct TargaContext {
00029 AVFrame picture;
00030 GetByteContext gb;
00031
00032 int color_type;
00033 int compression_type;
00034 } TargaContext;
00035
00036 static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s,
00037 uint8_t *dst, int w, int h, int stride, int bpp)
00038 {
00039 int x, y;
00040 int depth = (bpp + 1) >> 3;
00041 int type, count;
00042 int diff;
00043
00044 diff = stride - w * depth;
00045 x = y = 0;
00046 while (y < h) {
00047 if (bytestream2_get_bytes_left(&s->gb) <= 0) {
00048 av_log(avctx, AV_LOG_ERROR,
00049 "Ran ouf of data before end-of-image\n");
00050 return AVERROR_INVALIDDATA;
00051 }
00052 type = bytestream2_get_byteu(&s->gb);
00053 count = (type & 0x7F) + 1;
00054 type &= 0x80;
00055 if(x + count > (h - y) * w){
00056 av_log(avctx, AV_LOG_ERROR,
00057 "Packet went out of bounds: position (%i,%i) size %i\n",
00058 x, y, count);
00059 return AVERROR_INVALIDDATA;
00060 }
00061 if (!type) {
00062 do {
00063 int n = FFMIN(count, w - x);
00064 bytestream2_get_buffer(&s->gb, dst, n * depth);
00065 count -= n;
00066 dst += n * depth;
00067 x += n;
00068 if (x == w) {
00069 x = 0;
00070 y++;
00071 dst += diff;
00072 }
00073 } while (count > 0);
00074 } else {
00075 uint8_t tmp[4];
00076 bytestream2_get_buffer(&s->gb, tmp, depth);
00077 do {
00078 int n = FFMIN(count, w - x);
00079 count -= n;
00080 x += n;
00081 do {
00082 memcpy(dst, tmp, depth);
00083 dst += depth;
00084 } while (--n);
00085 if (x == w) {
00086 x = 0;
00087 y++;
00088 dst += diff;
00089 }
00090 } while (count > 0);
00091 }
00092 }
00093 return 0;
00094 }
00095
00096 static int decode_frame(AVCodecContext *avctx,
00097 void *data, int *data_size,
00098 AVPacket *avpkt)
00099 {
00100 TargaContext * const s = avctx->priv_data;
00101 AVFrame *picture = data;
00102 AVFrame * const p = &s->picture;
00103 uint8_t *dst;
00104 int stride;
00105 int idlen, pal, compr, y, w, h, bpp, flags;
00106 int first_clr, colors, csize;
00107
00108 bytestream2_init(&s->gb, avpkt->data, avpkt->size);
00109
00110
00111 idlen = bytestream2_get_byte(&s->gb);
00112 pal = bytestream2_get_byte(&s->gb);
00113 compr = bytestream2_get_byte(&s->gb);
00114 first_clr = bytestream2_get_le16(&s->gb);
00115 colors = bytestream2_get_le16(&s->gb);
00116 csize = bytestream2_get_byte(&s->gb);
00117 bytestream2_skip(&s->gb, 4);
00118 w = bytestream2_get_le16(&s->gb);
00119 h = bytestream2_get_le16(&s->gb);
00120 bpp = bytestream2_get_byte(&s->gb);
00121
00122 if (bytestream2_get_bytes_left(&s->gb) <= idlen) {
00123 av_log(avctx, AV_LOG_ERROR,
00124 "Not enough data to read header\n");
00125 return AVERROR_INVALIDDATA;
00126 }
00127
00128 flags = bytestream2_get_byte(&s->gb);
00129
00130 if (!pal && (first_clr || colors || csize)) {
00131 av_log(avctx, AV_LOG_WARNING, "File without colormap has colormap information set.\n");
00132
00133 first_clr = colors = csize = 0;
00134 }
00135
00136
00137 bytestream2_skip(&s->gb, idlen);
00138
00139 switch(bpp){
00140 case 8:
00141 avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? PIX_FMT_GRAY8 : PIX_FMT_PAL8;
00142 break;
00143 case 15:
00144 case 16:
00145 avctx->pix_fmt = PIX_FMT_RGB555LE;
00146 break;
00147 case 24:
00148 avctx->pix_fmt = PIX_FMT_BGR24;
00149 break;
00150 case 32:
00151 avctx->pix_fmt = PIX_FMT_BGRA;
00152 break;
00153 default:
00154 av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", bpp);
00155 return -1;
00156 }
00157
00158 if(s->picture.data[0])
00159 avctx->release_buffer(avctx, &s->picture);
00160
00161 if(av_image_check_size(w, h, 0, avctx))
00162 return -1;
00163 if(w != avctx->width || h != avctx->height)
00164 avcodec_set_dimensions(avctx, w, h);
00165 if(avctx->get_buffer(avctx, p) < 0){
00166 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00167 return -1;
00168 }
00169 if(flags & 0x20){
00170 dst = p->data[0];
00171 stride = p->linesize[0];
00172 }else{
00173 dst = p->data[0] + p->linesize[0] * (h - 1);
00174 stride = -p->linesize[0];
00175 }
00176
00177 if(colors){
00178 int pal_size, pal_sample_size;
00179 if((colors + first_clr) > 256){
00180 av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
00181 return -1;
00182 }
00183 switch (csize) {
00184 case 24: pal_sample_size = 3; break;
00185 case 16:
00186 case 15: pal_sample_size = 2; break;
00187 default:
00188 av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);
00189 return -1;
00190 }
00191 pal_size = colors * pal_sample_size;
00192 if(avctx->pix_fmt != PIX_FMT_PAL8)
00193 bytestream2_skip(&s->gb, pal_size);
00194 else{
00195 int t;
00196 uint32_t *pal = ((uint32_t *)p->data[1]) + first_clr;
00197
00198 if (bytestream2_get_bytes_left(&s->gb) < pal_size) {
00199 av_log(avctx, AV_LOG_ERROR,
00200 "Not enough data to read palette\n");
00201 return AVERROR_INVALIDDATA;
00202 }
00203 switch (pal_sample_size) {
00204 case 3:
00205
00206 for (t = 0; t < colors; t++)
00207 *pal++ = (0xffU<<24) | bytestream2_get_le24u(&s->gb);
00208 break;
00209 case 2:
00210
00211 for (t = 0; t < colors; t++) {
00212 uint32_t v = bytestream2_get_le16u(&s->gb);
00213 v = ((v & 0x7C00) << 9) |
00214 ((v & 0x03E0) << 6) |
00215 ((v & 0x001F) << 3);
00216
00217 v |= (v & 0xE0E0E0U) >> 5;
00218 *pal++ = (0xffU<<24) | v;
00219 }
00220 break;
00221 }
00222 p->palette_has_changed = 1;
00223 }
00224 }
00225 if ((compr & (~TGA_RLE)) == TGA_NODATA) {
00226 memset(p->data[0], 0, p->linesize[0] * h);
00227 } else {
00228 if(compr & TGA_RLE){
00229 int res = targa_decode_rle(avctx, s, dst, w, h, stride, bpp);
00230 if (res < 0)
00231 return res;
00232 } else {
00233 size_t img_size = w * ((bpp + 1) >> 3);
00234 if (bytestream2_get_bytes_left(&s->gb) < img_size * h) {
00235 av_log(avctx, AV_LOG_ERROR,
00236 "Not enough data available for image\n");
00237 return AVERROR_INVALIDDATA;
00238 }
00239 for (y = 0; y < h; y++) {
00240 bytestream2_get_bufferu(&s->gb, dst, img_size);
00241 dst += stride;
00242 }
00243 }
00244 }
00245 if(flags & 0x10){
00246 int x;
00247 for(y = 0; y < h; y++){
00248 void *line = &p->data[0][y * p->linesize[0]];
00249 for(x = 0; x < w >> 1; x++){
00250 switch(bpp){
00251 case 32:
00252 FFSWAP(uint32_t, ((uint32_t *)line)[x], ((uint32_t *)line)[w - x - 1]);
00253 break;
00254 case 24:
00255 FFSWAP(uint8_t, ((uint8_t *)line)[3 * x ], ((uint8_t *)line)[3 * w - 3 * x - 3]);
00256 FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 1], ((uint8_t *)line)[3 * w - 3 * x - 2]);
00257 FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 2], ((uint8_t *)line)[3 * w - 3 * x - 1]);
00258 break;
00259 case 16:
00260 FFSWAP(uint16_t, ((uint16_t *)line)[x], ((uint16_t *)line)[w - x - 1]);
00261 break;
00262 case 8:
00263 FFSWAP(uint8_t, ((uint8_t *)line)[x], ((uint8_t *)line)[w - x - 1]);
00264 }
00265 }
00266 }
00267 }
00268
00269 *picture = s->picture;
00270 *data_size = sizeof(AVPicture);
00271
00272 return avpkt->size;
00273 }
00274
00275 static av_cold int targa_init(AVCodecContext *avctx){
00276 TargaContext *s = avctx->priv_data;
00277
00278 avcodec_get_frame_defaults(&s->picture);
00279 avctx->coded_frame = &s->picture;
00280
00281 return 0;
00282 }
00283
00284 static av_cold int targa_end(AVCodecContext *avctx){
00285 TargaContext *s = avctx->priv_data;
00286
00287 if(s->picture.data[0])
00288 avctx->release_buffer(avctx, &s->picture);
00289
00290 return 0;
00291 }
00292
00293 AVCodec ff_targa_decoder = {
00294 .name = "targa",
00295 .type = AVMEDIA_TYPE_VIDEO,
00296 .id = CODEC_ID_TARGA,
00297 .priv_data_size = sizeof(TargaContext),
00298 .init = targa_init,
00299 .close = targa_end,
00300 .decode = decode_frame,
00301 .capabilities = CODEC_CAP_DR1,
00302 .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"),
00303 };