Mercurial > mplayer.hg
annotate libmpcodecs/vd_mtga.c @ 28992:947ef23ba798
Test if create_vdp_decoder() might succeed by calling it from config()
with a small value for max_reference_frames.
This does not make automatic recovery by using software decoder possible,
but lets MPlayer fail more graciously on - actually existing - buggy
hardware that does not support certain H264 widths when using
hardware accelerated decoding (784, 864, 944, 1024, 1808, 1888 pixels on
NVIDIA G98) and if the user tries to hardware-decode more samples at
the same time than supported.
Might break playback of H264 Intra-Only samples on hardware with very
little video memory.
author | cehoyos |
---|---|
date | Sat, 21 Mar 2009 20:11:05 +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 |