Mercurial > mplayer.hg
annotate libmpcodecs/vd_mtga.c @ 12334:eeddcef4fb08
"hard" frame duplication for mencoder. this finally makes it possible
to generate valid mpeg output from avi's that have duplicate frames in
them, or when using inverse telecine filters. to use it, put the
"harddup" filter at the end of your filter chain.
author | rfelker |
---|---|
date | Wed, 28 Apr 2004 04:02:46 +0000 |
parents | 1bec441675d1 |
children | 497ebe3ecc2b |
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; |
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 { |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
112 memcpy(final, data, num_bytes); |
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){ | |
117 memcpy(final+i,final,i); | |
118 i*=2; | |
119 } | |
120 memcpy(final+i,final,replen-i); | |
121 data += num_bytes; | |
7362 | 122 } |
123 else /* raw packet */ | |
7401 | 124 { |
125 memcpy(final, data, replen); | |
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; |
7392
e21841225e2a
query_format support by Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
alex
parents:
7362
diff
changeset
|
146 memcpy(final, data, info->width * num_bytes); |
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 |