* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000 VideoLAN
+ * $Id: video_output.c,v 1.129 2001/05/30 17:03:13 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
static void Print ( vout_thread_t *p_vout, int i_x, int i_y,
int i_h_align, int i_v_align,
unsigned char *psz_text );
+static void SetBuffers ( vout_thread_t *p_vout, void *, void * );
static void SetBufferArea ( vout_thread_t *p_vout, int i_x, int i_y,
int i_w, int i_h );
static void SetBufferPicture ( 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 RenderSubPicture ( vout_thread_t *p_vout,
+static void RenderSubPicture ( vout_thread_t *p_vout, picture_t *p_pic,
subpicture_t *p_subpic );
-static void RenderInterface ( vout_thread_t *p_vout );
static int RenderIdle ( vout_thread_t *p_vout );
-static int RenderSplash ( vout_thread_t *p_vout );
static void RenderInfo ( vout_thread_t *p_vout );
static int Manage ( vout_thread_t *p_vout );
static int Align ( vout_thread_t *p_vout, int *pi_x,
static void SetPalette ( p_vout_thread_t p_vout, u16 *red,
u16 *green, u16 *blue, u16 *transp );
+/*****************************************************************************
+ * vout_InitBank: initialize the video output bank.
+ *****************************************************************************/
+void vout_InitBank ( void )
+{
+ p_vout_bank->i_count = 0;
+
+ vlc_mutex_init( &p_vout_bank->lock );
+}
+
+/*****************************************************************************
+ * vout_EndBank: empty the video output bank.
+ *****************************************************************************
+ * This function ends all unused video outputs and empties the bank in
+ * case of success.
+ *****************************************************************************/
+void vout_EndBank ( void )
+{
+ /* Ask all remaining video outputs to die */
+ while( p_vout_bank->i_count )
+ {
+ vout_DestroyThread(
+ p_vout_bank->pp_vout[ --p_vout_bank->i_count ], NULL );
+ }
+
+ vlc_mutex_destroy( &p_vout_bank->lock );
+}
+
/*****************************************************************************
* vout_CreateThread: creates a new video output thread
*****************************************************************************
}
/* Choose the best module */
- p_vout->p_module = module_Need( p_main->p_bank,
- MODULE_CAPABILITY_VOUT, NULL );
+ p_vout->p_module = module_Need( MODULE_CAPABILITY_VOUT, NULL );
if( p_vout->p_module == NULL )
{
p_vout->pf_setpalette = f.pf_setpalette;
#undef f
+ /* Initialize callbacks */
+ p_vout->pf_setbuffers = SetBuffers;
+
if( p_vout->pf_setpalette == NULL )
{
- p_vout->pf_setpalette = SetPalette;
+ p_vout->pf_setpalette = SetPalette;
}
/* Initialize thread properties - thread id and locks will be initialized
p_vout->i_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
VOUT_HEIGHT_DEFAULT );
p_vout->i_bytes_per_line = p_vout->i_width * 2;
- p_vout->i_screen_depth = 15;
+ p_vout->i_screen_depth = main_GetIntVariable( VOUT_DEPTH_VAR,
+ VOUT_DEPTH_DEFAULT );
p_vout->i_bytes_per_pixel = 2;
- p_vout->f_gamma = VOUT_GAMMA;
+ p_vout->f_gamma = VOUT_GAMMA_DEFAULT; // FIXME: replace with
+ // variable
p_vout->b_need_render = 1;
+ p_vout->b_YCbr = 0;
p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR,
VOUT_GRAYSCALE_DEFAULT );
p_vout->b_info = 0;
p_vout->b_interface = 0;
p_vout->b_scale = 1;
+ p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
+ VOUT_FULLSCREEN_DEFAULT );
- intf_WarnMsg( 1, "wished configuration: %dx%d, %d/%d bpp (%d Bpl)",
+ intf_WarnMsg( 3, "wished configuration: %dx%d, %d/%d bpp (%d Bpl)",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
p_vout->i_bytes_per_pixel * 8, p_vout->i_bytes_per_line );
* 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_picture[i_index].i_type = EMPTY_PICTURE;
+ p_vout->p_picture[i_index].i_status = FREE_PICTURE;
}
+
for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++)
{
- p_vout->p_subpicture[i_index].i_type = EMPTY_SUBPICTURE;
- p_vout->p_subpicture[i_index].i_status= FREE_SUBPICTURE;
+ p_vout->p_subpicture[i_index].i_type = EMPTY_SUBPICTURE;
+ p_vout->p_subpicture[i_index].i_status = FREE_SUBPICTURE;
}
+
p_vout->i_pictures = 0;
/* Create and initialize system-dependant method - this function issues its
* own error messages */
if( p_vout->pf_create( p_vout ) )
{
- module_Unneed( p_main->p_bank, p_vout->p_module );
+ module_Unneed( p_vout->p_module );
free( p_vout );
return( NULL );
}
- intf_WarnMsg( 1, "actual configuration: %dx%d, %d/%d bpp (%d Bpl), "
+
+ intf_WarnMsg( 3, "actual configuration: %dx%d, %d/%d bpp (%d Bpl), "
"masks: 0x%x/0x%x/0x%x",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
p_vout->i_bytes_per_pixel * 8, p_vout->i_bytes_per_line,
if( p_vout->p_default_font == NULL )
{
intf_ErrMsg( "vout error: could not load default font" );
- p_vout->pf_destroy( p_vout );
- free( p_vout );
- return( NULL );
}
p_vout->p_large_font = vout_LoadFont( VOUT_LARGE_FONT );
if( p_vout->p_large_font == NULL )
{
intf_ErrMsg( "vout error: could not load large font" );
- vout_UnloadFont( p_vout->p_default_font );
- p_vout->pf_destroy( p_vout );
- free( p_vout );
- return( NULL );
}
/* Create thread and set locks */
return( NULL );
}
- intf_Msg( "vout: video display initialized (%dx%d, %d/%d bpp)",
+ intf_WarnMsg( 1, "vout: video display initialized (%dx%d, %d/%d bpp)",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
p_vout->i_bytes_per_pixel * 8 );
/*****************************************************************************
* vout_DisplaySubPicture: display a subpicture unit
*****************************************************************************
- * Remove the reservation flag of an subpicture, which will cause it to be ready
+ * Remove the reservation flag of a subpicture, 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_DisplaySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
{
-#ifdef DEBUG_VOUT
- char psz_begin_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
- char psz_end_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */
+#ifdef TRACE_VOUT
+ char psz_start[ MSTRTIME_MAX_SIZE ]; /* buffer for date string */
+ char psz_stop[ MSTRTIME_MAX_SIZE ]; /* buffer for date string */
#endif
#ifdef DEBUG
/* Check if status is valid */
if( p_subpic->i_status != RESERVED_SUBPICTURE )
{
- intf_DbgMsg("error: subpicture %p has invalid status %d", p_subpic,
+ intf_ErrMsg("error: subpicture %p has invalid status %d", p_subpic,
p_subpic->i_status );
}
#endif
/* Remove reservation flag */
p_subpic->i_status = READY_SUBPICTURE;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
/* Send subpicture information */
intf_DbgMsg("subpicture %p: type=%d, begin date=%s, end date=%s",
p_subpic, p_subpic->i_type,
- mstrtime( psz_begin_date, p_subpic->begin_date ),
- mstrtime( psz_end_date, p_subpic->end_date ) );
+ mstrtime( psz_start, p_subpic->i_start ),
+ mstrtime( psz_stop, p_subpic->i_stop ) );
#endif
}
* the best possible case, since no memory allocation needs
* to be done */
p_vout->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("subpicture %p (in destroyed subpicture slot)",
&p_vout->p_subpicture[i_subpic] );
#endif
}
else if( p_destroyed_subpic == NULL )
{
- /* Memory size do not match, but subpicture index will be kept in
- * case no other place are left */
+ /* Memory size do not match, but subpicture index will be kept
+ * in case we find no other place */
p_destroyed_subpic = &p_vout->p_subpicture[i_subpic];
}
}
break;
#ifdef DEBUG
default:
- intf_DbgMsg("error: unknown subpicture type %d", i_type );
+ intf_ErrMsg("error: unknown subpicture type %d", i_type );
p_free_subpic->p_data = NULL;
break;
#endif
strerror( ENOMEM ) );
}
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("subpicture %p (in free subpicture slot)", p_free_subpic );
#endif
vlc_mutex_unlock( &p_vout->subpicture_lock );
/* Check if status is valid */
if( p_subpic->i_status != RESERVED_SUBPICTURE )
{
- intf_DbgMsg("error: subpicture %p has invalid status %d",
+ intf_ErrMsg("error: subpicture %p has invalid status %d",
p_subpic, p_subpic->i_status );
}
#endif
p_subpic->i_status = DESTROYED_SUBPICTURE;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("subpicture %p", p_subpic);
#endif
}
break;
#ifdef DEBUG
default:
- intf_DbgMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status );
+ intf_ErrMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status );
break;
#endif
}
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("picture %p", p_pic);
#endif
vlc_mutex_unlock( &p_vout->picture_lock );
*****************************************************************************/
void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date )
{
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
char psz_date[MSTRTIME_MAX_SIZE]; /* date */
#endif
break;
#ifdef DEBUG
default:
- intf_DbgMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status );
+ intf_ErrMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status );
break;
#endif
}
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("picture %p, display date: %s", p_pic, mstrtime( psz_date, p_pic->date) );
#endif
vlc_mutex_unlock( &p_vout->picture_lock );
* memory allocation needs to be done */
p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
p_vout->i_pictures++;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("picture %p (in destroyed picture slot)",
&p_vout->p_picture[i_picture] );
#endif
break;
#ifdef DEBUG
default:
- intf_DbgMsg("error: unknown picture type %d", i_type );
+ intf_ErrMsg("error: unknown picture type %d", i_type );
p_free_picture->p_data = NULL;
break;
#endif
strerror( ENOMEM ) );
}
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("picture %p (in free picture slot)", p_free_picture );
#endif
vlc_mutex_unlock( &p_vout->picture_lock );
/* Initialize mutex */
vlc_mutex_init( &(p_free_picture->lock_deccount) );
-
+
return( p_free_picture );
}
(p_pic->i_status != RESERVED_DATED_PICTURE) &&
(p_pic->i_status != RESERVED_DISP_PICTURE) )
{
- intf_DbgMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status );
+ intf_ErrMsg("error: picture %p has invalid status %d", p_pic, p_pic->i_status );
}
#endif
p_pic->i_status = DESTROYED_PICTURE;
p_vout->i_pictures--;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("picture %p", p_pic);
#endif
/* destroy the lock that had been initialized in CreatePicture */
vlc_mutex_destroy( &(p_pic->lock_deccount) );
-
+
vlc_mutex_unlock( &p_vout->picture_lock );
}
vlc_mutex_lock( &p_vout->picture_lock );
p_pic->i_refcount++;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("picture %p refcount=%d", p_pic, p_pic->i_refcount );
#endif
vlc_mutex_lock( &p_vout->picture_lock );
p_pic->i_refcount--;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
if( p_pic->i_refcount < 0 )
{
intf_DbgMsg("error: refcount < 0");
p_vout->i_pictures--;
}
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("picture %p refcount=%d", p_pic, p_pic->i_refcount );
#endif
vlc_mutex_unlock( &p_vout->picture_lock );
}
-/*****************************************************************************
- * vout_SetBuffers: set buffers adresses
- *****************************************************************************
- * This function is called by system drivers to set buffers video memory
- * adresses.
- *****************************************************************************/
-void vout_SetBuffers( vout_thread_t *p_vout, void *p_buf1, void *p_buf2 )
-{
- /* No picture previously */
- p_vout->p_buffer[0].i_pic_x = 0;
- p_vout->p_buffer[0].i_pic_y = 0;
- p_vout->p_buffer[0].i_pic_width = 0;
- p_vout->p_buffer[0].i_pic_height = 0;
- p_vout->p_buffer[1].i_pic_x = 0;
- p_vout->p_buffer[1].i_pic_y = 0;
- p_vout->p_buffer[1].i_pic_width = 0;
- p_vout->p_buffer[1].i_pic_height = 0;
-
- /* The first area covers all the screen */
- p_vout->p_buffer[0].i_areas = 1;
- p_vout->p_buffer[0].pi_area_begin[0] = 0;
- p_vout->p_buffer[0].pi_area_end[0] = p_vout->i_height - 1;
- p_vout->p_buffer[1].i_areas = 1;
- p_vout->p_buffer[1].pi_area_begin[0] = 0;
- p_vout->p_buffer[1].pi_area_end[0] = p_vout->i_height - 1;
-
- /* Set adresses */
- p_vout->p_buffer[0].p_data = p_buf1;
- p_vout->p_buffer[1].p_data = p_buf2;
-}
-
/*****************************************************************************
* vout_Pixel2RGB: return red, green and blue from pixel value
*****************************************************************************
p_vout->b_active = 1;
*p_vout->pi_status = THREAD_READY;
-
+
intf_DbgMsg("thread ready");
return( 0 );
}
mtime_t current_date; /* current date */
mtime_t display_date; /* display date */
boolean_t b_display; /* display flag */
+
picture_t * p_pic; /* picture pointer */
+
subpicture_t * p_subpic; /* subpicture pointer */
+ subpicture_t * p_ephemer; /* youngest ephemer subpicture pointer */
+ mtime_t ephemer_date; /* earliest subpicture date */
/*
* Initialize thread
/* Initialize loop variables */
p_pic = NULL;
p_subpic = NULL;
+ p_ephemer = NULL;
+ ephemer_date = 0;
display_date = 0;
current_date = mdate();
#ifdef STATS
p_pic->i_status = DESTROYED_PICTURE;
p_vout->i_pictures--;
}
- intf_WarnMsg( 3,
+ intf_WarnMsg( 1,
"warning: late picture skipped (%p)", p_pic );
vlc_mutex_unlock( &p_vout->picture_lock );
display_date = 0;
}
}
+
/*
* Find the subpictures to display - this operation does not need
* lock, since only READY_SUBPICTURE are handled. If no picture
* has been selected, display_date will depend on the subpicture.
+ *
+ * We also check for ephemer DVD subpictures (subpictures that have
+ * to be removed if a newer one is available), which makes it a lot
+ * more difficult to guess if a subpicture has to be rendered or not.
+ *
* We get an easily parsable chained list of subpictures which
* ends with NULL since p_subpic was initialized to NULL.
*/
{
if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE )
{
- p_vout->p_subpicture[i_index].p_next = p_subpic;
- p_subpic = &p_vout->p_subpicture[i_index];
+ /* If it is a DVD subpicture, check its date */
+ if( p_vout->p_subpicture[i_index].i_type == DVD_SUBPICTURE )
+ {
+ if( display_date > p_vout->p_subpicture[i_index].i_stop )
+ {
+ /* Too late, destroy the subpic */
+ vout_DestroySubPicture( p_vout,
+ &p_vout->p_subpicture[i_index] );
+ continue;
+ }
+
+ if( display_date < p_vout->p_subpicture[i_index].i_start )
+ {
+ /* Too early, come back next monday */
+ continue;
+ }
+
+ /* If this is an ephemer subpic, see if it's the
+ * youngest we have */
+ if( p_vout->p_subpicture[i_index].b_ephemer )
+ {
+ if( p_ephemer == NULL )
+ {
+ p_ephemer = &p_vout->p_subpicture[i_index];
+ continue;
+ }
+
+ if( p_vout->p_subpicture[i_index].i_start
+ < p_ephemer->i_start )
+ {
+ /* Link the previous ephemer subpicture and
+ * replace it with the current one */
+ p_ephemer->p_next = p_subpic;
+ p_subpic = p_ephemer;
+ p_ephemer = &p_vout->p_subpicture[i_index];
+
+ /* If it's the 2nd youngest subpicture,
+ * register its date */
+ if( !ephemer_date
+ || ephemer_date > p_subpic->i_start )
+ {
+ ephemer_date = p_subpic->i_start;
+ }
+
+ continue;
+ }
+ }
+
+ p_vout->p_subpicture[i_index].p_next = p_subpic;
+ p_subpic = &p_vout->p_subpicture[i_index];
+
+ /* If it's the 2nd youngest subpicture, register its date */
+ if( !ephemer_date || ephemer_date > p_subpic->i_start )
+ {
+ ephemer_date = p_subpic->i_start;
+ }
+ }
+ /* If it's not a DVD subpicture, just register it */
+ else
+ {
+ p_vout->p_subpicture[i_index].p_next = p_subpic;
+ p_subpic = &p_vout->p_subpicture[i_index];
+ }
+ }
+ }
+
+ /* If we found an ephemer subpicture, check if it has to be
+ * displayed */
+ if( p_ephemer != NULL )
+ {
+ if( p_ephemer->i_start < ephemer_date )
+ {
+ /* Ephemer subpicture has lived too long */
+ vout_DestroySubPicture( p_vout, p_ephemer );
+ }
+ else
+ {
+ /* Ephemer subpicture can still live a bit */
+ p_ephemer->p_next = p_subpic;
+ p_subpic = p_ephemer;
}
}
p_vout->last_display_date = display_date;
p_vout->p_rendered_pic = p_pic;
-
-
-
/* Set picture dimensions and clear buffer */
SetBufferPicture( p_vout, p_pic );
RenderPictureInfo( p_vout, p_pic );
RenderInfo( p_vout );
}
+ }
+ if( b_display ) /* XXX: quick HACK */
+ {
if( p_subpic )
{
- RenderSubPicture( p_vout, p_subpic );
+ RenderSubPicture( p_vout, p_pic, p_subpic );
}
}
-
- /* Render interface and subpicture */
- if( b_display && p_vout->b_interface && p_vout->b_need_render )
- {
- RenderInterface( p_vout );
- }
-
}
- else if( p_vout->b_active && p_vout->b_need_render
+ else if( p_vout->b_active && p_vout->b_need_render
&& p_vout->init_display_date == 0)
{
/* Idle or interface screen alone */
if( b_display )
{
p_vout->last_idle_date = current_date;
- if( p_vout->b_interface )
- {
- RenderInterface( p_vout );
- }
}
}
* Check for the current time and
* display splash screen if everything is on time
*/
- if( p_vout->init_display_date > 0 && p_vout->b_need_render )
+ if( p_vout->init_display_date > 0 && p_vout->b_need_render )
{
- if( p_vout->b_active &&
- mdate()-p_vout->init_display_date < 5000000)
- {
- /* there is something to display ! */
- b_display = 1;
- RenderSplash( p_vout );
-
- } else {
- /* no splash screen ! */
- p_vout->init_display_date=0;
- }
+ p_vout->init_display_date = 0;
}
-
+
/*
* Sleep, wake up and display rendered picture
/* On awakening, take back lock and send immediately picture to display,
* then swap buffers */
vlc_mutex_lock( &p_vout->change_lock );
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg( "picture %p, subpicture %p in buffer %d, display=%d", p_pic, p_subpic,
p_vout->i_buffer_index, b_display /* && !(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) */ );
#endif
vlc_mutex_destroy( &p_vout->picture_lock );
vlc_mutex_destroy( &p_vout->subpicture_lock );
vlc_mutex_destroy( &p_vout->change_lock );
-
+
/* Release the module */
- module_Unneed( p_main->p_bank, p_vout->p_module );
+ module_Unneed( p_vout->p_module );
/* Free structure */
free( p_vout );
}
}
+/*****************************************************************************
+ * SetBuffers: set buffers adresses
+ *****************************************************************************
+ * This function is called by system drivers to set buffers video memory
+ * adresses.
+ *****************************************************************************/
+static void SetBuffers( vout_thread_t *p_vout, void *p_buf1, void *p_buf2 )
+{
+ /* No picture previously */
+ p_vout->p_buffer[0].i_pic_x = 0;
+ p_vout->p_buffer[0].i_pic_y = 0;
+ p_vout->p_buffer[0].i_pic_width = 0;
+ p_vout->p_buffer[0].i_pic_height = 0;
+ p_vout->p_buffer[1].i_pic_x = 0;
+ p_vout->p_buffer[1].i_pic_y = 0;
+ p_vout->p_buffer[1].i_pic_width = 0;
+ p_vout->p_buffer[1].i_pic_height = 0;
+
+ /* The first area covers all the screen */
+ p_vout->p_buffer[0].i_areas = 1;
+ p_vout->p_buffer[0].pi_area_begin[0] = 0;
+ p_vout->p_buffer[0].pi_area_end[0] = p_vout->i_height - 1;
+ p_vout->p_buffer[1].i_areas = 1;
+ p_vout->p_buffer[1].pi_area_begin[0] = 0;
+ p_vout->p_buffer[1].pi_area_end[0] = p_vout->i_height - 1;
+
+ /* Set adresses */
+ p_vout->p_buffer[0].p_data = p_buf1;
+ p_vout->p_buffer[1].p_data = p_buf2;
+}
+
/*****************************************************************************
* SetBufferArea: activate an area in current buffer
*****************************************************************************
}
else
{
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("area overflow");
#endif
p_buffer->pi_area_end[VOUT_MAX_AREAS - 1] = i_h;
* move all old areas down */
if( p_buffer->i_areas == VOUT_MAX_AREAS )
{
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("areas overflow");
#endif
p_buffer->pi_area_end[VOUT_MAX_AREAS - 2] = p_buffer->pi_area_end[VOUT_MAX_AREAS - 1];
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] );
+ //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;
*/
for( i_area = 0; i_area < p_buffer->i_areas; i_area++ )
{
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
intf_DbgMsg("clearing picture %p area in buffer %d: %d-%d", p_pic,
p_vout->i_buffer_index, p_buffer->pi_area_begin[i_area], p_buffer->pi_area_end[i_area] );
#endif
i_data_size = (p_buffer->pi_area_end[i_area] - p_buffer->pi_area_begin[i_area] + 1) * p_vout->i_bytes_per_line;
p_data = (u64*) (p_buffer->p_data + p_vout->i_bytes_per_line * p_buffer->pi_area_begin[i_area]);
+
for( i_data_index = i_data_size / 256; i_data_index-- ; )
{
/* Clear 256 bytes block */
*****************************************************************************/
static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
char psz_date[MSTRTIME_MAX_SIZE]; /* picture date */
mtime_t render_time; /* picture rendering time */
#endif
p_pic_data = p_buffer->p_data +
p_buffer->i_pic_x * p_vout->i_bytes_per_pixel +
p_buffer->i_pic_y * p_vout->i_bytes_per_line;
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
render_time = mdate();
#endif
-
-
+
+
/*
* Choose appropriate rendering function and render picture
*/
switch( p_pic->i_type )
{
case YUV_420_PICTURE:
- p_vout->yuv.p_Convert420( p_vout, p_pic_data,
- p_pic->p_y, p_pic->p_u, p_pic->p_v,
- p_pic->i_width, p_pic->i_height,
- p_buffer->i_pic_width, p_buffer->i_pic_height,
- p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
- p_pic->i_matrix_coefficients );
+ p_vout->yuv.pf_yuv420( p_vout, p_pic_data,
+ p_pic->p_y, p_pic->p_u, p_pic->p_v,
+ p_pic->i_width, p_pic->i_height,
+ p_buffer->i_pic_width, p_buffer->i_pic_height,
+ p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
+ p_pic->i_matrix_coefficients );
break;
case YUV_422_PICTURE:
- p_vout->yuv.p_Convert422( p_vout, p_pic_data,
- p_pic->p_y, p_pic->p_u, p_pic->p_v,
- p_pic->i_width, p_pic->i_height,
- p_buffer->i_pic_width, p_buffer->i_pic_height,
- p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
- p_pic->i_matrix_coefficients );
+ p_vout->yuv.pf_yuv422( p_vout, p_pic_data,
+ p_pic->p_y, p_pic->p_u, p_pic->p_v,
+ p_pic->i_width, p_pic->i_height,
+ p_buffer->i_pic_width, p_buffer->i_pic_height,
+ p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
+ p_pic->i_matrix_coefficients );
break;
case YUV_444_PICTURE:
- p_vout->yuv.p_Convert444( p_vout, p_pic_data,
- p_pic->p_y, p_pic->p_u, p_pic->p_v,
- p_pic->i_width, p_pic->i_height,
- p_buffer->i_pic_width, p_buffer->i_pic_height,
- p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
- p_pic->i_matrix_coefficients );
+ p_vout->yuv.pf_yuv444( p_vout, p_pic_data,
+ p_pic->p_y, p_pic->p_u, p_pic->p_v,
+ p_pic->i_width, p_pic->i_height,
+ p_buffer->i_pic_width, p_buffer->i_pic_height,
+ p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
+ p_pic->i_matrix_coefficients );
break;
#ifdef DEBUG
default:
- intf_DbgMsg("error: unknown picture type %d", p_pic->i_type );
+ intf_ErrMsg("error: unknown picture type %d", p_pic->i_type );
break;
#endif
}
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
/* Print picture date and rendering time */
intf_DbgMsg("picture %p rendered in buffer %d (%ld us), display date: %s", p_pic,
p_vout->i_buffer_index, (long) (mdate() - render_time),
#endif
}
-/*****************************************************************************
- * RenderSplash: render splash picture
- *****************************************************************************
- * This function will print something on the screen. It will return 0 if
- * nothing has been rendered, or 1 if something has been changed on the screen.
- * Note that if you absolutely want something to be printed, you will have
- * to force it by setting the last idle date to 0.
- * Unlike other rendering functions, this one calls the SetBufferPicture
- * function when needed.
- *****************************************************************************/
-int RenderSplash( vout_thread_t *p_vout )
-{
- int i_x = 0, i_y = 0; /* text position */
- int i_width, i_height; /* text size */
- char *psz_text = "VideoLAN Client (" VERSION ")"; /* text to display */
-
- memset( p_vout->p_buffer[ p_vout->i_buffer_index ].p_data,
- p_vout->i_bytes_per_line * p_vout->i_height, 12);
-
- // SetBufferPicture( p_vout, NULL );
- vout_TextSize( p_vout->p_large_font, WIDE_TEXT | OUTLINED_TEXT, psz_text,
- &i_width, &i_height );
- if( !Align( p_vout, &i_x, &i_y, i_width, i_height, CENTER_RALIGN, CENTER_RALIGN ) )
- {
- vout_Print( p_vout->p_large_font,
- p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
- i_x * p_vout->i_bytes_per_pixel + (i_y - 16 ) * p_vout->i_bytes_per_line,
- p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
- p_vout->i_white_pixel, p_vout->i_gray_pixel, 0,
- WIDE_TEXT | OUTLINED_TEXT, psz_text, 100);
- SetBufferArea( p_vout, i_x, i_y, i_width, i_height);
- }
- return( 1 );
-}
-
-
/*****************************************************************************
* RenderIdle: render idle picture
*****************************************************************************
current_date = mdate();
- if( (current_date - p_vout->last_display_date) > VOUT_IDLE_DELAY
-// && (current_date - p_vout->last_idle_date) > VOUT_IDLE_DELAY
+ if( (current_date - p_vout->last_display_date) > VOUT_IDLE_DELAY
+// && (current_date - p_vout->last_idle_date) > VOUT_IDLE_DELAY
)
{
/* FIXME: idle screen disabled */
&i_width, &i_height );
if( !Align( p_vout, &i_x, &i_y, i_width, i_height * 2, CENTER_RALIGN, CENTER_RALIGN ) )
{
- i_amount = (int) ((current_date - p_vout->last_display_date ) / 5000LL);
+ i_amount = (int) ((current_date - p_vout->last_display_date ) / 5000LL);
vout_Print( p_vout->p_large_font,
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
i_x * p_vout->i_bytes_per_pixel + i_y * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_vout->i_white_pixel, p_vout->i_gray_pixel, 0,
WIDE_TEXT | OUTLINED_TEXT, psz_wtext, (i_amount/5)%110 );
-
+
SetBufferArea( p_vout, i_x, i_y, i_width, i_height * 2 );
}
*****************************************************************************
* This function renders a sub picture unit.
*****************************************************************************/
-static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
+static void RenderSubPicture( vout_thread_t *p_vout, picture_t *p_pic,
+ subpicture_t *p_subpic )
{
p_vout_font_t p_font; /* text font */
int i_width, i_height; /* subpicture dimensions */
switch( p_subpic->i_type )
{
case DVD_SUBPICTURE: /* DVD subpicture unit */
- /* test if the picture really has to be displayed */
- if( mdate() < p_subpic->begin_date )
- {
- /* not yet, see you later */
- break;
- }
- if( mdate() > p_subpic->end_date )
- {
- /* too late, destroying the subpic */
- vout_DestroySubPicture( p_vout, p_subpic );
- break;
- }
- vout_RenderSPU( &p_vout->p_buffer[ p_vout->i_buffer_index ],
- p_subpic, p_vout->i_bytes_per_pixel,
- p_vout->i_bytes_per_line );
+ vout_RenderRGBSPU( p_pic, p_subpic,
+ &p_vout->p_buffer[ p_vout->i_buffer_index ],
+ p_vout->i_bytes_per_pixel,
+ p_vout->i_bytes_per_line );
+ /* vout_RenderYUVSPU( p_pic, p_subpic ); */
break;
+
case TEXT_SUBPICTURE: /* single line text */
/* Select default font if not specified */
p_font = p_subpic->type.text.p_font;
}
break;
-#ifdef DEBUG
default:
- intf_DbgMsg( "error: unknown subpicture %p type %d",
+#ifdef DEBUG
+ intf_ErrMsg( "error: unknown subpicture %p type %d",
p_subpic, p_subpic->i_type );
#endif
+ break;
}
p_subpic = p_subpic->p_next;
}
}
-/*****************************************************************************
- * RenderInterface: render the interface
- *****************************************************************************
- * This function renders the interface, if any.
- *****************************************************************************/
-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, psz_text_1, &i_width_1, &i_height );
- vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_2, &i_width_2, &i_text_height );
- i_height += i_text_height;
-
- /* Render background */
- 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++ )
- {
- /* XXX?? noooo ! */
- p_vout->p_buffer[ p_vout->i_buffer_index ].p_data[ i_byte ] = p_vout->i_blue_pixel;
- }
-
- /* 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,
- p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
- OUTLINED_TEXT, psz_text_1, 100 );
- }
- 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,
- p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
- OUTLINED_TEXT, psz_text_2, 100 );
- }
-
- /* Activate modified area */
- SetBufferArea( p_vout, 0, p_vout->i_height - i_height, p_vout->i_width, i_height );
-}
-
/*****************************************************************************
* Manage: manage thread
*****************************************************************************
*****************************************************************************/
static int Manage( vout_thread_t *p_vout )
{
-#ifdef DEBUG_VOUT
+#ifdef TRACE_VOUT
if( p_vout->i_changes )
{
intf_DbgMsg("changes: 0x%x (no display: 0x%x)", p_vout->i_changes,