Mercurial > mplayer.hg
annotate libmpcodecs/vd_mtga.c @ 32619:34c4e6ff7b17
Fix ad_faad crash when used on an empty audio stream.
author | reimar |
---|---|
date | Sun, 12 Dec 2010 13:56:35 +0000 |
parents | b40d593a463f |
children |
rev | line source |
---|---|
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
1 /* |
7362 | 2 * based on: XreaL's x_r_img_tga.* (http://www.sourceforge.net/projects/xreal/) |
3 * libtarga.* | |
4 * xli's tga.* | |
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
5 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
6 * Copyright (c) 2002 Tilman Sauerbeck <tsauerbeck@users.sourceforge.net> |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
7 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
8 * This file is part of MPlayer. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
9 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
10 * MPlayer is free software; you can redistribute it and/or modify |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
11 * it under the terms of the GNU General Public License as published by |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
12 * the Free Software Foundation; either version 2 of the License, or |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
13 * (at your option) any later version. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
14 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
15 * MPlayer is distributed in the hope that it will be useful, |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
18 * GNU General Public License for more details. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
19 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
20 * You should have received a copy of the GNU General Public License along |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
21 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
7362 | 23 */ |
24 | |
25 #include <stdio.h> | |
26 #include <stdlib.h> | |
23305
22d3d12c6dfb
Include string.h for memcpy, fastmemcpy.h alone is not enough.
reimar
parents:
21507
diff
changeset
|
27 #include <string.h> |
7362 | 28 |
29 #include "config.h" | |
30 #include "mp_msg.h" | |
31 | |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30702
diff
changeset
|
32 #include "libavutil/intreadwrite.h" |
7362 | 33 #include "libvo/fastmemcpy.h" |
34 | |
35 #include "vd_internal.h" | |
36 | |
30504
cc27da5d7286
Mark all ad_info_t/vd_info_t structure declarations as const.
diego
parents:
30421
diff
changeset
|
37 static const vd_info_t info = |
7362 | 38 { |
39 "TGA Images decoder", | |
40 "mtga", | |
7401 | 41 "Tilman Sauerbeck, A'rpi", |
7362 | 42 "Tilman Sauerbeck", |
43 "only 24bpp and 32bpp RGB targa files support so far" | |
44 }; | |
45 | |
46 LIBVD_EXTERN(mtga) | |
47 | |
48 typedef enum | |
49 { | |
50 TGA_NO_DATA, | |
51 TGA_UNCOMP_PALETTED, | |
52 TGA_UNCOMP_TRUECOLOR, | |
53 TGA_UNCOMP_GRAYSCALE, | |
54 TGA_RLE_PALETTED = 9, | |
55 TGA_RLE_TRUECOLOR, | |
56 TGA_RLE_GRAYSCALE | |
57 } TGAImageType; | |
58 | |
59 typedef struct | |
60 { | |
61 unsigned char id_len; | |
62 unsigned short img_type; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
63 |
7362 | 64 unsigned short width; |
65 unsigned short height; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
66 |
7362 | 67 unsigned char bpp; |
68 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
|
69 unsigned short start_row; |
9605 | 70 short increment; |
7362 | 71 } TGAInfo; |
72 | |
73 static unsigned int out_fmt = 0; | |
74 | |
75 static int last_w = -1; | |
76 static int last_h = -1; | |
77 static int last_c = -1; | |
78 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
79 |
7362 | 80 /* to set/get/query special features/parameters */ |
81 static int control(sh_video_t *sh, int cmd, void *arg, ...) | |
82 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
83 switch (cmd) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
84 { |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
85 case VDCTRL_QUERY_FORMAT: |
7401 | 86 if (*((int *) arg) == out_fmt) return CONTROL_TRUE; |
87 return CONTROL_FALSE; | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
88 } |
7401 | 89 return CONTROL_UNKNOWN; |
7362 | 90 } |
91 | |
92 /* init driver */ | |
93 static int init(sh_video_t *sh) | |
94 { | |
30702 | 95 sh->context = calloc(1, sizeof(TGAInfo)); |
7362 | 96 last_w = -1; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
97 |
7362 | 98 return 1; |
99 } | |
100 | |
101 | |
102 /* uninit driver */ | |
103 static void uninit(sh_video_t *sh) | |
104 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
105 TGAInfo *info = sh->context; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
106 free(info); |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
107 return; |
7362 | 108 } |
109 | |
110 | |
111 /* decode a runlength-encoded tga */ | |
7401 | 112 static void decode_rle_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 113 { |
7401 | 114 int row, col, replen, i, num_bytes = info->bpp / 8; |
7362 | 115 unsigned char repetitions, packet_header, *final; |
116 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
117 /* 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
|
118 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 119 { |
7401 | 120 final = mpi->planes[0] + mpi->stride[0] * row; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
121 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
122 for (col = 0; col < info->width; col += repetitions) |
7362 | 123 { |
124 packet_header = *data++; | |
7401 | 125 repetitions = (1 + (packet_header & 0x7f)); |
126 replen = repetitions * num_bytes; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
127 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
128 if (packet_header & 0x80) /* runlength encoded packet */ |
7362 | 129 { |
23458
973e53dc7df5
Do not use fast_memcpy for small size copy, esp. when the size is constant
reimar
parents:
23457
diff
changeset
|
130 memcpy(final, data, num_bytes); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
131 |
7401 | 132 // Note: this will be slow when DR to vram! |
133 i=num_bytes; | |
134 while(2*i<=replen){ | |
23459
2c09fe135c93
Do not use fast_memcpy when data is read again immediately afterwards.
reimar
parents:
23458
diff
changeset
|
135 memcpy(final+i,final,i); |
7401 | 136 i*=2; |
137 } | |
23459
2c09fe135c93
Do not use fast_memcpy when data is read again immediately afterwards.
reimar
parents:
23458
diff
changeset
|
138 memcpy(final+i,final,replen-i); |
7401 | 139 data += num_bytes; |
7362 | 140 } |
141 else /* raw packet */ | |
7401 | 142 { |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
23305
diff
changeset
|
143 fast_memcpy(final, data, replen); |
7401 | 144 data += replen; |
145 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
146 |
7401 | 147 final += replen; |
7362 | 148 } |
149 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
150 |
7362 | 151 return; |
152 } | |
153 | |
154 | |
7401 | 155 static void decode_uncompressed_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi) |
7362 | 156 { |
157 unsigned char *final; | |
7401 | 158 int row, num_bytes = info->bpp / 8; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
159 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
160 /* 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
|
161 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment) |
7362 | 162 { |
7401 | 163 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
|
164 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
|
165 data += info->width * num_bytes; |
7362 | 166 } |
167 | |
168 return; | |
169 } | |
170 | |
171 | |
7401 | 172 static short read_tga_header(unsigned char *buf, TGAInfo *info) |
7362 | 173 { |
7401 | 174 info->id_len = buf[0]; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
175 |
7401 | 176 info->img_type = buf[2]; |
7362 | 177 |
178 /* targa data is always stored in little endian byte order */ | |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30702
diff
changeset
|
179 info->width = AV_RL16(&buf[12]); |
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30702
diff
changeset
|
180 info->height = AV_RL16(&buf[14]); |
7362 | 181 |
7401 | 182 info->bpp = buf[16]; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
183 |
7401 | 184 info->origin = (buf[17] & 0x20) >> 5; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
185 |
7362 | 186 /* FIXME check for valid targa data */ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
187 |
7362 | 188 return 0; |
189 } | |
190 | |
191 | |
192 /* decode a frame */ | |
193 static mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags) | |
194 { | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
195 TGAInfo *info = sh->context; |
7362 | 196 unsigned char *data = raw; |
197 mp_image_t *mpi; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
198 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
199 |
7362 | 200 if (len <= 0) |
201 return NULL; /* skip frame */ | |
202 | |
7401 | 203 read_tga_header(data, info); /* read information about the file */ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
204 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
205 if (info->bpp == 24) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
206 out_fmt = IMGFMT_BGR24; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
207 else if (info->bpp == 32) |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
208 out_fmt = IMGFMT_BGR32; |
7362 | 209 else |
210 { | |
7401 | 211 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type! depth=%d\n",info->bpp); |
7362 | 212 return NULL; |
213 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
214 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
215 if (info->img_type != TGA_UNCOMP_TRUECOLOR && info->img_type != TGA_RLE_TRUECOLOR) /* not a true color image */ |
7362 | 216 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
217 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type: %i!\n", info->img_type); |
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 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
|
222 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
|
223 info->increment = (info->origin) ? 1 : -1; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
224 |
7362 | 225 /* 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
|
226 data += 18 + info->id_len; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
227 |
7362 | 228 /* (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
|
229 if (last_w != info->width || last_h != info->height || last_c != out_fmt) |
7362 | 230 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
231 last_w = info->width; |
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
232 last_h = info->height; |
7362 | 233 last_c = out_fmt; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
234 |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
235 if (!out_fmt || !mpcodecs_config_vo(sh, info->width, info->height, out_fmt)) |
7362 | 236 return NULL; |
237 } | |
238 | |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
239 if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, info->width, info->height))) |
7362 | 240 return NULL; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
241 |
7362 | 242 /* finally decode the image */ |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
243 if (info->img_type == TGA_UNCOMP_TRUECOLOR) |
7401 | 244 decode_uncompressed_tga(info, data, mpi); |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
245 else if (info->img_type == TGA_RLE_TRUECOLOR) |
7401 | 246 decode_rle_tga(info, data, mpi); |
247 // else | |
248 // mpi = NULL; | |
7362 | 249 |
250 return mpi; | |
251 } |