⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swf_play.c

📁 Flush解码源程序
💻 C
字号:
#include <swfdec.h>#include <gtk/gtk.h>#include <gdk/gdk.h>#include <gdk/gdkx.h>#include <glib.h>#include <getopt.h>#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>#include <sys/wait.h>#include <sys/time.h>#include <time.h>#include <string.h>#include <SDL.h>struct sound_buffer_struct{	int len;	int offset;	void *data;};typedef struct sound_buffer_struct SoundBuffer;gboolean debug = FALSE;SwfdecDecoder *s;unsigned char *image;GtkWidget *drawing_area;GtkWidget *gtk_wind;int plugged;GdkWindow *gdk_parent;GIOChannel *input_chan;guint input_idle_id;guint render_idle_id;unsigned long xid;int width;int height;int fast = FALSE;int enable_sound = TRUE;int quit_at_eof = FALSE;int interval;struct timeval image_time;static void do_help(void);static void read_swf_file(char *fn);static void read_swf_stdin(void);static void new_gtk_window(void);static void sound_setup(void);/* GTK callbacks */static void destroy_cb (GtkWidget *widget, gpointer data);static int expose_cb (GtkWidget *widget, GdkEventExpose *evt, gpointer data);static int key_press (GtkWidget *widget, GdkEventKey *evt, gpointer data);static int motion_notify (GtkWidget *widget, GdkEventMotion *evt, gpointer data);static void embedded (GtkPlug *plug, gpointer data);static int configure_cb (GtkWidget *widget, GdkEventConfigure *evt, gpointer data);/* GIOChan callbacks */static gboolean input(GIOChannel *chan, GIOCondition cond, gpointer ignored);static gboolean render_idle(gpointer data);/* fault handling stuff */void fault_handler(int signum, siginfo_t *si, void *misc);void fault_restore(void);void fault_setup(void);int main(int argc, char *argv[]){	int c;	int index;	static struct option options[] = {		{ "xid", 1, NULL, 'x' },		{ "width", 1, NULL, 'w' },		{ "height", 1, NULL, 'h' },		{ "fast", 0, NULL, 'f' },		{ "no-sound", 0, NULL, 's' },		{ "quit", 0, NULL, 'q' },		{ 0 },	};	//fault_setup();	gtk_init(&argc,&argv);	gdk_rgb_init ();	gtk_widget_set_default_colormap(gdk_rgb_get_cmap());	gtk_widget_set_default_visual(gdk_rgb_get_visual());	s = swfdec_decoder_new();	while(1){		c = getopt_long(argc, argv, "qsfx:w:h:", options, &index);		if(c==-1)break;		switch(c){		case 'x':			xid = strtoul(optarg, NULL, 0);			break;		case 'w':			width = strtoul(optarg, NULL, 0);			printf("width set to %d\n",width);			break;		case 'h':			height = strtoul(optarg, NULL, 0);			printf("height set to %d\n",height);			break;		case 'f':			fast = TRUE;			break;		case 's':			enable_sound = FALSE;			break;		case 'q':			quit_at_eof = TRUE;			break;		default:			do_help();			break;		}	}	if(optind != argc-1)do_help();	if(width){		swfdec_decoder_set_image_size(s,width,height);	}	if(strcmp(argv[optind],"-")==0){		read_swf_stdin();	}else{		read_swf_file(argv[optind]);	}	if(xid){		plugged = 1;	}	new_gtk_window();	if(enable_sound)sound_setup();	gtk_main();	exit(0);}static void do_help(void){	fprintf(stderr,"swf_play [--xid NNN] file.swf\n");	exit(1);}static void new_gtk_window(void){	if(plugged){		gtk_wind = gtk_plug_new(0);		gtk_signal_connect(GTK_OBJECT(gtk_wind), "embedded",			GTK_SIGNAL_FUNC(embedded), NULL);		gdk_parent = gdk_window_foreign_new(xid);		gdk_window_get_geometry(gdk_parent, NULL, NULL, &width, &height, NULL);		printf("width=%d height=%d\n",width,height);	}else{		gtk_wind = gtk_window_new(GTK_WINDOW_TOPLEVEL);	}	gtk_window_set_default_size(GTK_WINDOW(gtk_wind), width, height);	gtk_signal_connect(GTK_OBJECT(gtk_wind), "delete_event",		GTK_SIGNAL_FUNC (destroy_cb), NULL);	gtk_signal_connect(GTK_OBJECT(gtk_wind), "destroy",		GTK_SIGNAL_FUNC(destroy_cb), NULL);	drawing_area = gtk_drawing_area_new();	gtk_container_add(GTK_CONTAINER(gtk_wind),		GTK_WIDGET(drawing_area));	g_signal_connect(G_OBJECT(drawing_area), "expose_event",		GTK_SIGNAL_FUNC(expose_cb), NULL);	g_signal_connect (G_OBJECT (drawing_area), "configure_event",		GTK_SIGNAL_FUNC(configure_cb), NULL);	g_signal_connect (G_OBJECT(gtk_wind), "key_press_event",		GTK_SIGNAL_FUNC(key_press), NULL);	g_signal_connect (G_OBJECT(gtk_wind), "motion_notify_event",		GTK_SIGNAL_FUNC(motion_notify), NULL);	gtk_widget_add_events(gtk_wind, GDK_POINTER_MOTION_MASK);	gtk_widget_show_all(gtk_wind);	if(plugged){		XReparentWindow(GDK_WINDOW_XDISPLAY(gtk_wind->window),			GDK_WINDOW_XID(gtk_wind->window),			xid, 0, 0);		XMapWindow(GDK_WINDOW_XDISPLAY(gtk_wind->window),			GDK_WINDOW_XID(gtk_wind->window));	}}static void read_swf_file(char *fn){	struct stat sb;	int fd;	int ret;	unsigned char *data;	int len;	fd = open(fn,O_RDONLY);	if(fd<0){		perror(fn);		exit(1);	}	ret = fstat(fd, &sb);	if(ret<0){		perror("stat");		exit(1);	}	len = sb.st_size;	data = malloc(len);	ret = read(fd, data, len);	if(ret<0){		perror("read");		exit(1);	}	ret = swfdec_decoder_addbits(s,data,len);	free(data);	if(!render_idle_id)render_idle_id = g_idle_add(render_idle,NULL);}static void read_swf_stdin(void){	GError *error = NULL;	input_chan = g_io_channel_unix_new(0);	g_io_channel_set_encoding(input_chan, NULL, &error);	g_io_channel_set_flags(input_chan, G_IO_FLAG_NONBLOCK, &error);	input_idle_id = g_io_add_watch(input_chan, G_IO_IN, input, NULL);}GList *sound_buffers;int sound_bytes;unsigned char *sound_buf;static void fill_audio(void *udata, Uint8 *stream, int len){	GList *g;	SoundBuffer *buffer;	int n;	int offset = 0;	while(1){		g = g_list_first(sound_buffers);		if(!g)break;		buffer = (SoundBuffer *)g->data;		n = MIN(buffer->len - buffer->offset,len - offset);		memcpy(sound_buf + offset, buffer->data + buffer->offset, n);		sound_bytes -= n;		buffer->offset += n;		offset += n;		if(buffer->offset >= buffer->len){			sound_buffers = g_list_delete_link(sound_buffers,g);			free(buffer->data);			free(buffer);		}		if(offset >= len)break;	}	if(offset<len){		memset(sound_buf+offset,0,len-offset);	}	SDL_MixAudio(stream, sound_buf, len, SDL_MIX_MAXVOLUME);}static void pull_sound(SwfdecDecoder *s){	SoundBuffer *sb;	void *data;	int n;	while(1){		data = swfdec_decoder_get_sound_chunk(s, &n);		if(!data)return;		if(enable_sound){			sb = g_new(SoundBuffer,1);			sb->len = n;			sb->offset = 0;			sb->data = data;			sound_buffers = g_list_append(sound_buffers, sb);			sound_bytes += n;		}else{			g_free(data);		}	}}static void sound_setup(void){	SDL_AudioSpec wanted;	wanted.freq = 44100;#if G_BYTE_ORDER == 4321	wanted.format = AUDIO_S16MSB;#else	wanted.format = AUDIO_S16LSB;#endif	wanted.channels = 2;    /* 1 = mono, 2 = stereo */	wanted.samples = 1024;  /* Good low-latency value for callback */	wanted.callback = fill_audio;	wanted.userdata = NULL;	sound_buf = malloc(1024*2*2);	if ( SDL_OpenAudio(&wanted, NULL) < 0 ) {		fprintf(stderr, "Couldn't open audio: %s, disabling\n", SDL_GetError());		enable_sound = FALSE;	}	SDL_PauseAudio(0);}/* GTK callbacks */static int key_press (GtkWidget *widget, GdkEventKey *evt, gpointer data){	if(debug)fprintf(stderr,"key press\n");		return FALSE;}static int motion_notify (GtkWidget *widget, GdkEventMotion *evt, gpointer data){	if(debug)fprintf(stderr,"motion notify\n");		return FALSE;}static int configure_cb (GtkWidget *widget, GdkEventConfigure *evt, gpointer data){	return FALSE;}static int expose_cb (GtkWidget *widget, GdkEventExpose *evt, gpointer data){	if(image){		gdk_draw_rgb_image (widget->window, widget->style->black_gc, 			0, 0, width, height, 			GDK_RGB_DITHER_NONE,			image,			width*3);	}	return FALSE;}static void destroy_cb (GtkWidget *widget, gpointer data){	gtk_main_quit ();}static void embedded (GtkPlug *plug, gpointer data){}/* idle stuff */static gboolean input(GIOChannel *chan, GIOCondition cond, gpointer ignored){	char *data;	int bytes_read;	GError *error = NULL;	int ret;	data = malloc(4096);	ret = g_io_channel_read_chars(chan, data, 4096, &bytes_read, &error);	if(ret==G_IO_STATUS_NORMAL){		ret = swfdec_decoder_addbits(s,data,bytes_read);		if(!render_idle_id)render_idle_id = g_idle_add(render_idle,NULL);	}else if(ret==G_IO_STATUS_ERROR){		exit(1);	}else if(ret==G_IO_STATUS_EOF){		gtk_idle_remove(input_idle_id);		if(!render_idle_id)render_idle_id = g_idle_add(render_idle,NULL);	}	free(data);	return TRUE;}static void tv_add_usec(struct timeval *a, unsigned int x){	a->tv_usec += x;	while(a->tv_usec >= 1000000){		a->tv_sec++;		a->tv_usec-=1000000;	}}static int tv_compare(struct timeval *a,struct timeval *b){	if(a->tv_sec > b->tv_sec)return 1;	if(a->tv_sec == b->tv_sec){		if(a->tv_usec > b->tv_usec)return 1;		if(a->tv_usec == b->tv_usec)return 0;	}	return -1;}static int tv_diff(struct timeval *a,struct timeval *b){	int diff;	diff = (a->tv_sec - b->tv_sec)*1000000;	diff += (a->tv_usec - b->tv_usec);	return diff;}static gboolean render_idle(gpointer data){	int ret;	static int ack = 0;	ack++;	if(ack>=1)ack=0;	/* disabled temporarily */#if 0	if(ack==0){		swfdec_decoder_enable_render(s);	}else{		swfdec_decoder_disable_render(s);	}#endif	ret = swfdec_decoder_parse(s);	if(ret==SWF_NEEDBITS){		gtk_idle_remove(render_idle_id);		render_idle_id = 0;	}	if(ret==SWF_EOF){		swfdec_decoder_get_image(s,&image);		swfdec_decoder_free(s);		s = NULL;		if(quit_at_eof){			if(image) g_free(image);			gtk_exit(0);		}		gtk_idle_remove(render_idle_id);		render_idle_id = 0;	}	if(ret==SWF_IMAGE){		struct timeval now;		swfdec_decoder_peek_image(s,&image);		pull_sound(s);		if(!enable_sound){			gettimeofday(&now, NULL);			tv_add_usec(&image_time, interval);			if(tv_compare(&image_time, &now) > 0){				int x = tv_diff(&image_time, &now);				//printf("sleeping for %d us\n",x);				if(!fast)usleep(x);			}else{				gettimeofday(&image_time, NULL);			}		}else{			while(sound_bytes>=10000){				usleep(10000);			}		}		gdk_draw_rgb_image (drawing_area->window,			drawing_area->style->black_gc, 			0, 0, width, height, 			GDK_RGB_DITHER_NONE,			image,			width*3);	}	if(ret==SWF_CHANGE && !plugged){		double rate;		swfdec_decoder_get_rate(s, &rate);		interval = 1000000/rate;		swfdec_decoder_get_image_size(s, &width, &height);		gtk_window_resize(GTK_WINDOW(gtk_wind),			width, height);	}	return TRUE;}extern volatile gboolean glib_on_error_halt;void fault_handler(int signum, siginfo_t *si, void *misc){	//int spinning = TRUE;	fault_restore();	if(si->si_signo == SIGSEGV){		g_print ("Caught SIGSEGV accessing address %p\n", si->si_addr);	}else if(si->si_signo == SIGQUIT){		g_print ("Caught SIGQUIT\n");	}else{		g_print ("signo:  %d\n",si->si_signo);		g_print ("errno:  %d\n",si->si_errno);		g_print ("code:   %d\n",si->si_code);	}	glib_on_error_halt = FALSE;	g_on_error_stack_trace("swf_play");	wait(NULL);	_exit(0);}void fault_restore(void){	struct sigaction action;	memset(&action,0,sizeof(action));	action.sa_handler = SIG_DFL;	sigaction(SIGSEGV, &action, NULL);	sigaction(SIGQUIT, &action, NULL);}void fault_setup(void){	struct sigaction action;	memset(&action,0,sizeof(action));	action.sa_sigaction = fault_handler;	action.sa_flags = SA_SIGINFO;	sigaction(SIGSEGV, &action, NULL);	sigaction(SIGQUIT, &action, NULL);}

⌨️ 快捷键说明

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