Commit 57509f75 authored by Vincent Seguin's avatar Vincent Seguin

Toujours du nettoyage.

Une API pour les sous titres.
parent 653053d2
...@@ -120,9 +120,8 @@ ...@@ -120,9 +120,8 @@
#define INTF_IDLE_SLEEP 100000 #define INTF_IDLE_SLEEP 100000
/* Factor for changing gamma, and minimum and maximum values */ /* Factor for changing gamma, and minimum and maximum values */
#define INTF_GAMMA_FACTOR 1.1 #define INTF_GAMMA_FACTOR .1
#define INTF_GAMMA_MIN 0.1 #define INTF_GAMMA_MAX 3
#define INTF_GAMMA_MAX 10
/* /*
* X11 settings * X11 settings
...@@ -247,7 +246,7 @@ ...@@ -247,7 +246,7 @@
#define VOUT_GRAYSCALE_DEFAULT 0 #define VOUT_GRAYSCALE_DEFAULT 0
/* Default gamma */ /* Default gamma */
#define VOUT_GAMMA 1. #define VOUT_GAMMA 0.
/* /*
* Time settings * Time settings
...@@ -338,7 +337,7 @@ ...@@ -338,7 +337,7 @@
/* Define to enable messages queues - disabling messages queue can be usefull /* Define to enable messages queues - disabling messages queue can be usefull
* when debugging, since it allows messages which would not otherwise be printed, * when debugging, since it allows messages which would not otherwise be printed,
* due to a crash, to be printed anyway */ * due to a crash, to be printed anyway */
//#define INTF_MSG_QUEUE #define INTF_MSG_QUEUE
/* Format of the header for debug messages. The arguments following this header /* Format of the header for debug messages. The arguments following this header
* are the file (char *), the function (char *) and the line (int) in which the * are the file (char *), the function (char *) and the line (int) in which the
......
...@@ -24,7 +24,7 @@ typedef u8 yuv_data_t; ...@@ -24,7 +24,7 @@ typedef u8 yuv_data_t;
* Picture type and flags should only be modified by the output thread. Note * Picture type and flags should only be modified by the output thread. Note
* that an empty picture MUST have its flags set to 0. * that an empty picture MUST have its flags set to 0.
*******************************************************************************/ *******************************************************************************/
typedef struct typedef struct picture_s
{ {
/* Type and flags - should NOT be modified except by the vout thread */ /* Type and flags - should NOT be modified except by the vout thread */
int i_type; /* picture type */ int i_type; /* picture type */
...@@ -69,7 +69,6 @@ typedef struct ...@@ -69,7 +69,6 @@ typedef struct
yuv_data_t * p_v; /* pointer to beginning of V image in p_data */ yuv_data_t * p_v; /* pointer to beginning of V image in p_data */
} picture_t; } picture_t;
/* Pictures types */ /* Pictures types */
#define EMPTY_PICTURE 0 /* picture slot is empty and available */ #define EMPTY_PICTURE 0 /* picture slot is empty and available */
#define YUV_420_PICTURE 100 /* 4:2:0 YUV picture */ #define YUV_420_PICTURE 100 /* 4:2:0 YUV picture */
...@@ -88,3 +87,38 @@ typedef struct ...@@ -88,3 +87,38 @@ typedef struct
#define AR_3_4_PICTURE 2 /* 3:4 picture (TV) */ #define AR_3_4_PICTURE 2 /* 3:4 picture (TV) */
#define AR_16_9_PICTURE 3 /* 16:9 picture (wide screen) */ #define AR_16_9_PICTURE 3 /* 16:9 picture (wide screen) */
#define AR_221_1_PICTURE 4 /* 2.21:1 picture (movie) */ #define AR_221_1_PICTURE 4 /* 2.21:1 picture (movie) */
/*******************************************************************************
* subtitle_t: video subtitle
*******************************************************************************
* Any subtitle destined to be displayed by a video output thread should be
* stored in this structure from it's creation to it's effective display.
* Subtitle type and flags should only be modified by the output thread. Note
* that an empty subtitle MUST have its flags set to 0.
*******************************************************************************/
typedef struct subtitle_s
{
/* Type and flags - should NOT be modified except by the vout thread */
int i_type; /* subtitle type */
int i_status; /* subtitle flags */
/* Other properties */
mtime_t begin_date; /* beginning of display date */
mtime_t end_date; /* end of display date */
/* Subtitle data - data can always be freely modified. p_data itself
* (the pointer) should NEVER be modified. */
void * p_data; /* subtitle data */
} subtitle_t;
/* Subtitle types */
#define EMPTY_SUBTITLE 0 /* subtitle slot is empty and available */
#define RLE_SUBTITLE 100 /* RLE encoded subtitle */
/* Subtitle status */
#define FREE_SUBTITLE 0 /* subtitle is free and not allocated */
#define RESERVED_SUBTITLE 1 /* subtitle is allocated and reserved */
#define READY_SUBTITLE 2 /* subtitle is ready for display */
#define DISPLAYED_SUBTITLE 3 /* subtitle has been displayed but is linked */
#define DESTROYED_SUBTITLE 4 /* subtitle is allocated but no more used */
...@@ -84,46 +84,40 @@ typedef struct vout_thread_s ...@@ -84,46 +84,40 @@ typedef struct vout_thread_s
boolean_t b_die; /* `die' flag */ boolean_t b_die; /* `die' flag */
boolean_t b_error; /* `error' flag */ boolean_t b_error; /* `error' flag */
boolean_t b_active; /* `active' flag */ boolean_t b_active; /* `active' flag */
pthread_t thread_id; /* id for pthread functions */ vlc_thread_t thread_id; /* id for pthread functions */
pthread_mutex_t lock; /* thread lock */ vlc_mutex_t picture_lock; /* picture heap lock */
vlc_mutex_t subtitle_lock; /* subtitle heap lock */
int * pi_status; /* temporary status flag */ int * pi_status; /* temporary status flag */
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_info; /* print additionnal informations */ boolean_t b_info; /* print additionnal informations */
boolean_t b_grayscale; /* color or grayscale display */ 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) */
int i_screen_depth; /* bits per pixel - FIXED */ int i_screen_depth; /* bits per pixel */
int i_bytes_per_pixel; /* real screen depth - FIXED */ int i_bytes_per_pixel; /* real screen depth */
float f_x_ratio; /* horizontal display ratio */ float f_x_ratio; /* horizontal display ratio */
float f_y_ratio; /* vertical display ratio */ float f_y_ratio; /* vertical display ratio */
float f_gamma; /* gamma */ float f_gamma; /* gamma */
/* Changed properties values - some of them are treated directly by the
* thread, the over may be ignored or handled by vout_SysManage */
//?? info, grayscale, width, height, bytes per line, x ratio, y ratio, gamma
boolean_t b_gamma_change; /* gamma change indicator */
int i_new_width; /* new width */
int i_new_height; /* new height */
#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 */
count_t c_loops; /* number of loops */ mtime_t loop_time; /* last picture loop time */
count_t c_idle_loops; /* number of idle loops */ 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 fps_sample[ VOUT_FPS_SAMPLES ]; /* FPS samples dates */
#endif #endif
#ifdef DEBUG_VIDEO /* Running properties */
/* Additionnal video debugging informations */ u16 i_changes; /* changes made to the thread */
mtime_t picture_render_time; /* last picture rendering time */ mtime_t last_picture_date; /* last picture display date */
#endif mtime_t last_idle_date; /* last idle screen displaydate */
/* Video 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 */
vout_tables_t tables; /* translation tables */ vout_tables_t tables; /* translation tables */
vout_convert_t * p_ConvertYUV420; /* YUV 4:2:0 converter */ vout_convert_t * p_ConvertYUV420; /* YUV 4:2:0 converter */
vout_convert_t * p_ConvertYUV422; /* YUV 4:2:2 converter */ vout_convert_t * p_ConvertYUV422; /* YUV 4:2:2 converter */
...@@ -131,25 +125,34 @@ typedef struct vout_thread_s ...@@ -131,25 +125,34 @@ typedef struct vout_thread_s
vout_scale_t * p_Scale; /* scaler */ vout_scale_t * p_Scale; /* scaler */
} vout_thread_t; } vout_thread_t;
/* Flags for changes - these flags are set in the i_changes field when another
* thread changed a variable */
#define VOUT_INFO_CHANGE 0x0001 /* b_info changed */
#define VOUT_GRAYSCALE_CHANGE 0x0002 /* b_grayscale changed */
#define VOUT_SIZE_CHANGE 0x0004 /* size changed */
#define VOUT_DEPTH_CHANGE 0x0008 /* depth changed */
#define VOUT_RATIO_CHANGE 0x0010 /* display ratio changed */
#define VOUT_GAMMA_CHANGE 0x0020 /* gamma changed */
/******************************************************************************* /*******************************************************************************
* Prototypes * Prototypes
*******************************************************************************/ *******************************************************************************/
vout_thread_t * vout_CreateThread ( vout_thread_t * vout_CreateThread (
#ifdef VIDEO_X11 #ifdef VIDEO_X11
char *psz_display, Window root_window, char *psz_display, Window root_window,
#endif #endif
int i_width, int i_height, int *pi_status int i_width, int i_height, int *pi_status
); );
void vout_DestroyThread ( vout_thread_t *p_vout, int *pi_status );
void vout_DestroyThread ( vout_thread_t *p_vout, int *pi_status ); picture_t * vout_CreatePicture ( vout_thread_t *p_vout, int i_type,
int i_width, int i_height );
picture_t * vout_CreatePicture ( vout_thread_t *p_vout, int i_type, void vout_DestroyPicture ( vout_thread_t *p_vout, picture_t *p_pic );
int i_width, int i_height ); void vout_DisplayPicture ( vout_thread_t *p_vout, picture_t *p_pic );
void vout_DestroyPicture ( vout_thread_t *p_vout, picture_t *p_pic ); void vout_LinkPicture ( vout_thread_t *p_vout, picture_t *p_pic );
void vout_DisplayPicture ( vout_thread_t *p_vout, picture_t *p_pic ); void vout_UnlinkPicture ( vout_thread_t *p_vout, picture_t *p_pic );
void vout_LinkPicture ( vout_thread_t *p_vout, picture_t *p_pic ); subtitle_t * vout_CreateSubtitle ( vout_thread_t *p_vout, int i_type, int i_size );
void vout_UnlinkPicture ( vout_thread_t *p_vout, picture_t *p_pic ); void vout_DestroySubtitle ( vout_thread_t *p_vout, subtitle_t *p_sub );
void vout_DisplaySubtitle ( vout_thread_t *p_vout, subtitle_t *p_sub );
......
...@@ -33,5 +33,5 @@ void ConvertYUV420RGB16MMX( u8* p_y, u8* p_u, u8 *p_v, ...@@ -33,5 +33,5 @@ void ConvertYUV420RGB16MMX( u8* p_y, u8* p_u, u8 *p_v,
unsigned int i_ypitch, unsigned int i_vpitch, unsigned int i_ypitch, unsigned int i_vpitch,
unsigned int i_aspect, u8 *p_pic, unsigned int i_aspect, u8 *p_pic,
u32 i_dci_offset, u32 i_offset_to_line_0, u32 i_dci_offset, u32 i_offset_to_line_0,
int CCOPitch, int i_colortype ); int i_pitch, int i_colortype );
#endif #endif
...@@ -421,6 +421,17 @@ static void Usage( void ) ...@@ -421,6 +421,17 @@ static void Usage( void )
intf_Msg("VLANs (Virtual Local Aera Networks) parameters:\n" \ intf_Msg("VLANs (Virtual Local Aera Networks) parameters:\n" \
" vlan_server=<host>[:<port>] VLANs server address and port\n" \ " vlan_server=<host>[:<port>] VLANs server address and port\n" \
); );
/* Interfaces keys */
intf_Msg("Interface keys: most interface accept the following commands:\n" \
" [esc], q quit\n" \
" +, - change volume\n" \
" m mute\n" \
" f fullscreen\n" \
" 0 - 9 select channel\n" \
" [space] toggle info printing\n" \
" g, G change gamma\n" \
);
} }
/******************************************************************************* /*******************************************************************************
......
...@@ -122,15 +122,11 @@ void vout_SysDestroy( vout_thread_t *p_vout ) ...@@ -122,15 +122,11 @@ void vout_SysDestroy( vout_thread_t *p_vout )
* vout_SysManage: handle Sys events * vout_SysManage: handle Sys events
******************************************************************************* *******************************************************************************
* This function should be called regularly by video output thread. It returns * This function should be called regularly by video output thread. It returns
* a negative value if something happened which does not allow the thread to * a non null value if an error occured.
* continue, and a positive one if the thread can go on, but the images have
* been modified and therefore it is useless to display them.
*******************************************************************************/ *******************************************************************************/
int vout_SysManage( vout_thread_t *p_vout ) int vout_SysManage( vout_thread_t *p_vout )
{ {
//?? return( 0 );
return( 0 );
} }
/******************************************************************************* /*******************************************************************************
......
...@@ -39,7 +39,9 @@ static void ErrorThread ( vout_thread_t *p_vout ); ...@@ -39,7 +39,9 @@ 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 RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic ); static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic ); static void RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic );
static int RenderIdle ( vout_thread_t *p_vout, int i_level ); static int RenderIdle ( vout_thread_t *p_vout );
static int RenderInfo ( vout_thread_t *p_vout );
static int Manage ( vout_thread_t *p_vout );
/******************************************************************************* /*******************************************************************************
* vout_CreateThread: creates a new video output thread * vout_CreateThread: creates a new video output thread
...@@ -112,20 +114,15 @@ vout_thread_t * vout_CreateThread ( ...@@ -112,20 +114,15 @@ vout_thread_t * vout_CreateThread (
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale ); p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->b_grayscale );
/* Initialize changement properties */
p_vout->b_gamma_change = 0;
p_vout->i_new_width = p_vout->i_width;
p_vout->i_new_height = p_vout->i_height;
#ifdef STATS #ifdef STATS
/* Initialize statistics fields */ /* Initialize statistics fields */
p_vout->c_loops = 0; p_vout->loop_time = 0;
p_vout->c_idle_loops = 0; p_vout->c_fps_samples = 0;
p_vout->c_fps_samples = 0;
#endif #endif
/* Create thread and set locks */ /* Create thread and set locks */
vlc_mutex_init( &p_vout->lock ); vlc_mutex_init( &p_vout->picture_lock );
vlc_mutex_init( &p_vout->subtitle_lock );
if( vlc_thread_create( &p_vout->thread_id, "video output", if( vlc_thread_create( &p_vout->thread_id, "video output",
(void *) RunThread, (void *) p_vout) ) (void *) RunThread, (void *) p_vout) )
{ {
...@@ -184,6 +181,78 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status ) ...@@ -184,6 +181,78 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
} }
} }
/*******************************************************************************
* vout_DisplaySubtitle: display a subtitle
*******************************************************************************
* Remove the reservation flag of a subtitle, which will cause it to be ready for
* display. The picture does not need to be locked, since it is ignored by
* the output thread if is reserved.
*******************************************************************************/
void vout_DisplaySubtitle( vout_thread_t *p_vout, subtitle_t *p_sub )
{
#ifdef DEBUG_VIDEO
char psz_begin_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
char psz_end_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
#endif
#ifdef DEBUG
/* Check if status is valid */
if( p_sub->i_status != RESERVED_SUBTITLE )
{
intf_DbgMsg("error: subtitle %p has invalid status %d\n", p_sub, p_sub->i_status );
}
#endif
/* Remove reservation flag */
p_sub->i_status = READY_SUBTITLE;
#ifdef DEBUG_VIDEO
/* Send subtitle informations */
intf_DbgMsg("subtitle %p: type=%d, begin date=%s, end date=%s\n", p_sub, p_sub->i_type,
mstrtime( psz_begin_date, p_sub->begin_date ),
mstrtime( psz_end_date, p_sub->end_date ) );
#endif
}
/*******************************************************************************
* vout_CreateSubtitle: allocate a subtitle in the video output heap.
*******************************************************************************
* This function create a reserved subtitle in the video output heap.
* A null pointer is returned if the function fails. This method provides an
* already allocated zone of memory in the subtitle data fields. It needs locking
* since several pictures can be created by several producers threads.
*******************************************************************************/
subtitle_t *vout_CreateSubtitle( vout_thread_t *p_vout, int i_type,
int i_size )
{
//???
}
/*******************************************************************************
* vout_DestroySubtitle: remove a permanent or reserved subtitle from the heap
*******************************************************************************
* This function frees a previously reserved subtitle.
* It is meant to be used when the construction of a picture aborted.
* This function does not need locking since reserved subtitles are ignored by
* the output thread.
*******************************************************************************/
void vout_DestroySubtitle( vout_thread_t *p_vout, subtitle_t *p_sub )
{
#ifdef DEBUG
/* Check if subtitle status is valid */
if( p_sub->i_status != RESERVED_SUBTITLE )
{
intf_DbgMsg("error: subtitle %p has invalid status %d\n", p_sub, p_sub->i_status );
}
#endif
p_sub->i_status = DESTROYED_SUBTITLE;
#ifdef DEBUG_VIDEO
intf_DbgMsg("subtitle %p\n", p_sub);
#endif
}
/******************************************************************************* /*******************************************************************************
* vout_DisplayPicture: display a picture * vout_DisplayPicture: display a picture
******************************************************************************* *******************************************************************************
...@@ -201,7 +270,7 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -201,7 +270,7 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
/* Check if picture status is valid */ /* Check if picture status is valid */
if( p_pic->i_status != RESERVED_PICTURE ) if( p_pic->i_status != RESERVED_PICTURE )
{ {
intf_DbgMsg("error: picture %d has invalid status %d\n", p_pic, p_pic->i_status ); intf_DbgMsg("error: picture %p has invalid status %d\n", p_pic, p_pic->i_status );
} }
#endif #endif
...@@ -232,7 +301,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, ...@@ -232,7 +301,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
picture_t * p_destroyed_picture = NULL; /* first destroyed picture */ picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
/* Get lock */ /* Get lock */
vlc_mutex_lock( &p_vout->lock ); vlc_mutex_lock( &p_vout->picture_lock );
/* /*
* Look for an empty place * Look for an empty place
...@@ -258,7 +327,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, ...@@ -258,7 +327,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
intf_DbgMsg("picture %p (in destroyed picture slot)\n", intf_DbgMsg("picture %p (in destroyed picture slot)\n",
&p_vout->p_picture[i_picture] ); &p_vout->p_picture[i_picture] );
#endif #endif
vlc_mutex_unlock( &p_vout->lock ); vlc_mutex_unlock( &p_vout->picture_lock );
return( &p_vout->p_picture[i_picture] ); return( &p_vout->p_picture[i_picture] );
} }
else if( p_destroyed_picture == NULL ) else if( p_destroyed_picture == NULL )
...@@ -350,13 +419,13 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, ...@@ -350,13 +419,13 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
intf_DbgMsg("picture %p (in free picture slot)\n", p_free_picture ); intf_DbgMsg("picture %p (in free picture slot)\n", p_free_picture );
#endif #endif
vlc_mutex_unlock( &p_vout->lock ); vlc_mutex_unlock( &p_vout->picture_lock );
return( p_free_picture ); return( p_free_picture );
} }
// No free or destroyed picture could be found // No free or destroyed picture could be found
intf_DbgMsg( "warning: heap is full\n" ); intf_DbgMsg( "warning: heap is full\n" );
vlc_mutex_unlock( &p_vout->lock ); vlc_mutex_unlock( &p_vout->picture_lock );
return( NULL ); return( NULL );
} }
...@@ -375,7 +444,7 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -375,7 +444,7 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
/* Check if picture status is valid */ /* Check if picture status is valid */
if( p_pic->i_status != RESERVED_PICTURE ) if( p_pic->i_status != RESERVED_PICTURE )
{ {
intf_DbgMsg("error: picture %d has invalid status %d\n", p_pic, p_pic->i_status ); intf_DbgMsg("error: picture %p has invalid status %d\n", p_pic, p_pic->i_status );
} }
#endif #endif
...@@ -394,9 +463,9 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -394,9 +463,9 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
*******************************************************************************/ *******************************************************************************/
void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
{ {
vlc_mutex_lock( &p_vout->lock ); vlc_mutex_lock( &p_vout->picture_lock );
p_pic->i_refcount++; p_pic->i_refcount++;
vlc_mutex_unlock( &p_vout->lock ); vlc_mutex_unlock( &p_vout->picture_lock );
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
intf_DbgMsg("picture %p\n", p_pic); intf_DbgMsg("picture %p\n", p_pic);
...@@ -410,13 +479,13 @@ void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -410,13 +479,13 @@ void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
*******************************************************************************/ *******************************************************************************/
void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
{ {
vlc_mutex_lock( &p_vout->lock ); vlc_mutex_lock( &p_vout->picture_lock );
p_pic->i_refcount--; p_pic->i_refcount--;
if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) ) if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) )
{ {
p_pic->i_status = DESTROYED_PICTURE; p_pic->i_status = DESTROYED_PICTURE;
} }
vlc_mutex_unlock( &p_vout->lock ); vlc_mutex_unlock( &p_vout->picture_lock );
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
intf_DbgMsg("picture %p\n", p_pic); intf_DbgMsg("picture %p\n", p_pic);
...@@ -446,11 +515,13 @@ static int InitThread( vout_thread_t *p_vout ) ...@@ -446,11 +515,13 @@ static int InitThread( vout_thread_t *p_vout )
return( 1 ); return( 1 );
} }
/* Initialize pictures */ /* Initialize pictures and subtitles */
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++) 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_type = EMPTY_PICTURE;
p_vout->p_picture[i_index].i_status= FREE_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 */
...@@ -477,11 +548,8 @@ static int InitThread( vout_thread_t *p_vout ) ...@@ -477,11 +548,8 @@ 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_picture; /* picture index */
int i_err; /* error code */
int i_idle_level = 0; /* idle level */
mtime_t current_date; /* current date */ mtime_t current_date; /* current date */
mtime_t pic_date = 0; /* picture date */ mtime_t pic_date = 0; /* picture date */
mtime_t last_date = 0; /* last picture 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 */
...@@ -506,6 +574,7 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -506,6 +574,7 @@ static void RunThread( vout_thread_t *p_vout)
* since only READY_PICTURES are handled * since only READY_PICTURES are handled
*/ */
p_pic = NULL; p_pic = NULL;
current_date = mdate();
for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ ) 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_picture].i_status == READY_PICTURE) &&
...@@ -516,8 +585,7 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -516,8 +585,7 @@ static void RunThread( vout_thread_t *p_vout)
pic_date = p_pic->date; pic_date = p_pic->date;
} }
} }
current_date = mdate();
/* /*
* Render picture if any * Render picture if any
*/ */
...@@ -531,9 +599,9 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -531,9 +599,9 @@ static void RunThread( vout_thread_t *p_vout)
{ {
/* 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->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->lock ); vlc_mutex_unlock( &p_vout->picture_lock );
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
intf_DbgMsg( "warning: late picture %p skipped\n", p_pic ); intf_DbgMsg( "warning: late picture %p skipped\n", p_pic );
#endif #endif
...@@ -546,91 +614,72 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -546,91 +614,72 @@ static void RunThread( vout_thread_t *p_vout)
* 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;
} }
else
{
/* Picture has not yet been displayed, and has a valid display
* date : render it, then mark it as displayed */
if( p_vout->b_active )
{
RenderPicture( p_vout, p_pic );
if( p_vout->b_info )
{
RenderPictureInfo( p_vout, p_pic );
}
}
vlc_mutex_lock( &p_vout->lock );
p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE;
vlc_mutex_unlock( &p_vout->lock );
}
} }
/*
* Rebuild tables if gamma has changed /*
* Perform rendering, sleep and display rendered picture
*/ */
if( p_vout->b_gamma_change ) if( p_pic )
{ {
//?? /* A picture is ready to be displayed : render it */
p_vout->b_gamma_change = 0; if( p_vout->b_active )
vout_ResetTables( p_vout ); // ?? test return value {
} RenderPicture( p_vout, p_pic );
if( p_vout->b_info )
{
RenderPictureInfo( p_vout, p_pic );
RenderInfo( p_vout );
}
b_display = 1;
}
else
{
b_display = 0;
}
/* Remove picture from heap */
vlc_mutex_lock( &p_vout->picture_lock );
p_pic->i_status = p_pic->i_refcount ? DISPLAYED_PICTURE : DESTROYED_PICTURE;
vlc_mutex_unlock( &p_vout->picture_lock );
}
else
{
/* No picture. However, an idle screen may be ready to display */
b_display = p_vout->b_active && ( RenderIdle( p_vout ) |
( p_vout->b_info && RenderInfo( p_vout ) ));
}
/* Sleep a while or until a given date */
if( p_pic )
{
#ifdef STATS
/* Computes loop time */
p_vout->loop_time = mdate() - current_date;
#endif
mwait( pic_date );
}
else
{
msleep( VOUT_IDLE_SLEEP );
}
/* On awakening, send immediately picture to display */
if( b_display && p_vout->b_active )
{
vout_SysDisplay( p_vout );
}
/* /*
* Check events, sleep and display picture * Check events and manage thread
*/ */
i_err = vout_SysManage( p_vout ); if( vout_SysManage( p_vout ) | Manage( p_vout ) )
if( i_err < 0 )
{ {
/* A fatal error occured, and the thread must terminate immediately, /* A fatal error occured, and the thread must terminate immediately,
* without displaying anything - setting b_error to 1 cause the * without displaying anything - setting b_error to 1 cause the
* immediate end of the main while() loop. */ * immediate end of the main while() loop. */
p_vout->b_error = 1; p_vout->b_error = 1;
} }
else
{
if( p_pic )
{
/* A picture is ready to be displayed : remove blank screen flag */
last_date = pic_date;
i_idle_level = 0;
b_display = 1;
/* Sleep until its display date */
mwait( pic_date );
}
else
{
/* If last picture was a long time ago, increase idle level, reset
* date and render idle screen */
if( !i_err && (current_date - last_date > VOUT_IDLE_DELAY) )
{
last_date = current_date;
b_display = p_vout->b_active && RenderIdle( p_vout, i_idle_level++ );
}
else
{
b_display = 0;
}
#ifdef STATS
/* Update counters */
p_vout->c_idle_loops++;
#endif
/* Sleep to wait for new pictures */
msleep( VOUT_IDLE_SLEEP );
}
/* On awakening, send immediately picture to display */
if( b_display && p_vout->b_active )
{
vout_SysDisplay( p_vout );
}
}
#ifdef STATS
/* Update counters */
p_vout->c_loops++;
#endif
} }
/* /*
...@@ -709,12 +758,6 @@ static void EndThread( vout_thread_t *p_vout ) ...@@ -709,12 +758,6 @@ static void EndThread( vout_thread_t *p_vout )
*******************************************************************************/ *******************************************************************************/
static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
{ {
#ifdef DEBUG_VIDEO
/* Send picture informations and store rendering start date */
intf_DbgMsg("picture %p\n", p_pic );
p_vout->picture_render_time = mdate();
#endif
/* /*
* Prepare scaling * Prepare scaling
*/ */
...@@ -724,8 +767,8 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -724,8 +767,8 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
/* X11: window can be resized, so resize it - the picture won't be /* X11: window can be resized, so resize it - the picture won't be
* rendered since any alteration of the window size means recreating the * rendered since any alteration of the window size means recreating the
* XImages */ * XImages */
p_vout->i_new_width = p_pic->i_width; /* p_vout->i_new_width = p_pic->i_width;
p_vout->i_new_height = p_pic->i_height; p_vout->i_new_height = p_pic->i_height;*/
return; return;
#else #else
/* Other drivers: the video output thread can't change its size, so /* Other drivers: the video output thread can't change its size, so
...@@ -746,7 +789,7 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -746,7 +789,7 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
4, p_pic->i_matrix_coefficients ); 4, p_pic->i_matrix_coefficients );
break; break;
case YUV_422_PICTURE: case YUV_422_PICTURE:
/* ??? p_vout->p_convert_yuv_420( p_vout, /* ??? p_vout->p_convert_yuv_420( p_vout,
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_chroma_width, i_chroma_height, i_chroma_width, i_chroma_height,
p_vout->i_width / 2, p_vout->i_height, p_vout->i_width / 2, p_vout->i_height,
...@@ -772,11 +815,6 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -772,11 +815,6 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
* Terminate scaling * Terminate scaling
*/ */
//?? //??
#ifdef DEBUG_VIDEO
/* Computes rendering time */
p_vout->picture_render_time = mdate() - p_vout->picture_render_time;
#endif
} }
...@@ -810,9 +848,8 @@ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -810,9 +848,8 @@ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic )
/* /*
* Print statistics in upper left corner * Print statistics in upper left corner
*/ */
sprintf( psz_buffer, "gamma=%.2f %ld frames (%.1f %% idle)", sprintf( psz_buffer, "gamma=%.2f %ld frames",
p_vout->f_gamma, p_vout->c_fps_samples, p_vout->c_loops ? p_vout->f_gamma, p_vout->c_fps_samples );
(double ) p_vout->c_idle_loops * 100 / p_vout->c_loops : 100. );
vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer ); vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer );
#endif #endif
...@@ -838,67 +875,49 @@ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -838,67 +875,49 @@ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic )
#endif #endif
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
/* //??
* Print picture info in lower right corner
*/
switch( p_pic->i_type )
{
case YUV_420_PICTURE:
sprintf( psz_buffer, "YUV 4:2:0 picture, rendering time: %lu us",
(unsigned long) p_vout->picture_render_time );
break;
case YUV_422_PICTURE:
sprintf( psz_buffer, "YUV 4:2:2 picture, rendering time: %lu us",
(unsigned long) p_vout->picture_render_time );
break;
case YUV_444_PICTURE:
sprintf( psz_buffer, "YUV 4:4:4 picture, rendering time: %lu us",
(unsigned long) p_vout->picture_render_time );
break;
default:
sprintf( psz_buffer, "unknown picture, rendering time: %lu us",
(unsigned long) p_vout->picture_render_time );
break;
}
vout_SysPrint( p_vout, p_vout->i_width, p_vout->i_height, 1, 1, psz_buffer );
#endif #endif
} }
/******************************************************************************* /*******************************************************************************
* RenderIdle: render idle picture * RenderIdle: render idle picture
******************************************************************************* *******************************************************************************
* This function will clear the display or print a logo. Level will vary from 0 * This function will clear the display or print a logo.
* to a very high value that noone should never reach. It returns non 0 if
* something needs to be displayed and 0 if the previous picture can be kept.
*******************************************************************************/ *******************************************************************************/
static int RenderIdle( vout_thread_t *p_vout, int i_level ) static int RenderIdle( vout_thread_t *p_vout )
{ {
byte_t *pi_pic; /* pointer to picture data */ //??
return( 0 );
/* Get frame pointer and clear display */ }
pi_pic = vout_SysGetPicture( p_vout );
switch( i_level )
{
case 0: /* level 0: clear screen */
memset( pi_pic, 0, p_vout->i_bytes_per_line * p_vout->i_height );
break;
case 1: /* level 1: "no stream" */
memset( pi_pic, 0, p_vout->i_bytes_per_line * p_vout->i_height );
vout_SysPrint( p_vout, p_vout->i_width / 2, p_vout->i_height / 2,
0, 0, "no stream" );
break;
case 50: /* level 50: copyright message */
memset( pi_pic, 0, p_vout->i_bytes_per_line * p_vout->i_height );
vout_SysPrint( p_vout, p_vout->i_width / 2, p_vout->i_height / 2,
0, 0, COPYRIGHT_MESSAGE );
break;
default: /* other levels: keep previous picture */
return( 0 );
break;
}
return( 1 ); /*******************************************************************************
* RenderInfo: render additionnal informations
*******************************************************************************
* ??
*******************************************************************************/
static int RenderInfo( vout_thread_t *p_vout )
{
//??
return( 0 );
} }
/*******************************************************************************
* Manage: manage thread
*******************************************************************************
* ??
*******************************************************************************/
static int Manage( vout_thread_t *p_vout )
{
//??
/* Detect unauthorized changes */
if( p_vout->i_changes )
{
/* Some changes were not acknowledged by vout_SysManage or this function,
* it means they should not be authorized */
intf_ErrMsg( "error: unauthorized changes in the video output thread\n" );
return( 1 );
}
return( 0 );
}
...@@ -206,30 +206,25 @@ void vout_SysDestroy( vout_thread_t *p_vout ) ...@@ -206,30 +206,25 @@ void vout_SysDestroy( vout_thread_t *p_vout )
* vout_SysManage: handle X11 events * vout_SysManage: handle X11 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
* X11 events and allows window resizing. It returns a negative value if * X11 events and allows window resizing. It returns a non null value on
* something happened which does not allow the thread to continue, and a * error.
* positive one if the thread can go on, but the images have been modified and
* therefore it is useless to display them.
*******************************************************************************/ *******************************************************************************/
int vout_SysManage( vout_thread_t *p_vout ) int vout_SysManage( vout_thread_t *p_vout )
{ {
if( (p_vout->i_width != p_vout->i_new_width) || if( p_vout->i_changes & VOUT_SIZE_CHANGE )
(p_vout->i_height != p_vout->i_new_height) ) {
{ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
intf_DbgMsg("resizing window\n"); intf_DbgMsg("resizing window\n");
/* Resize window */ /* Resize window */
XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window, XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
p_vout->i_new_width, p_vout->i_new_height ); p_vout->i_width, p_vout->i_height );
/* Destroy then recreate XImages to change their size */ /* Destroy XImages to change their size */
vout_SysEnd( p_vout ); vout_SysEnd( p_vout );
p_vout->i_width = p_vout->i_new_width;
p_vout->i_height = p_vout->i_new_height;
/* If SysInit failed, the thread can't go on. Otherwise, it won't display /* Recreate XImages. If SysInit failed, the thread can't go on. */
* the rendered image, but can continue */ return( vout_SysInit( p_vout ) );
return( vout_SysInit( p_vout ) ? -1 : 1);
} }
return 0; return 0;
......
...@@ -413,7 +413,7 @@ static void SetTables( vout_thread_t *p_vout ) ...@@ -413,7 +413,7 @@ static void SetTables( vout_thread_t *p_vout )
*/ */
for( i_index = 0; i_index < 256; i_index++ ) for( i_index = 0; i_index < 256; i_index++ )
{ {
i_gamma[i_index] = 255. * pow( (double)i_index / 255., p_vout->f_gamma ); i_gamma[i_index] = 255. * exp( (double)i_index * p_vout->f_gamma / 255. );
} }
/* /*
......
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