Use proper length specifiers in mp_msg calls, fixes the warnings:
[mplayer/greg.git] / libmpcodecs / vd_mtga.c
blobf15c7345b9308dc0b6156cffcb9d9701981ba9ac
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 "libavutil/common.h"
15 #include "mpbswap.h"
16 #include "libvo/fastmemcpy.h"
18 #include "vd_internal.h"
20 static vd_info_t info =
22 "TGA Images decoder",
23 "mtga",
24 "Tilman Sauerbeck, A'rpi",
25 "Tilman Sauerbeck",
26 "only 24bpp and 32bpp RGB targa files support so far"
29 LIBVD_EXTERN(mtga)
31 typedef enum
33 TGA_NO_DATA,
34 TGA_UNCOMP_PALETTED,
35 TGA_UNCOMP_TRUECOLOR,
36 TGA_UNCOMP_GRAYSCALE,
37 TGA_RLE_PALETTED = 9,
38 TGA_RLE_TRUECOLOR,
39 TGA_RLE_GRAYSCALE
40 } TGAImageType;
42 typedef struct
44 unsigned char id_len;
45 unsigned short img_type;
47 unsigned short width;
48 unsigned short height;
50 unsigned char bpp;
51 unsigned char origin; /* 0 = lower left, 1 = upper left */
52 unsigned short start_row;
53 short increment;
54 } TGAInfo;
56 static unsigned int out_fmt = 0;
58 static int last_w = -1;
59 static int last_h = -1;
60 static int last_c = -1;
63 /* to set/get/query special features/parameters */
64 static int control(sh_video_t *sh, int cmd, void *arg, ...)
66 switch (cmd)
68 case VDCTRL_QUERY_FORMAT:
69 if (*((int *) arg) == out_fmt) return CONTROL_TRUE;
70 return CONTROL_FALSE;
72 return CONTROL_UNKNOWN;
75 /* init driver */
76 static int init(sh_video_t *sh)
78 sh->context = (TGAInfo *) calloc(1, sizeof(TGAInfo));
79 last_w = -1;
81 return 1;
85 /* uninit driver */
86 static void uninit(sh_video_t *sh)
88 TGAInfo *info = sh->context;
89 free(info);
90 return;
94 /* decode a runlength-encoded tga */
95 static void decode_rle_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi)
97 int row, col, replen, i, num_bytes = info->bpp / 8;
98 unsigned char repetitions, packet_header, *final;
100 /* see line 207 to see why this loop is set up like this */
101 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment)
103 final = mpi->planes[0] + mpi->stride[0] * row;
105 for (col = 0; col < info->width; col += repetitions)
107 packet_header = *data++;
108 repetitions = (1 + (packet_header & 0x7f));
109 replen = repetitions * num_bytes;
111 if (packet_header & 0x80) /* runlength encoded packet */
113 memcpy(final, data, num_bytes);
115 // Note: this will be slow when DR to vram!
116 i=num_bytes;
117 while(2*i<=replen){
118 memcpy(final+i,final,i);
119 i*=2;
121 memcpy(final+i,final,replen-i);
122 data += num_bytes;
124 else /* raw packet */
126 fast_memcpy(final, data, replen);
127 data += replen;
130 final += replen;
134 return;
138 static void decode_uncompressed_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi)
140 unsigned char *final;
141 int row, num_bytes = info->bpp / 8;
143 /* see line 207 to see why this loop is set up like this */
144 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment)
146 final = mpi->planes[0] + mpi->stride[0] * row;
147 fast_memcpy(final, data, info->width * num_bytes);
148 data += info->width * num_bytes;
151 return;
155 static short read_tga_header(unsigned char *buf, TGAInfo *info)
157 info->id_len = buf[0];
159 info->img_type = buf[2];
161 /* targa data is always stored in little endian byte order */
162 info->width = le2me_16(*(unsigned short *) &buf[12]);
163 info->height = le2me_16(*(unsigned short *) &buf[14]);
165 info->bpp = buf[16];
167 info->origin = (buf[17] & 0x20) >> 5;
169 /* FIXME check for valid targa data */
171 return 0;
175 /* decode a frame */
176 static mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags)
178 TGAInfo *info = sh->context;
179 unsigned char *data = raw;
180 mp_image_t *mpi;
183 if (len <= 0)
184 return NULL; /* skip frame */
186 read_tga_header(data, info); /* read information about the file */
188 if (info->bpp == 24)
189 out_fmt = IMGFMT_BGR24;
190 else if (info->bpp == 32)
191 out_fmt = IMGFMT_BGR32;
192 else
194 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type! depth=%d\n",info->bpp);
195 return NULL;
198 if (info->img_type != TGA_UNCOMP_TRUECOLOR && info->img_type != TGA_RLE_TRUECOLOR) /* not a true color image */
200 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type: %i!\n", info->img_type);
201 return NULL;
204 /* if img.origin is 0, we decode from bottom to top. if it's 1, we decode from top to bottom */
205 info->start_row = (info->origin) ? 0 : info->height - 1;
206 info->increment = (info->origin) ? 1 : -1;
208 /* set data to the beginning of the image data */
209 data += 18 + info->id_len;
211 /* (re)init libvo if image parameters changed (width/height/colorspace) */
212 if (last_w != info->width || last_h != info->height || last_c != out_fmt)
214 last_w = info->width;
215 last_h = info->height;
216 last_c = out_fmt;
218 if (!out_fmt || !mpcodecs_config_vo(sh, info->width, info->height, out_fmt))
219 return NULL;
222 if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, info->width, info->height)))
223 return NULL;
225 /* finally decode the image */
226 if (info->img_type == TGA_UNCOMP_TRUECOLOR)
227 decode_uncompressed_tga(info, data, mpi);
228 else if (info->img_type == TGA_RLE_TRUECOLOR)
229 decode_rle_tga(info, data, mpi);
230 // else
231 // mpi = NULL;
233 return mpi;