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