X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Ffb.c;h=95ea2fe1a317b5df5284080e885488a52eb07b65;hb=d5a04763bde647b3a59ac18898dc06d12bc52491;hp=079128123cf78f761800b19fc3baa63a102b80e9;hpb=806cf5165824be921bf2402ecf11fd3ee6501f9c;p=vlc diff --git a/modules/video_output/fb.c b/modules/video_output/fb.c index 079128123c..95ea2fe1a3 100644 --- a/modules/video_output/fb.c +++ b/modules/video_output/fb.c @@ -25,6 +25,11 @@ /***************************************************************************** * Preamble *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include /* ENOMEM */ #include /* SIGUSR1, SIGUSR2 */ #include /* open() */ @@ -38,7 +43,8 @@ #include /* VT_* */ #include /* KD* */ -#include +#include +#include #include /***************************************************************************** @@ -53,12 +59,17 @@ static int Manage ( vout_thread_t * ); static void Display ( vout_thread_t *, picture_t * ); static int Control ( vout_thread_t *, int, va_list ); +static int NewPicture ( vout_thread_t *, picture_t * ); +static void FreePicture ( vout_thread_t *, picture_t * ); + static int OpenDisplay ( vout_thread_t * ); static void CloseDisplay ( vout_thread_t * ); static void SwitchDisplay ( int i_signal ); static void TextMode ( int i_tty ); static void GfxMode ( int i_tty ); +#define MAX_DIRECTBUFFERS 1 + /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -86,25 +97,28 @@ static void GfxMode ( int i_tty ); "Select the resolution for the framebuffer. Currently it supports " \ "the values 0=QCIF 1=CIF 2=NTSC 3=PAL, 4=auto (default 4=auto)" ) +#define HW_ACCEL_TEXT N_("Framebuffer uses hw acceleration.") +#define HW_ACCEL_LONGTEXT N_( \ + "If your framebuffer supports hardware acceleration or does double buffering " \ + "in hardware then you must disable this option. It then does double buffering " \ + "in software." ) + vlc_module_begin(); set_shortname( "Framebuffer" ); set_category( CAT_VIDEO ); set_subcategory( SUBCAT_VIDEO_VOUT ); add_file( FB_DEV_VAR, "/dev/fb0", NULL, DEVICE_TEXT, DEVICE_LONGTEXT, - VLC_FALSE ); - change_safe(); /* ioctl() prevents doing bad things */ - add_bool( "fb-tty", 1, NULL, TTY_TEXT, TTY_LONGTEXT, VLC_TRUE ); - change_safe(); + false ); + add_bool( "fb-tty", 1, NULL, TTY_TEXT, TTY_LONGTEXT, true ); add_string( "fb-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, - VLC_TRUE ); - change_safe(); + true ); add_string( "fb-aspect-ratio", NULL, NULL, ASPECT_RATIO_TEXT, - ASPECT_RATIO_LONGTEXT, VLC_TRUE ); - change_safe(); + ASPECT_RATIO_LONGTEXT, true ); add_integer( "fb-mode", 4, NULL, FB_MODE_TEXT, FB_MODE_LONGTEXT, - VLC_TRUE ); - change_safe(); - set_description( _("GNU/Linux console framebuffer video output") ); + true ); + add_bool( "fb-hw-accel", true, NULL, HW_ACCEL_TEXT, HW_ACCEL_LONGTEXT, + true ); + set_description( N_("GNU/Linux console framebuffer video output") ); set_capability( "video output", 30 ); set_callbacks( Create, Destroy ); vlc_module_end(); @@ -119,7 +133,7 @@ struct vout_sys_t { /* System information */ int i_tty; /* tty device handle */ - vlc_bool_t b_tty; + bool b_tty; struct termios old_termios; /* Original configuration information */ @@ -131,23 +145,29 @@ struct vout_sys_t int i_fd; /* device handle */ struct fb_var_screeninfo old_info; /* original mode information */ struct fb_var_screeninfo var_info; /* current mode information */ - vlc_bool_t b_pan; /* does device supports panning ? */ + bool b_pan; /* does device supports panning ? */ struct fb_cmap fb_cmap; /* original colormap */ uint16_t *p_palette; /* original palette */ + bool b_hw_accel; /* has hardware support */ /* Video information */ uint32_t i_width; uint32_t i_height; - int i_aspect; - int i_bytes_per_pixel; - vlc_bool_t b_auto; /* Automatically adjust video size to fb size */ + int i_aspect; + int i_bytes_per_pixel; + bool b_auto; /* Automatically adjust video size to fb size */ vlc_fourcc_t i_chroma; /* Video memory */ - byte_t * p_video; /* base adress */ + uint8_t *p_video; /* base adress */ size_t i_page_size; /* page size */ }; +struct picture_sys_t +{ + uint8_t * p_data; /* base adress */ +}; + /***************************************************************************** * Create: allocates FB video thread output method ***************************************************************************** @@ -167,10 +187,7 @@ static int Create( vlc_object_t *p_this ) /* Allocate instance and initialize some members */ p_vout->p_sys = p_sys = malloc( sizeof( vout_sys_t ) ); if( p_vout->p_sys == NULL ) - { - msg_Err( p_vout, "out of memory" ); return VLC_ENOMEM; - }; memset( p_sys, 0, sizeof(vout_sys_t) ); p_vout->pf_init = Init; @@ -180,6 +197,9 @@ static int Create( vlc_object_t *p_this ) p_vout->pf_display = Display; p_vout->pf_control = Control; + /* Does the framebuffer uses hw acceleration? */ + p_sys->b_hw_accel = var_CreateGetBool( p_vout, "fb-hw-accel" ); + /* Set tty and fb devices */ p_sys->i_tty = 0; /* 0 == /dev/tty0 == current console */ p_sys->b_tty = var_CreateGetBool( p_vout, "fb-tty" ); @@ -238,7 +258,7 @@ static int Create( vlc_object_t *p_this ) psz_aspect = NULL; } - p_sys->b_auto = VLC_FALSE; + p_sys->b_auto = false; i_mode = var_CreateGetInteger( p_vout, "fb-mode" ); switch( i_mode ) { @@ -260,7 +280,7 @@ static int Create( vlc_object_t *p_this ) break; case 4: default: - p_sys->b_auto = VLC_TRUE; + p_sys->b_auto = true; break; } @@ -355,6 +375,102 @@ static int Create( vlc_object_t *p_this ) return VLC_SUCCESS; } + +/***************************************************************************** + * Destroy: destroy FB video thread output method + ***************************************************************************** + * Terminate an output method created by Create + *****************************************************************************/ +static void Destroy( vlc_object_t *p_this ) +{ + vout_thread_t *p_vout = (vout_thread_t *)p_this; + + CloseDisplay( p_vout ); + + if( p_vout->p_sys->b_tty ) + { + /* Reset the terminal */ + ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &p_vout->p_sys->vt_mode ); + + /* Remove signal handlers */ + sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL ); + sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL ); + + /* Reset the keyboard state */ + tcsetattr( 0, 0, &p_vout->p_sys->old_termios ); + + /* Return to text mode */ + TextMode( p_vout->p_sys->i_tty ); + } + + /* Destroy structure */ + free( p_vout->p_sys ); +} + +/***************************************************************************** + * NewPicture: allocate a picture + ***************************************************************************** + * Returns 0 on success, -1 otherwise + *****************************************************************************/ +static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic ) +{ + /* We know the chroma, allocate a buffer which will be used + * directly by the decoder */ + p_pic->p_sys = malloc( sizeof( picture_sys_t ) ); + if( p_pic->p_sys == NULL ) + { + return VLC_ENOMEM; + } + + /* Fill in picture_t fields */ + vout_InitPicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma, + p_vout->output.i_width, p_vout->output.i_height, + p_vout->output.i_aspect ); + + p_pic->p_sys->p_data = malloc( p_vout->p_sys->i_page_size ); + if( !p_pic->p_sys->p_data ) + { + free( p_pic->p_sys ); + p_pic->p_sys = NULL; + return VLC_ENOMEM; + } + + p_pic->p->p_pixels = (uint8_t*) p_pic->p_sys->p_data; + + p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel; + p_pic->p->i_lines = p_vout->p_sys->var_info.yres; + p_pic->p->i_visible_lines = p_vout->p_sys->var_info.yres; + + if( p_vout->p_sys->var_info.xres_virtual ) + { + p_pic->p->i_pitch = p_vout->p_sys->var_info.xres_virtual + * p_vout->p_sys->i_bytes_per_pixel; + } + else + { + p_pic->p->i_pitch = p_vout->p_sys->var_info.xres + * p_vout->p_sys->i_bytes_per_pixel; + } + + p_pic->p->i_visible_pitch = p_vout->p_sys->var_info.xres + * p_vout->p_sys->i_bytes_per_pixel; + p_pic->i_planes = 1; + + return VLC_SUCCESS; +} + +/***************************************************************************** + * FreePicture: destroy a picture allocated with NewPicture + ***************************************************************************** + * Destroy Image AND associated data. + *****************************************************************************/ +static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic ) +{ + free( p_pic->p_sys->p_data ); + free( p_pic->p_sys ); + p_pic->p_sys = NULL; +} + /***************************************************************************** * Init: initialize framebuffer video thread output method *****************************************************************************/ @@ -362,10 +478,15 @@ static int Init( vout_thread_t *p_vout ) { vout_sys_t *p_sys = p_vout->p_sys; int i_index; - picture_t *p_pic; + picture_t *p_pic = NULL; I_OUTPUTPICTURES = 0; + p_vout->output.i_width = p_vout->render.i_width; + p_vout->output.i_height = p_vout->render.i_height; + p_vout->output.i_aspect = p_vout->render.i_aspect; + + p_vout->fmt_out = p_vout->fmt_in; if( p_sys->i_chroma == 0 ) { /* Initialize the output structure: RGB with square pixels, whatever @@ -404,13 +525,12 @@ static int Init( vout_thread_t *p_vout ) } p_vout->fmt_out.i_chroma = p_vout->output.i_chroma; - if( !p_sys->b_auto ) - { - p_vout->render.i_width = p_sys->i_width; - p_vout->render.i_height = p_sys->i_height; - } - p_vout->output.i_width = p_sys->i_width; - p_vout->output.i_height = p_sys->i_height; + p_vout->output.i_width = + p_vout->fmt_out.i_width = + p_vout->fmt_out.i_visible_width = p_sys->i_width; + p_vout->output.i_height = + p_vout->fmt_out.i_height = + p_vout->fmt_out.i_visible_height = p_sys->i_height; /* Assume we have square pixels */ if( p_sys->i_aspect < 0 ) @@ -422,56 +542,91 @@ static int Init( vout_thread_t *p_vout ) p_vout->fmt_out.i_sar_num = p_vout->fmt_out.i_sar_den = 1; p_vout->fmt_out.i_aspect = p_vout->render.i_aspect = p_vout->output.i_aspect; + p_vout->fmt_out.i_x_offset= p_vout->fmt_out.i_y_offset = 0; /* Clear the screen */ memset( p_sys->p_video, 0, p_sys->i_page_size ); - /* Try to initialize 1 direct buffer */ - p_pic = NULL; - - /* Find an empty picture slot */ - for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) + if( !p_sys->b_hw_accel ) { - if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) + /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */ + while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS ) { - p_pic = p_vout->p_picture + i_index; - break; + p_pic = NULL; + + /* Find an empty picture slot */ + for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) + { + if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) + { + p_pic = p_vout->p_picture + i_index; + break; + } + } + + /* Allocate the picture */ + if( p_pic == NULL || NewPicture( p_vout, p_pic ) ) + { + break; + } + + p_pic->i_status = DESTROYED_PICTURE; + p_pic->i_type = DIRECT_PICTURE; + + PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; + + I_OUTPUTPICTURES++; } } - - /* Allocate the picture */ - if( p_pic == NULL ) + else { - return VLC_EGENERIC; - } + /* Try to initialize 1 direct buffer */ + p_pic = NULL; - /* We know the chroma, allocate a buffer which will be used - * directly by the decoder */ - p_pic->p->p_pixels = p_vout->p_sys->p_video; - p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel; - p_pic->p->i_lines = p_vout->p_sys->var_info.yres; - p_pic->p->i_visible_lines = p_vout->p_sys->var_info.yres; + /* Find an empty picture slot */ + for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) + { + if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) + { + p_pic = p_vout->p_picture + i_index; + break; + } + } - if( p_vout->p_sys->var_info.xres_virtual ) - { - p_pic->p->i_pitch = p_vout->p_sys->var_info.xres_virtual - * p_vout->p_sys->i_bytes_per_pixel; - } - else - { - p_pic->p->i_pitch = p_vout->p_sys->var_info.xres - * p_vout->p_sys->i_bytes_per_pixel; - } + /* Allocate the picture */ + if( p_pic == NULL ) + { + return VLC_EGENERIC; + } - p_pic->p->i_visible_pitch = p_vout->p_sys->var_info.xres - * p_vout->p_sys->i_bytes_per_pixel; - p_pic->i_planes = 1; - p_pic->i_status = DESTROYED_PICTURE; - p_pic->i_type = DIRECT_PICTURE; + /* We know the chroma, allocate a buffer which will be used + * directly by the decoder */ + p_pic->p->p_pixels = p_vout->p_sys->p_video; + p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel; + p_pic->p->i_lines = p_vout->p_sys->var_info.yres; + p_pic->p->i_visible_lines = p_vout->p_sys->var_info.yres; + + if( p_vout->p_sys->var_info.xres_virtual ) + { + p_pic->p->i_pitch = p_vout->p_sys->var_info.xres_virtual + * p_vout->p_sys->i_bytes_per_pixel; + } + else + { + p_pic->p->i_pitch = p_vout->p_sys->var_info.xres + * p_vout->p_sys->i_bytes_per_pixel; + } + + p_pic->p->i_visible_pitch = p_vout->p_sys->var_info.xres + * p_vout->p_sys->i_bytes_per_pixel; + p_pic->i_planes = 1; + p_pic->i_status = DESTROYED_PICTURE; + p_pic->i_type = DIRECT_PICTURE; - PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; + PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; - I_OUTPUTPICTURES++; + I_OUTPUTPICTURES++; + } return VLC_SUCCESS; } @@ -481,39 +636,20 @@ static int Init( vout_thread_t *p_vout ) *****************************************************************************/ static void End( vout_thread_t *p_vout ) { - /* Clear the screen */ - memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size ); -} - -/***************************************************************************** - * Destroy: destroy FB video thread output method - ***************************************************************************** - * Terminate an output method created by Create - *****************************************************************************/ -static void Destroy( vlc_object_t *p_this ) -{ - vout_thread_t *p_vout = (vout_thread_t *)p_this; - - CloseDisplay( p_vout ); - - if( p_vout->p_sys->b_tty ) + if( !p_vout->p_sys->b_hw_accel ) { - /* Reset the terminal */ - ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &p_vout->p_sys->vt_mode ); - - /* Remove signal handlers */ - sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL ); - sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL ); + int i_index; - /* Reset the keyboard state */ - tcsetattr( 0, 0, &p_vout->p_sys->old_termios ); + /* Free the direct buffers we allocated */ + for( i_index = I_OUTPUTPICTURES ; i_index ; ) + { + i_index--; + FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] ); + } - /* Return to text mode */ - TextMode( p_vout->p_sys->i_tty ); } - - /* Destroy structure */ - free( p_vout->p_sys ); + /* Clear the screen */ + memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size ); } /***************************************************************************** @@ -610,6 +746,12 @@ static int panned=0; panned++; } } + + if( !p_vout->p_sys->b_hw_accel ) + { + vlc_memcpy( p_vout->p_sys->p_video, p_pic->p->p_pixels, + p_vout->p_sys->i_page_size ); + } } #if 0 @@ -702,7 +844,7 @@ static int OpenDisplay( vout_thread_t *p_vout ) if( (p_sys->i_height != p_sys->var_info.yres) || (p_sys->i_width != p_sys->var_info.xres) ) { - p_sys->b_auto = VLC_TRUE; + p_sys->b_auto = true; msg_Warn( p_vout, "using framebuffer native resolution instead of requested (%ix%i)", p_sys->i_width, p_sys->i_height ); @@ -729,8 +871,6 @@ static int OpenDisplay( vout_thread_t *p_vout ) p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) ); if( !p_sys->p_palette ) { - msg_Err( p_vout, "out of memory" ); - /* Restore fb config */ ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->old_info ); @@ -836,7 +976,7 @@ static void CloseDisplay( vout_thread_t *p_vout ) * This function activates or deactivates the output of the thread. It is * called by the VT driver, on terminal change. *****************************************************************************/ -static void SwitchDisplay(int i_signal) +static void SwitchDisplay( int i_signal ) { #if 0 vout_thread_t *p_vout;