Mercurial > mplayer.hg
comparison libvo/vo_gif89a.c @ 9540:ea4ca6a17d96
remove yuv2rgb and support frame duplication
author | joey |
---|---|
date | Thu, 06 Mar 2003 04:59:20 +0000 |
parents | 8b572238f63e |
children | e49a62a6e3cb |
comparison
equal
deleted
inserted
replaced
9539:1df740eaa156 | 9540:ea4ca6a17d96 |
---|---|
56 #include "video_out.h" | 56 #include "video_out.h" |
57 #include "video_out_internal.h" | 57 #include "video_out_internal.h" |
58 #include "../postproc/rgb2rgb.h" | 58 #include "../postproc/rgb2rgb.h" |
59 | 59 |
60 #define MPLAYER_VERSION 0.90 | 60 #define MPLAYER_VERSION 0.90 |
61 #define VO_GIF_REVISION 4 | 61 #define VO_GIF_REVISION 6 |
62 | 62 |
63 static vo_info_t info = { | 63 static vo_info_t info = { |
64 "animated GIF output", | 64 "animated GIF output", |
65 "gif89a", | 65 "gif89a", |
66 "Joey Parrish joey@nicewarrior.org", | 66 "Joey Parrish joey@nicewarrior.org", |
93 // the output width and height | 93 // the output width and height |
94 static uint32_t img_width; | 94 static uint32_t img_width; |
95 static uint32_t img_height; | 95 static uint32_t img_height; |
96 // image data for slice rendering | 96 // image data for slice rendering |
97 static uint8_t *slice_data = NULL; | 97 static uint8_t *slice_data = NULL; |
98 // pointer for whole frame rendering | |
99 static uint8_t *frame_data = NULL; | |
100 // reduced image data for flip_page | 98 // reduced image data for flip_page |
101 static uint8_t *reduce_data = NULL; | 99 static uint8_t *reduce_data = NULL; |
102 // reduced color map for flip_page | 100 // reduced color map for flip_page |
103 static ColorMapObject *reduce_cmap = NULL; | 101 static ColorMapObject *reduce_cmap = NULL; |
104 | 102 |
196 // reconfigure need not be a fatal error, so return 0. | 194 // reconfigure need not be a fatal error, so return 0. |
197 // multiple configs without uninit will result in two | 195 // multiple configs without uninit will result in two |
198 // movies concatenated in one gif file. the output | 196 // movies concatenated in one gif file. the output |
199 // gif will have the dimensions of the first movie. | 197 // gif will have the dimensions of the first movie. |
200 | 198 |
201 switch (format) { | 199 if (format != IMGFMT_RGB24) { |
202 case IMGFMT_RGB24: break; | 200 printf("GIF89a: Error - given unsupported colorspace.\n"); |
203 case IMGFMT_YV12: | 201 return 1; |
204 yuv2rgb_init(24, MODE_BGR); | 202 } |
205 slice_data = malloc(img_width * img_height * 3); | 203 |
206 if (slice_data == NULL) { | |
207 printf("GIF89a: malloc failed.\n"); | |
208 return 1; | |
209 } | |
210 break; | |
211 default: | |
212 printf("GIF89a: Error - given unsupported colorspace.\n"); | |
213 return 1; | |
214 } | |
215 | |
216 // the EGifSetGifVersion line causes segfaults in certain | 204 // the EGifSetGifVersion line causes segfaults in certain |
217 // earlier versions of libungif. i don't know exactly which, | 205 // earlier versions of libungif. i don't know exactly which, |
218 // but certainly in all those before v4. if you have problems, | 206 // but certainly in all those before v4. if you have problems, |
219 // you need to upgrade your gif library. | 207 // you need to upgrade your gif library. |
220 #ifdef HAVE_GIF_4 | 208 #ifdef HAVE_GIF_4 |
228 if (new_gif == NULL) { | 216 if (new_gif == NULL) { |
229 printf("GIF89a: error opening file \"%s\" for output.\n", gif_filename); | 217 printf("GIF89a: error opening file \"%s\" for output.\n", gif_filename); |
230 return 1; | 218 return 1; |
231 } | 219 } |
232 | 220 |
221 slice_data = malloc(img_width * img_height * 3); | |
222 if (slice_data == NULL) { | |
223 printf("GIF89a: malloc failed.\n"); | |
224 return 1; | |
225 } | |
226 | |
233 reduce_data = malloc(img_width * img_height); | 227 reduce_data = malloc(img_width * img_height); |
234 if (reduce_data == NULL) { | 228 if (reduce_data == NULL) { |
235 printf("GIF89a: malloc failed.\n"); | 229 printf("GIF89a: malloc failed.\n"); |
236 return 1; | 230 return 1; |
237 } | 231 } |
293 static void flip_page(void) | 287 static void flip_page(void) |
294 { | 288 { |
295 char CB[4]; // control block | 289 char CB[4]; // control block |
296 int delay = 0; | 290 int delay = 0; |
297 int ret; | 291 int ret; |
298 uint8_t *img_data; | |
299 | 292 |
300 cycle_pos++; | 293 cycle_pos++; |
301 if (cycle_pos < frame_cycle - frame_adj) | 294 if (cycle_pos < frame_cycle - frame_adj) |
302 return; // we are skipping this frame | 295 return; // we are skipping this frame |
303 | 296 |
304 // slice_data is used for per slice rendering, | |
305 // and frame_data is used for per frame rendering. | |
306 // i seperated these two because slice_data is | |
307 // ram i allocate, and frame_data is not. | |
308 // using one pointer for both can lead to | |
309 // either segfault (freeing ram that i'm not supposed | |
310 // to) or memory leaks (not freeing any ram at all) | |
311 if (slice_data != NULL) img_data = slice_data; | |
312 else img_data = frame_data; | |
313 | |
314 // quantize the image | 297 // quantize the image |
315 ret = gif_reduce(img_width, img_height, img_data, reduce_data, reduce_cmap->Colors); | 298 ret = gif_reduce(img_width, img_height, slice_data, reduce_data, reduce_cmap->Colors); |
316 if (ret == GIF_ERROR) { | 299 if (ret == GIF_ERROR) { |
317 printf("GIF89a: Quantize failed.\n"); | 300 printf("GIF89a: Quantize failed.\n"); |
318 return; | 301 return; |
319 } | 302 } |
320 | 303 |
340 EGifPutLine(new_gif, reduce_data, img_width * img_height); | 323 EGifPutLine(new_gif, reduce_data, img_width * img_height); |
341 } | 324 } |
342 | 325 |
343 static uint32_t draw_frame(uint8_t *src[]) | 326 static uint32_t draw_frame(uint8_t *src[]) |
344 { | 327 { |
345 frame_data = src[0]; | 328 return 1; |
329 } | |
330 | |
331 static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y) | |
332 { | |
333 uint8_t *dst, *frm; | |
334 int i; | |
335 dst = slice_data + (img_width * y + x) * 3; | |
336 frm = src[0]; | |
337 for (i = 0; i < h; i++) { | |
338 memcpy(dst, frm, w * 3); | |
339 dst += (img_width * 3); | |
340 frm += stride[0]; | |
341 } | |
346 return 0; | 342 return 0; |
347 } | 343 } |
348 | 344 |
349 static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y) | |
350 { | |
351 uint8_t *dst; | |
352 dst = slice_data + (img_width * y + x) * 3; | |
353 yuv2rgb(dst, src[0], src[1], src[2], w, h, img_width * 3, stride[0], stride[1]); | |
354 return 0; | |
355 } | |
356 | |
357 static uint32_t query_format(uint32_t format) | 345 static uint32_t query_format(uint32_t format) |
358 { | 346 { |
359 switch (format) { | 347 if (format == IMGFMT_RGB24) |
360 case IMGFMT_YV12: | 348 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_TIMER | VFCAP_ACCEPT_STRIDE; |
361 return VFCAP_CSP_SUPPORTED | VFCAP_TIMER | VFCAP_ACCEPT_STRIDE; | |
362 case IMGFMT_RGB24: | |
363 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_TIMER; | |
364 } | |
365 return 0; | 349 return 0; |
366 } | 350 } |
367 | 351 |
368 static uint32_t control(uint32_t request, void *data, ...) | 352 static uint32_t control(uint32_t request, void *data, ...) |
369 { | 353 { |
370 if (request == VOCTRL_QUERY_FORMAT) { | 354 if (request == VOCTRL_QUERY_FORMAT) { |
371 return query_format(*((uint32_t*)data)); | 355 return query_format(*((uint32_t*)data)); |
356 } | |
357 if (request == VOCTRL_DUPLICATE_FRAME) { | |
358 flip_page(); | |
359 return VO_TRUE; | |
372 } | 360 } |
373 return VO_NOTIMPL; | 361 return VO_NOTIMPL; |
374 } | 362 } |
375 | 363 |
376 static void uninit(void) | 364 static void uninit(void) |
395 if (reduce_cmap != NULL) FreeMapObject(reduce_cmap); | 383 if (reduce_cmap != NULL) FreeMapObject(reduce_cmap); |
396 | 384 |
397 // set the pointers back to null. | 385 // set the pointers back to null. |
398 new_gif = NULL; | 386 new_gif = NULL; |
399 gif_filename = NULL; | 387 gif_filename = NULL; |
400 frame_data = NULL; | |
401 slice_data = NULL; | 388 slice_data = NULL; |
402 reduce_data = NULL; | 389 reduce_data = NULL; |
403 reduce_cmap = NULL; | 390 reduce_cmap = NULL; |
404 } | 391 } |
405 | 392 |