20% faster hqdn3d on x86_64
[mplayer/glamo.git] / libmpcodecs / vd_mtga.c
blob72612d8d5d011e4dc1a7bb4576c6a7f27e303847
1 /* author: Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
2 * based on: XreaL's x_r_img_tga.* (http://www.sourceforge.net/projects/xreal/)
3 * libtarga.*
4 * xli's tga.*
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
11 #include "config.h"
12 #include "mp_msg.h"
14 #include "mpbswap.h"
15 #include "libvo/fastmemcpy.h"
17 #include "vd_internal.h"
19 static vd_info_t info =
21 "TGA Images decoder",
22 "mtga",
23 "Tilman Sauerbeck, A'rpi",
24 "Tilman Sauerbeck",
25 "only 24bpp and 32bpp RGB targa files support so far"
28 LIBVD_EXTERN(mtga)
30 typedef enum
32 TGA_NO_DATA,
33 TGA_UNCOMP_PALETTED,
34 TGA_UNCOMP_TRUECOLOR,
35 TGA_UNCOMP_GRAYSCALE,
36 TGA_RLE_PALETTED = 9,
37 TGA_RLE_TRUECOLOR,
38 TGA_RLE_GRAYSCALE
39 } TGAImageType;
41 typedef struct
43 unsigned char id_len;
44 unsigned short img_type;
46 unsigned short width;
47 unsigned short height;
49 unsigned char bpp;
50 unsigned char origin; /* 0 = lower left, 1 = upper left */
51 unsigned short start_row;
52 short increment;
53 } TGAInfo;
55 static unsigned int out_fmt = 0;
57 static int last_w = -1;
58 static int last_h = -1;
59 static int last_c = -1;
62 /* to set/get/query special features/parameters */
63 static int control(sh_video_t *sh, int cmd, void *arg, ...)
65 switch (cmd)
67 case VDCTRL_QUERY_FORMAT:
68 if (*((int *) arg) == out_fmt) return CONTROL_TRUE;
69 return CONTROL_FALSE;
71 return CONTROL_UNKNOWN;
74 /* init driver */
75 static int init(sh_video_t *sh)
77 sh->context = (TGAInfo *) calloc(1, sizeof(TGAInfo));
78 last_w = -1;
80 return 1;
84 /* uninit driver */
85 static void uninit(sh_video_t *sh)
87 TGAInfo *info = sh->context;
88 free(info);
89 return;
93 /* decode a runlength-encoded tga */
94 static void decode_rle_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi)
96 int row, col, replen, i, num_bytes = info->bpp / 8;
97 unsigned char repetitions, packet_header, *final;
99 /* see line 207 to see why this loop is set up like this */
100 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment)
102 final = mpi->planes[0] + mpi->stride[0] * row;
104 for (col = 0; col < info->width; col += repetitions)
106 packet_header = *data++;
107 repetitions = (1 + (packet_header & 0x7f));
108 replen = repetitions * num_bytes;
110 if (packet_header & 0x80) /* runlength encoded packet */
112 memcpy(final, data, num_bytes);
114 // Note: this will be slow when DR to vram!
115 i=num_bytes;
116 while(2*i<=replen){
117 memcpy(final+i,final,i);
118 i*=2;
120 memcpy(final+i,final,replen-i);
121 data += num_bytes;
123 else /* raw packet */
125 fast_memcpy(final, data, replen);
126 data += replen;
129 final += replen;
133 return;
137 static void decode_uncompressed_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi)
139 unsigned char *final;
140 int row, num_bytes = info->bpp / 8;
142 /* see line 207 to see why this loop is set up like this */
143 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment)
145 final = mpi->planes[0] + mpi->stride[0] * row;
146 fast_memcpy(final, data, info->width * num_bytes);
147 data += info->width * num_bytes;
150 return;
154 static short read_tga_header(unsigned char *buf, TGAInfo *info)
156 info->id_len = buf[0];
158 info->img_type = buf[2];
160 /* targa data is always stored in little endian byte order */
161 info->width = le2me_16(*(unsigned short *) &buf[12]);
162 info->height = le2me_16(*(unsigned short *) &buf[14]);
164 info->bpp = buf[16];
166 info->origin = (buf[17] & 0x20) >> 5;
168 /* FIXME check for valid targa data */
170 return 0;
174 /* decode a frame */
175 static mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags)
177 TGAInfo *info = sh->context;
178 unsigned char *data = raw;
179 mp_image_t *mpi;
182 if (len <= 0)
183 return NULL; /* skip frame */
185 read_tga_header(data, info); /* read information about the file */
187 if (info->bpp == 24)
188 out_fmt = IMGFMT_BGR24;
189 else if (info->bpp == 32)
190 out_fmt = IMGFMT_BGR32;
191 else
193 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type! depth=%d\n",info->bpp);
194 return NULL;
197 if (info->img_type != TGA_UNCOMP_TRUECOLOR && info->img_type != TGA_RLE_TRUECOLOR) /* not a true color image */
199 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type: %i!\n", info->img_type);
200 return NULL;
203 /* if img.origin is 0, we decode from bottom to top. if it's 1, we decode from top to bottom */
204 info->start_row = (info->origin) ? 0 : info->height - 1;
205 info->increment = (info->origin) ? 1 : -1;
207 /* set data to the beginning of the image data */
208 data += 18 + info->id_len;
210 /* (re)init libvo if image parameters changed (width/height/colorspace) */
211 if (last_w != info->width || last_h != info->height || last_c != out_fmt)
213 last_w = info->width;
214 last_h = info->height;
215 last_c = out_fmt;
217 if (!out_fmt || !mpcodecs_config_vo(sh, info->width, info->height, out_fmt))
218 return NULL;
221 if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, info->width, info->height)))
222 return NULL;
224 /* finally decode the image */
225 if (info->img_type == TGA_UNCOMP_TRUECOLOR)
226 decode_uncompressed_tga(info, data, mpi);
227 else if (info->img_type == TGA_RLE_TRUECOLOR)
228 decode_rle_tga(info, data, mpi);
229 // else
230 // mpi = NULL;
232 return mpi;