Mercurial > mplayer.hg
annotate libmpcodecs/vd_mtga.c @ 7449:28785e6e6900
"One can cause a permanent hang on a seek, and the other just causes
general jerkiness because the writer thread was holding a lock
during the time it was writing to the network."
patch by Sidik Isani <lksi@cfht.hawaii.edu>
author | arpi |
---|---|
date | Fri, 20 Sep 2002 18:26:54 +0000 |
parents | 8b90281ed8aa |
children | c4434bdf6e51 |
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> | |
9 | |
10 #include "config.h" | |
11 #include "mp_msg.h" | |
12 | |
13 #include "bswap.h" | |
14 #include "postproc/rgb2rgb.h" | |
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; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
52 unsigned 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 TGAInfo *info = (TGAInfo *) sh->context; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
66 switch (cmd) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
67 { |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
68 case VDCTRL_QUERY_FORMAT: |
7401 | 69 if (*((int *) arg) == out_fmt) return CONTROL_TRUE; |
70 return CONTROL_FALSE; | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
71 } |
7401 | 72 return CONTROL_UNKNOWN; |
7362 | 73 } |
74 | |
75 /* init driver */ | |
76 static int init(sh_video_t *sh) | |
77 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
78 sh->context = (TGAInfo *) calloc(1, sizeof(TGAInfo)); |
7362 | 79 last_w = -1; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
80 |
7362 | 81 return 1; |
82 } | |
83 | |
84 | |
85 /* uninit driver */ | |
86 static void uninit(sh_video_t *sh) | |
87 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
88 TGAInfo *info = sh->context; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
89 free(info); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
90 return; |
7362 | 91 } |
92 | |
93 | |
94 /* decode a runlength-encoded tga */ | |
7401 | 95 static void decode_rle_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 96 { |
7401 | 97 int row, col, replen, i, num_bytes = info->bpp / 8; |
7362 | 98 unsigned char repetitions, packet_header, *final; |
99 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
100 /* 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
|
101 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 102 { |
7401 | 103 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
|
104 |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
105 for (col = 0; col < info->width; col += repetitions) |
7362 | 106 { |
107 packet_header = *data++; | |
7401 | 108 repetitions = (1 + (packet_header & 0x7f)); |
109 replen = repetitions * num_bytes; | |
7362 | 110 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
111 if (packet_header & 0x80) /* runlength encoded packet */ |
7362 | 112 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
113 memcpy(final, data, num_bytes); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
114 |
7401 | 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; | |
120 } | |
121 memcpy(final+i,final,replen-i); | |
122 data += num_bytes; | |
7362 | 123 } |
124 else /* raw packet */ | |
7401 | 125 { |
126 memcpy(final, data, replen); | |
127 data += replen; | |
128 } | |
129 | |
130 final += replen; | |
7362 | 131 } |
132 } | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
133 |
7362 | 134 return; |
135 } | |
136 | |
137 | |
7401 | 138 static void decode_uncompressed_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 139 { |
140 unsigned char *final; | |
7401 | 141 int row, num_bytes = info->bpp / 8; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
142 |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
143 /* 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
|
144 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 145 { |
7401 | 146 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
|
147 memcpy(final, data, info->width * num_bytes); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
148 data += info->width * num_bytes; |
7362 | 149 } |
150 | |
151 return; | |
152 } | |
153 | |
154 | |
7401 | 155 static short read_tga_header(unsigned char *buf, TGAInfo *info) |
7362 | 156 { |
7401 | 157 info->id_len = buf[0]; |
7362 | 158 |
7401 | 159 info->img_type = buf[2]; |
7362 | 160 |
161 /* targa data is always stored in little endian byte order */ | |
7401 | 162 info->width = le2me_16(*(unsigned short *) &buf[12]); |
163 info->height = le2me_16(*(unsigned short *) &buf[14]); | |
7362 | 164 |
7401 | 165 info->bpp = buf[16]; |
7362 | 166 |
7401 | 167 info->origin = (buf[17] & 0x20) >> 5; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
168 |
7362 | 169 /* FIXME check for valid targa data */ |
170 | |
171 return 0; | |
172 } | |
173 | |
174 | |
175 /* decode a frame */ | |
176 static mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags) | |
177 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
178 TGAInfo *info = sh->context; |
7362 | 179 unsigned char *data = raw; |
180 mp_image_t *mpi; | |
181 | |
182 | |
183 if (len <= 0) | |
184 return NULL; /* skip frame */ | |
185 | |
7401 | 186 read_tga_header(data, info); /* read information about the file */ |
7362 | 187 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
188 if (info->bpp == 24) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
189 out_fmt = IMGFMT_BGR24; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
190 else if (info->bpp == 32) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
191 out_fmt = IMGFMT_BGR32; |
7362 | 192 else |
193 { | |
7401 | 194 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type! depth=%d\n",info->bpp); |
7362 | 195 return NULL; |
196 } | |
197 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
198 if (info->img_type != TGA_UNCOMP_TRUECOLOR && info->img_type != TGA_RLE_TRUECOLOR) /* not a true color image */ |
7362 | 199 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
200 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type: %i!\n", info->img_type); |
7362 | 201 return NULL; |
202 } | |
203 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
204 /* 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
|
205 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
|
206 info->increment = (info->origin) ? 1 : -1; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
207 |
7362 | 208 /* 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
|
209 data += 18 + info->id_len; |
7362 | 210 |
211 /* (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
|
212 if (last_w != info->width || last_h != info->height || last_c != out_fmt) |
7362 | 213 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
214 last_w = info->width; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
215 last_h = info->height; |
7362 | 216 last_c = out_fmt; |
217 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
218 if (!out_fmt || !mpcodecs_config_vo(sh, info->width, info->height, out_fmt)) |
7362 | 219 return NULL; |
220 } | |
221 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
222 if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, info->width, info->height))) |
7362 | 223 return NULL; |
224 | |
225 /* finally decode the image */ | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
226 if (info->img_type == TGA_UNCOMP_TRUECOLOR) |
7401 | 227 decode_uncompressed_tga(info, data, mpi); |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
228 else if (info->img_type == TGA_RLE_TRUECOLOR) |
7401 | 229 decode_rle_tga(info, data, mpi); |
230 // else | |
231 // mpi = NULL; | |
7362 | 232 |
233 return mpi; | |
234 } | |
235 |