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