Commit a2972b3c authored by Vincent Seguin's avatar Vincent Seguin

Nouvelle interface, effacement des zones modifi�es d'une image sur 2,

calcul de la taille optimale d'une image, scaling.

-Le scaling donne de bonnes tailles, mais les conversions YUV ne peuvent
pas suivre pour le moment.
-J'ai peut etre un peu cass� le fb et ggi (trop long � compiler pour tester).
En cas de probl�me, je corrige de suite.
-Les idle screens ("no stream") sont temporairement hors service.
parent 32414c55
...@@ -89,7 +89,7 @@ endif ...@@ -89,7 +89,7 @@ endif
# Libraries # Libraries
# #
LIB += -lpthread LIB += -lpthread
LIB += -lm LIN += -lm
ifeq ($(VIDEO),X11) ifeq ($(VIDEO),X11)
LIB += -L/usr/X11R6/lib LIB += -L/usr/X11R6/lib
......
...@@ -228,10 +228,17 @@ ...@@ -228,10 +228,17 @@
#define VOUT_WIDTH_DEFAULT 640 #define VOUT_WIDTH_DEFAULT 640
#define VOUT_HEIGHT_DEFAULT 480 #define VOUT_HEIGHT_DEFAULT 480
/* Default video heap size - remember that a decompressed picture is big /* Video heap size - remember that a decompressed picture is big
* (~1 Mbyte) before using huge values */ * (~1 Mbyte) before using huge values */
#define VOUT_MAX_PICTURES 10 #define VOUT_MAX_PICTURES 10
/* Maximum number of active areas in a rendering buffer. Active areas are areas
* of the picture which need to be cleared before re-using the buffer. If a
* picture, including its many additions such as subtitles, additionnal user
* informations and interface, has too many active areas, some of them are
* joined. */
#define VOUT_MAX_AREAS 5
/* Environment variable for grayscale output mode, and default value */ /* Environment variable for grayscale output mode, and default value */
#define VOUT_GRAYSCALE_VAR "vlc_grayscale" #define VOUT_GRAYSCALE_VAR "vlc_grayscale"
#define VOUT_GRAYSCALE_DEFAULT 0 #define VOUT_GRAYSCALE_DEFAULT 0
......
...@@ -117,6 +117,5 @@ typedef struct subtitle_s ...@@ -117,6 +117,5 @@ typedef struct subtitle_s
#define FREE_SUBTITLE 0 /* subtitle is free and not allocated */ #define FREE_SUBTITLE 0 /* subtitle is free and not allocated */
#define RESERVED_SUBTITLE 1 /* subtitle is allocated and reserved */ #define RESERVED_SUBTITLE 1 /* subtitle is allocated and reserved */
#define READY_SUBTITLE 2 /* subtitle is ready for display */ #define READY_SUBTITLE 2 /* subtitle is ready for display */
#define DISPLAYED_SUBTITLE 3 /* subtitle has been displayed but is linked */ #define DESTROYED_SUBTITLE 3 /* subtitle is allocated but no more used */
#define DESTROYED_SUBTITLE 4 /* subtitle is allocated but no more used */
...@@ -24,6 +24,27 @@ typedef struct vout_tables_s ...@@ -24,6 +24,27 @@ typedef struct vout_tables_s
} yuv; } yuv;
} vout_tables_t; } vout_tables_t;
/*******************************************************************************
* vout_buffer_t: rendering buffer
*******************************************************************************
* This structure store informations about a buffer. Buffers are not completely
* cleared between displays, and modified areas needs to be stored.
*******************************************************************************/
typedef struct vout_buffer_s
{
/* Picture area */
int i_pic_x, i_pic_y; /* picture position */
int i_pic_width, i_pic_height; /* picture extension */
/* Other areas - only vertical extensions of areas are stored */
int i_areas; /* number of areas */
int pi_area_begin[VOUT_MAX_AREAS]; /* beginning of area */
int pi_area_end[VOUT_MAX_AREAS]; /* end of area */
/* Picture data */
byte_t * p_data; /* memory address */
} vout_buffer_t;
/******************************************************************************* /*******************************************************************************
* vout_convert_t: convertion function * vout_convert_t: convertion function
******************************************************************************* *******************************************************************************
...@@ -70,7 +91,6 @@ typedef struct vout_thread_s ...@@ -70,7 +91,6 @@ typedef struct vout_thread_s
p_vout_sys_t p_sys; /* system output method */ p_vout_sys_t p_sys; /* system output method */
/* Current display properties */ /* Current display properties */
boolean_t b_grayscale; /* color or grayscale display */
int i_width; /* current output method width */ int i_width; /* current output method width */
int i_height; /* current output method height */ int i_height; /* current output method height */
int i_bytes_per_line;/* bytes per line (including virtual) */ int i_bytes_per_line;/* bytes per line (including virtual) */
...@@ -79,14 +99,17 @@ typedef struct vout_thread_s ...@@ -79,14 +99,17 @@ typedef struct vout_thread_s
float f_gamma; /* gamma */ float f_gamma; /* gamma */
/* Pictures and rendering properties */ /* Pictures and rendering properties */
boolean_t b_grayscale; /* color or grayscale display */
boolean_t b_info; /* print additionnal informations */ boolean_t b_info; /* print additionnal informations */
boolean_t b_interface; /* render interface */
boolean_t b_scale; /* allow picture scaling */
#ifdef STATS #ifdef STATS
/* Statistics - these numbers are not supposed to be accurate, but are a /* Statistics - these numbers are not supposed to be accurate, but are a
* good indication of the thread status */ * good indication of the thread status */
mtime_t render_time; /* last picture render time */ mtime_t render_time; /* last picture render time */
count_t c_fps_samples; /* picture counts */ count_t c_fps_samples; /* picture counts */
mtime_t fps_sample[ VOUT_FPS_SAMPLES ]; /* FPS samples dates */ mtime_t p_fps_sample[ VOUT_FPS_SAMPLES ]; /* FPS samples dates */
#endif #endif
/* Running properties */ /* Running properties */
...@@ -94,6 +117,10 @@ typedef struct vout_thread_s ...@@ -94,6 +117,10 @@ typedef struct vout_thread_s
mtime_t last_picture_date; /* last picture display date */ mtime_t last_picture_date; /* last picture display date */
mtime_t last_display_date; /* last screen display date */ mtime_t last_display_date; /* last screen display date */
/* Rendering buffers */
int i_buffer_index; /* buffer index */
vout_buffer_t p_buffer[2]; /* buffers properties */
/* Videos heap and translation tables */ /* Videos heap and translation tables */
picture_t p_picture[VOUT_MAX_PICTURES]; /* pictures */ picture_t p_picture[VOUT_MAX_PICTURES]; /* pictures */
subtitle_t p_subtitle[VOUT_MAX_PICTURES]; /* subtitles */ subtitle_t p_subtitle[VOUT_MAX_PICTURES]; /* subtitles */
...@@ -111,10 +138,12 @@ typedef struct vout_thread_s ...@@ -111,10 +138,12 @@ typedef struct vout_thread_s
* thread changed a variable */ * thread changed a variable */
#define VOUT_INFO_CHANGE 0x0001 /* b_info changed */ #define VOUT_INFO_CHANGE 0x0001 /* b_info changed */
#define VOUT_GRAYSCALE_CHANGE 0x0002 /* b_grayscale changed */ #define VOUT_GRAYSCALE_CHANGE 0x0002 /* b_grayscale changed */
#define VOUT_SIZE_CHANGE 0x0008 /* size changed */ #define VOUT_INTF_CHANGE 0x0004 /* b_interface changed */
#define VOUT_DEPTH_CHANGE 0x0010 /* depth changed */ #define VOUT_SCALE_CHANGE 0x0008 /* b_scale changed */
#define VOUT_GAMMA_CHANGE 0x0080 /* gamma changed */ #define VOUT_SIZE_CHANGE 0x0200 /* size changed */
#define VOUT_NODISPLAY_CHANGE 0xffff /* changes which forbidden display */ #define VOUT_DEPTH_CHANGE 0x0400 /* depth changed */
#define VOUT_GAMMA_CHANGE 0x0010 /* gamma changed */
#define VOUT_NODISPLAY_CHANGE 0xff00 /* changes which forbidden display */
/******************************************************************************* /*******************************************************************************
* Prototypes * Prototypes
...@@ -132,7 +161,7 @@ void vout_UnlinkPicture ( vout_thread_t *p_vout, picture_t *p_pi ...@@ -132,7 +161,7 @@ void vout_UnlinkPicture ( vout_thread_t *p_vout, picture_t *p_pi
subtitle_t * vout_CreateSubtitle ( vout_thread_t *p_vout, int i_type, int i_size ); subtitle_t * vout_CreateSubtitle ( vout_thread_t *p_vout, int i_type, int i_size );
void vout_DestroySubtitle ( vout_thread_t *p_vout, subtitle_t *p_sub ); void vout_DestroySubtitle ( vout_thread_t *p_vout, subtitle_t *p_sub );
void vout_DisplaySubtitle ( vout_thread_t *p_vout, subtitle_t *p_sub ); void vout_DisplaySubtitle ( vout_thread_t *p_vout, subtitle_t *p_sub );
void vout_ClearBuffer ( vout_thread_t *p_vout, vout_buffer_t *p_buffer );
......
...@@ -12,7 +12,6 @@ void vout_SysEnd ( p_vout_thread_t p_vout ); ...@@ -12,7 +12,6 @@ void vout_SysEnd ( p_vout_thread_t p_vout );
void vout_SysDestroy ( p_vout_thread_t p_vout ); void vout_SysDestroy ( p_vout_thread_t p_vout );
int vout_SysManage ( p_vout_thread_t p_vout ); int vout_SysManage ( p_vout_thread_t p_vout );
void vout_SysDisplay ( p_vout_thread_t p_vout ); void vout_SysDisplay ( p_vout_thread_t p_vout );
void * vout_SysGetPicture ( p_vout_thread_t p_vout );
...@@ -15,14 +15,15 @@ ...@@ -15,14 +15,15 @@
/******************************************************************************* /*******************************************************************************
* Prototypes * Prototypes
*******************************************************************************/ *******************************************************************************/
p_vout_font_t vout_LoadFont ( char *psz_name ); p_vout_font_t vout_LoadFont ( const char *psz_name );
void vout_UnloadFont ( p_vout_font_t p_font ); void vout_UnloadFont ( p_vout_font_t p_font );
void vout_TextSize ( p_vout_font_t p_font, int i_style, char *psz_text, void vout_TextSize ( p_vout_font_t p_font, int i_style,
const char *psz_text,
int *pi_width, int *pi_height ); int *pi_width, int *pi_height );
void vout_Print ( p_vout_font_t p_font, byte_t *p_pic, int i_depth, void vout_Print ( p_vout_font_t p_font, byte_t *p_pic,
int i_bytes_per_pixel, u32 i_char_color, int i_bytes_per_pixel, int i_bytes_per_line,
u32 i_border_color, u32 i_bg_color, u32 i_char_color, u32 i_border_color, u32 i_bg_color,
int i_style, char *psz_text ); int i_style, const char *psz_text );
......
...@@ -228,7 +228,16 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key ) ...@@ -228,7 +228,16 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
vlc_mutex_unlock( &p_intf->p_vout->change_lock ); vlc_mutex_unlock( &p_intf->p_vout->change_lock );
} }
break; break;
case ' ': /* toggle info */ case ' ': /* toggle interface */
if( p_intf->p_vout != NULL )
{
vlc_mutex_lock( &p_intf->p_vout->change_lock );
p_intf->p_vout->b_interface = !p_intf->p_vout->b_interface;
p_intf->p_vout->i_changes |= VOUT_INTF_CHANGE;
vlc_mutex_unlock( &p_intf->p_vout->change_lock );
}
break;
case 'i': /* toggle info */
if( p_intf->p_vout != NULL ) if( p_intf->p_vout != NULL )
{ {
vlc_mutex_lock( &p_intf->p_vout->change_lock ); vlc_mutex_lock( &p_intf->p_vout->change_lock );
...@@ -237,7 +246,16 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key ) ...@@ -237,7 +246,16 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
vlc_mutex_unlock( &p_intf->p_vout->change_lock ); vlc_mutex_unlock( &p_intf->p_vout->change_lock );
} }
break; break;
default: /* unknown key */ case 's': /* toggle scaling */
if( p_intf->p_vout != NULL )
{
vlc_mutex_lock( &p_intf->p_vout->change_lock );
p_intf->p_vout->b_scale = !p_intf->p_vout->b_scale;
p_intf->p_vout->i_changes |= VOUT_SCALE_CHANGE;
vlc_mutex_unlock( &p_intf->p_vout->change_lock );
}
break;
default: /* unknown key */
return( 1 ); return( 1 );
} }
......
...@@ -443,11 +443,13 @@ static void Usage( void ) ...@@ -443,11 +443,13 @@ static void Usage( void )
/* Interfaces keys */ /* Interfaces keys */
intf_Msg("Interface keys: most interfaces accept the following commands:\n" \ intf_Msg("Interface keys: most interfaces accept the following commands:\n" \
" [space] \ttoggle interface\n"
" [esc], q \tquit\n" \ " [esc], q \tquit\n" \
" 0 - 9 \tselect channel\n" \
" +, -, m \tchange volume, mute\n" \ " +, -, m \tchange volume, mute\n" \
" g, G, c \tchange gamma, toggle grayscale\n" \ " g, G, c \tchange gamma, toggle grayscale\n" \
" 0 - 9 \tselect channel\n" \ " i \ttoggle info printing\n" \
" [space] \ttoggle info printing\n" \ " s \ttoggle picture scaling\n" \
); );
} }
......
...@@ -41,25 +41,11 @@ typedef struct vout_sys_s ...@@ -41,25 +41,11 @@ typedef struct vout_sys_s
{ {
/* System informations */ /* System informations */
int i_fb_dev; /* framebuffer device handle */ int i_fb_dev; /* framebuffer device handle */
size_t i_page_size; /* page size */
struct fb_var_screeninfo var_info; /* framebuffer mode informations */ struct fb_var_screeninfo var_info; /* framebuffer mode informations */
/* Video memory */ /* Video memory */
byte_t * p_video; byte_t * p_video; /* base adress */
size_t i_page_size; /* page size */
/* User settings */
boolean_t b_shm; /* shared memory extension flag */
/* Font information */
int i_char_bytes_per_line; /* character width (bytes) */
int i_char_height; /* character height (lines) */
int i_char_interspacing;/* space between centers (pixels) */
byte_t * pi_font; /* pointer to font data */
/* Display buffers information */
int i_buffer_index; /* buffer index */
void * p_image[2]; /* image */
} vout_sys_t; } vout_sys_t;
/****************************************************************************** /******************************************************************************
...@@ -98,32 +84,18 @@ int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window ...@@ -98,32 +84,18 @@ int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window
/****************************************************************************** /******************************************************************************
* vout_SysInit: initialize framebuffer video thread output method * vout_SysInit: initialize framebuffer video thread output method
******************************************************************************
* This function creates the images needed by the output thread. It is called
* at the beginning of the thread, but also each time the display is resized.
******************************************************************************/ ******************************************************************************/
int vout_SysInit( vout_thread_t *p_vout ) 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 );
//memset( p_vout->p_sys->p_image[0], 0xf0, p_vout->p_sys->i_page_size );
//memset( p_vout->p_sys->p_image[1], 0x0f, p_vout->p_sys->i_page_size );
/* Set buffer index to 0 */
p_vout->p_sys->i_buffer_index = 0;
return( 0 ); return( 0 );
} }
/****************************************************************************** /******************************************************************************
* vout_SysEnd: terminate FB video thread output method * vout_SysEnd: terminate FB video thread output method
******************************************************************************
* Destroy the FB images created by vout_SysInit. It is called at the end of
* the thread, but also each time the window is resized.
******************************************************************************/ ******************************************************************************/
void vout_SysEnd( vout_thread_t *p_vout ) void vout_SysEnd( vout_thread_t *p_vout )
{ {
intf_DbgMsg("%p\n", p_vout ); ;
} }
/****************************************************************************** /******************************************************************************
...@@ -141,19 +113,10 @@ void vout_SysDestroy( vout_thread_t *p_vout ) ...@@ -141,19 +113,10 @@ void vout_SysDestroy( vout_thread_t *p_vout )
* vout_SysManage: handle FB events * vout_SysManage: handle FB events
****************************************************************************** ******************************************************************************
* This function should be called regularly by video output thread. It manages * This function should be called regularly by video output thread. It manages
* console events and allows screen resizing. It returns a non null value on * console events. It returns a non null value on error.
* error.
******************************************************************************/ ******************************************************************************/
int vout_SysManage( vout_thread_t *p_vout ) int vout_SysManage( vout_thread_t *p_vout )
{ {
/* XXX */
if( p_vout->i_changes & VOUT_SIZE_CHANGE )
{
intf_DbgMsg("resizing window\n");
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
FBBlankDisplay( p_vout );
}
return 0; return 0;
} }
...@@ -165,10 +128,6 @@ int vout_SysManage( vout_thread_t *p_vout ) ...@@ -165,10 +128,6 @@ int vout_SysManage( vout_thread_t *p_vout )
******************************************************************************/ ******************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout ) 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;
p_vout->p_sys->i_buffer_index = 0;
/* tout est bien affich, on peut changer les 2 crans */ /* tout est bien affich, on peut changer les 2 crans */
p_vout->p_sys->var_info.xoffset = 0; p_vout->p_sys->var_info.xoffset = 0;
p_vout->p_sys->var_info.yoffset = p_vout->p_sys->var_info.yoffset =
...@@ -179,16 +138,6 @@ void vout_SysDisplay( vout_thread_t *p_vout ) ...@@ -179,16 +138,6 @@ void vout_SysDisplay( vout_thread_t *p_vout )
ioctl( p_vout->p_sys->i_fb_dev, FBIOPAN_DISPLAY, &p_vout->p_sys->var_info ); ioctl( p_vout->p_sys->i_fb_dev, FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );
} }
/******************************************************************************
* vout_SysGetPicture: get current display buffer informations
******************************************************************************
* This function returns the address of the current display buffer.
******************************************************************************/
void * vout_SysGetPicture( vout_thread_t *p_vout )
{
return( p_vout->p_sys->p_image[ p_vout->p_sys->i_buffer_index ] );
}
/* following functions are local */ /* following functions are local */
/****************************************************************************** /******************************************************************************
...@@ -291,8 +240,12 @@ static int FBOpenDisplay( vout_thread_t *p_vout ) ...@@ -291,8 +240,12 @@ static int FBOpenDisplay( vout_thread_t *p_vout )
close( p_vout->p_sys->i_fb_dev ); close( p_vout->p_sys->i_fb_dev );
return( 1 ); return( 1 );
} }
p_vout->p_sys->p_image[ 0 ] = p_vout->p_sys->p_video;
p_vout->p_sys->p_image[ 1 ] = p_vout->p_sys->p_video + p_vout->p_sys->i_page_size; /* Set and initialize buffers */
p_vout->p_buffer[0].p_data = p_vout->p_sys->p_video;
p_vout->p_buffer[1].p_data = p_vout->p_sys->p_video + p_vout->p_sys->i_page_size;
vout_ClearBuffer( p_vout, &p_vout->p_buffer[0] );
vout_ClearBuffer( p_vout, &p_vout->p_buffer[1] );
intf_DbgMsg("framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d\n", 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 ); fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
...@@ -310,20 +263,6 @@ static int FBOpenDisplay( vout_thread_t *p_vout ) ...@@ -310,20 +263,6 @@ static int FBOpenDisplay( vout_thread_t *p_vout )
******************************************************************************/ ******************************************************************************/
static void FBCloseDisplay( vout_thread_t *p_vout ) static void FBCloseDisplay( vout_thread_t *p_vout )
{ {
// Free font info
free( p_vout->p_sys->pi_font );
// Destroy window and close display // Destroy window and close display
close( p_vout->p_sys->i_fb_dev ); close( p_vout->p_sys->i_fb_dev );
} }
/******************************************************************************
* FBBlankDisplay: render a blank screen
******************************************************************************
* This function is called by all other rendering functions when they arrive on
* a non blanked screen.
******************************************************************************/
static void FBBlankDisplay( vout_thread_t *p_vout )
{
memset( p_vout->p_sys->p_video, 0x00, 2*p_vout->p_sys->i_page_size );
}
...@@ -33,13 +33,8 @@ typedef struct vout_sys_s ...@@ -33,13 +33,8 @@ typedef struct vout_sys_s
ggi_visual_t p_display; /* display device */ ggi_visual_t p_display; /* display device */
/* Buffers informations */ /* Buffers informations */
int i_buffer_index; /* buffer index */
ggi_directbuffer * p_buffer[2]; /* buffers */ ggi_directbuffer * p_buffer[2]; /* buffers */
boolean_t b_must_acquire; /* must be acquired before writing */ boolean_t b_must_acquire; /* must be acquired before writing */
/* Characters size */
int i_char_width;
int i_char_height;
} vout_sys_t; } vout_sys_t;
/******************************************************************************* /*******************************************************************************
...@@ -72,7 +67,6 @@ int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window ...@@ -72,7 +67,6 @@ int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window
free( p_vout->p_sys ); free( p_vout->p_sys );
return( 1 ); return( 1 );
} }
return( 0 ); return( 0 );
} }
...@@ -84,10 +78,9 @@ int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window ...@@ -84,10 +78,9 @@ int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window
int vout_SysInit( vout_thread_t *p_vout ) int vout_SysInit( vout_thread_t *p_vout )
{ {
/* Acquire first buffer */ /* Acquire first buffer */
p_vout->p_sys->i_buffer_index = 0;
if( p_vout->p_sys->b_must_acquire ) if( p_vout->p_sys->b_must_acquire )
{ {
ggiResourceAcquire( p_vout->p_sys->p_buffer[ 0 ]->resource, GGI_ACTYPE_WRITE ); ggiResourceAcquire( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource, GGI_ACTYPE_WRITE );
} }
return( 0 ); return( 0 );
...@@ -103,7 +96,7 @@ void vout_SysEnd( vout_thread_t *p_vout ) ...@@ -103,7 +96,7 @@ void vout_SysEnd( vout_thread_t *p_vout )
/* Release buffer */ /* Release buffer */
if( p_vout->p_sys->b_must_acquire ) if( p_vout->p_sys->b_must_acquire )
{ {
ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource ); ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource );
} }
} }
...@@ -140,64 +133,20 @@ void vout_SysDisplay( vout_thread_t *p_vout ) ...@@ -140,64 +133,20 @@ void vout_SysDisplay( vout_thread_t *p_vout )
/* Change display frame */ /* Change display frame */
if( p_vout->p_sys->b_must_acquire ) if( p_vout->p_sys->b_must_acquire )
{ {
ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource ); ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource );
} }
ggiFlush( p_vout->p_sys->p_display ); // ?? ggiFlush( p_vout->p_sys->p_display ); // ??
ggiSetDisplayFrame( p_vout->p_sys->p_display, ggiSetDisplayFrame( p_vout->p_sys->p_display,
p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->frame ); p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->frame );
/* Swap buffers and change write frame */ /* Swap buffers and change write frame */
p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
if( p_vout->p_sys->b_must_acquire ) if( p_vout->p_sys->b_must_acquire )
{ {
ggiResourceAcquire( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource, ggiResourceAcquire( p_vout->p_sys->p_buffer[ (p_vout->i_buffer_index + 1) & 1]->resource,
GGI_ACTYPE_WRITE ); GGI_ACTYPE_WRITE );
} }
ggiSetWriteFrame( p_vout->p_sys->p_display, ggiSetWriteFrame( p_vout->p_sys->p_display,
p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->frame ); p_vout->p_sys->p_buffer[ (p_vout->i_buffer_index + 1) & 1]->frame );
}
/*******************************************************************************
* vout_SysGetPicture: get current display buffer informations
*******************************************************************************
* This function returns the address of the current display buffer.
*******************************************************************************/
void * vout_SysGetPicture( vout_thread_t *p_vout )
{
return( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->write );
}
/*******************************************************************************
* vout_SysPrint: print simple text on a picture
*******************************************************************************
* This function will print a simple text on the picture. It is designed to
* print debugging or general informations, not to render subtitles.
*******************************************************************************/
void vout_SysPrint( vout_thread_t *p_vout, int i_x, int i_y, int i_halign,
int i_valign, unsigned char *psz_text )
{
/* Update upper left coordinates according to alignment */
switch( i_halign )
{
case 0: /* centered */
i_x -= p_vout->p_sys->i_char_width * strlen( psz_text ) / 2;
break;
case 1: /* right aligned */
i_x -= p_vout->p_sys->i_char_width * strlen( psz_text );
break;
}
switch( i_valign )
{
case 0: /* centered */
i_y -= p_vout->p_sys->i_char_height / 2;
break;
case 1: /* bottom aligned */
i_y -= p_vout->p_sys->i_char_height;
break;
}
/* Print text */
ggiPuts( p_vout->p_sys->p_display, i_x, i_y, psz_text );
} }
/******************************************************************************* /*******************************************************************************
...@@ -373,6 +322,12 @@ static int GGIOpenDisplay( vout_thread_t *p_vout, char *psz_display ) ...@@ -373,6 +322,12 @@ static int GGIOpenDisplay( vout_thread_t *p_vout, char *psz_display )
break; break;
} }
/* Set and initialize buffers */
p_vout->p_buffer[0].p_data = p_vout->p_sys->p_buffer[ 0 ]->write;
p_vout->p_buffer[1].p_data = p_vout->p_sys->p_buffer[ 1 ]->write;
vout_ClearBuffer( p_vout, &p_vout->p_buffer[0] );
vout_ClearBuffer( p_vout, &p_vout->p_buffer[1] );
return( 0 ); return( 0 );
} }
......
...@@ -34,12 +34,17 @@ static int InitThread ( vout_thread_t *p_vout ); ...@@ -34,12 +34,17 @@ static int InitThread ( vout_thread_t *p_vout );
static void RunThread ( vout_thread_t *p_vout ); static void RunThread ( vout_thread_t *p_vout );
static void ErrorThread ( vout_thread_t *p_vout ); static void ErrorThread ( vout_thread_t *p_vout );
static void EndThread ( vout_thread_t *p_vout ); static void EndThread ( vout_thread_t *p_vout );
static void DestroyThread ( vout_thread_t *p_vout, int i_status );
static void Print ( vout_thread_t *p_vout, int i_x, int i_y, int i_halign, int i_valign, unsigned char *psz_text ); static void Print ( vout_thread_t *p_vout, int i_x, int i_y, int i_halign, int i_valign, unsigned char *psz_text );
static void RenderBlank ( vout_thread_t *p_vout );
static int RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_blank ); static void SetBufferArea ( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int i_h );
static int RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_blank ); static void SetBufferPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static int RenderIdle ( vout_thread_t *p_vout, boolean_t b_blank ); static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static int RenderInfo ( vout_thread_t *p_vout, boolean_t b_balnk ); static void RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderSubtitle ( vout_thread_t *p_vout, subtitle_t *p_sub );
static void RenderInterface ( vout_thread_t *p_vout );
static void RenderIdle ( vout_thread_t *p_vout );
static void RenderInfo ( vout_thread_t *p_vout );
static int Manage ( vout_thread_t *p_vout ); static int Manage ( vout_thread_t *p_vout );
/****************************************************************************** /******************************************************************************
...@@ -55,6 +60,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ ...@@ -55,6 +60,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
{ {
vout_thread_t * p_vout; /* thread descriptor */ vout_thread_t * p_vout; /* thread descriptor */
int i_status; /* thread status */ int i_status; /* thread status */
int i_index; /* index for array initialization */
/* Allocate descriptor */ /* Allocate descriptor */
intf_DbgMsg("\n"); intf_DbgMsg("\n");
...@@ -65,7 +71,8 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ ...@@ -65,7 +71,8 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
return( NULL ); return( NULL );
} }
/* Initialize thread properties */ /* Initialize thread properties - thread id and locks will be initialized
* later */
p_vout->b_die = 0; p_vout->b_die = 0;
p_vout->b_error = 0; p_vout->b_error = 0;
p_vout->b_active = 0; p_vout->b_active = 0;
...@@ -74,22 +81,46 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ ...@@ -74,22 +81,46 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
/* Initialize some fields used by the system-dependant method - these fields will /* Initialize some fields used by the system-dependant method - these fields will
* probably be modified by the method, and are only preferences */ * probably be modified by the method, and are only preferences */
p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR,
VOUT_GRAYSCALE_DEFAULT );
p_vout->i_width = i_width; p_vout->i_width = i_width;
p_vout->i_height = i_height; p_vout->i_height = i_height;
p_vout->i_bytes_per_line = i_width * 2; p_vout->i_bytes_per_line = i_width * 2;
p_vout->i_screen_depth = 15; p_vout->i_screen_depth = 15;
p_vout->i_bytes_per_pixel = 2; p_vout->i_bytes_per_pixel = 2;
p_vout->f_gamma = VOUT_GAMMA; p_vout->f_gamma = VOUT_GAMMA;
#ifdef DEBUG
p_vout->b_info = 1; p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR,
#else VOUT_GRAYSCALE_DEFAULT );
p_vout->b_info = 0; p_vout->b_info = 0;
#endif p_vout->b_interface = 0;
p_vout->b_scale = 0;
intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line)\n", intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line)\n",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line ); p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line );
#ifdef STATS
/* Initialize statistics fields */
p_vout->render_time = 0;
p_vout->c_fps_samples = 0;
#endif
/* Initialize running properties */
p_vout->i_changes = 0;
p_vout->last_picture_date = 0;
p_vout->last_display_date = 0;
/* Initialize buffer index */
p_vout->i_buffer_index = 0;
/* Initialize pictures and subtitles - translation tables and functions
* will be initialized later in InitThread */
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
{
p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
p_vout->p_picture[i_index].i_status = FREE_PICTURE;
p_vout->p_subtitle[i_index].i_type = EMPTY_SUBTITLE;
p_vout->p_subtitle[i_index].i_status= FREE_SUBTITLE;
}
/* Create and initialize system-dependant method - this function issues its /* Create and initialize system-dependant method - this function issues its
* own error messages */ * own error messages */
...@@ -102,7 +133,8 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ ...@@ -102,7 +133,8 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line ); p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line );
/* Load fonts */ /* Load fonts - fonts must be initialized after the systme method since
* they may be dependant of screen depth and other thread properties */
p_vout->p_default_font = vout_LoadFont( VOUT_DEFAULT_FONT ); p_vout->p_default_font = vout_LoadFont( VOUT_DEFAULT_FONT );
if( p_vout->p_default_font == NULL ) if( p_vout->p_default_font == NULL )
{ {
...@@ -117,18 +149,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_ ...@@ -117,18 +149,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
vout_SysDestroy( p_vout ); vout_SysDestroy( p_vout );
free( p_vout ); free( p_vout );
return( NULL ); return( NULL );
} }
#ifdef STATS
/* Initialize statistics fields */
p_vout->render_time = 0;
p_vout->c_fps_samples = 0;
#endif
/* Initialize running properties */
p_vout->i_changes = 0;
p_vout->last_picture_date = 0;
p_vout->last_display_date = 0;
/* Create thread and set locks */ /* Create thread and set locks */
vlc_mutex_init( &p_vout->picture_lock ); vlc_mutex_init( &p_vout->picture_lock );
...@@ -239,7 +260,7 @@ void vout_DisplaySubtitle( vout_thread_t *p_vout, subtitle_t *p_sub ) ...@@ -239,7 +260,7 @@ void vout_DisplaySubtitle( vout_thread_t *p_vout, subtitle_t *p_sub )
subtitle_t *vout_CreateSubtitle( vout_thread_t *p_vout, int i_type, subtitle_t *vout_CreateSubtitle( vout_thread_t *p_vout, int i_type,
int i_size ) int i_size )
{ {
//??? //??
} }
/****************************************************************************** /******************************************************************************
...@@ -553,6 +574,26 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -553,6 +574,26 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
} }
/******************************************************************************
* vout_ClearBuffer: clear a whole buffer
******************************************************************************
* This function is called when a buffer is initialized. It clears the whole
* buffer.
******************************************************************************/
void vout_ClearBuffer( vout_thread_t *p_vout, vout_buffer_t *p_buffer )
{
/* No picture previously */
p_buffer->i_pic_x = 0;
p_buffer->i_pic_y = 0;
p_buffer->i_pic_width = 0;
p_buffer->i_pic_height = 0;
/* The first area covers all the screen */
p_buffer->i_areas = 1;
p_buffer->pi_area_begin[0] = 0;
p_buffer->pi_area_end[0] = p_vout->i_height - 1;
}
/* following functions are local */ /* following functions are local */
/****************************************************************************** /******************************************************************************
...@@ -564,8 +605,6 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -564,8 +605,6 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
******************************************************************************/ ******************************************************************************/
static int InitThread( vout_thread_t *p_vout ) static int InitThread( vout_thread_t *p_vout )
{ {
int i_index; /* generic index */
/* Update status */ /* Update status */
intf_DbgMsg("\n"); intf_DbgMsg("\n");
*p_vout->pi_status = THREAD_START; *p_vout->pi_status = THREAD_START;
...@@ -573,19 +612,9 @@ static int InitThread( vout_thread_t *p_vout ) ...@@ -573,19 +612,9 @@ static int InitThread( vout_thread_t *p_vout )
/* Initialize output method - this function issues its own error messages */ /* Initialize output method - this function issues its own error messages */
if( vout_SysInit( p_vout ) ) if( vout_SysInit( p_vout ) )
{ {
*p_vout->pi_status = THREAD_ERROR;
return( 1 ); return( 1 );
} }
/* Initialize pictures and subtitles */
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
{
p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
p_vout->p_picture[i_index].i_status = FREE_PICTURE;
p_vout->p_subtitle[i_index].i_type = EMPTY_SUBTITLE;
p_vout->p_subtitle[i_index].i_status= FREE_SUBTITLE;
}
/* Initialize convertion tables and functions */ /* Initialize convertion tables and functions */
if( vout_InitTables( p_vout ) ) if( vout_InitTables( p_vout ) )
{ {
...@@ -609,20 +638,20 @@ static int InitThread( vout_thread_t *p_vout ) ...@@ -609,20 +638,20 @@ static int InitThread( vout_thread_t *p_vout )
******************************************************************************/ ******************************************************************************/
static void RunThread( vout_thread_t *p_vout) static void RunThread( vout_thread_t *p_vout)
{ {
int i_picture; /* picture index */ int i_index; /* index in heap */
mtime_t current_date; /* current date */ mtime_t current_date; /* current date */
mtime_t pic_date = 0; /* picture date */ mtime_t display_date; /* display date */
boolean_t b_display; /* display flag */ boolean_t b_display; /* display flag */
picture_t * p_pic; /* picture pointer */ picture_t * p_pic; /* picture pointer */
subtitle_t * p_sub; /* subtitle pointer */
/* /*
* Initialize thread and free configuration * Initialize thread
*/ */
p_vout->b_error = InitThread( p_vout ); p_vout->b_error = InitThread( p_vout );
if( p_vout->b_error ) if( p_vout->b_error )
{ {
//?? DestroyThread( p_vout, THREAD_ERROR );
free( p_vout ); /* destroy descriptor */
return; return;
} }
intf_DbgMsg("\n"); intf_DbgMsg("\n");
...@@ -632,115 +661,171 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -632,115 +661,171 @@ static void RunThread( vout_thread_t *p_vout)
* initialization * initialization
*/ */
while( (!p_vout->b_die) && (!p_vout->b_error) ) while( (!p_vout->b_die) && (!p_vout->b_error) )
{ {
/* Initialize loop variables */
p_pic = NULL;
p_sub = NULL;
display_date = 0;
current_date = mdate();
/* /*
* Find the picture to display - this operation does not need lock, * Find the picture to display - this operation does not need lock,
* since only READY_PICTURES are handled * since only READY_PICTUREs are handled
*/ */
p_pic = NULL; for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
current_date = mdate();
for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
{ {
if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) && if( (p_vout->p_picture[i_index].i_status == READY_PICTURE) &&
( (p_pic == NULL) || ( (p_pic == NULL) ||
(p_vout->p_picture[i_picture].date < pic_date) ) ) (p_vout->p_picture[i_index].date < display_date) ) )
{ {
p_pic = &p_vout->p_picture[i_picture]; p_pic = &p_vout->p_picture[i_index];
pic_date = p_pic->date; display_date = p_pic->date;
} }
} }
/*
* Render picture if any
*/
if( p_pic ) if( p_pic )
{ {
#ifdef STATS #ifdef STATS
/* Computes FPS rate */ /* Computes FPS rate */
p_vout->fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ] = pic_date; p_vout->p_fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ] = display_date;
#endif #endif
if( pic_date < current_date ) if( display_date < current_date )
{ {
/* Picture is late: it will be destroyed and the thread will sleep and /* Picture is late: it will be destroyed and the thread will sleep and
* go to next picture */ * go to next picture */
vlc_mutex_lock( &p_vout->picture_lock ); vlc_mutex_lock( &p_vout->picture_lock );
p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE; p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE;
#ifdef DEBUG_VIDEO
intf_DbgMsg( "warning: late picture %p skipped refcount=%d\n", p_pic, p_pic->i_refcount ); intf_DbgMsg( "warning: late picture %p skipped refcount=%d\n", p_pic, p_pic->i_refcount );
#endif
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
p_pic = NULL; p_pic = NULL;
display_date = 0;
} }
else if( pic_date > current_date + VOUT_DISPLAY_DELAY ) else if( display_date > current_date + VOUT_DISPLAY_DELAY )
{ {
/* A picture is ready to be rendered, but its rendering date is /* A picture is ready to be rendered, but its rendering date is
* far from the current one so the thread will perform an empty loop * far from the current one so the thread will perform an empty loop
* as if no picture were found. The picture state is unchanged */ * as if no picture were found. The picture state is unchanged */
p_pic = NULL; p_pic = NULL;
display_date = 0;
} }
} }
/*
* Find the subtitle to display - this operation does not need lock, since
* only READY_SUBTITLEs are handled. If no picture has been selected,
* display_date will depend on the subtitle
*/
//??
/* /*
* Perform rendering, sleep and display rendered picture * Perform rendering, sleep and display rendered picture
*/ */
if( p_pic ) if( p_pic ) /* picture and perhaps subtitle */
{ {
/* A picture is ready to be displayed : render it */ b_display = p_vout->b_active;
if( p_vout->b_active )
{ if( b_display )
b_display = RenderPicture( p_vout, p_pic, 1 ); {
/* Set picture dimensions and clear buffer */
SetBufferPicture( p_vout, p_pic );
/* Render picture and informations */
RenderPicture( p_vout, p_pic );
if( p_vout->b_info ) if( p_vout->b_info )
{ {
b_display |= RenderPictureInfo( p_vout, p_pic, b_display ); RenderPictureInfo( p_vout, p_pic );
b_display |= RenderInfo( p_vout, b_display ); RenderInfo( p_vout );
} }
} }
else
{
b_display = 0;
}
/* Remove picture from heap */ /* Remove picture from heap */
vlc_mutex_lock( &p_vout->picture_lock ); vlc_mutex_lock( &p_vout->picture_lock );
p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE; p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE;
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
}
else /* Render interface and subtitles */
if( b_display && p_vout->b_interface )
{
RenderInterface( p_vout );
}
if( p_sub )
{
if( b_display )
{
RenderSubtitle( p_vout, p_sub );
}
/* Remove subtitle from heap */
vlc_mutex_lock( &p_vout->subtitle_lock );
p_sub->i_status = DESTROYED_SUBTITLE;
vlc_mutex_unlock( &p_vout->subtitle_lock );
}
}
else if( p_sub ) /* subtitle alone */
{ {
/* No picture. However, an idle screen may be ready to display */ b_display = p_vout->b_active;
if( p_vout->b_active )
if( b_display )
{ {
b_display = RenderIdle( p_vout, 1 ); /* Clear buffer */
SetBufferPicture( p_vout, NULL );
/* Render informations, interface and subtitle */
if( p_vout->b_info ) if( p_vout->b_info )
{ {
b_display |= RenderInfo( p_vout, b_display ); RenderInfo( p_vout );
} }
} if( p_vout->b_interface )
else {
{ RenderInterface( p_vout );
b_display = 0; }
RenderSubtitle( p_vout, p_sub );
} }
/* Remove subtitle from heap */
vlc_mutex_lock( &p_vout->subtitle_lock );
p_sub->i_status = DESTROYED_SUBTITLE;
vlc_mutex_unlock( &p_vout->subtitle_lock );
}
else /* idle screen alone */
{
//??? render on idle screen or interface change
b_display = 0; //???
} }
/*
* Sleep, wake up and display rendered picture
*/
#ifdef STATS
/* Store render time */
p_vout->render_time = mdate() - current_date;
#endif
/* Give back change lock */ /* Give back change lock */
vlc_mutex_unlock( &p_vout->change_lock ); vlc_mutex_unlock( &p_vout->change_lock );
/* Sleep a while or until a given date */ /* Sleep a while or until a given date */
if( p_pic ) if( display_date != 0 )
{ {
mwait( pic_date ); mwait( display_date );
} }
else else
{ {
msleep( VOUT_IDLE_SLEEP ); msleep( VOUT_IDLE_SLEEP );
} }
/* On awakening, take back lock and send immediately picture to display */ /* On awakening, take back lock and send immediately picture to display,
* then swap buffers */
vlc_mutex_lock( &p_vout->change_lock ); vlc_mutex_lock( &p_vout->change_lock );
if( b_display && p_vout->b_active && #ifdef DEBUG_VIDEO
!(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) ) intf_DbgMsg( "picture %p, subtitle %p\n", p_pic, p_sub );
#endif
if( b_display && !(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) )
{ {
vout_SysDisplay( p_vout ); vout_SysDisplay( p_vout );
p_vout->i_buffer_index = ++p_vout->i_buffer_index & 1;
} }
/* /*
...@@ -756,7 +841,7 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -756,7 +841,7 @@ static void RunThread( vout_thread_t *p_vout)
} }
/* /*
* Error loop * Error loop - wait until the thread destruction is requested
*/ */
if( p_vout->b_error ) if( p_vout->b_error )
{ {
...@@ -765,6 +850,7 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -765,6 +850,7 @@ static void RunThread( vout_thread_t *p_vout)
/* End of thread */ /* End of thread */
EndThread( p_vout ); EndThread( p_vout );
DestroyThread( p_vout, THREAD_OVER );
intf_DbgMsg( "thread end\n" ); intf_DbgMsg( "thread end\n" );
} }
...@@ -786,43 +872,58 @@ static void ErrorThread( vout_thread_t *p_vout ) ...@@ -786,43 +872,58 @@ static void ErrorThread( vout_thread_t *p_vout )
} }
} }
/****************************************************************************** /*******************************************************************************
* EndThread: thread destruction * EndThread: thread destruction
****************************************************************************** *******************************************************************************
* This function is called when the thread ends after a sucessfull * This function is called when the thread ends after a sucessfull
* initialization. * initialization. It frees all ressources allocated by InitThread.
******************************************************************************/ *******************************************************************************/
static void EndThread( vout_thread_t *p_vout ) static void EndThread( vout_thread_t *p_vout )
{ {
int * pi_status; /* thread status */ int i_index; /* index in heap */
int i_picture;
/* Store status */ /* Store status */
intf_DbgMsg("\n"); intf_DbgMsg("\n");
pi_status = p_vout->pi_status; *p_vout->pi_status = THREAD_END;
*pi_status = THREAD_END;
/* Destroy all remaining pictures */ /* Destroy all remaining pictures and subtitles */
for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ ) for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
{ {
if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE ) if( p_vout->p_picture[i_index].i_status != FREE_PICTURE )
{ {
free( p_vout->p_picture[i_picture].p_data ); free( p_vout->p_picture[i_index].p_data );
} }
if( p_vout->p_subtitle[i_index].i_status != FREE_SUBTITLE )
{
free( p_vout->p_subtitle[i_index].p_data );
}
} }
/* Destroy translation tables */ /* Destroy translation tables */
vout_EndTables( p_vout ); vout_EndTables( p_vout );
vout_SysEnd( p_vout );
}
/*******************************************************************************
* DestroyThread: thread destruction
*******************************************************************************
* This function is called when the thread ends. It frees all ressources
* allocated by CreateThread. Status is available at this stage.
*******************************************************************************/
static void DestroyThread( vout_thread_t *p_vout, int i_status )
{
int *pi_status; /* status adress */
/* Store status adress */
intf_DbgMsg("\n");
pi_status = p_vout->pi_status;
/* Destroy thread structures allocated by Create and InitThread */ /* Destroy thread structures allocated by Create and InitThread */
vout_SysEnd( p_vout );
vout_UnloadFont( p_vout->p_default_font ); vout_UnloadFont( p_vout->p_default_font );
vout_UnloadFont( p_vout->p_large_font ); vout_UnloadFont( p_vout->p_large_font );
vout_SysDestroy( p_vout ); vout_SysDestroy( p_vout );
free( p_vout ); free( p_vout );
*pi_status = i_status;
/* Update status */
*pi_status = THREAD_OVER;
} }
/******************************************************************************* /*******************************************************************************
...@@ -865,55 +966,308 @@ void Print( vout_thread_t *p_vout, int i_x, int i_y, int i_halign, int i_valign, ...@@ -865,55 +966,308 @@ void Print( vout_thread_t *p_vout, int i_x, int i_y, int i_halign, int i_valign,
return; return;
} }
/* Print text */ /* Set area and print text */
vout_Print( p_vout->p_default_font, vout_SysGetPicture( p_vout ) + SetBufferArea( p_vout, i_x, i_y, i_text_width, i_text_height );
vout_Print( p_vout->p_default_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
i_y * p_vout->i_bytes_per_line + i_x * p_vout->i_bytes_per_pixel, i_y * p_vout->i_bytes_per_line + i_x * p_vout->i_bytes_per_pixel,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
0xffffffff, 0x00000000, 0x00000000, 0, psz_text ); 0xffffffff, 0x00000000, 0x00000000, TRANSPARENT_TEXT, psz_text );
} }
/****************************************************************************** /*******************************************************************************
* RenderBlank: render a blank screen * SetBufferArea: activate an area in current buffer
****************************************************************************** *******************************************************************************
* This function is called by all other rendering functions when they arrive on * This function is called when something is rendered on the current buffer.
* a non blanked screen. * It set the area as active and prepare it to be cleared on next rendering.
******************************************************************************/ * Pay attention to the fact that in this functions, i_h is in fact the end y
static void RenderBlank( vout_thread_t *p_vout ) * coordinate of the new area.
*******************************************************************************/
static void SetBufferArea( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int i_h )
{ {
//?? toooooo slow vout_buffer_t * p_buffer; /* current buffer */
int i_index; /* current 64 bits sample */ int i_area_begin, i_area_end; /* area vertical extension */
int i_width; /* number of 64 bits samples */ int i_area, i_area_copy; /* area index */
u64 *p_pic; /* pointer to 64 bits samples */ int i_area_shift; /* shift distance for areas */
/* Initialize variables */ /* Choose buffer and modify h to end of area position */
p_pic = vout_SysGetPicture( p_vout ); p_buffer = &p_vout->p_buffer[ p_vout->i_buffer_index ];
i_width = p_vout->i_bytes_per_line * p_vout->i_height / 256; i_h += i_y - 1;
/*
* Remove part of the area which is inside the picture - this is done
* by calling again SetBufferArea with the correct areas dimensions.
*/
if( (i_x >= p_buffer->i_pic_x) && (i_x + i_w <= p_buffer->i_pic_x + p_buffer->i_pic_width) )
{
i_area_begin = p_buffer->i_pic_y;
i_area_end = i_area_begin + p_buffer->i_pic_height - 1;
if( ((i_y >= i_area_begin) && (i_y <= i_area_end)) ||
((i_h >= i_area_begin) && (i_h <= i_area_end)) ||
((i_y < i_area_begin) && (i_h > i_area_end)) )
{
/* Keep the stripe above the picture, if any */
if( i_y < i_area_begin )
{
SetBufferArea( p_vout, i_x, i_y, i_w, i_area_begin - i_y );
}
/* Keep the stripe below the picture, if any */
if( i_h > i_area_end )
{
SetBufferArea( p_vout, i_x, i_area_end, i_w, i_h - i_area_end );
}
return;
}
}
/* Clear beginning of screen by 256 bytes blocks */ /* Skip some extensions until interesting areas */
for( i_index = 0; i_index < i_width; i_index++ ) for( i_area = 0;
(i_area < p_buffer->i_areas) &&
(p_buffer->pi_area_end[i_area] + 1 <= i_y);
i_area++ )
{ {
*p_pic++ = 0; *p_pic++ = 0; ;
*p_pic++ = 0; *p_pic++ = 0; }
*p_pic++ = 0; *p_pic++ = 0;
*p_pic++ = 0; *p_pic++ = 0; if( i_area == p_buffer->i_areas )
*p_pic++ = 0; *p_pic++ = 0; {
*p_pic++ = 0; *p_pic++ = 0; /* New area is below all existing ones: just add it at the end of the
*p_pic++ = 0; *p_pic++ = 0; * array, if possible - else, append it to the last one */
*p_pic++ = 0; *p_pic++ = 0; if( i_area < VOUT_MAX_AREAS )
*p_pic++ = 0; *p_pic++ = 0; {
*p_pic++ = 0; *p_pic++ = 0; p_buffer->pi_area_begin[i_area] = i_y;
*p_pic++ = 0; *p_pic++ = 0; p_buffer->pi_area_end[i_area] = i_h;
*p_pic++ = 0; *p_pic++ = 0; p_buffer->i_areas++;
*p_pic++ = 0; *p_pic++ = 0; }
*p_pic++ = 0; *p_pic++ = 0; else
*p_pic++ = 0; *p_pic++ = 0; {
*p_pic++ = 0; *p_pic++ = 0; #ifdef DEBUG_VIDEO
intf_DbgMsg("areas overflow\n");
#endif
p_buffer->pi_area_end[VOUT_MAX_AREAS - 1] = i_h;
}
} }
else
{
i_area_begin = p_buffer->pi_area_begin[i_area];
i_area_end = p_buffer->pi_area_end[i_area];
if( i_y < i_area_begin )
{
if( i_h >= i_area_begin - 1 )
{
/* Extend area above */
p_buffer->pi_area_begin[i_area] = i_y;
}
else
{
/* Create a new area above : merge last area if overflow, then
* move all old areas down */
if( p_buffer->i_areas == VOUT_MAX_AREAS )
{
#ifdef DEBUG_VIDEO
intf_DbgMsg("areas overflow\n");
#endif
p_buffer->pi_area_end[VOUT_MAX_AREAS - 2] = p_buffer->pi_area_end[VOUT_MAX_AREAS - 1];
}
else
{
p_buffer->i_areas++;
}
for( i_area_copy = p_buffer->i_areas - 1; i_area_copy > i_area; i_area_copy++ )
{
p_buffer->pi_area_begin[i_area_copy] = p_buffer->pi_area_begin[i_area_copy - 1];
p_buffer->pi_area_end[i_area_copy] = p_buffer->pi_area_end[i_area_copy - 1];
}
p_buffer->pi_area_begin[i_area] = i_y;
p_buffer->pi_area_end[i_area] = i_h;
return;
}
}
if( i_h > i_area_end )
{
/* Find further areas which can be merged with the new one */
for( i_area_copy = i_area + 1;
(i_area_copy < p_buffer->i_areas) &&
(p_buffer->pi_area_begin[i_area] <= i_h);
i_area_copy++ )
{
;
}
i_area_copy--;
/* Clear last pixels */ if( i_area_copy != i_area )
//?? {
/* Merge with last possible areas */
p_buffer->pi_area_end[i_area] = MAX( i_h, p_buffer->pi_area_end[i_area_copy] );
/* Shift lower areas upward */
i_area_shift = i_area_copy - i_area;
p_buffer->i_areas -= i_area_shift;
for( i_area_copy = i_area + 1; i_area_copy < p_buffer->i_areas; i_area_copy++ )
{
p_buffer->pi_area_begin[i_area_copy] = p_buffer->pi_area_begin[i_area_copy + i_area_shift];
p_buffer->pi_area_end[i_area_copy] = p_buffer->pi_area_end[i_area_copy + i_area_shift];
}
}
else
{
/* Extend area below */
p_buffer->pi_area_end[i_area] = i_h;
}
}
}
} }
/*******************************************************************************
* SetBufferPicture: clear buffer and set picture area
*******************************************************************************
* This function is called before any rendering. It clears the current
* rendering buffer and set the new picture area. If the picture pointer is
* NULL, then no picture area is defined. Floating operations are avoided since
* some MMX calculations may follow.
*******************************************************************************/
static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vout_buffer_t * p_buffer; /* current buffer */
int i_pic_x, i_pic_y; /* picture position */
int i_pic_width, i_pic_height; /* picture dimensions */
int i_old_pic_y, i_old_pic_height; /* old picture area */
int i_vout_width, i_vout_height; /* display dimensions */
int i_area; /* area index */
int i_data_index; /* area data index */
int i_data_size; /* area data size, in 256 bytes blocs */
u64 * p_data; /* area data */
/* Choose buffer and set display dimensions */
p_buffer = &p_vout->p_buffer[ p_vout->i_buffer_index ];
i_vout_width = p_vout->i_width;
i_vout_height = p_vout->i_height;
/*
* Computes new picture size
*/
if( p_pic != NULL )
{
/* Try horizontal scaling first */
i_pic_width = ( p_vout->b_scale || (p_pic->i_width > i_vout_width)) ?
i_vout_width : p_pic->i_width;
i_pic_width = i_pic_width / 16 * 16; //?? currently, width must be multiple of 16
switch( p_pic->i_aspect_ratio )
{
case AR_3_4_PICTURE:
i_pic_height = i_pic_width * 3 / 4;
break;
case AR_16_9_PICTURE:
i_pic_height = i_pic_width * 9 / 16;
break;
case AR_221_1_PICTURE:
i_pic_height = i_pic_width * 100 / 221;
break;
case AR_SQUARE_PICTURE:
default:
i_pic_height = p_pic->i_height * i_pic_width / p_pic->i_width;
break;
}
/* If picture dimensions using horizontal scaling are too large, use
* vertical scaling */
if( i_pic_height > i_vout_height )
{
i_pic_height = ( p_vout->b_scale || (p_pic->i_height > i_vout_height)) ?
i_vout_height : p_pic->i_height;
switch( p_pic->i_aspect_ratio )
{
case AR_3_4_PICTURE:
i_pic_width = i_pic_height * 4 / 3;
break;
case AR_16_9_PICTURE:
i_pic_width = i_pic_height * 16 / 9;
break;
case AR_221_1_PICTURE:
i_pic_width = i_pic_height * 221 / 100;
break;
case AR_SQUARE_PICTURE:
default:
i_pic_width = p_pic->i_width * i_pic_height / p_pic->i_height;
break;
}
i_pic_width = i_pic_width / 16 * 16; //?? currently, width must be multiple of 16
}
/* Set picture position */
i_pic_x = (p_vout->i_width - i_pic_width) / 2;
i_pic_y = (p_vout->i_height - i_pic_height) / 2;
}
else
{
/* No picture: size is 0 */
i_pic_x = 0;
i_pic_y = 0;
i_pic_width = 0;
i_pic_height = 0;
}
/*
* Set new picture size - if is is smaller than the previous one, clear
* around it. Since picture are centered, only their size is tested.
*/
if( (p_buffer->i_pic_width > i_pic_width) || (p_buffer->i_pic_height > i_pic_height) )
{
i_old_pic_y = p_buffer->i_pic_y;
i_old_pic_height = p_buffer->i_pic_height;
p_buffer->i_pic_x = i_pic_x;
p_buffer->i_pic_y = i_pic_y;
p_buffer->i_pic_width = i_pic_width;
p_buffer->i_pic_height = i_pic_height;
SetBufferArea( p_vout, 0, i_old_pic_y, p_vout->i_width, i_old_pic_height );
}
else
{
p_buffer->i_pic_x = i_pic_x;
p_buffer->i_pic_y = i_pic_y;
p_buffer->i_pic_width = i_pic_width;
p_buffer->i_pic_height = i_pic_height;
}
/*
* Clear areas
*/
for( i_area = 0; i_area < p_buffer->i_areas; i_area++ )
{
#ifdef DEBUG_VIDEO
intf_DbgMsg("clearing picture %p area: %d-%d\n", p_pic,
p_buffer->pi_area_begin[i_area], p_buffer->pi_area_end[i_area]);
#endif
p_data = (u64*) (p_buffer->p_data + p_vout->i_bytes_per_line * p_buffer->pi_area_begin[i_area]);
i_data_size = (p_buffer->pi_area_end[i_area] - p_buffer->pi_area_begin[i_area] + 1) *
p_vout->i_bytes_per_line / 256;
for( i_data_index = 0; i_data_index < i_data_size; i_data_index++ )
{
/* Clear 256 bytes block */
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
*p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0;
}
i_data_size = (p_buffer->pi_area_end[i_area] - p_buffer->pi_area_begin[i_area] + 1) *
p_vout->i_bytes_per_line % 256 / 4;
for( i_data_index = 0; i_data_index < i_data_size; i_data_index++ )
{
/* Clear remaining 4 bytes blocks */
*p_data++ = 0;
}
}
/*
* Clear areas array
*/
p_buffer->i_areas = 0;
}
/****************************************************************************** /******************************************************************************
* RenderPicture: render a picture * RenderPicture: render a picture
...@@ -923,66 +1277,35 @@ static void RenderBlank( vout_thread_t *p_vout ) ...@@ -923,66 +1277,35 @@ static void RenderBlank( vout_thread_t *p_vout )
* rendered picture has been determined as existant, and will only be destroyed * rendered picture has been determined as existant, and will only be destroyed
* by the vout thread later. * by the vout thread later.
******************************************************************************/ ******************************************************************************/
static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_blank ) static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
{ {
int i_display_height, i_display_width; /* display dimensions */ vout_buffer_t * p_buffer; /* rendering buffer */
int i_height, i_width; /* source picture dimensions */ byte_t * p_convert_dst; /* convertion destination */
int i_scaled_height; /* scaled height of the picture */ int i_width, i_height, i_eol, i_pic_eol, i_scale; /* ?? tmp variables*/
int i_aspect_scale; /* aspect ratio vertical scale */
int i_eol; /* end of line offset for source */
byte_t * p_convert_dst; /* convertion destination */
#ifdef STATS /* Get and set rendering informations */
/* Start recording render time */ p_buffer = &p_vout->p_buffer[ p_vout->i_buffer_index ];
p_vout->render_time = mdate();
#endif
/* Mark last picture date */
p_vout->last_picture_date = p_pic->date; p_vout->last_picture_date = p_pic->date;
i_width = p_pic->i_width; p_convert_dst = p_buffer->p_data + p_buffer->i_pic_x * p_vout->i_bytes_per_pixel +
i_height = p_pic->i_height; p_buffer->i_pic_y * p_vout->i_bytes_per_line;
i_display_width = p_vout->i_width;
i_display_height = p_vout->i_height; // ?? temporary section: rebuild aspect scale from size informations.
// ?? when definitive convertion prototype will be used, those info will
/* Select scaling depending of aspect ratio */ // ?? no longer be required
switch( p_pic->i_aspect_ratio ) i_width = MIN( p_pic->i_width, p_buffer->i_pic_width );
{ i_eol = p_pic->i_width - i_width / 16 * 16;
case AR_3_4_PICTURE: i_pic_eol = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
i_aspect_scale = (4 * i_height - 3 * i_width) ? if( p_pic->i_height == p_buffer->i_pic_height )
1 + 3 * i_width / ( 4 * i_height - 3 * i_width ) : 0; {
break; i_scale = 0;
case AR_16_9_PICTURE: }
i_aspect_scale = ( 16 * i_height - 9 * i_width ) ?
1 + 9 * i_width / ( 16 * i_height - 9 * i_width ) : 0;
break;
case AR_221_1_PICTURE:
i_aspect_scale = ( 221 * i_height - 100 * i_width ) ?
1 + 100 * i_width / ( 221 * i_height - 100 * i_width ) : 0;
break;
case AR_SQUARE_PICTURE:
default:
i_aspect_scale = 0;
}
i_scaled_height = (i_aspect_scale ? i_height * (i_aspect_scale - 1) / i_aspect_scale : i_height);
/* Crop picture if too large for the screen */
if( i_width > i_display_width )
{
i_eol = i_width - i_display_width / 16 * 16;
i_width = i_display_width / 16 * 16;
}
else else
{ {
i_eol = 0; i_scale = p_pic->i_height / (p_pic->i_height - p_buffer->i_pic_height);
}
if( i_scaled_height > i_display_height )
{
i_height = (i_aspect_scale * i_display_height / (i_aspect_scale - 1)) / 2 * 2;
i_scaled_height = i_display_height;
} }
p_convert_dst = vout_SysGetPicture( p_vout ) + i_eol = p_pic->i_width - p_buffer->i_pic_width;
( i_display_width - i_width ) / 2 * p_vout->i_bytes_per_pixel + i_height = p_pic->i_height * i_width / p_pic->i_width;
( i_display_height - i_scaled_height ) / 2 * p_vout->i_bytes_per_line; // ?? end of temporary code
/* /*
* Choose appropriate rendering function and render picture * Choose appropriate rendering function and render picture
...@@ -992,23 +1315,20 @@ static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_b ...@@ -992,23 +1315,20 @@ static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_b
case YUV_420_PICTURE: case YUV_420_PICTURE:
p_vout->p_ConvertYUV420( p_vout, p_convert_dst, p_vout->p_ConvertYUV420( p_vout, p_convert_dst,
p_pic->p_y, p_pic->p_u, p_pic->p_v, p_pic->p_y, p_pic->p_u, p_pic->p_v,
i_width, i_height, i_eol, i_width, i_height, i_eol, i_pic_eol, i_scale,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width, p_pic->i_matrix_coefficients );
i_aspect_scale, p_pic->i_matrix_coefficients );
break; break;
case YUV_422_PICTURE: case YUV_422_PICTURE:
p_vout->p_ConvertYUV422( p_vout, p_convert_dst, p_vout->p_ConvertYUV422( p_vout, p_convert_dst,
p_pic->p_y, p_pic->p_u, p_pic->p_v, p_pic->p_y, p_pic->p_u, p_pic->p_v,
i_width, i_height, i_eol, i_width, i_height, i_eol, i_pic_eol, i_scale,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width, p_pic->i_matrix_coefficients );
i_aspect_scale, p_pic->i_matrix_coefficients );
break; break;
case YUV_444_PICTURE: case YUV_444_PICTURE:
p_vout->p_ConvertYUV444( p_vout, p_convert_dst, p_vout->p_ConvertYUV444( p_vout, p_convert_dst,
p_pic->p_y, p_pic->p_u, p_pic->p_v, p_pic->p_y, p_pic->p_u, p_pic->p_v,
i_width, i_height, i_eol, i_width, i_height, i_eol, i_pic_eol, i_scale,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width, p_pic->i_matrix_coefficients );
i_aspect_scale, p_pic->i_matrix_coefficients );
break; break;
#ifdef DEBUG #ifdef DEBUG
default: default:
...@@ -1016,12 +1336,6 @@ static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_b ...@@ -1016,12 +1336,6 @@ static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_b
break; break;
#endif #endif
} }
#ifdef STATS
/* End recording render time */
p_vout->render_time = mdate() - p_vout->render_time;
#endif
return( 1 );
} }
/****************************************************************************** /******************************************************************************
...@@ -1030,9 +1344,11 @@ static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_b ...@@ -1030,9 +1344,11 @@ static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_b
* This function will print informations such as fps and other picture * This function will print informations such as fps and other picture
* dependant informations. * dependant informations.
******************************************************************************/ ******************************************************************************/
static int RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_blank ) static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic )
{ {
#if defined(STATS) || defined(DEBUG)
char psz_buffer[256]; /* string buffer */ char psz_buffer[256]; /* string buffer */
#endif
#ifdef STATS #ifdef STATS
/* /*
...@@ -1041,24 +1357,24 @@ static int RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic, boolean_t ...@@ -1041,24 +1357,24 @@ static int RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic, boolean_t
if( p_vout->c_fps_samples > VOUT_FPS_SAMPLES ) if( p_vout->c_fps_samples > VOUT_FPS_SAMPLES )
{ {
sprintf( psz_buffer, "%.2f fps", (double) VOUT_FPS_SAMPLES * 1000000 / sprintf( psz_buffer, "%.2f fps", (double) VOUT_FPS_SAMPLES * 1000000 /
( p_vout->fps_sample[ (p_vout->c_fps_samples - 1) % VOUT_FPS_SAMPLES ] - ( p_vout->p_fps_sample[ (p_vout->c_fps_samples - 1) % VOUT_FPS_SAMPLES ] -
p_vout->fps_sample[ p_vout->c_fps_samples % VOUT_FPS_SAMPLES ] ) ); p_vout->p_fps_sample[ p_vout->c_fps_samples % VOUT_FPS_SAMPLES ] ) );
Print( p_vout, p_vout->i_width, 0, 1, -1, psz_buffer ); Print( p_vout, p_vout->i_width, 0, 1, -1, psz_buffer );
} }
/* /*
* Print frames count and loop time in upper left corner * Print frames count and loop time in upper left corner
*/ */
sprintf( psz_buffer, "%ld frames render time: %lu us", sprintf( psz_buffer, "%ld frames rendering: %ld us",
p_vout->c_fps_samples, (long unsigned) p_vout->render_time ); (long) p_vout->c_fps_samples, (long) p_vout->render_time );
Print( p_vout, 0, 0, -1, -1, psz_buffer ); Print( p_vout, 0, 0, -1, -1, psz_buffer );
#endif #endif
#ifdef DEBUG #ifdef DEBUG
/* /*
* Print picture information in lower right corner * Print picture information in lower right corner
*/ */
sprintf( psz_buffer, "%s picture %dx%d (%dx%d%+d%+d %s)", sprintf( psz_buffer, "%s picture %dx%d (%dx%d%+d%+d %s) -> %dx%d+%d+%d",
(p_pic->i_type == YUV_420_PICTURE) ? "4:2:0" : (p_pic->i_type == YUV_420_PICTURE) ? "4:2:0" :
((p_pic->i_type == YUV_422_PICTURE) ? "4:2:2" : ((p_pic->i_type == YUV_422_PICTURE) ? "4:2:2" :
((p_pic->i_type == YUV_444_PICTURE) ? "4:4:4" : "ukn-type")), ((p_pic->i_type == YUV_444_PICTURE) ? "4:4:4" : "ukn-type")),
...@@ -1068,33 +1384,25 @@ static int RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic, boolean_t ...@@ -1068,33 +1384,25 @@ static int RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic, boolean_t
(p_pic->i_aspect_ratio == AR_SQUARE_PICTURE) ? "sq" : (p_pic->i_aspect_ratio == AR_SQUARE_PICTURE) ? "sq" :
((p_pic->i_aspect_ratio == AR_3_4_PICTURE) ? "4:3" : ((p_pic->i_aspect_ratio == AR_3_4_PICTURE) ? "4:3" :
((p_pic->i_aspect_ratio == AR_16_9_PICTURE) ? "16:9" : ((p_pic->i_aspect_ratio == AR_16_9_PICTURE) ? "16:9" :
((p_pic->i_aspect_ratio == AR_221_1_PICTURE) ? "2.21:1" : "ukn-ar" )))); ((p_pic->i_aspect_ratio == AR_221_1_PICTURE) ? "2.21:1" : "ukn-ar" ))),
p_vout->p_buffer[ p_vout->i_buffer_index ].i_pic_width,
p_vout->p_buffer[ p_vout->i_buffer_index ].i_pic_height,
p_vout->p_buffer[ p_vout->i_buffer_index ].i_pic_x,
p_vout->p_buffer[ p_vout->i_buffer_index ].i_pic_y );
Print( p_vout, p_vout->i_width, p_vout->i_height, 1, 1, psz_buffer ); Print( p_vout, p_vout->i_width, p_vout->i_height, 1, 1, psz_buffer );
#endif #endif
return( 0 );
} }
/****************************************************************************** /******************************************************************************
* RenderIdle: render idle picture * RenderIdle: render idle picture
****************************************************************************** ******************************************************************************
* This function will clear the display or print a logo. * This function will print something on the screen.
******************************************************************************/ ******************************************************************************/
static int RenderIdle( vout_thread_t *p_vout, boolean_t b_blank ) static void RenderIdle( vout_thread_t *p_vout )
{ {
/* Blank screen if required */ //??
if( (mdate() - p_vout->last_picture_date > VOUT_IDLE_DELAY) && Print( p_vout, p_vout->i_width / 2, p_vout->i_height / 2, 0, 0,
(p_vout->last_picture_date > p_vout->last_display_date) && "no stream" ); //??
b_blank )
{
RenderBlank( p_vout );
p_vout->last_display_date = mdate();
Print( p_vout, p_vout->i_width / 2, p_vout->i_height / 2, 0, 0,
"no stream" ); //??
return( 1 );
}
return( 0 );
} }
/****************************************************************************** /******************************************************************************
...@@ -1103,10 +1411,10 @@ static int RenderIdle( vout_thread_t *p_vout, boolean_t b_blank ) ...@@ -1103,10 +1411,10 @@ static int RenderIdle( vout_thread_t *p_vout, boolean_t b_blank )
* This function render informations which do not depend of the current picture * This function render informations which do not depend of the current picture
* rendered. * rendered.
******************************************************************************/ ******************************************************************************/
static int RenderInfo( vout_thread_t *p_vout, boolean_t b_blank ) static void RenderInfo( vout_thread_t *p_vout )
{ {
char psz_buffer[256]; /* string buffer */
#ifdef DEBUG #ifdef DEBUG
char psz_buffer[256]; /* string buffer */
int i_ready_pic = 0; /* ready pictures */ int i_ready_pic = 0; /* ready pictures */
int i_reserved_pic = 0; /* reserved pictures */ int i_reserved_pic = 0; /* reserved pictures */
int i_picture; /* picture index */ int i_picture; /* picture index */
...@@ -1130,14 +1438,70 @@ static int RenderInfo( vout_thread_t *p_vout, boolean_t b_blank ) ...@@ -1130,14 +1438,70 @@ static int RenderInfo( vout_thread_t *p_vout, boolean_t b_blank )
break; break;
} }
} }
sprintf( psz_buffer, "%dx%d:%d g%+.2f pic: %d/%d/%d", sprintf( psz_buffer, "pic: %d/%d/%d",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, i_reserved_pic, i_ready_pic, VOUT_MAX_PICTURES );
p_vout->f_gamma, i_reserved_pic, i_ready_pic,
VOUT_MAX_PICTURES );
Print( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer ); Print( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer );
#endif #endif
}
/*******************************************************************************
* RenderSubtitle: render a subtitle
*******************************************************************************
* This function render a subtitle.
*******************************************************************************/
static void RenderSubtitle( vout_thread_t *p_vout, subtitle_t *p_sub )
{
//??
}
/*******************************************************************************
* RenderInterface: render the interface
*******************************************************************************
* This function render the interface, if any.
* ?? this is obviously only a temporary interface !
*******************************************************************************/
static void RenderInterface( vout_thread_t *p_vout )
{
int i_height, i_text_height; /* total and text height */
int i_width_1, i_width_2; /* text width */
int i_byte; /* byte index */
const char *psz_text_1 = "[1-9] Channel [i]nfo [c]olor [g/G]amma";
const char *psz_text_2 = "[+/-] Volume [m]ute [s]caling [Q]uit";
/* Get text size */
vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT | TRANSPARENT_TEXT, psz_text_1, &i_width_1, &i_height );
vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT | TRANSPARENT_TEXT, psz_text_2, &i_width_2, &i_text_height );
i_height += i_text_height;
/* Render background - effective background color will depend of the screen
* depth */
for( i_byte = (p_vout->i_height - i_height) * p_vout->i_bytes_per_line;
i_byte < p_vout->i_height * p_vout->i_bytes_per_line;
i_byte++ )
{
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data[ i_byte ] = 0x33;
}
return( 0 ); /* Render text, if not larger than screen */
if( i_width_1 < p_vout->i_width )
{
vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
(p_vout->i_height - i_height) * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
0xffffffff, 0x00000000, 0x00000000,
OUTLINED_TEXT | TRANSPARENT_TEXT, psz_text_1 );
}
if( i_width_2 < p_vout->i_width )
{
vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
(p_vout->i_height - i_height + i_text_height) * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
0xffffffff, 0x00000000, 0x00000000,
OUTLINED_TEXT | TRANSPARENT_TEXT, psz_text_2 );
}
/* Activate modified area */
SetBufferArea( p_vout, 0, p_vout->i_height - i_height, p_vout->i_width, i_height );
} }
/****************************************************************************** /******************************************************************************
...@@ -1147,6 +1511,14 @@ static int RenderInfo( vout_thread_t *p_vout, boolean_t b_blank ) ...@@ -1147,6 +1511,14 @@ static int RenderInfo( vout_thread_t *p_vout, boolean_t b_blank )
******************************************************************************/ ******************************************************************************/
static int Manage( vout_thread_t *p_vout ) static int Manage( vout_thread_t *p_vout )
{ {
#ifdef DEBUG_VIDEO
if( p_vout->i_changes )
{
intf_DbgMsg("changes: 0x%x (no display: 0x%x)\n", p_vout->i_changes,
p_vout->i_changes & VOUT_NODISPLAY_CHANGE );
}
#endif
/* On gamma or grayscale change, rebuild tables */ /* On gamma or grayscale change, rebuild tables */
if( p_vout->i_changes & (VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE) ) if( p_vout->i_changes & (VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE) )
{ {
...@@ -1155,7 +1527,7 @@ static int Manage( vout_thread_t *p_vout ) ...@@ -1155,7 +1527,7 @@ static int Manage( vout_thread_t *p_vout )
/* Clear changes flags which does not need management or have been handled */ /* Clear changes flags which does not need management or have been handled */
p_vout->i_changes &= ~(VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE | p_vout->i_changes &= ~(VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE |
VOUT_INFO_CHANGE ); VOUT_INFO_CHANGE | VOUT_INTF_CHANGE | VOUT_SCALE_CHANGE );
/* Detect unauthorized changes */ /* Detect unauthorized changes */
if( p_vout->i_changes ) if( p_vout->i_changes )
......
...@@ -175,7 +175,7 @@ static void PutByte32( u32 *p_pic, int i_byte, byte_t i_char, byte_t i_border, b ...@@ -175,7 +175,7 @@ static void PutByte32( u32 *p_pic, int i_byte, byte_t i_char, byte_t i_border, b
* This function will try to open a .psf font and load it. It will return * This function will try to open a .psf font and load it. It will return
* NULL on error. * NULL on error.
*******************************************************************************/ *******************************************************************************/
vout_font_t *vout_LoadFont( char *psz_name ) vout_font_t *vout_LoadFont( const char *psz_name )
{ {
int i_char, i_line; /* character and line indexes */ int i_char, i_line; /* character and line indexes */
int i_file; /* source file */ int i_file; /* source file */
...@@ -305,7 +305,7 @@ void vout_UnloadFont( vout_font_t *p_font ) ...@@ -305,7 +305,7 @@ void vout_UnloadFont( vout_font_t *p_font )
* This function is used to align text. It returns the width and height of a * This function is used to align text. It returns the width and height of a
* given text. * given text.
*******************************************************************************/ *******************************************************************************/
void vout_TextSize( vout_font_t *p_font, int i_style, char *psz_text, int *pi_width, int *pi_height ) void vout_TextSize( vout_font_t *p_font, int i_style, const char *psz_text, int *pi_width, int *pi_height )
{ {
switch( p_font->i_type ) switch( p_font->i_type )
{ {
...@@ -333,7 +333,7 @@ void vout_TextSize( vout_font_t *p_font, int i_style, char *psz_text, int *pi_wi ...@@ -333,7 +333,7 @@ void vout_TextSize( vout_font_t *p_font, int i_style, char *psz_text, int *pi_wi
* loaded bitmap font. * loaded bitmap font.
*******************************************************************************/ *******************************************************************************/
void vout_Print( vout_font_t *p_font, byte_t *p_pic, int i_bytes_per_pixel, int i_bytes_per_line, void vout_Print( vout_font_t *p_font, byte_t *p_pic, int i_bytes_per_pixel, int i_bytes_per_line,
u32 i_char_color, u32 i_border_color, u32 i_bg_color, int i_style, char *psz_text ) u32 i_char_color, u32 i_border_color, u32 i_bg_color, int i_style, const char *psz_text )
{ {
byte_t *p_char, *p_border; /* character and border mask data */ byte_t *p_char, *p_border; /* character and border mask data */
int i_char_mask, i_border_mask, i_bg_mask; /* masks */ int i_char_mask, i_border_mask, i_bg_mask; /* masks */
......
...@@ -48,7 +48,6 @@ typedef struct vout_sys_s ...@@ -48,7 +48,6 @@ typedef struct vout_sys_s
GC gc; /* graphic context instance handler */ GC gc; /* graphic context instance handler */
/* Display buffers and shared memory information */ /* Display buffers and shared memory information */
int i_buffer_index; /* buffer index */
XImage * p_ximage[2]; /* XImage pointer */ XImage * p_ximage[2]; /* XImage pointer */
XShmSegmentInfo shm_info[2]; /* shared memory zone information */ XShmSegmentInfo shm_info[2]; /* shared memory zone information */
} vout_sys_t; } vout_sys_t;
...@@ -157,8 +156,11 @@ int vout_SysInit( vout_thread_t *p_vout ) ...@@ -157,8 +156,11 @@ int vout_SysInit( vout_thread_t *p_vout )
/* Set bytes per line */ /* Set bytes per line */
p_vout->i_bytes_per_line = p_vout->p_sys->p_ximage[0]->bytes_per_line; p_vout->i_bytes_per_line = p_vout->p_sys->p_ximage[0]->bytes_per_line;
/* Set buffer index to 0 */ /* Set and initialize buffers */
p_vout->p_sys->i_buffer_index = 0; p_vout->p_buffer[0].p_data = p_vout->p_sys->p_ximage[ 0 ]->data;
p_vout->p_buffer[1].p_data = p_vout->p_sys->p_ximage[ 1 ]->data;
vout_ClearBuffer( p_vout, &p_vout->p_buffer[0] );
vout_ClearBuffer( p_vout, &p_vout->p_buffer[1] );
return( 0 ); return( 0 );
} }
...@@ -222,7 +224,7 @@ int vout_SysManage( vout_thread_t *p_vout ) ...@@ -222,7 +224,7 @@ int vout_SysManage( vout_thread_t *p_vout )
intf_ErrMsg("error: can't resize display\n"); intf_ErrMsg("error: can't resize display\n");
return( 1 ); return( 1 );
} }
intf_Msg("Video display resized to %dx%d\n", p_vout->i_width, p_vout->i_height); intf_Msg("Video display resized (%dx%d)\n", p_vout->i_width, p_vout->i_height);
} }
return 0; return 0;
...@@ -240,10 +242,10 @@ void vout_SysDisplay( vout_thread_t *p_vout ) ...@@ -240,10 +242,10 @@ void vout_SysDisplay( vout_thread_t *p_vout )
{ {
/* Display rendered image using shared memory extension */ /* Display rendered image using shared memory extension */
XShmPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc, XShmPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ], p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ],
0, 0, 0, 0, 0, 0, 0, 0,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->width,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height, True); p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->height, True);
/* Send the order to the X server */ /* Send the order to the X server */
XFlush(p_vout->p_sys->p_display); XFlush(p_vout->p_sys->p_display);
...@@ -251,27 +253,14 @@ void vout_SysDisplay( vout_thread_t *p_vout ) ...@@ -251,27 +253,14 @@ void vout_SysDisplay( vout_thread_t *p_vout )
else /* regular X11 capabilities are used */ else /* regular X11 capabilities are used */
{ {
XPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc, XPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ], p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ],
0, 0, 0, 0, 0, 0, 0, 0,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->width,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height); p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->height);
/* Send the order to the X server */ /* Send the order to the X server */
XFlush(p_vout->p_sys->p_display); XFlush(p_vout->p_sys->p_display);
} }
/* Swap buffers */
p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
}
/*******************************************************************************
* vout_SysGetPicture: get current display buffer informations
*******************************************************************************
* This function returns the address of the current display buffer.
*******************************************************************************/
void * vout_SysGetPicture( vout_thread_t *p_vout )
{
return( p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->data );
} }
/* following functions are local */ /* following functions are local */
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
/******************************************************************************* /*******************************************************************************
* Preamble * Preamble
*******************************************************************************/ *******************************************************************************/
#include <errno.h>
#include <math.h> #include <math.h>
#include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -46,6 +46,7 @@ const int MATRIX_COEFFICIENTS_TABLE[8][4] = ...@@ -46,6 +46,7 @@ const int MATRIX_COEFFICIENTS_TABLE[8][4] =
*******************************************************************************/ *******************************************************************************/
static int BinaryLog ( u32 i ); static int BinaryLog ( u32 i );
static void MaskToShift ( int *pi_right, int *pi_left, u32 i_mask ); static void MaskToShift ( int *pi_right, int *pi_left, u32 i_mask );
static void SetGammaTable ( int *pi_table, double f_gamma );
static void SetTables ( vout_thread_t *p_vout ); static void SetTables ( vout_thread_t *p_vout );
static void ConvertY4Gray16 ( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, static void ConvertY4Gray16 ( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
...@@ -387,24 +388,38 @@ static void MaskToShift (int *pi_right, int *pi_left, u32 i_mask) ...@@ -387,24 +388,38 @@ static void MaskToShift (int *pi_right, int *pi_left, u32 i_mask)
} }
/******************************************************************************* /*******************************************************************************
* SetTables: compute tables and set function pointers * SetGammaTable: return intensity table transformed by gamma curve.
*******************************************************************************
* pi_table is a table of 256 entries from 0 to 255.
*******************************************************************************/ *******************************************************************************/
static void SetGammaTable( int *pi_table, double f_gamma )
{
int i_y; /* base intensity */
/* Use exp(gamma) instead of gamma */
f_gamma = exp(f_gamma );
/* Build gamma table */
for( i_y = 0; i_y < 256; i_y++ )
{
pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
}
}
/*******************************************************************************
* SetTables: compute tables and set function pointers
+ *******************************************************************************/
static void SetTables( vout_thread_t *p_vout ) static void SetTables( vout_thread_t *p_vout )
{ {
u8 i_gamma[256]; /* gamma table */ int pi_gamma[256]; /* gamma table */
int i_index; /* index in tables */ int i_index; /* index in tables */
int i_red_right, i_red_left; /* red shifts */ int i_red_right, i_red_left; /* red shifts */
int i_green_right, i_green_left; /* green shifts */ int i_green_right, i_green_left; /* green shifts */
int i_blue_right, i_blue_left; /* blue shifts */ int i_blue_right, i_blue_left; /* blue shifts */
/* /* Build gamma table */
* Build gamma table SetGammaTable( pi_gamma, p_vout->f_gamma );
*/
for( i_index = 0; i_index < 256; i_index++ )
{
i_gamma[i_index] = 255. * pow( (double)i_index / 255., exp(p_vout->f_gamma) );
}
/* /*
* Set color masks and shifts * Set color masks and shifts
*/ */
...@@ -447,9 +462,9 @@ static void SetTables( vout_thread_t *p_vout ) ...@@ -447,9 +462,9 @@ static void SetTables( vout_thread_t *p_vout )
for( i_index = -384; i_index < 640; i_index++) for( i_index = -384; i_index < 640; i_index++)
{ {
p_vout->tables.yuv.gray16.p_gray[ i_index ] = p_vout->tables.yuv.gray16.p_gray[ i_index ] =
((i_gamma[CLIP_BYTE( i_index )] >> i_red_right) << i_red_left) | ((pi_gamma[CLIP_BYTE( i_index )] >> i_red_right) << i_red_left) |
((i_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) | ((pi_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) |
((i_gamma[CLIP_BYTE( i_index )] >> i_blue_right) << i_blue_left); ((pi_gamma[CLIP_BYTE( i_index )] >> i_blue_right) << i_blue_left);
} }
break; break;
case 24: case 24:
...@@ -458,9 +473,9 @@ static void SetTables( vout_thread_t *p_vout ) ...@@ -458,9 +473,9 @@ static void SetTables( vout_thread_t *p_vout )
for( i_index = -384; i_index < 640; i_index++) for( i_index = -384; i_index < 640; i_index++)
{ {
p_vout->tables.yuv.gray32.p_gray[ i_index ] = p_vout->tables.yuv.gray32.p_gray[ i_index ] =
((i_gamma[CLIP_BYTE( i_index )] >> i_red_right) << i_red_left) | ((pi_gamma[CLIP_BYTE( i_index )] >> i_red_right) << i_red_left) |
((i_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) | ((pi_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) |
((i_gamma[CLIP_BYTE( i_index )] >> i_blue_right) << i_blue_left); ((pi_gamma[CLIP_BYTE( i_index )] >> i_blue_right) << i_blue_left);
} }
break; break;
} }
...@@ -477,9 +492,9 @@ static void SetTables( vout_thread_t *p_vout ) ...@@ -477,9 +492,9 @@ static void SetTables( vout_thread_t *p_vout )
p_vout->tables.yuv.rgb16.p_blue = (u16 *)p_vout->tables.p_base + 2*1024 + 384; p_vout->tables.yuv.rgb16.p_blue = (u16 *)p_vout->tables.p_base + 2*1024 + 384;
for( i_index = -384; i_index < 640; i_index++) for( i_index = -384; i_index < 640; i_index++)
{ {
p_vout->tables.yuv.rgb16.p_red[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_red_right)<<i_red_left; p_vout->tables.yuv.rgb16.p_red[i_index] = (pi_gamma[CLIP_BYTE(i_index)]>>i_red_right)<<i_red_left;
p_vout->tables.yuv.rgb16.p_green[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_green_right)<<i_green_left; p_vout->tables.yuv.rgb16.p_green[i_index] = (pi_gamma[CLIP_BYTE(i_index)]>>i_green_right)<<i_green_left;
p_vout->tables.yuv.rgb16.p_blue[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_blue_right)<<i_blue_left; p_vout->tables.yuv.rgb16.p_blue[i_index] = (pi_gamma[CLIP_BYTE(i_index)]>>i_blue_right)<<i_blue_left;
} }
break; break;
case 24: case 24:
...@@ -489,9 +504,9 @@ static void SetTables( vout_thread_t *p_vout ) ...@@ -489,9 +504,9 @@ static void SetTables( vout_thread_t *p_vout )
p_vout->tables.yuv.rgb32.p_blue = (u32 *)p_vout->tables.p_base + 2*1024 + 384; p_vout->tables.yuv.rgb32.p_blue = (u32 *)p_vout->tables.p_base + 2*1024 + 384;
for( i_index = -384; i_index < 640; i_index++) for( i_index = -384; i_index < 640; i_index++)
{ {
p_vout->tables.yuv.rgb32.p_red[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_red_right)<<i_red_left; p_vout->tables.yuv.rgb32.p_red[i_index] = (pi_gamma[CLIP_BYTE(i_index)]>>i_red_right)<<i_red_left;
p_vout->tables.yuv.rgb32.p_green[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_green_right)<<i_green_left; p_vout->tables.yuv.rgb32.p_green[i_index] = (pi_gamma[CLIP_BYTE(i_index)]>>i_green_right)<<i_green_left;
p_vout->tables.yuv.rgb32.p_blue[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_blue_right)<<i_blue_left; p_vout->tables.yuv.rgb32.p_blue[i_index] = (pi_gamma[CLIP_BYTE(i_index)]>>i_blue_right)<<i_blue_left;
} }
break; break;
} }
......
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