summaryrefslogtreecommitdiffstats
path: root/libvo/vo_gif89a.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvo/vo_gif89a.c')
-rw-r--r--libvo/vo_gif89a.c376
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;
-}