Mercurial > mplayer.hg
annotate libvo/vo_gif89a.c @ 6994:c7d6b72b6fc0
messages moved from vf.c and vd.c
author | jaf |
---|---|
date | Tue, 13 Aug 2002 23:32:05 +0000 |
parents | a59795bd14d0 |
children | eca7dbad0166 |
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" | |
18 | |
19 #include "../postproc/rgb2rgb.h" | |
20 | |
21 #include <gif_lib.h> | |
22 | |
23 #define GIFWHORE_version 0.90 | |
24 | |
25 LIBVO_EXTERN (gif89a) | |
26 | |
27 static vo_info_t vo_info = | |
28 { | |
29 "GIF89a (out.gif)", | |
30 "gif89a", | |
31 "GifWhore <joey@yunamusic.com>", | |
32 "" | |
33 }; | |
34 | |
35 extern int verbose; | |
36 extern int vo_config_count; | |
37 | |
38 static int image_width; | |
39 static int image_height; | |
40 static int image_format; | |
41 static uint8_t *image_data=NULL; | |
42 | |
43 static int reverse_map = 0; | |
44 static unsigned char framenum = 0; | |
45 static int gif_frameskip; | |
46 static int gif_framedelay; | |
47 static int target_fps = 0; | |
48 | |
49 GifFileType *newgif=NULL; | |
50 | |
51 static uint32_t config | |
52 (uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, | |
53 uint32_t fullscreen, char *title, uint32_t format, const vo_tune_info_t *info) { | |
54 char filename[] = "out.gif"; | |
55 ColorMapObject *Cmap; | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
56 #ifdef HAVE_GIF_4 |
6053 | 57 char LB[] = { |
58 'N','E','T','S', | |
59 'C','A','P','E', | |
60 '2','.','0' }; | |
61 char LB2[] = { 1, 0x00, 0x00 }; | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
62 #endif |
6053 | 63 |
64 if (target_fps == 0) target_fps = 5; | |
65 gif_frameskip = (vo_fps + 0.25) / target_fps; | |
66 gif_framedelay = 100 / target_fps; | |
67 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
68 image_width = width; |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
69 image_height = height; |
6053 | 70 image_format = format; |
71 | |
72 Cmap = MakeMapObject(256, NULL); | |
73 | |
74 switch(format) { | |
75 case IMGFMT_BGR24: | |
76 reverse_map = 1; | |
77 break; | |
78 case IMGFMT_RGB24: | |
79 break; | |
80 case IMGFMT_YV12: | |
81 yuv2rgb_init(24, MODE_RGB); | |
82 image_data = malloc(image_width*image_height*3); | |
83 break; | |
84 default: | |
85 return 1; | |
86 } | |
87 | |
88 if (vo_config_count > 0) | |
89 return 0; | |
90 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
91 // 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
|
92 // 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
|
93 // 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
|
94 #ifdef HAVE_GIF_4 |
6053 | 95 EGifSetGifVersion("89a"); |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
96 #else |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
97 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
|
98 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
|
99 #endif |
6053 | 100 newgif = EGifOpenFileName(filename, 0); |
101 if (newgif == NULL) | |
102 { | |
103 fprintf(stderr, "error opening file for output.\n"); | |
104 return(1); | |
105 } | |
106 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
|
107 #ifdef HAVE_GIF_4 |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
108 // 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
|
109 // for this version, looping will be disabled. |
6053 | 110 EGifPutExtensionFirst(newgif, 0xFF, 11, LB); |
111 EGifPutExtensionLast(newgif, 0, 3, LB2); | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
112 #endif |
6053 | 113 |
114 return 0; | |
115 } | |
116 | |
117 static const vo_info_t* get_info(void) | |
118 { | |
119 return &vo_info; | |
120 } | |
121 | |
122 static uint32_t draw_frame(uint8_t * src[]) | |
123 { | |
124 uint8_t *use_data; | |
125 ColorMapObject *Cmap; | |
126 uint8_t Colors[256 * 3]; | |
127 int z; | |
128 char CB[] = { (char)(gif_framedelay >> 8), (char)(gif_framedelay & 0xff), 0, 0}; | |
129 | |
130 if ((framenum++ % gif_frameskip)) return(0); | |
131 | |
132 Cmap = MakeMapObject(256, NULL); | |
133 use_data = (uint8_t *)malloc(image_width * image_height); | |
134 if (gif_reduce(image_width, image_height, src[0], use_data, Colors)) return(0); | |
135 | |
136 if (reverse_map) | |
137 { | |
138 for (z = 0; z < 256; z++) { | |
139 Cmap->Colors[z].Blue = Colors[(z * 3) + 0]; | |
140 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
141 Cmap->Colors[z].Red = Colors[(z * 3) + 2]; | |
142 } | |
143 } | |
144 else | |
145 { | |
146 for (z = 0; z < 256; z++) { | |
147 Cmap->Colors[z].Red = Colors[(z * 3) + 0]; | |
148 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
149 Cmap->Colors[z].Blue = Colors[(z * 3) + 2]; | |
150 } | |
151 } | |
152 | |
153 EGifPutExtension(newgif, 0xF9, 0x04, CB); | |
154 EGifPutImageDesc(newgif, 0, 0, image_width, image_height, 0, Cmap); | |
155 EGifPutLine(newgif, use_data, image_width * image_height); | |
156 FreeMapObject(Cmap); | |
157 free(use_data); | |
158 | |
159 return (0); | |
160 } | |
161 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
162 #ifdef USE_OSD |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
163 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
|
164 { |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
165 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
|
166 } |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
167 #endif |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
168 |
6053 | 169 static void draw_osd(void) |
170 { | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
171 #ifdef USE_OSD |
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
172 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
|
173 #endif |
6053 | 174 } |
175 | |
176 static void flip_page (void) | |
177 { | |
178 uint8_t *use_data; | |
179 ColorMapObject *Cmap; | |
180 uint8_t Colors[256 * 3]; | |
181 int z; | |
182 char CB[] = { (char)(gif_framedelay >> 8), (char)(gif_framedelay & 0xff), 0, 0}; | |
183 | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
184 if (image_format == IMGFMT_YV12) { |
6053 | 185 |
186 if ((framenum++ % gif_frameskip)) return; | |
187 | |
188 Cmap = MakeMapObject(256, NULL); | |
189 use_data = (uint8_t *)malloc(image_width * image_height); | |
190 if (gif_reduce(image_width, image_height, image_data, use_data, Colors)) return; | |
191 | |
192 if (reverse_map) | |
193 { | |
194 for (z = 0; z < 256; z++) { | |
195 Cmap->Colors[z].Blue = Colors[(z * 3) + 0]; | |
196 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
197 Cmap->Colors[z].Red = Colors[(z * 3) + 2]; | |
198 } | |
199 } | |
200 else | |
201 { | |
202 for (z = 0; z < 256; z++) { | |
203 Cmap->Colors[z].Red = Colors[(z * 3) + 0]; | |
204 Cmap->Colors[z].Green = Colors[(z * 3) + 1]; | |
205 Cmap->Colors[z].Blue = Colors[(z * 3) + 2]; | |
206 } | |
207 } | |
208 | |
209 EGifPutExtension(newgif, 0xF9, 0x04, CB); | |
210 EGifPutImageDesc(newgif, 0, 0, image_width, image_height, 0, Cmap); | |
211 EGifPutLine(newgif, use_data, image_width * image_height); | |
212 FreeMapObject(Cmap); | |
213 free(use_data); | |
214 } | |
215 } | |
216 | |
217 static uint32_t draw_slice( uint8_t *src[],int stride[],int w,int h,int x,int y ) | |
218 { | |
6078
4a9c7041141d
cleanups, removed swscaler, osd support - by Joey Parrish <joey@yunamusic.com>
arpi
parents:
6053
diff
changeset
|
219 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
|
220 yuv2rgb(dst,src[0],src[1],src[2],w,h,image_width*3,stride[0],stride[1]); |
6053 | 221 return 0; |
222 } | |
223 | |
224 static uint32_t | |
225 query_format(uint32_t format) | |
226 { | |
227 switch(format){ | |
228 case IMGFMT_YV12: | |
6211 | 229 return VFCAP_CSP_SUPPORTED | VFCAP_TIMER | VFCAP_ACCEPT_STRIDE; |
6053 | 230 case IMGFMT_RGB|24: |
231 case IMGFMT_BGR|24: | |
6211 | 232 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD | VFCAP_TIMER; |
6053 | 233 } |
234 return 0; | |
235 } | |
236 | |
237 static void | |
238 uninit(void) | |
239 { | |
240 char temp[256]; | |
241 | |
242 if (image_data) { free(image_data); image_data=NULL; } | |
243 | |
244 if (vo_config_count > 0) { | |
245 sprintf(temp, "gifwhore v%2.2f (c) %s\r\n", | |
246 GIFWHORE_version, "joey@yunamusic.com"); | |
247 EGifPutComment(newgif, temp); | |
248 EGifCloseFile(newgif); | |
249 } | |
250 } | |
251 | |
252 | |
253 static void check_events(void) | |
254 { | |
255 } | |
256 | |
257 int gif_reduce(int width, int height, | |
258 unsigned char *source, | |
259 unsigned char *destination, | |
260 unsigned char *palette) | |
261 { | |
262 GifColorType cmap[256]; | |
263 unsigned char Ra[width * height]; | |
264 unsigned char Ga[width * height]; | |
265 unsigned char Ba[width * height]; | |
266 unsigned char *R, *G, *B; | |
267 int Size = 256; | |
268 int i; | |
269 | |
270 R = Ra; G = Ga; B = Ba; | |
271 for (i = 0; i < width * height; i++) | |
272 { | |
273 *R++ = *source++; | |
274 *G++ = *source++; | |
275 *B++ = *source++; | |
276 } | |
277 | |
278 R = Ra; G = Ga; B = Ba; | |
279 if (QuantizeBuffer(width, height, &Size, | |
280 R, G, B, | |
281 destination, cmap) == GIF_ERROR) | |
282 { | |
283 fprintf(stderr, "vo_gif89a: Quantize failed!\n"); | |
284 return(-1); | |
285 } | |
286 | |
287 for (i = 0; i < Size; i++) | |
288 { | |
289 *palette++ = cmap[i].Red; | |
290 *palette++ = cmap[i].Green; | |
291 *palette++ = cmap[i].Blue; | |
292 } | |
293 | |
294 return(0); | |
295 } | |
296 | |
297 static uint32_t preinit(const char *arg) | |
298 { | |
299 int i = 0; | |
300 if (arg) i = atoi(arg); | |
301 if (i > vo_fps) i = vo_fps; | |
302 if (i < 1) i = 5; | |
303 target_fps = i; | |
304 return 0; | |
305 } | |
306 | |
307 static uint32_t control(uint32_t request, void *data, ...) | |
308 { | |
309 switch (request) { | |
310 case VOCTRL_QUERY_FORMAT: | |
311 return query_format(*((uint32_t*)data)); | |
312 } | |
313 return VO_NOTIMPL; | |
314 } | |
315 |