vo_gif89a.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 380 行

C
380
字号
/*   MPlayer video driver for animated gif output     (C) 2002      Written by Joey Parrish <joey@nicewarrior.org>   Based on vo_directfb2.c   This library 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 of the License, or (at your option) any later version.   This library 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 this library; 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 <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.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 6static vo_info_t info = {	"animated GIF output",	"gif89a",	"Joey Parrish joey@nicewarrior.org",	""};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 framesstatic float frame_cycle;// position in the framedrop cyclestatic int cycle_pos;// adjustment of the framedrop cyclestatic float frame_adj;// the output width and heightstatic uint32_t img_width;static uint32_t img_height;// image data for slice renderingstatic uint8_t *slice_data = NULL;// reduced image data for flip_pagestatic uint8_t *reduce_data = NULL;// reduced color map for flip_pagestatic ColorMapObject *reduce_cmap = NULL;// a pointer to the gif structurestatic GifFileType *new_gif = NULL;// a string to contain the filename of the output gifstatic char *gif_filename = NULL;// the default output filename#define DEFAULT_FILE "out.gif"static opt_t subopts[] = {  {"output",       OPT_ARG_MSTRZ, &gif_filename, NULL, 0},  {"fps",          OPT_ARG_FLOAT, &target_fps,   NULL, 0},  {NULL, 0, NULL, NULL, 0}};#undef memcpy#define memcpy uc_memcpystatic 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 HAVE_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 HAVE_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 HAVE_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() {}// 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	if (gif_filename != NULL) free(gif_filename);	if (slice_data != NULL) free(slice_data);	if (reduce_data != NULL) 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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?