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/pixdesc.h"
00024 #include "avcodec.h"
00025 #include "rle.h"
00026 #include "targa.h"
00027
00028 typedef struct TargaContext {
00029 AVFrame picture;
00030 } TargaContext;
00031
00042 static int targa_encode_rle(uint8_t *outbuf, int out_size, AVFrame *pic,
00043 int bpp, int w, int h)
00044 {
00045 int y,ret;
00046 uint8_t *out;
00047
00048 out = outbuf;
00049
00050 for(y = 0; y < h; y ++) {
00051 ret = ff_rle_encode(out, out_size, pic->data[0] + pic->linesize[0] * y, bpp, w, 0x7f, 0, -1, 0);
00052 if(ret == -1){
00053 return -1;
00054 }
00055 out+= ret;
00056 out_size -= ret;
00057 }
00058
00059 return out - outbuf;
00060 }
00061
00062 static int targa_encode_normal(uint8_t *outbuf, AVFrame *pic, int bpp, int w, int h)
00063 {
00064 int i, n = bpp * w;
00065 uint8_t *out = outbuf;
00066 uint8_t *ptr = pic->data[0];
00067
00068 for(i=0; i < h; i++) {
00069 memcpy(out, ptr, n);
00070 out += n;
00071 ptr += pic->linesize[0];
00072 }
00073
00074 return out - outbuf;
00075 }
00076
00077 static int targa_encode_frame(AVCodecContext *avctx,
00078 unsigned char *outbuf,
00079 int buf_size, void *data){
00080 AVFrame *p = data;
00081 int bpp, picsize, datasize = -1;
00082 uint8_t *out;
00083
00084 if(avctx->width > 0xffff || avctx->height > 0xffff) {
00085 av_log(avctx, AV_LOG_ERROR, "image dimensions too large\n");
00086 return AVERROR(EINVAL);
00087 }
00088 picsize = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
00089 if(buf_size < picsize + 45) {
00090 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
00091 return AVERROR(EINVAL);
00092 }
00093
00094 p->pict_type= AV_PICTURE_TYPE_I;
00095 p->key_frame= 1;
00096
00097
00098 memset(outbuf, 0, 12);
00099 AV_WL16(outbuf+12, avctx->width);
00100 AV_WL16(outbuf+14, avctx->height);
00101
00102 outbuf[17] = 0x20 | (avctx->pix_fmt == PIX_FMT_BGRA ? 8 : 0);
00103
00104 switch(avctx->pix_fmt) {
00105 case PIX_FMT_GRAY8:
00106 outbuf[2] = TGA_BW;
00107 outbuf[16] = 8;
00108 break;
00109 case PIX_FMT_RGB555LE:
00110 outbuf[2] = TGA_RGB;
00111 outbuf[16] = 16;
00112 break;
00113 case PIX_FMT_BGR24:
00114 outbuf[2] = TGA_RGB;
00115 outbuf[16] = 24;
00116 break;
00117 case PIX_FMT_BGRA:
00118 outbuf[2] = TGA_RGB;
00119 outbuf[16] = 32;
00120 break;
00121 default:
00122 av_log(avctx, AV_LOG_ERROR, "Pixel format '%s' not supported.\n",
00123 av_get_pix_fmt_name(avctx->pix_fmt));
00124 return AVERROR(EINVAL);
00125 }
00126 bpp = outbuf[16] >> 3;
00127
00128 out = outbuf + 18;
00129
00130
00131 if (avctx->coder_type != FF_CODER_TYPE_RAW)
00132 datasize = targa_encode_rle(out, picsize, p, bpp, avctx->width, avctx->height);
00133
00134
00135 if(datasize >= 0)
00136 outbuf[2] |= 8;
00137
00138
00139 else datasize = targa_encode_normal(out, p, bpp, avctx->width, avctx->height);
00140
00141 out += datasize;
00142
00143
00144
00145
00146 memcpy(out, "\0\0\0\0\0\0\0\0TRUEVISION-XFILE.", 26);
00147
00148 return out + 26 - outbuf;
00149 }
00150
00151 static av_cold int targa_encode_init(AVCodecContext *avctx)
00152 {
00153 TargaContext *s = avctx->priv_data;
00154
00155 avcodec_get_frame_defaults(&s->picture);
00156 s->picture.key_frame= 1;
00157 avctx->coded_frame= &s->picture;
00158
00159 return 0;
00160 }
00161
00162 AVCodec ff_targa_encoder = {
00163 .name = "targa",
00164 .type = AVMEDIA_TYPE_VIDEO,
00165 .id = CODEC_ID_TARGA,
00166 .priv_data_size = sizeof(TargaContext),
00167 .init = targa_encode_init,
00168 .encode = targa_encode_frame,
00169 .pix_fmts= (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_BGRA, PIX_FMT_RGB555LE, PIX_FMT_GRAY8, PIX_FMT_NONE},
00170 .long_name= NULL_IF_CONFIG_SMALL("Truevision Targa image"),
00171 };