/*******************************************************************************
- * vout_x11.c: X11 video output display method
+ * vout_fb.c: framebuffer video output display method
* (c)1998 VideoLAN
- *******************************************************************************
- * The X11 method for video output thread. It's properties (and the vout_x11_t
- * type) are defined in vout.h. The functions declared here should not be
- * needed by any other module than vout.c.
*******************************************************************************/
/*******************************************************************************
* Preamble
*******************************************************************************/
-#include "vlc.h"
-/*
+
#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <netinet/in.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <sys/shm.h>
-#include <sys/soundcard.h>
-#include <sys/uio.h>
-
+#include <sys/uio.h> /* for input.h */
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
-#include "xutils.h"
#include "input.h"
-#include "input_vlan.h"
-
-#include "audio_output.h"
-
#include "video.h"
#include "video_output.h"
#include "video_sys.h"
-
-#include "xconsole.h"
-#include "interface.h"
#include "intf_msg.h"
-*/
+#include "main.h"
/*******************************************************************************
* vout_sys_t: video output framebuffer method descriptor
* dynamically resized to adapt to the size of the streams.
*******************************************************************************/
typedef struct vout_sys_s
-{
- int i_dummy;
+{
+ /* System informations */
+ int i_fb_dev; /* framebuffer device handle */
+ size_t i_page_size; /* page size */
+ /* Video memory */
+ byte_t * p_video;
} vout_sys_t;
/*******************************************************************************
* Local prototypes
*******************************************************************************/
-
+static int FBOpenDisplay ( vout_thread_t *p_vout );
+static void FBCloseDisplay ( vout_thread_t *p_vout );
/*******************************************************************************
- * vout_SysCreate: allocate X11 video thread output method
+ * vout_SysCreate: allocate framebuffer video thread output method
*******************************************************************************
- * This function allocate and initialize a X11 vout method.
+ * This function allocate and initialize a framebuffer vout method.
*******************************************************************************/
int vout_SysCreate( vout_thread_t *p_vout )
-{
+{
+ /* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
- if( p_vout->p_sys != NULL )
+ if( p_vout->p_sys == NULL )
{
- //??
- return( 0 );
+ intf_ErrMsg("vout error: %s\n", strerror(ENOMEM) );
+ return( 1 );
}
- return( 1 );
+ /* Open and initialize device */
+ if( FBOpenDisplay( p_vout ) )
+ {
+ intf_ErrMsg("vout error: can't open display\n");
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ return( 0 );
}
/*******************************************************************************
* vout_SysInit: initialize Sys video thread output method
*******************************************************************************
- * This function create a Sys window according to the user configuration.
+ * This function initialize the framebuffer device.
*******************************************************************************/
int vout_SysInit( vout_thread_t *p_vout )
{
+ // Blank both screens
+ memset( p_vout->p_sys->p_video, 0x00, 2*p_vout->p_sys->i_page_size );
+
+
+
+ //??
//??
- intf_DbgMsg("%p -> success, depth=%d bpp",
- p_vout, p_vout->i_screen_depth );
+// intf_Msg("vout: framebuffer display initialized (%s), %dx%d depth=%d bpp",
+// fb_fix_screeninfo.id, p_vout->i_witdh, p_vout->i_height,
+// p_vout->i_screen_depth );
return( 0 );
}
*******************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
- //??
+ FBCloseDisplay( p_vout );
free( p_vout->p_sys );
}
*******************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout )
{
- //??
-
+
/* Swap buffers */
//?? p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
}
+/* following functions are local */
+
+/*******************************************************************************
+ * FBOpenDisplay: open and initialize framebuffer device
+ *******************************************************************************
+ * ?? The framebuffer mode is only provided as a fast and efficient way to
+ * display video, providing the card is configured and the mode ok. It is
+ * not portable, and is not supposed to work with many cards. Use at your
+ * own risks !
+ *******************************************************************************/
+static int FBOpenDisplay( vout_thread_t *p_vout )
+{
+ char *psz_device; /* framebuffer device path */
+ struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
+ struct fb_var_screeninfo var_info; /* frambuffer mode informations */
+
+ /* Open framebuffer device */
+ psz_device = main_GetPszVariable( VOUT_FB_DEV_VAR, VOUT_FB_DEV_DEFAULT );
+ p_vout->p_sys->i_fb_dev = open( psz_device, O_RDWR);
+ if( p_vout->p_sys->i_fb_dev == -1 )
+ {
+ intf_ErrMsg("vout error: can't open %s (%s)\n", psz_device, strerror(errno) );
+ return( 1 );
+ }
+
+ // ?? here would be the code used to save the current mode and
+ // ?? change to the most appropriate mode...
+
+ /* Get framebuffer device informations */
+ if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &var_info ) )
+ {
+ intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
+ close( p_vout->p_sys->i_fb_dev );
+ return( 1 );
+ }
+
+ /* Framebuffer must have some basic properties to be usable */
+ //??
+
+ /* Set some attributes */
+ var_info.activate = FB_ACTIVATE_NXTOPEN;
+ var_info.xoffset = 0;
+ var_info.yoffset = 0;
+ //??ask sam p_vout->p_sys->mode_info.sync = FB_SYNC_VERT_HIGH_ACT;
+ //???
+ if( ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &var_info ) )
+ {
+ intf_ErrMsg("vout error: can't set framebuffer informations (%s)\n", strerror(errno) );
+ close( p_vout->p_sys->i_fb_dev );
+ return( 1 );
+ }
+
+ /* Get some informations again, in the definitive configuration */
+ if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_FSCREENINFO, &fix_info ) ||
+ ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &var_info ) )
+ {
+ intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
+ // ?? restore fb config
+ close( p_vout->p_sys->i_fb_dev );
+ return( 1 );
+ }
+
+ p_vout->i_width = var_info.xres;
+ p_vout->i_height = var_info.yres;
+ p_vout->i_screen_depth = var_info.bits_per_pixel;
+ p_vout->p_sys->i_page_size = var_info.xres *
+ var_info.yres * var_info.bits_per_pixel / 8;
+
+
+ /* Map two framebuffers a the very beginning of the fb */
+ p_vout->p_sys->p_video = mmap(0, p_vout->p_sys->i_page_size * 2,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ p_vout->p_sys->i_fb_dev, 0 );
+ if( p_vout->p_sys->p_video == -1 ) //?? according to man, it is -1. What about NULL ?
+ {
+ intf_ErrMsg("vout error: can't map video memory (%s)\n", strerror(errno) );
+ // ?? restore fb config
+ close( p_vout->p_sys->i_fb_dev );
+ return( 1 );
+ }
+
+ intf_DbgMsg("framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d\n",
+ fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
+ intf_Msg("vout: framebuffer display initialized (%s), %dx%d depth=%d bpp\n",
+ fix_info.id, p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth );
+ return( 0 );
+}
+
+/*******************************************************************************
+ * FBCloseDisplay: close and reset framebuffer device
+ *******************************************************************************
+ * This function returns all resources allocated by FBOpenDisplay and restore
+ * the original state of the device.
+ *******************************************************************************/
+static void FBCloseDisplay( vout_thread_t *p_vout )
+{
+ //?? unmap memory
+ //?? restore original mode
+ close( p_vout->p_sys->i_fb_dev );
+}
+
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
{
- return( 1 );
-
+ intf_ErrMsg("vout error: %s\n", strerror(ENOMEM) );
+ return( 1 );
}
/* Since XLib is usually not thread-safe, we can't use the same display
X11DestroyWindow( p_vout );
return( 1 );
}
- intf_DbgMsg("%p -> success, depth=%d bpp, Shm=%d\n",
- p_vout, p_vout->i_screen_depth, p_vout->p_sys->b_shm );
+ intf_Msg("vout: X11 display initialized, depth=%d bpp, Shm=%d\n",
+ p_vout->i_screen_depth, p_vout->p_sys->b_shm );
return( 0 );
}
break;
default: /* unsupported screen depth */
- intf_ErrMsg("vout error 106-2: screen depth %i is not supported\n",
+ intf_ErrMsg("vout error: screen depth %i is not supported\n",
p_vout->i_screen_depth);
return( 1 );
break;
* Create two XImages which will be used as rendering buffers. On error, non 0
* will be returned and the images pointer will be set to NULL (see
* vout_X11ManageOutputMethod()).
- *******************************************************************************
- * Messages type: vout, major code: 108
*******************************************************************************/
static int X11CreateImages( vout_thread_t *p_vout )
{
{
if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[0] ) )
{
- intf_Msg("vout error 108-1: can't create images\n");
+ intf_Msg("vout error: can't create images\n");
p_vout->p_sys->p_ximage[0] = NULL;
p_vout->p_sys->p_ximage[1] = NULL;
return( -1 );
}
if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[1] ) )
{
- intf_Msg("vout error 108-2: can't create images\n");
+ intf_Msg("vout error: can't create images\n");
X11DestroyImage( p_vout->p_sys->p_ximage[0] );
p_vout->p_sys->p_ximage[0] = NULL;
p_vout->p_sys->p_ximage[1] = NULL;
* X11DestroyImages: destroy X11 rendering buffers
*******************************************************************************
* Destroy buffers created by vout_X11CreateImages().
- *******************************************************************************
- * Messages type: vout, major code: 109
*******************************************************************************/
static void X11DestroyImages( vout_thread_t *p_vout )
{
* X11DestroyWindow: destroy X11 window
*******************************************************************************
* Destroy an X11 window created by vout_X11CreateWindow
- *******************************************************************************
- * Messages type: vout, major code: 110
*******************************************************************************/
static void X11DestroyWindow( vout_thread_t *p_vout )
{
/*******************************************************************************
* X11CreateImage: create an XImage
- *******************************************************************************
- * Messages type: vout, major code 112
*******************************************************************************/
static int X11CreateImage( vout_thread_t *p_vout, XImage **pp_ximage )
{
* p_vout->i_height );
if( !pb_data ) /* error */
{
- intf_ErrMsg("vout error 112-1: %s\n", strerror(ENOMEM));
+ intf_ErrMsg("vout error: %s\n", strerror(ENOMEM));
return( -1 );
}
p_vout->i_width, p_vout->i_height, i_quantum, 0);
if(! *pp_ximage ) /* error */
{
- intf_ErrMsg( "vout error 112-2: XCreateImage() failed\n" );
+ intf_ErrMsg( "vout error: can't create XImages\n" );
free( pb_data );
return( -1 );
}
* Minor opcode of failed request: 1 (X_ShmAttach)
* Serial number of failed request: 17
* Current serial number in output stream: 18
- *******************************************************************************
- * Messages type: vout, major code 113
*******************************************************************************/
static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
XShmSegmentInfo *p_shm_info)
p_shm_info, p_vout->i_width, p_vout->i_height );
if(! *pp_ximage ) /* error */
{
- intf_ErrMsg("vout error 113-1: XShmCreateImage() failed\n");
+ intf_ErrMsg("vout error: can't create XImages with shared memory\n");
return( -1 );
}
IPC_CREAT | 0777);
if( p_shm_info->shmid < 0) /* error */
{
- intf_ErrMsg("vout error 113-2: can't allocate shared image data (%s)\n",
+ intf_ErrMsg("vout error: can't allocate shared image data (%s)\n",
strerror(errno));
XDestroyImage( *pp_ximage );
return( -1 );
p_shm_info->shmaddr = (*pp_ximage)->data = shmat(p_shm_info->shmid, 0, 0);
if(! p_shm_info->shmaddr )
{ /* error */
- intf_ErrMsg("vout error 113-3: can't attach shared memory (%s)\n",
+ intf_ErrMsg("vout error: can't attach shared memory (%s)\n",
strerror(errno));
shmctl( p_shm_info->shmid, IPC_RMID, 0 ); /* free shared memory */
XDestroyImage( *pp_ximage );
p_shm_info->readOnly = True;
if( XShmAttach( p_vout->p_sys->p_display, p_shm_info ) == False ) /* error */
{
- intf_ErrMsg("vout error 113-4: can't attach shared memory to server\n");
+ intf_ErrMsg("vout error: can't attach shared memory to X11 server\n");
shmdt( p_shm_info->shmaddr ); /* detach shared memory from process
* and automatic free */
XDestroyImage( *pp_ximage );
XDestroyImage( p_ximage );
if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
{ /* also automatic freeing... */
- intf_ErrMsg("vout error 115-1: can't detach shared memory (%s)\n",
+ intf_ErrMsg("vout error: can't detach shared memory (%s)\n",
strerror(errno));
}
}