Mercurial > mplayer.hg
annotate libmpcodecs/vd_mtga.c @ 20213:cc316541564f
during stream detection always parse ts_probesize bytes (even with -nosound set),
otherwise the demuxer may not have a chance to correctly identify the stream type
(e.g. H264 was misidentified as MPEG2 with -nosound set)
author | nicodvb |
---|---|
date | Sun, 15 Oct 2006 09:29:02 +0000 |
parents | 497ebe3ecc2b |
children | 1767c271d710 |
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 "libvo/fastmemcpy.h" | |
15 | |
16 #include "vd_internal.h" | |
17 | |
18 static vd_info_t info = | |
19 { | |
20 "TGA Images decoder", | |
21 "mtga", | |
7401 | 22 "Tilman Sauerbeck, A'rpi", |
7362 | 23 "Tilman Sauerbeck", |
24 "only 24bpp and 32bpp RGB targa files support so far" | |
25 }; | |
26 | |
27 LIBVD_EXTERN(mtga) | |
28 | |
29 typedef enum | |
30 { | |
31 TGA_NO_DATA, | |
32 TGA_UNCOMP_PALETTED, | |
33 TGA_UNCOMP_TRUECOLOR, | |
34 TGA_UNCOMP_GRAYSCALE, | |
35 TGA_RLE_PALETTED = 9, | |
36 TGA_RLE_TRUECOLOR, | |
37 TGA_RLE_GRAYSCALE | |
38 } TGAImageType; | |
39 | |
40 typedef struct | |
41 { | |
42 unsigned char id_len; | |
43 unsigned short img_type; | |
44 | |
45 unsigned short width; | |
46 unsigned short height; | |
47 | |
48 unsigned char bpp; | |
49 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
|
50 unsigned short start_row; |
9605 | 51 short increment; |
7362 | 52 } TGAInfo; |
53 | |
54 static unsigned int out_fmt = 0; | |
55 | |
56 static int last_w = -1; | |
57 static int last_h = -1; | |
58 static int last_c = -1; | |
59 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
60 |
7362 | 61 /* to set/get/query special features/parameters */ |
62 static int control(sh_video_t *sh, int cmd, void *arg, ...) | |
63 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
64 switch (cmd) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
65 { |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
66 case VDCTRL_QUERY_FORMAT: |
7401 | 67 if (*((int *) arg) == out_fmt) return CONTROL_TRUE; |
68 return CONTROL_FALSE; | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
69 } |
7401 | 70 return CONTROL_UNKNOWN; |
7362 | 71 } |
72 | |
73 /* init driver */ | |
74 static int init(sh_video_t *sh) | |
75 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
76 sh->context = (TGAInfo *) calloc(1, sizeof(TGAInfo)); |
7362 | 77 last_w = -1; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
78 |
7362 | 79 return 1; |
80 } | |
81 | |
82 | |
83 /* uninit driver */ | |
84 static void uninit(sh_video_t *sh) | |
85 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
86 TGAInfo *info = sh->context; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
87 free(info); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
88 return; |
7362 | 89 } |
90 | |
91 | |
92 /* decode a runlength-encoded tga */ | |
7401 | 93 static void decode_rle_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 94 { |
7401 | 95 int row, col, replen, i, num_bytes = info->bpp / 8; |
7362 | 96 unsigned char repetitions, packet_header, *final; |
97 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
98 /* 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
|
99 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 100 { |
7401 | 101 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
|
102 |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
103 for (col = 0; col < info->width; col += repetitions) |
7362 | 104 { |
105 packet_header = *data++; | |
7401 | 106 repetitions = (1 + (packet_header & 0x7f)); |
107 replen = repetitions * num_bytes; | |
7362 | 108 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
109 if (packet_header & 0x80) /* runlength encoded packet */ |
7362 | 110 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
111 memcpy(final, data, num_bytes); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
112 |
7401 | 113 // Note: this will be slow when DR to vram! |
114 i=num_bytes; | |
115 while(2*i<=replen){ | |
116 memcpy(final+i,final,i); | |
117 i*=2; | |
118 } | |
119 memcpy(final+i,final,replen-i); | |
120 data += num_bytes; | |
7362 | 121 } |
122 else /* raw packet */ | |
7401 | 123 { |
124 memcpy(final, data, replen); | |
125 data += replen; | |
126 } | |
127 | |
128 final += replen; | |
7362 | 129 } |
130 } | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
131 |
7362 | 132 return; |
133 } | |
134 | |
135 | |
7401 | 136 static void decode_uncompressed_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 137 { |
138 unsigned char *final; | |
7401 | 139 int row, num_bytes = info->bpp / 8; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
140 |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
141 /* 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
|
142 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 143 { |
7401 | 144 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
|
145 memcpy(final, data, info->width * num_bytes); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
146 data += info->width * num_bytes; |
7362 | 147 } |
148 | |
149 return; | |
150 } | |
151 | |
152 | |
7401 | 153 static short read_tga_header(unsigned char *buf, TGAInfo *info) |
7362 | 154 { |
7401 | 155 info->id_len = buf[0]; |
7362 | 156 |
7401 | 157 info->img_type = buf[2]; |
7362 | 158 |
159 /* targa data is always stored in little endian byte order */ | |
7401 | 160 info->width = le2me_16(*(unsigned short *) &buf[12]); |
161 info->height = le2me_16(*(unsigned short *) &buf[14]); | |
7362 | 162 |
7401 | 163 info->bpp = buf[16]; |
7362 | 164 |
7401 | 165 info->origin = (buf[17] & 0x20) >> 5; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
166 |
7362 | 167 /* FIXME check for valid targa data */ |
168 | |
169 return 0; | |
170 } | |
171 | |
172 | |
173 /* decode a frame */ | |
174 static mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags) | |
175 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
176 TGAInfo *info = sh->context; |
7362 | 177 unsigned char *data = raw; |
178 mp_image_t *mpi; | |
179 | |
180 | |
181 if (len <= 0) | |
182 return NULL; /* skip frame */ | |
183 | |
7401 | 184 read_tga_header(data, info); /* read information about the file */ |
7362 | 185 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
186 if (info->bpp == 24) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
187 out_fmt = IMGFMT_BGR24; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
188 else if (info->bpp == 32) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
189 out_fmt = IMGFMT_BGR32; |
7362 | 190 else |
191 { | |
7401 | 192 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type! depth=%d\n",info->bpp); |
7362 | 193 return NULL; |
194 } | |
195 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
196 if (info->img_type != TGA_UNCOMP_TRUECOLOR && info->img_type != TGA_RLE_TRUECOLOR) /* not a true color image */ |
7362 | 197 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
198 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type: %i!\n", info->img_type); |
7362 | 199 return NULL; |
200 } | |
201 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
202 /* 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
|
203 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
|
204 info->increment = (info->origin) ? 1 : -1; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
205 |
7362 | 206 /* 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
|
207 data += 18 + info->id_len; |
7362 | 208 |
209 /* (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
|
210 if (last_w != info->width || last_h != info->height || last_c != out_fmt) |
7362 | 211 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
212 last_w = info->width; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
213 last_h = info->height; |
7362 | 214 last_c = out_fmt; |
215 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
216 if (!out_fmt || !mpcodecs_config_vo(sh, info->width, info->height, out_fmt)) |
7362 | 217 return NULL; |
218 } | |
219 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
220 if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, info->width, info->height))) |
7362 | 221 return NULL; |
222 | |
223 /* finally decode the image */ | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
224 if (info->img_type == TGA_UNCOMP_TRUECOLOR) |
7401 | 225 decode_uncompressed_tga(info, data, mpi); |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
226 else if (info->img_type == TGA_RLE_TRUECOLOR) |
7401 | 227 decode_rle_tga(info, data, mpi); |
228 // else | |
229 // mpi = NULL; | |
7362 | 230 |
231 return mpi; | |
232 } | |
233 |