Mercurial > mplayer.hg
annotate libmpcodecs/vd_mtga.c @ 27072:15b870cf3592
Add auto-close option to libmenu playlist handling part.
author | ben |
---|---|
date | Fri, 20 Jun 2008 19:43:19 +0000 |
parents | b21e1506e50b |
children | 0f1b5b68af32 |
rev | line source |
---|---|
7362 | 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 */ | |
6 | |
7 #include <stdio.h> | |
8 #include <stdlib.h> | |
23305
22d3d12c6dfb
Include string.h for memcpy, fastmemcpy.h alone is not enough.
reimar
parents:
21507
diff
changeset
|
9 #include <string.h> |
7362 | 10 |
11 #include "config.h" | |
12 #include "mp_msg.h" | |
13 | |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
14 #include "mpbswap.h" |
7362 | 15 #include "libvo/fastmemcpy.h" |
16 | |
17 #include "vd_internal.h" | |
18 | |
19 static vd_info_t info = | |
20 { | |
21 "TGA Images decoder", | |
22 "mtga", | |
7401 | 23 "Tilman Sauerbeck, A'rpi", |
7362 | 24 "Tilman Sauerbeck", |
25 "only 24bpp and 32bpp RGB targa files support so far" | |
26 }; | |
27 | |
28 LIBVD_EXTERN(mtga) | |
29 | |
30 typedef enum | |
31 { | |
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; | |
40 | |
41 typedef struct | |
42 { | |
43 unsigned char id_len; | |
44 unsigned short img_type; | |
45 | |
46 unsigned short width; | |
47 unsigned short height; | |
48 | |
49 unsigned char bpp; | |
50 unsigned char origin; /* 0 = lower left, 1 = upper left */ | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
51 unsigned short start_row; |
9605 | 52 short increment; |
7362 | 53 } TGAInfo; |
54 | |
55 static unsigned int out_fmt = 0; | |
56 | |
57 static int last_w = -1; | |
58 static int last_h = -1; | |
59 static int last_c = -1; | |
60 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
61 |
7362 | 62 /* to set/get/query special features/parameters */ |
63 static int control(sh_video_t *sh, int cmd, void *arg, ...) | |
64 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
65 switch (cmd) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
66 { |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
67 case VDCTRL_QUERY_FORMAT: |
7401 | 68 if (*((int *) arg) == out_fmt) return CONTROL_TRUE; |
69 return CONTROL_FALSE; | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
70 } |
7401 | 71 return CONTROL_UNKNOWN; |
7362 | 72 } |
73 | |
74 /* init driver */ | |
75 static int init(sh_video_t *sh) | |
76 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
77 sh->context = (TGAInfo *) calloc(1, sizeof(TGAInfo)); |
7362 | 78 last_w = -1; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
79 |
7362 | 80 return 1; |
81 } | |
82 | |
83 | |
84 /* uninit driver */ | |
85 static void uninit(sh_video_t *sh) | |
86 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
87 TGAInfo *info = sh->context; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
88 free(info); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
89 return; |
7362 | 90 } |
91 | |
92 | |
93 /* decode a runlength-encoded tga */ | |
7401 | 94 static void decode_rle_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 95 { |
7401 | 96 int row, col, replen, i, num_bytes = info->bpp / 8; |
7362 | 97 unsigned char repetitions, packet_header, *final; |
98 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
99 /* see line 207 to see why this loop is set up like this */ |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
100 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 101 { |
7401 | 102 final = mpi->planes[0] + mpi->stride[0] * row; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
103 |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
104 for (col = 0; col < info->width; col += repetitions) |
7362 | 105 { |
106 packet_header = *data++; | |
7401 | 107 repetitions = (1 + (packet_header & 0x7f)); |
108 replen = repetitions * num_bytes; | |
7362 | 109 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
110 if (packet_header & 0x80) /* runlength encoded packet */ |
7362 | 111 { |
23458
973e53dc7df5
Do not use fast_memcpy for small size copy, esp. when the size is constant
reimar
parents:
23457
diff
changeset
|
112 memcpy(final, data, num_bytes); |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
113 |
7401 | 114 // Note: this will be slow when DR to vram! |
115 i=num_bytes; | |
116 while(2*i<=replen){ | |
23459
2c09fe135c93
Do not use fast_memcpy when data is read again immediately afterwards.
reimar
parents:
23458
diff
changeset
|
117 memcpy(final+i,final,i); |
7401 | 118 i*=2; |
119 } | |
23459
2c09fe135c93
Do not use fast_memcpy when data is read again immediately afterwards.
reimar
parents:
23458
diff
changeset
|
120 memcpy(final+i,final,replen-i); |
7401 | 121 data += num_bytes; |
7362 | 122 } |
123 else /* raw packet */ | |
7401 | 124 { |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
23305
diff
changeset
|
125 fast_memcpy(final, data, replen); |
7401 | 126 data += replen; |
127 } | |
128 | |
129 final += replen; | |
7362 | 130 } |
131 } | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
132 |
7362 | 133 return; |
134 } | |
135 | |
136 | |
7401 | 137 static void decode_uncompressed_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 138 { |
139 unsigned char *final; | |
7401 | 140 int row, num_bytes = info->bpp / 8; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
141 |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
142 /* see line 207 to see why this loop is set up like this */ |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
143 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 144 { |
7401 | 145 final = mpi->planes[0] + mpi->stride[0] * row; |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
23305
diff
changeset
|
146 fast_memcpy(final, data, info->width * num_bytes); |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
147 data += info->width * num_bytes; |
7362 | 148 } |
149 | |
150 return; | |
151 } | |
152 | |
153 | |
7401 | 154 static short read_tga_header(unsigned char *buf, TGAInfo *info) |
7362 | 155 { |
7401 | 156 info->id_len = buf[0]; |
7362 | 157 |
7401 | 158 info->img_type = buf[2]; |
7362 | 159 |
160 /* targa data is always stored in little endian byte order */ | |
7401 | 161 info->width = le2me_16(*(unsigned short *) &buf[12]); |
162 info->height = le2me_16(*(unsigned short *) &buf[14]); | |
7362 | 163 |
7401 | 164 info->bpp = buf[16]; |
7362 | 165 |
7401 | 166 info->origin = (buf[17] & 0x20) >> 5; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
167 |
7362 | 168 /* FIXME check for valid targa data */ |
169 | |
170 return 0; | |
171 } | |
172 | |
173 | |
174 /* decode a frame */ | |
175 static mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags) | |
176 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
177 TGAInfo *info = sh->context; |
7362 | 178 unsigned char *data = raw; |
179 mp_image_t *mpi; | |
180 | |
181 | |
182 if (len <= 0) | |
183 return NULL; /* skip frame */ | |
184 | |
7401 | 185 read_tga_header(data, info); /* read information about the file */ |
7362 | 186 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
187 if (info->bpp == 24) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
188 out_fmt = IMGFMT_BGR24; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
189 else if (info->bpp == 32) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
190 out_fmt = IMGFMT_BGR32; |
7362 | 191 else |
192 { | |
7401 | 193 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type! depth=%d\n",info->bpp); |
7362 | 194 return NULL; |
195 } | |
196 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
197 if (info->img_type != TGA_UNCOMP_TRUECOLOR && info->img_type != TGA_RLE_TRUECOLOR) /* not a true color image */ |
7362 | 198 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
199 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type: %i!\n", info->img_type); |
7362 | 200 return NULL; |
201 } | |
202 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
203 /* if img.origin is 0, we decode from bottom to top. if it's 1, we decode from top to bottom */ |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
204 info->start_row = (info->origin) ? 0 : info->height - 1; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
205 info->increment = (info->origin) ? 1 : -1; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
206 |
7362 | 207 /* set data to the beginning of the image data */ |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
208 data += 18 + info->id_len; |
7362 | 209 |
210 /* (re)init libvo if image parameters changed (width/height/colorspace) */ | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
211 if (last_w != info->width || last_h != info->height || last_c != out_fmt) |
7362 | 212 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
213 last_w = info->width; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
214 last_h = info->height; |
7362 | 215 last_c = out_fmt; |
216 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
217 if (!out_fmt || !mpcodecs_config_vo(sh, info->width, info->height, out_fmt)) |
7362 | 218 return NULL; |
219 } | |
220 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
221 if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, info->width, info->height))) |
7362 | 222 return NULL; |
223 | |
224 /* finally decode the image */ | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
225 if (info->img_type == TGA_UNCOMP_TRUECOLOR) |
7401 | 226 decode_uncompressed_tga(info, data, mpi); |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
227 else if (info->img_type == TGA_RLE_TRUECOLOR) |
7401 | 228 decode_rle_tga(info, data, mpi); |
229 // else | |
230 // mpi = NULL; | |
7362 | 231 |
232 return mpi; | |
233 } | |
234 |