swfdec使用x11和sdl输出,上次改用framebuffer和oss输出,这样简单,这次来整理下
/*ao_oss.h*/
#ifndef _AO_OSS_H_
#define _AO_OSS_H_
#include
#include
typedef struct audio_dev_t{
long samplerate;
long channels;
long format;
int fd;
char dev_name[16];
}AUDIO_DEV,*PAUDIO_DEV;
int open_audio(PAUDIO_DEV paudio_dev);
int close_audio(PAUDIO_DEV paudio_dev);
#endif
/*ao_oss.c*/
#include
#include
#include
#include
#include
#include
#include "ao_oss.h"
#define PATH_DEV_DSP "/dev/dsp"
int open_audio(PAUDIO_DEV paudio_dev)
{
int result;
if ( ( paudio_dev->fd = open ( paudio_dev->dev_name, O_RDWR ) ) < 0 ) {
fprintf (stderr, " Can't open sound device!\n");
return -1;
}
result = ioctl (paudio_dev->fd, SNDCTL_DSP_SPEED, &(paudio_dev->samplerate));
if ( result == -1 ) {
perror("ioctl sample format");
return -1;
}
result = ioctl (paudio_dev->fd, SNDCTL_DSP_CHANNELS, &(paudio_dev->channels));
if ( result == -1 ) {
perror("ioctl sample format");
return -1;
}
//format = AFMT_S16_BE;
//format = AFMT_S16_LE;
result = ioctl(paudio_dev->fd, SNDCTL_DSP_SETFMT, &(paudio_dev->format));
if ( result == -1 ) {
perror("ioctl sample format");
return -1;
}
fprintf (stderr, "setup audio args,speed:%ld, channels:%ld, format:%ld\n",paudio_dev->samplerate,paudio_dev->channels,paudio_dev->format);
return 0;
}
int close_audio(PAUDIO_DEV paudio_dev)
{
close(paudio_dev->fd);
}
/*vo_fbdev.h*/
#ifndef _VO_FBDEV_H_
#define _VO_FBDEV_H_
#include
typedef struct fbdev{
int fb;
unsigned long fb_mem_offset;
unsigned long fb_mem;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char dev[20];
} FBDEV, *PFBDEV;
int fb_open(PFBDEV pFbdev);
int fb_close(PFBDEV pFbdev);
int get_display_depth(PFBDEV pFbdev);
void fb_memset(void *addr, int c, size_t len);
#endif
/*vo_fbdev.c*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "vo_fbdev.h"
#define TRUE 1
#define FALSE 0
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
int fb_open(PFBDEV pFbdev)
{
pFbdev->fb = open(pFbdev->dev, O_RDWR);
if(pFbdev->fb < 0)
{
printf("Error opening %s: %m. Check kernel config\n", pFbdev->dev);
return FALSE;
}
if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
{
printf("ioctl FBIOGET_VSCREENINFO\n");
return FALSE;
}
if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
{
printf("ioctl FBIOGET_FSCREENINFO\n");
return FALSE;
}
pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len + pFbdev->fb_mem_offset, PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);
printf("---screen width:%d,screen height:%d,depth:%d-----\n",pFbdev->fb_var.xres, pFbdev->fb_var.yres, pFbdev->fb_var.bits_per_pixel);
if (-1L == (long) pFbdev->fb_mem)
{
printf("mmap error! mem:%d offset:%d\n", pFbdev->fb_mem, pFbdev->fb_mem_offset);
return FALSE;
}
return TRUE;
}
int fb_close(PFBDEV pFbdev)
{
close(pFbdev->fb);
pFbdev->fb=-1;
}
int get_display_depth(PFBDEV pFbdev)
{
if(pFbdev->fb<=0)
{
printf("fb device not open, open it first\n");
return FALSE;
}
return pFbdev->fb_var.bits_per_pixel;
}
void fb_memset (void *addr, int c, size_t len)
{
memset(addr, c, len);
}
#if 0
int main()
{
FBDEV fbdev;
memset(&fbdev, 0, sizeof(FBDEV));
strcpy(fbdev.dev, "/dev/fb0");
if(fb_open(&fbdev)==FALSE)
{
printf("open frame. buffer error\n");
return;
}
fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 1, fbdev.fb_fix.smem_len);
fb_close(&fbdev);
return 0;
}
#endif
/*swf_play.c*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
//#include
#include "spp.h"
#include "vo_fbdev.h"
#include "ao_oss.h"
//#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
#define DEBUG(...)
#define ENABLE_AUDIO 1
typedef struct _Packet Packet;
struct _Packet
{
int code;
int length;
void *data;
};
static Packet *packet_get (int fd);
static void packet_free (Packet * packet);
static void packet_write (int fd, int code, int len, const char *s);
static gboolean render_idle_audio (gpointer data);
static gboolean render_idle_noaudio (gpointer data);
static void do_help (void);
static void do_safe (int standalone);
//static void new_window (void);
static void sound_setup (void);
/* vars */
static gboolean go = TRUE;
static int render_time;
static SwfdecDecoder *s;
//static SDL_Surface *sdl_screen;
static int width;
static int height;
static gboolean enable_sound = TRUE;
static gboolean noskip = FALSE;
static gboolean slow = FALSE;
static gboolean safe = FALSE;
static gboolean hidden = FALSE;
//static unsigned long xid;
static double rate;
static int interval;
static GList *sound_buffers;
static int sound_bytes;
static unsigned char *sound_buf;
static FBDEV fbdev;
static AUDIO_DEV audiodev;
int
main (int argc, char *argv[])
{
int c;
int index;
static struct option options[] = {
{"help", 0, NULL, 'h'},
{"xid", 1, NULL, 'x'},
{"no-sound", 0, NULL, 's'},
{"plugin", 0, NULL, 'p'},
{"slow", 0, NULL, 'o'},
{"safe", 0, NULL, 'f'},
{0},
};
int ret;
int standalone = TRUE;
int rendering = FALSE;
int starting = FALSE;
Packet *packet;
int fd = 0;
int send_fd = 1;
DEBUG ("swf_play: starting player\n");
while (1) {
c = getopt_long (argc, argv, "sx:p", options, &index);
if (c == -1)
break;
switch (c) {
case 's':
enable_sound = FALSE;
break;
case 'x':
//setenv ("SDL_WINDOWID", optarg, 1);
//xid = strtol (optarg, NULL, 0);
break;
case 'p':
standalone = FALSE;
break;
case 'o':
slow = TRUE;
break;
case 'f':
safe = TRUE;
break;
case 'h':
default:
do_help ();
break;
}
}
if (standalone) {
if (optind != argc - 1)
do_help ();
} else {
if (optind != argc)
do_help ();
}
// SDL_Init (SDL_INIT_NOPARACHUTE | SDL_INIT_AUDIO | SDL_INIT_VIDEO |
// SDL_INIT_TIMER);
/* SDL thinks it's smart by overriding SIGINT. It's not */
signal (SIGINT, SIG_DFL);
// SDL_EventState (SDL_ACTIVEEVENT, SDL_ENABLE);
// if (safe) {
// do_safe(standalone);
// }
s = swfdec_decoder_new ();
if (standalone) {
char *contents;
gsize length;
ret = g_file_get_contents (argv[optind], &contents, &length, NULL);
if (!ret) {
DEBUG ("error reading file\n");
exit (1);
}
swfdec_decoder_add_data (s, contents, length);
swfdec_decoder_eof (s);
ret = swfdec_decoder_parse (s);
if (ret == SWF_ERROR) {
DEBUG ("error while parsing\n");
exit (1);
}
starting = TRUE;
}
while (1) {
// SDL_Event event;
int did_something = FALSE;
if (!standalone) {
packet = packet_get (fd);
if (packet) {
switch (packet->code) {
case SPP_EXIT:
exit (0);
break;
case SPP_DATA:
swfdec_decoder_add_data (s, packet->data, packet->length);
packet->data = NULL;
break;
case SPP_EOF:
swfdec_decoder_eof (s);
starting = TRUE;
break;
case SPP_SIZE:
width = ((int *) packet->data)[0];
height = ((int *) packet->data)[1];
swfdec_decoder_set_image_size (s, width, height);
// new_window ();
break;
default:
/* ignore it */
break;
}
packet_free (packet);
did_something = TRUE;
}
}
#if 0
//if (standalone) {
if (SDL_PollEvent (&event)) {
did_something = TRUE;
DEBUG ("event %d\n", event.type);
switch (event.type) {
case SDL_VIDEORESIZE:
width = event.resize.w;
height = event.resize.h;
swfdec_decoder_set_image_size (s, width, height);
new_window ();
break;
case SDL_MOUSEMOTION:
swfdec_decoder_set_mouse (s, event.motion.x, event.motion.y,
event.motion.state);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
swfdec_decoder_set_mouse (s, event.button.x, event.button.y,
event.button.state);
break;
case SDL_ACTIVEEVENT:
if (event.active.state & SDL_APPMOUSEFOCUS) {
if (event.active.gain == 0) {
swfdec_decoder_set_mouse (s, -1, -1, 0);
}
}
if (event.active.state & SDL_APPACTIVE) {
hidden = !event.active.gain;
}
break;
default:
break;
}
}
//}
#endif
if (starting) {
ret = swfdec_decoder_parse (s);
DEBUG ("parse ret = %d\n", ret);
ret = swfdec_decoder_parse (s);
DEBUG ("parse ret = %d\n", ret);
ret = swfdec_decoder_parse (s);
DEBUG ("parse ret = %d\n", ret);
ret = swfdec_decoder_parse (s);
DEBUG ("parse ret = %d\n", ret);
swfdec_decoder_get_rate (s, &rate);
interval = 1000.0 / rate;
swfdec_decoder_get_image_size (s, &width, &height);
DEBUG ("size %dx%d\n", width, height);
// new_window ();
memset(&fbdev, 0, sizeof(FBDEV));
strcpy(fbdev.dev, "/dev/fb0");
if(fb_open(&fbdev)==FALSE)
{
printf("open frame. buffer error\n");
return;
}
fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 1, fbdev.fb_fix.smem_len);
#ifdef ENABLE_AUDIO
if (enable_sound)
sound_setup ();
#endif
render_time = 0;
starting = FALSE;
rendering = TRUE;
did_something = TRUE;
}
if (rendering) {
//int now = SDL_GetTicks ();
struct timeval tv;
int now;
gettimeofday(&tv, NULL);
now = tv.tv_sec*1000+tv.tv_usec/1000;
if (now >= render_time) {
char *url;
#ifdef ENABLE_AUDIO
if (enable_sound) {
render_idle_audio (NULL);
} else
#endif
{
render_idle_noaudio (NULL);
}
did_something = TRUE;
url = swfdec_decoder_get_url (s);
if (url) {
DEBUG ("sending URL packet\n");
packet_write (send_fd, SPP_GO_TO_URL, strlen(url), url);
g_free (url);
}
}
}
if (!did_something) {
usleep (10000);
}
}
exit (0);
}
static void
do_help (void)
{
g_print ("swf_play [--xid|-x XID] [--no-sound|-s] [--slow] file.swf\n");
g_print ("swf_play [--xid|-x XID] [--no-sound|-s] [--slow] [--plugin|-p]\n");
g_print ("swf_play [--help]\n");
exit (1);
}
#if 0
static void
do_safe (int standalone)
{
Packet *packet;
int fd = 0;
width = 100;
height = 100;
new_window ();
SDL_FillRect (sdl_screen, NULL, 0x80808000);
SDL_UpdateRect (sdl_screen, 0, 0, width, height);
while (1) {
int did_something = FALSE;
SDL_Event event;
if (!standalone) {
packet = packet_get (fd);
if (packet) {
switch (packet->code) {
case SPP_EXIT:
exit (0);
break;
case SPP_DATA:
swfdec_decoder_add_data (s, packet->data, packet->length);
packet->data = NULL;
break;
case SPP_EOF:
swfdec_decoder_eof (s);
//starting = TRUE;
break;
case SPP_SIZE:
width = ((int *) packet->data)[0];
height = ((int *) packet->data)[1];
new_window ();
SDL_FillRect (sdl_screen, NULL, 0x80808000);
SDL_UpdateRect (sdl_screen, 0, 0, width, height);
break;
default:
/* ignore it */
break;
}
packet_free (packet);
did_something = TRUE;
}
}
if (SDL_PollEvent (&event)) {
did_something = TRUE;
switch (event.type) {
case SDL_VIDEORESIZE:
width = event.resize.w;
height = event.resize.h;
new_window ();
SDL_FillRect (sdl_screen, NULL, 0x80808000);
SDL_UpdateRect (sdl_screen, 0, 0, width, height);
break;
case SDL_MOUSEMOTION:
swfdec_decoder_set_mouse (s, event.motion.x, event.motion.y,
event.motion.state);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
swfdec_decoder_set_mouse (s, event.button.x, event.button.y,
event.button.state);
break;
default:
break;
}
}
if (!did_something) {
usleep (10000);
}
}
}
#endif
#if 0
static void
new_window (void)
{
sdl_screen = SDL_SetVideoMode (width, height, 32, SDL_SWSURFACE|SDL_RESIZABLE);
if (sdl_screen == NULL) {
DEBUG ("SDL_SetVideoMode failed\n");
}
}
#endif
#ifdef ENABLE_AUDIO
/*static void
fill_audio (void *udata, Uint8 * stream, int len)
{
GList *g;
SwfdecBuffer *buffer;
int n;
int offset = 0;
while (1) {
g = g_list_first (sound_buffers);
if (!g)
break;
buffer = (SwfdecBuffer *) g->data;
if (buffer->length < len - offset) {
n = buffer->length;
memcpy (sound_buf + offset, buffer->data, n);
swfdec_buffer_unref (buffer);
sound_buffers = g_list_delete_link (sound_buffers, g);
} else {
SwfdecBuffer *subbuffer;
n = len - offset;
memcpy (sound_buf + offset, buffer->data, n);
subbuffer = swfdec_buffer_new_subbuffer (buffer, n, buffer->length - n);
g->data = subbuffer;
swfdec_buffer_unref (buffer);
}
sound_bytes -= n;
offset += n;
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
sound_setup (void)
{
strcpy(audiodev.dev_name, "/dev/dsp");
if (slow) {
audiodev.samplerate = 22050;
}else{
audiodev.samplerate = 44100;
}
#if G_BYTE_ORDER == 4321
audiodev.format = AFMT_S16_BE;
#else
audiodev.format = AFMT_S16_LE;
#endif
audiodev.channels = 2;
//wanted.samples = 1024;
//wanted.callback = fill_audio;
//wanted.userdata = NULL;
//sound_buf = malloc (1024 * 2 * 2);
if (open_audio (&audiodev) < 0) {
DEBUG ("Couldn't open audio, disabling\n");
enable_sound = FALSE;
}
//SDL_PauseAudio (0);
}
static gboolean
render_idle_audio (gpointer data)
{
SwfdecBuffer *video_buffer;
SwfdecBuffer *audio_buffer;
gboolean ret;
#if 0
if (hidden) {
struct timeval tv;
int now;
gettimeofday(&tv, NULL);
now = tv.tv_sec*1000+tv.tv_usec/1000;
// int now = SDL_GetTicks ();
render_time = now + 10;
return FALSE;
}
if (sound_bytes >= 40000) {
struct timeval tv;
int now;
gettimeofday(&tv, NULL);
now = tv.tv_sec*1000+tv.tv_usec/1000;
//int now = SDL_GetTicks ();
render_time = now + 10;
return FALSE;
}
#endif
ret = swfdec_render_iterate (s);
if (!ret) {
go = FALSE;
return FALSE;
}
audio_buffer = swfdec_render_get_audio (s);
if (audio_buffer == NULL) {
/* error */
go = FALSE;
}
// sound_buffers = g_list_append (sound_buffers, audio_buffer);
sound_bytes += audio_buffer->length;
ret = write(audiodev.fd, audio_buffer->data, audio_buffer->length);
//close_audio(&audiodev);
#if 0
if (slow) {
swfdec_buffer_ref (audio_buffer);
sound_buffers = g_list_append (sound_buffers, audio_buffer);
sound_bytes += audio_buffer->length;
}
#endif
if (sound_bytes > 20000 || noskip) {
video_buffer = swfdec_render_get_image (s);
} else {
video_buffer = NULL;
DEBUG ("video_buffer == NULL\n");
}
if (video_buffer) {
int ret;
//SDL_Surface *surface;
int i;
if (video_buffer->length != width * height * 4) {
DEBUG ("video buffer wrong size (%d should be %d)\n",
video_buffer->length, width * height * 4);
}
#if G_BYTE_ORDER == 4321
#define RED_MASK 0x0000ff00
#define GREEN_MASK 0x00ff0000
#define BLUE_MASK 0xff000000
#define ALPHA_MASK 0x000000ff
#else
#define RED_MASK 0x00ff0000
#define GREEN_MASK 0x0000ff00
#define BLUE_MASK 0x000000ff
#define ALPHA_MASK 0xff000000
#endif
/* surface = SDL_CreateRGBSurfaceFrom (video_buffer->data, width,
height, 32, width * 4, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK);
SDL_SetAlpha (surface, 0, SDL_ALPHA_OPAQUE);
ret = SDL_BlitSurface (surface, NULL, sdl_screen, NULL);
if (ret < 0) {
DEBUG ("SDL_BlitSurface failed\n");
}
SDL_UpdateRect (sdl_screen, 0, 0, width, height);
*/
for(i=0; i memcpy(fbdev.fb_mem + fbdev.fb_mem_offset+i*fbdev.fb_var.xres*4, video_buffer->data+i*width*4,width*4);
}
swfdec_buffer_unref (video_buffer);
// SDL_FreeSurface (surface);
}