diff options
Diffstat (limited to 'libvo/vo_gif89a.c')
-rw-r--r-- | libvo/vo_gif89a.c | 376 |
1 files changed, 0 insertions, 376 deletions
diff --git a/libvo/vo_gif89a.c b/libvo/vo_gif89a.c deleted file mode 100644 index b808f8182b..0000000000 --- a/libvo/vo_gif89a.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * MPlayer video driver for animated GIF output - * - * copyright (C) 2002 Joey Parrish <joey@nicewarrior.org> - * based on vo_directfb2.c - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* Notes: - * when setting output framerate, frames will be ignored as needed - * to achieve the desired rate. no frames will be duplicated. - * - * output framerate can be specified as a float - * value now, instead of just an int. - * - * adjustments will be made to both the frame drop cycle and the - * delay per frame to achieve the desired output framerate. - * - * time values are in centiseconds, because that's - * what the gif spec uses for it's delay values. - * - * preinit looks for arguments in one of the following formats (in this order): - * fps:filename -- sets the framerate (float) and output file - * fps -- sets the framerate (float), default file out.gif - * filename -- defaults to 5 fps, sets output file - * (none) -- defaults to 5 fps, output file out.gif - * - * trying to put the filename before the framerate will result in the - * entire argument being interpretted as the filename. - */ - -#include <gif_lib.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "config.h" -#include "subopt-helper.h" -#include "video_out.h" -#include "video_out_internal.h" -#include "mp_msg.h" - -#define MPLAYER_VERSION 0.90 -#define VO_GIF_REVISION 6 - -static const vo_info_t info = { - "animated GIF output", - "gif89a", - "Joey Parrish joey@nicewarrior.org", - "" -}; - -const LIBVO_EXTERN(gif89a) - - -// how many frames per second we are aiming for during output. -static float target_fps; -// default value for output fps. -static const float default_fps = 5.00; -// the ideal gif delay per frame. -static float ideal_delay; -// the ideal time thus far. -static float ideal_time; -// actual time thus far. -static int real_time; -// nominal framedrop cycle length in frames -static float frame_cycle; -// position in the framedrop cycle -static int cycle_pos; -// adjustment of the framedrop cycle -static float frame_adj; - -// the output width and height -static uint32_t img_width; -static uint32_t img_height; -// image data for slice rendering -static uint8_t *slice_data = NULL; -// reduced image data for flip_page -static uint8_t *reduce_data = NULL; -// reduced color map for flip_page -static ColorMapObject *reduce_cmap = NULL; - -// a pointer to the gif structure -static GifFileType *new_gif = NULL; -// a string to contain the filename of the output gif -static char *gif_filename = NULL; -// the default output filename -#define DEFAULT_FILE "out.gif" - -static const opt_t subopts[] = { - {"output", OPT_ARG_MSTRZ, &gif_filename, NULL}, - {"fps", OPT_ARG_FLOAT, &target_fps, NULL}, - {NULL, 0, NULL, NULL} -}; - -static int preinit(const char *arg) -{ - target_fps = 0; - - if (subopt_parse(arg, subopts) != 0) { - mp_msg(MSGT_VO, MSGL_FATAL, - "\n-vo gif89a command line help:\n" - "Example: mplayer -vo gif89a:output=file.gif:fps=4.9\n" - "\nOptions:\n" - " output=<filename>\n" - " Specify the output file. The default is out.gif.\n" - " fps=<rate>\n" - " Specify the target framerate. The default is 5.0.\n" - "\n"); - return -1; - } - - if (target_fps > vo_fps) - target_fps = vo_fps; // i will not duplicate frames. - - if (target_fps <= 0) { - target_fps = default_fps; - mp_msg(MSGT_VO, MSGL_V, "GIF89a: default, %.2f fps\n", target_fps); - } else { - mp_msg(MSGT_VO, MSGL_V, "GIF89a: output fps forced to %.2f\n", target_fps); - } - - ideal_delay = 100 / target_fps; // in centiseconds - frame_cycle = vo_fps / target_fps; - // we make one output frame every (frame_cycle) frames, on average. - - if (gif_filename == NULL) { - gif_filename = strdup(DEFAULT_FILE); - mp_msg(MSGT_VO, MSGL_V, "GIF89a: default, file \"%s\"\n", gif_filename); - } else { - mp_msg(MSGT_VO, MSGL_V, "GIF89a: file forced to \"%s\"\n", gif_filename); - } - - mp_msg(MSGT_VO, MSGL_DBG2, "GIF89a: Preinit OK\n"); - return 0; -} - -static int config(uint32_t s_width, uint32_t s_height, uint32_t d_width, - uint32_t d_height, uint32_t flags, char *title, - uint32_t format) -{ -#ifdef CONFIG_GIF_4 - // these are control blocks for the gif looping extension. - char LB1[] = "NETSCAPE2.0"; - char LB2[] = { 1, 0, 0 }; -#endif - - mp_msg(MSGT_VO, MSGL_DBG2, "GIF89a: Config entered [%dx%d]\n", s_width,s_height); - mp_msg(MSGT_VO, MSGL_DBG2, "GIF89a: With requested format: %s\n", vo_format_name(format)); - - // save these for later. - img_width = s_width; - img_height = s_height; - - // multiple configs without uninit are not allowed. - // this is because config opens a new gif file. - if (vo_config_count > 0) { - mp_msg(MSGT_VO, MSGL_V, "GIF89a: Reconfigure attempted.\n"); - return 0; - } - // reconfigure need not be a fatal error, so return 0. - // multiple configs without uninit will result in two - // movies concatenated in one gif file. the output - // gif will have the dimensions of the first movie. - - if (format != IMGFMT_RGB24) { - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: Error - given unsupported colorspace.\n"); - return 1; - } - - // the EGifSetGifVersion line causes segfaults in certain - // earlier versions of libungif. i don't know exactly which, - // but certainly in all those before v4. if you have problems, - // you need to upgrade your gif library. -#ifdef CONFIG_GIF_4 - EGifSetGifVersion("89a"); -#else - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: Your version of libungif needs to be upgraded.\n"); - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: Some functionality has been disabled.\n"); -#endif - - new_gif = EGifOpenFileName(gif_filename, 0); - if (new_gif == NULL) { - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: error opening file \"%s\" for output.\n", gif_filename); - return 1; - } - - slice_data = malloc(img_width * img_height * 3); - if (slice_data == NULL) { - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: malloc failed.\n"); - return 1; - } - - reduce_data = malloc(img_width * img_height); - if (reduce_data == NULL) { - free(slice_data); slice_data = NULL; - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: malloc failed.\n"); - return 1; - } - - reduce_cmap = MakeMapObject(256, NULL); - if (reduce_cmap == NULL) { - free(slice_data); slice_data = NULL; - free(reduce_data); reduce_data = NULL; - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: malloc failed.\n"); - return 1; - } - - // initialize the delay and framedrop variables. - ideal_time = 0; - real_time = 0; - cycle_pos = 0; - frame_adj = 0; - - // set the initial width and height info. - EGifPutScreenDesc(new_gif, s_width, s_height, 256, 0, reduce_cmap); -#ifdef CONFIG_GIF_4 - // version 3 of libungif does not support multiple control blocks. - // looping requires multiple control blocks. - // therefore, looping is only enabled for v4 and up. - EGifPutExtensionFirst(new_gif, 0xFF, 11, LB1); - EGifPutExtensionLast(new_gif, 0, 3, LB2); -#endif - - mp_msg(MSGT_VO, MSGL_DBG2, "GIF89a: Config finished.\n"); - return 0; -} - -// we do not draw osd. -void draw_osd(void) {} - -// we do not handle events. -static void check_events(void) {} - -static int gif_reduce(int width, int height, uint8_t *src, uint8_t *dst, GifColorType *colors) -{ - unsigned char Ra[width * height]; - unsigned char Ga[width * height]; - unsigned char Ba[width * height]; - unsigned char *R, *G, *B; - int size = 256; - int i; - - R = Ra; G = Ga; B = Ba; - for (i = 0; i < width * height; i++) - { - *R++ = *src++; - *G++ = *src++; - *B++ = *src++; - } - - R = Ra; G = Ga; B = Ba; - return QuantizeBuffer(width, height, &size, R, G, B, dst, colors); -} - -static void flip_page(void) -{ - char CB[4]; // control block - int delay = 0; - int ret; - - cycle_pos++; - if (cycle_pos < frame_cycle - frame_adj) - return; // we are skipping this frame - - // quantize the image - ret = gif_reduce(img_width, img_height, slice_data, reduce_data, reduce_cmap->Colors); - if (ret == GIF_ERROR) { - mp_msg(MSGT_VO, MSGL_ERR, "GIF89a: Quantize failed.\n"); - return; - } - - // calculate frame delays and frame skipping - ideal_time += ideal_delay; - delay = (int)(ideal_time - real_time); - real_time += delay; - frame_adj += cycle_pos; - frame_adj -= frame_cycle; - cycle_pos = 0; - - // set up the delay control block - CB[0] = (char)(delay >> 8); - CB[1] = (char)(delay & 0xff); - CB[2] = 0; - CB[3] = 0; - - // put the control block with delay info - EGifPutExtension(new_gif, 0xF9, 0x04, CB); - // put the image description - EGifPutImageDesc(new_gif, 0, 0, img_width, img_height, 0, reduce_cmap); - // put the image itself - EGifPutLine(new_gif, reduce_data, img_width * img_height); -} - -static int draw_frame(uint8_t *src[]) -{ - return 1; -} - -static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y) -{ - uint8_t *dst, *frm; - int i; - dst = slice_data + (img_width * y + x) * 3; - frm = src[0]; - for (i = 0; i < h; i++) { - memcpy(dst, frm, w * 3); - dst += (img_width * 3); - frm += stride[0]; - } - return 0; -} - -static int query_format(uint32_t format) -{ - if (format == IMGFMT_RGB24) - return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_TIMER | VFCAP_ACCEPT_STRIDE; - return 0; -} - -static int control(uint32_t request, void *data) -{ - if (request == VOCTRL_QUERY_FORMAT) { - return query_format(*((uint32_t*)data)); - } - if (request == VOCTRL_DUPLICATE_FRAME) { - flip_page(); - return VO_TRUE; - } - return VO_NOTIMPL; -} - -static void uninit(void) -{ - mp_msg(MSGT_VO, MSGL_DBG2, "GIF89a: Uninit entered\n"); - - if (new_gif != NULL) { - char temp[256]; - // comment the gif and close it - snprintf(temp, 256, "MPlayer gif output v%2.2f-%d (c) %s\r\n", - MPLAYER_VERSION, VO_GIF_REVISION, - "joey@nicewarrior.org"); - EGifPutComment(new_gif, temp); - EGifCloseFile(new_gif); // also frees gif storage space. - } - - // free our allocated ram - free(gif_filename); - free(slice_data); - free(reduce_data); - if (reduce_cmap != NULL) FreeMapObject(reduce_cmap); - - // set the pointers back to null. - new_gif = NULL; - gif_filename = NULL; - slice_data = NULL; - reduce_data = NULL; - reduce_cmap = NULL; -} |