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