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