Mercurial > mplayer.hg
annotate libvo/vo_gif89a.c @ 7743:a280cc3087ea
All right: The patch adresses two issues which I found, when I analyzed
the input from some DVDs with known subtitle-dropouts:
1. The packet-size at the beginning of the packet, which is used to
check, whether we got all fragments, is sometimes one byte too long. It
seems to be always padded to an even number, while the actual size can
be odd.
2. The original algorythm used to assemble the fragments relies on the
timestamps to check, whether a new packet begins. This has proven to be
unrelieable on some disks. So instead, I use the timestamp only to
check, whether it's been too long (defined as 0,01sec) since the last
fragment, which is probably indicating a broken packet, and normaly
starting a new packet when the last one has been finished.
patch by Christof Buergi <christof@buergi.lugs.ch>
author | arpi |
---|---|
date | Tue, 15 Oct 2002 00:47:17 +0000 |
parents | e60109dfc85c |
children | 9fc45fe0d444 |
rev | line source |
---|---|
6053 | 1 /* |
2 * vo_gif89a.c Generate gif89a output in file out.gif | |
3 * | |
4 * Originally based on vo_png.c | |
5 * | |
6 * Stolen (C) 2002 by GifWhore <joey@yunamusic.com> | |
7 * | |
8 */ | |
9 | |
10 #include <stdio.h> | |
11 #include <stdlib.h> | |
12 #include <string.h> | |
13 #include <errno.h> | |
14 | |
15 #include "config.h" | |
16 #include "video_out.h" | |
17 #include "video_out_internal.h" | |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
7124
diff
changeset
|
18 #include "sub.h" |
6053 | 19 |
20 #include "../postproc/rgb2rgb.h" | |
21 | |
22 #include <gif_lib.h> | |
23 | |
24 #define GIFWHORE_version 0.90 | |
25 | |
26 LIBVO_EXTERN (gif89a) | |
27 | |
28 static vo_info_t vo_info = | |
29 { | |
30 "GIF89a (out.gif)", | |
31 "gif89a", | |
32 "GifWhore <joey@yunamusic.com>", | |
33 "" | |
34 }; | |
35 | |
36 extern int verbose; | |
37 extern int vo_config_count; | |
38 | |
39 static int image_width; | |
40 static int image_height; | |
41 static int image_format; | |
42 static uint8_t *image_data=NULL; | |
43 | |
44 static int reverse_map = 0; | |
45 static unsigned char framenum = 0; | |
46 static int gif_frameskip; | |
47 static int gif_framedelay; | |
48 static int target_fps = 0; | |
49 | |
50 GifFileType *newgif=NULL; | |
51 | |
52 static uint32_t config | |
53 (uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, | |
7124
eca7dbad0166
finally removed query_vaa, bes_da and vo_tune_info - the obsoleted libvo api
alex
parents:
6211
diff
changeset
|
54 uint32_t fullscreen, char *title, uint32_t format) { |
6053 | 55 char filename[] = "out.gif"; |
56 ColorMapObject *Cmap; | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
57 #ifdef HAVE_GIF_4 |
6053 | 58 char LB[] = { |
59 'N','E','T','S', | |
60 'C','A','P','E', | |
61 '2','.','0' }; | |
62 char LB2[] = { 1, 0x00, 0x00 }; | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
63 #endif |
6053 | 64 |
65 if (target_fps == 0) target_fps = 5; | |
66 gif_frameskip = (vo_fps + 0.25) / target_fps; | |
67 gif_framedelay = 100 / target_fps; | |
68 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
69 image_width = width; |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
70 image_height = height; |
6053 | 71 image_format = format; |
72 | |
73 Cmap = MakeMapObject(256, NULL); | |
74 | |
75 switch(format) { | |
76 case IMGFMT_BGR24: | |
77 reverse_map = 1; | |
78 break; | |
79 case IMGFMT_RGB24: | |
80 break; | |
81 case IMGFMT_YV12: | |
7487
e60109dfc85c
U-V swapping fixed, patch by Joey Parrish <joey@yunamusic.com>
arpi
parents:
7472
diff
changeset
|
82 yuv2rgb_init(24, MODE_BGR); |
6053 | 83 image_data = malloc(image_width*image_height*3); |
84 break; | |
85 default: | |
86 return 1; | |
87 } | |
88 | |
89 if (vo_config_count > 0) | |
90 return 0; | |
91 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
92 // this line causes crashes in certain earlier versions of libungif. |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
93 // i don't know exactly which, but certainly all those before v4. |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
94 // if you have problems, you need to upgrade your gif library. |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
95 #ifdef HAVE_GIF_4 |
6053 | 96 EGifSetGifVersion("89a"); |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
97 #else |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
98 fprintf(stderr, "vo_gif89a: Your version of libgif/libungif needs to be upgraded.\n"); |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
99 fprintf(stderr, "vo_gif89a: Some functionality has been disabled.\n"); |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
100 #endif |
6053 | 101 newgif = EGifOpenFileName(filename, 0); |
102 if (newgif == NULL) | |
103 { | |
104 fprintf(stderr, "error opening file for output.\n"); | |
105 return(1); | |
106 } | |
107 EGifPutScreenDesc(newgif, image_width, image_height, 256, 0, Cmap); | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
108 #ifdef HAVE_GIF_4 |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
109 // version 3 of libgif/libungif does not support multiple control blocks. |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
110 // for this version, looping will be disabled. |
6053 | 111 EGifPutExtensionFirst(newgif, 0xFF, 11, LB); |
112 EGifPutExtensionLast(newgif, 0, 3, LB2); | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
113 #endif |
6053 | 114 |
115 return 0; | |
116 } | |
117 | |
118 static const vo_info_t* get_info(void) | |
119 { | |
120 return &vo_info; | |
121 } | |
122 | |
123 static uint32_t draw_frame(uint8_t * src[]) | |
124 { | |
125 uint8_t *use_data; | |
126 ColorMapObject *Cmap; | |
127 uint8_t Colors[256 * 3]; | |
128 int z; | |
129 char CB[] = { (char)(gif_framedelay >> 8), (char)(gif_framedelay & 0xff), 0, 0}; | |
130 | |
131 if ((framenum++ % gif_frameskip)) return(0); | |
132 | |
133 Cmap = MakeMapObject(256, NULL); | |
134 use_data = (uint8_t *)malloc(image_width * image_height); | |
135 if (gif_reduce(image_width, image_height, src[0], use_data, Colors)) return(0); | |
136 | |
137 if (reverse_map) | |
138 { | |
139 for (z = 0; z < 256; z++) { | |
140 Cmap->Colors[z].Blue = Colors[(z * 3) + 0]; | |
141 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
142 Cmap->Colors[z].Red = Colors[(z * 3) + 2]; | |
143 } | |
144 } | |
145 else | |
146 { | |
147 for (z = 0; z < 256; z++) { | |
148 Cmap->Colors[z].Red = Colors[(z * 3) + 0]; | |
149 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
150 Cmap->Colors[z].Blue = Colors[(z * 3) + 2]; | |
151 } | |
152 } | |
153 | |
154 EGifPutExtension(newgif, 0xF9, 0x04, CB); | |
155 EGifPutImageDesc(newgif, 0, 0, image_width, image_height, 0, Cmap); | |
156 EGifPutLine(newgif, use_data, image_width * image_height); | |
157 FreeMapObject(Cmap); | |
158 free(use_data); | |
159 | |
160 return (0); | |
161 } | |
162 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
163 #ifdef USE_OSD |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
164 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
165 { |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
166 vo_draw_alpha_rgb24(w, h, src, srca, stride, image_data + 3 * (y0 * image_width + x0), 3 * image_width); |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
167 } |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
168 #endif |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
169 |
6053 | 170 static void draw_osd(void) |
171 { | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
172 #ifdef USE_OSD |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
173 vo_draw_text(image_width, image_height, draw_alpha); |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
174 #endif |
6053 | 175 } |
176 | |
177 static void flip_page (void) | |
178 { | |
179 uint8_t *use_data; | |
180 ColorMapObject *Cmap; | |
181 uint8_t Colors[256 * 3]; | |
182 int z; | |
183 char CB[] = { (char)(gif_framedelay >> 8), (char)(gif_framedelay & 0xff), 0, 0}; | |
184 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
185 if (image_format == IMGFMT_YV12) { |
6053 | 186 |
187 if ((framenum++ % gif_frameskip)) return; | |
188 | |
189 Cmap = MakeMapObject(256, NULL); | |
190 use_data = (uint8_t *)malloc(image_width * image_height); | |
191 if (gif_reduce(image_width, image_height, image_data, use_data, Colors)) return; | |
192 | |
193 if (reverse_map) | |
194 { | |
195 for (z = 0; z < 256; z++) { | |
196 Cmap->Colors[z].Blue = Colors[(z * 3) + 0]; | |
197 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
198 Cmap->Colors[z].Red = Colors[(z * 3) + 2]; | |
199 } | |
200 } | |
201 else | |
202 { | |
203 for (z = 0; z < 256; z++) { | |
204 Cmap->Colors[z].Red = Colors[(z * 3) + 0]; | |
205 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
206 Cmap->Colors[z].Blue = Colors[(z * 3) + 2]; | |
207 } | |
208 } | |
209 | |
210 EGifPutExtension(newgif, 0xF9, 0x04, CB); | |
211 EGifPutImageDesc(newgif, 0, 0, image_width, image_height, 0, Cmap); | |
212 EGifPutLine(newgif, use_data, image_width * image_height); | |
213 FreeMapObject(Cmap); | |
214 free(use_data); | |
215 } | |
216 } | |
217 | |
218 static uint32_t draw_slice( uint8_t *src[],int stride[],int w,int h,int x,int y ) | |
219 { | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
220 uint8_t *dst = image_data + (image_width * y + x) * 3; |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
221 yuv2rgb(dst,src[0],src[1],src[2],w,h,image_width*3,stride[0],stride[1]); |
6053 | 222 return 0; |
223 } | |
224 | |
225 static uint32_t | |
226 query_format(uint32_t format) | |
227 { | |
228 switch(format){ | |
229 case IMGFMT_YV12: | |
6211 | 230 return VFCAP_CSP_SUPPORTED | VFCAP_TIMER | VFCAP_ACCEPT_STRIDE; |
6053 | 231 case IMGFMT_RGB|24: |
232 case IMGFMT_BGR|24: | |
6211 | 233 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD | VFCAP_TIMER; |
6053 | 234 } |
235 return 0; | |
236 } | |
237 | |
238 static void | |
239 uninit(void) | |
240 { | |
241 char temp[256]; | |
242 | |
243 if (image_data) { free(image_data); image_data=NULL; } | |
244 | |
245 if (vo_config_count > 0) { | |
246 sprintf(temp, "gifwhore v%2.2f (c) %s\r\n", | |
247 GIFWHORE_version, "joey@yunamusic.com"); | |
248 EGifPutComment(newgif, temp); | |
249 EGifCloseFile(newgif); | |
250 } | |
251 } | |
252 | |
253 | |
254 static void check_events(void) | |
255 { | |
256 } | |
257 | |
258 int gif_reduce(int width, int height, | |
259 unsigned char *source, | |
260 unsigned char *destination, | |
261 unsigned char *palette) | |
262 { | |
263 GifColorType cmap[256]; | |
264 unsigned char Ra[width * height]; | |
265 unsigned char Ga[width * height]; | |
266 unsigned char Ba[width * height]; | |
267 unsigned char *R, *G, *B; | |
268 int Size = 256; | |
269 int i; | |
270 | |
271 R = Ra; G = Ga; B = Ba; | |
272 for (i = 0; i < width * height; i++) | |
273 { | |
274 *R++ = *source++; | |
275 *G++ = *source++; | |
276 *B++ = *source++; | |
277 } | |
278 | |
279 R = Ra; G = Ga; B = Ba; | |
280 if (QuantizeBuffer(width, height, &Size, | |
281 R, G, B, | |
282 destination, cmap) == GIF_ERROR) | |
283 { | |
284 fprintf(stderr, "vo_gif89a: Quantize failed!\n"); | |
285 return(-1); | |
286 } | |
287 | |
288 for (i = 0; i < Size; i++) | |
289 { | |
290 *palette++ = cmap[i].Red; | |
291 *palette++ = cmap[i].Green; | |
292 *palette++ = cmap[i].Blue; | |
293 } | |
294 | |
295 return(0); | |
296 } | |
297 | |
298 static uint32_t preinit(const char *arg) | |
299 { | |
300 int i = 0; | |
301 if (arg) i = atoi(arg); | |
302 if (i > vo_fps) i = vo_fps; | |
303 if (i < 1) i = 5; | |
304 target_fps = i; | |
305 return 0; | |
306 } | |
307 | |
308 static uint32_t control(uint32_t request, void *data, ...) | |
309 { | |
310 switch (request) { | |
311 case VOCTRL_QUERY_FORMAT: | |
312 return query_format(*((uint32_t*)data)); | |
313 } | |
314 return VO_NOTIMPL; | |
315 } | |
316 |