Commit 53690304 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Allow width/height mode selections to match framebuffer output capabilities.

parent f1a86075
...@@ -80,6 +80,11 @@ static void GfxMode ( int i_tty ); ...@@ -80,6 +80,11 @@ static void GfxMode ( int i_tty );
#define ASPECT_RATIO_LONGTEXT N_( \ #define ASPECT_RATIO_LONGTEXT N_( \
"Aspect ratio of the video image (4:3, 16:9). Default is square pixels." ) "Aspect ratio of the video image (4:3, 16:9). Default is square pixels." )
#define FB_MODE_TEXT N_("Framebuffer resolution to use.")
#define FB_MODE_LONGTEXT N_( \
"Select the resolution for the framebuffer. Currently it supports " \
"the values 0=QCIF 1=CIF 2=NTSC 3=PAL (default 3=PAL)" )
vlc_module_begin(); vlc_module_begin();
set_shortname( "Framebuffer" ); set_shortname( "Framebuffer" );
set_category( CAT_VIDEO ); set_category( CAT_VIDEO );
...@@ -91,6 +96,8 @@ vlc_module_begin(); ...@@ -91,6 +96,8 @@ vlc_module_begin();
VLC_TRUE ); VLC_TRUE );
add_string( "fb-aspect-ratio", NULL, NULL, ASPECT_RATIO_TEXT, add_string( "fb-aspect-ratio", NULL, NULL, ASPECT_RATIO_TEXT,
ASPECT_RATIO_LONGTEXT, VLC_TRUE ); ASPECT_RATIO_LONGTEXT, VLC_TRUE );
add_integer( "fb-mode", 3, NULL, FB_MODE_TEXT, FB_MODE_LONGTEXT,
VLC_TRUE );
set_description( _("GNU/Linux console framebuffer video output") ); set_description( _("GNU/Linux console framebuffer video output") );
set_capability( "video output", 30 ); set_capability( "video output", 30 );
set_callbacks( Create, Destroy ); set_callbacks( Create, Destroy );
...@@ -145,6 +152,7 @@ static int Create( vlc_object_t *p_this ) ...@@ -145,6 +152,7 @@ static int Create( vlc_object_t *p_this )
vout_sys_t *p_sys; vout_sys_t *p_sys;
char *psz_chroma; char *psz_chroma;
char *psz_aspect; char *psz_aspect;
int i_mode;
struct sigaction sig_tty; /* sigaction for tty change */ struct sigaction sig_tty; /* sigaction for tty change */
struct vt_mode vt_mode; /* vt current mode */ struct vt_mode vt_mode; /* vt current mode */
struct termios new_termios; struct termios new_termios;
...@@ -222,6 +230,28 @@ static int Create( vlc_object_t *p_this ) ...@@ -222,6 +230,28 @@ static int Create( vlc_object_t *p_this )
psz_aspect = NULL; psz_aspect = NULL;
} }
i_mode = var_CreateGetInteger( p_vout, "fb-mode" );
switch( i_mode )
{
case 0: /* QCIF */
p_sys->i_width = 176;
p_sys->i_height = 144;
break;
case 1: /* CIF */
p_sys->i_width = 352;
p_sys->i_height = 288;
break;
case 2: /* NTSC */
p_sys->i_width = 640;
p_sys->i_height = 480;
break;
case 3: /* PAL */
default:
p_sys->i_width = 704;
p_sys->i_height = 576;
break;
}
/* tty handling */ /* tty handling */
if( p_sys->b_tty ) if( p_sys->b_tty )
{ {
...@@ -572,6 +602,7 @@ static void SetPalette( vout_thread_t *p_vout, uint16_t *red, uint16_t *green, ...@@ -572,6 +602,7 @@ static void SetPalette( vout_thread_t *p_vout, uint16_t *red, uint16_t *green,
*****************************************************************************/ *****************************************************************************/
static int OpenDisplay( vout_thread_t *p_vout ) static int OpenDisplay( vout_thread_t *p_vout )
{ {
vout_sys_t *p_sys = (vout_sys_t *) p_vout->p_sys;
char *psz_device; /* framebuffer device path */ char *psz_device; /* framebuffer device path */
struct fb_fix_screeninfo fix_info; /* framebuffer fix information */ struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
...@@ -582,8 +613,8 @@ static int OpenDisplay( vout_thread_t *p_vout ) ...@@ -582,8 +613,8 @@ static int OpenDisplay( vout_thread_t *p_vout )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_vout->p_sys->i_fd = open( psz_device, O_RDWR); p_sys->i_fd = open( psz_device, O_RDWR);
if( p_vout->p_sys->i_fd == -1 ) if( p_sys->i_fd == -1 )
{ {
msg_Err( p_vout, "cannot open %s (%m)", psz_device ); msg_Err( p_vout, "cannot open %s (%m)", psz_device );
free( psz_device ); free( psz_device );
...@@ -593,136 +624,142 @@ static int OpenDisplay( vout_thread_t *p_vout ) ...@@ -593,136 +624,142 @@ static int OpenDisplay( vout_thread_t *p_vout )
psz_device = NULL; psz_device = NULL;
/* Get framebuffer device information */ /* Get framebuffer device information */
if( ioctl( p_vout->p_sys->i_fd, if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) )
FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
{ {
msg_Err( p_vout, "cannot get fb info (%m)" ); msg_Err( p_vout, "cannot get fb info (%m)" );
close( p_vout->p_sys->i_fd ); close( p_sys->i_fd );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
memcpy( &p_vout->p_sys->old_info, &p_vout->p_sys->var_info, memcpy( &p_sys->old_info, &p_sys->var_info,
sizeof( struct fb_var_screeninfo ) ); sizeof( struct fb_var_screeninfo ) );
/* Get some info on the framebuffer itself */
if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) == 0 )
{
p_sys->var_info.xres = p_sys->var_info.xres_virtual = p_sys->i_width;
p_sys->var_info.yres = p_sys->var_info.yres_virtual = p_sys->i_height;
p_vout->fmt_out.i_width = p_sys->i_width;
p_vout->fmt_out.i_height = p_sys->i_height;
}
/* Set some attributes */ /* Set some attributes */
p_vout->p_sys->var_info.activate = FB_ACTIVATE_NXTOPEN; p_sys->var_info.activate = p_sys->b_tty
p_vout->p_sys->var_info.xoffset = 0; ? FB_ACTIVATE_NXTOPEN
p_vout->p_sys->var_info.yoffset = 0; : FB_ACTIVATE_NOW;
p_sys->var_info.xoffset = 0;
p_sys->var_info.yoffset = 0;
if( ioctl( p_vout->p_sys->i_fd, if( ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->var_info ) )
FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
{ {
msg_Err( p_vout, "cannot set fb info (%m)" ); msg_Err( p_vout, "cannot set fb info (%m)" );
close( p_vout->p_sys->i_fd ); close( p_sys->i_fd );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Get some information again, in the definitive configuration */ /* Get some information again, in the definitive configuration */
if( ioctl( p_vout->p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info )
|| ioctl( p_vout->p_sys->i_fd, || ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) )
FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
{ {
msg_Err( p_vout, "cannot get additional fb info (%m)" ); msg_Err( p_vout, "cannot get additional fb info (%m)" );
/* Restore fb config */ /* Restore fb config */
ioctl( p_vout->p_sys->i_fd, ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->old_info );
FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
close( p_vout->p_sys->i_fd ); close( p_sys->i_fd );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* FIXME: if the image is full-size, it gets cropped on the left /* FIXME: if the image is full-size, it gets cropped on the left
* because of the xres / xres_virtual slight difference */ * because of the xres / xres_virtual slight difference */
msg_Dbg( p_vout, "%ix%i (virtual %ix%i)", msg_Dbg( p_vout, "%ix%i (virtual %ix%i)",
p_vout->p_sys->var_info.xres, p_vout->p_sys->var_info.yres, p_sys->var_info.xres, p_sys->var_info.yres,
p_vout->p_sys->var_info.xres_virtual, p_sys->var_info.xres_virtual,
p_vout->p_sys->var_info.yres_virtual ); p_sys->var_info.yres_virtual );
p_vout->p_sys->i_height = p_vout->p_sys->var_info.yres; /* If the fb has limitations on mode change,
p_vout->p_sys->i_width = p_vout->p_sys->var_info.xres_virtual * then keep the resolution of the fb */
? p_vout->p_sys->var_info.xres_virtual p_sys->i_height = p_sys->var_info.yres;
: p_vout->p_sys->var_info.xres; p_sys->i_width = p_sys->var_info.xres_virtual
? p_sys->var_info.xres_virtual
: p_sys->var_info.xres;
p_vout->p_sys->p_palette = NULL; p_sys->p_palette = NULL;
p_vout->p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep ); p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
switch( p_vout->p_sys->var_info.bits_per_pixel ) switch( p_sys->var_info.bits_per_pixel )
{ {
case 8: case 8:
p_vout->p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) ); p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) );
if( !p_vout->p_sys->p_palette ) if( !p_sys->p_palette )
{ {
msg_Err( p_vout, "out of memory" ); msg_Err( p_vout, "out of memory" );
/* Restore fb config */ /* Restore fb config */
ioctl( p_vout->p_sys->i_fd, ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->old_info );
FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
close( p_vout->p_sys->i_fd ); close( p_sys->i_fd );
return VLC_ENOMEM; return VLC_ENOMEM;
} }
p_vout->p_sys->fb_cmap.start = 0; p_sys->fb_cmap.start = 0;
p_vout->p_sys->fb_cmap.len = 256; p_sys->fb_cmap.len = 256;
p_vout->p_sys->fb_cmap.red = p_vout->p_sys->p_palette; p_sys->fb_cmap.red = p_sys->p_palette;
p_vout->p_sys->fb_cmap.green = p_vout->p_sys->p_palette + 256 * sizeof( uint16_t ); p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t );
p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->p_palette + 2 * 256 * sizeof( uint16_t ); p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t );
p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->p_palette + 3 * 256 * sizeof( uint16_t ); p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t );
/* Save the colormap */ /* Save the colormap */
ioctl( p_vout->p_sys->i_fd, FBIOGETCMAP, &p_vout->p_sys->fb_cmap ); ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap );
p_vout->p_sys->i_bytes_per_pixel = 1; p_sys->i_bytes_per_pixel = 1;
break; break;
case 15: case 15:
case 16: case 16:
p_vout->p_sys->i_bytes_per_pixel = 2; p_sys->i_bytes_per_pixel = 2;
break; break;
case 24: case 24:
p_vout->p_sys->i_bytes_per_pixel = 3; p_sys->i_bytes_per_pixel = 3;
break; break;
case 32: case 32:
p_vout->p_sys->i_bytes_per_pixel = 4; p_sys->i_bytes_per_pixel = 4;
break; break;
default: default:
msg_Err( p_vout, "screen depth %d is not supported", msg_Err( p_vout, "screen depth %d is not supported",
p_vout->p_sys->var_info.bits_per_pixel ); p_sys->var_info.bits_per_pixel );
/* Restore fb config */ /* Restore fb config */
ioctl( p_vout->p_sys->i_fd, ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->old_info );
FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
close( p_vout->p_sys->i_fd ); close( p_sys->i_fd );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_vout->p_sys->i_page_size = p_vout->p_sys->i_width * p_sys->i_page_size = p_sys->i_width * p_sys->i_height *
p_vout->p_sys->i_height * p_vout->p_sys->i_bytes_per_pixel; p_sys->i_bytes_per_pixel;
/* Map a framebuffer at the beginning */ /* Map a framebuffer at the beginning */
p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->i_page_size, p_sys->p_video = mmap( 0, p_sys->i_page_size,
PROT_READ | PROT_WRITE, MAP_SHARED, PROT_READ | PROT_WRITE, MAP_SHARED,
p_vout->p_sys->i_fd, 0 ); p_sys->i_fd, 0 );
if( p_vout->p_sys->p_video == ((void*)-1) ) if( p_sys->p_video == ((void*)-1) )
{ {
msg_Err( p_vout, "cannot map video memory (%m)" ); msg_Err( p_vout, "cannot map video memory (%m)" );
if( p_vout->p_sys->var_info.bits_per_pixel == 8 ) if( p_sys->var_info.bits_per_pixel == 8 )
{ {
free( p_vout->p_sys->p_palette ); free( p_sys->p_palette );
p_vout->p_sys->p_palette = NULL; p_sys->p_palette = NULL;
} }
/* Restore fb config */ /* Restore fb config */
ioctl( p_vout->p_sys->i_fd, ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
close( p_vout->p_sys->i_fd ); close( p_sys->i_fd );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment