#include "intf_cmd.h"
#include "intf_console.h"
#include "main.h"
+#include "video.h"
+#include "video_output.h"
#include "intf_sys.h"
/* Manage specific interface */
intf_SysManage( p_intf );
+ /* Check attached threads status */
+ if( (p_intf->p_vout != NULL) && p_intf->p_vout->b_error )
+ {
+ //?? add aout error detection
+ p_intf->b_die = 1;
+ }
+ if( (p_intf->p_input != NULL) && p_intf->p_input->b_error )
+ {
+ input_DestroyThread( p_intf->p_input /*, NULL */ );
+ p_intf->p_input = NULL;
+ intf_DbgMsg("Input thread destroyed\n");
+ }
+
/* Sleep to avoid using all CPU - since some interfaces needs to access
* keyboard events, a 100ms delay is a good compromise */
msleep( INTF_IDLE_SLEEP );
return( (p_cfg != NULL) && (p_intf->p_input == NULL) );
}
+/*******************************************************************************
+ * intf_ProcessKey: process standard keys
+ *******************************************************************************
+ * This function will process standard keys and return non 0 if the key was
+ * unknown.
+ *******************************************************************************/
+int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
+{
+ switch( i_key )
+ {
+ case 'Q': /* quit order */
+ case 'q':
+ case 27:
+ p_intf->b_die = 1;
+ break;
+ case '0': /* source change */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ // ??
+ break;
+ case '+': /* volume + */
+ // ??
+ break;
+ case '-': /* volume - */
+ // ??
+ break;
+ case 'M': /* toggle mute */
+ case 'm':
+ // ??
+ break;
+ case 'g': /* gamma - */
+ if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_gamma > -INTF_GAMMA_MAX) )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->f_gamma -= INTF_GAMMA_STEP;
+ p_intf->p_vout->i_changes |= VOUT_GAMMA_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ case 'G': /* gamma + */
+ if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_gamma < INTF_GAMMA_MAX) )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->f_gamma += INTF_GAMMA_STEP;
+ p_intf->p_vout->i_changes |= VOUT_GAMMA_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ case 'c': /* toggle grayscale */
+ if( p_intf->p_vout != NULL )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->b_grayscale = !p_intf->p_vout->b_grayscale;
+ p_intf->p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ case 'x': /* horizontal aspect ratio - */
+ if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_x_ratio > INTF_RATIO_MIN) )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->f_x_ratio /= INTF_RATIO_FACTOR;
+ p_intf->p_vout->i_changes |= VOUT_RATIO_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ case 'X': /* horizontal aspect ratio + */
+ if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_x_ratio < INTF_RATIO_MAX) )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->f_x_ratio *= INTF_RATIO_FACTOR;
+ p_intf->p_vout->i_changes |= VOUT_RATIO_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ case 'y': /* vertical aspect ratio - */
+ if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_y_ratio > INTF_RATIO_MIN) )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->f_y_ratio /= INTF_RATIO_FACTOR;
+ p_intf->p_vout->i_changes |= VOUT_RATIO_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ case 'Y': /* horizontal aspect ratio + */
+ if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_y_ratio < INTF_RATIO_MAX) )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->f_y_ratio *= INTF_RATIO_FACTOR;
+ p_intf->p_vout->i_changes |= VOUT_RATIO_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ case 'f': /* toggle fullscreen */
+ //??
+ break;
+ case ' ': /* toggle info */
+ if( p_intf->p_vout != NULL )
+ {
+ vlc_mutex_lock( &p_intf->p_vout->change_lock );
+ p_intf->p_vout->b_info = !p_intf->p_vout->b_info;
+ p_intf->p_vout->i_changes |= VOUT_INFO_CHANGE;
+ vlc_mutex_unlock( &p_intf->p_vout->change_lock );
+ }
+ break;
+ default: /* unknown key */
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+
#include <stdio.h>
#include <string.h>
-#ifdef VIDEO_X11
-#include <X11/Xlib.h> /* for video_sys.h in X11 mode */
-#endif
-
#include "common.h"
#include "config.h"
#include "mtime.h"
static void RunThread ( vout_thread_t *p_vout );
static void ErrorThread ( 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 RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic );
-static int RenderIdle ( vout_thread_t *p_vout );
-static int RenderInfo ( vout_thread_t *p_vout );
+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 int RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_blank );
+static int RenderIdle ( vout_thread_t *p_vout, boolean_t b_blank );
+static int RenderInfo ( vout_thread_t *p_vout, boolean_t b_balnk );
static int Manage ( vout_thread_t *p_vout );
/*******************************************************************************
* If pi_status is NULL, then the function will block until the thread is ready.
* If not, it will be updated using one of the THREAD_* constants.
*******************************************************************************/
-vout_thread_t * vout_CreateThread (
-#ifdef VIDEO_X11
- char *psz_display, Window root_window,
-#endif
- int i_width, int i_height, int *pi_status
- )
+vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window,
+ int i_width, int i_height, int *pi_status )
{
vout_thread_t * p_vout; /* thread descriptor */
int i_status; /* thread status */
/* Create and initialize system-dependant method - this function issues its
* own error messages */
- if( vout_SysCreate( p_vout
-#if defined(VIDEO_X11)
- , psz_display, root_window
-#endif
- ) )
+ if( vout_SysCreate( p_vout, psz_display, i_root_window ) )
{
free( p_vout );
return( NULL );
#ifdef STATS
/* Initialize statistics fields */
- p_vout->loop_time = 0;
+ 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 */
vlc_mutex_init( &p_vout->picture_lock );
vlc_mutex_init( &p_vout->subtitle_lock );
- if( vlc_thread_create( &p_vout->thread_id, "video output",
- (void *) RunThread, (void *) p_vout) )
+ vlc_mutex_init( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->change_lock );
+ if( vlc_thread_create( &p_vout->thread_id, "video output", (void *) RunThread, (void *) p_vout) )
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM));
vout_SysDestroy( p_vout );
p_pic = NULL;
}
}
-
/*
* Perform rendering, sleep and display rendered picture
/* A picture is ready to be displayed : render it */
if( p_vout->b_active )
{
- RenderPicture( p_vout, p_pic );
+ b_display = RenderPicture( p_vout, p_pic, 1 );
if( p_vout->b_info )
{
- RenderPictureInfo( p_vout, p_pic );
- RenderInfo( p_vout );
+ b_display |= RenderPictureInfo( p_vout, p_pic, b_display );
+ b_display |= RenderInfo( p_vout, b_display );
}
- b_display = 1;
}
else
{
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 ) ));
+ if( p_vout->b_active )
+ {
+ b_display = RenderIdle( p_vout, 1 );
+ if( p_vout->b_info )
+ {
+ b_display |= RenderInfo( p_vout, b_display );
+ }
+ }
+ else
+ {
+ b_display = 0;
+ }
}
+ /* Give back change lock */
+ vlc_mutex_unlock( &p_vout->change_lock );
+
/* 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 )
+ /* On awakening, take back lock and send immediately picture to display */
+ vlc_mutex_lock( &p_vout->change_lock );
+ if( b_display && p_vout->b_active &&
+ !(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) )
{
vout_SysDisplay( p_vout );
}
*pi_status = THREAD_OVER;
}
+/*******************************************************************************
+ * RenderBlank: render a blank screen
+ *******************************************************************************
+ * This function is called by all other rendering functions when they arrive on
+ * a non blanked screen.
+ *******************************************************************************/
+static void RenderBlank( vout_thread_t *p_vout )
+{
+ int i_index; /* current 32 bits sample */
+ int i_width; /* number of 32 bits samples */
+ u32 *p_pic; /* pointer to 32 bits samples */
+
+ /* Initialize variables */
+ p_pic = vout_SysGetPicture( p_vout );
+ i_width = p_vout->i_bytes_per_line * p_vout->i_height / 128;
+
+ /* Clear beginning of screen by 128 bytes blocks */
+ for( i_index = 0; i_index < i_width; i_index++ )
+ {
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ *p_pic++ = 0; *p_pic++ = 0;
+ }
+
+ /* Clear last pixels */
+ //??
+}
+
+
/*******************************************************************************
* RenderPicture: render a picture
*******************************************************************************
* rendered picture has been determined as existant, and will only be destroyed
* by the vout thread later.
*******************************************************************************/
-static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
+static int RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_blank )
{
+ /* Mark last picture date */
+ p_vout->last_picture_date = p_pic->date;
+
+ /* Blank screen if required */
+ if( b_blank )
+ {
+ RenderBlank( p_vout );
+ }
+
/*
* Prepare scaling
*/
* XImages */
/* p_vout->i_new_width = p_pic->i_width;
p_vout->i_new_height = p_pic->i_height;*/
- return;
#else
/* Other drivers: the video output thread can't change its size, so
* we need to change the aspect ratio */
* Terminate scaling
*/
//??
+
+ return( 1 );
}
/*******************************************************************************
* RenderPictureInfo: print additionnal informations on a picture
*******************************************************************************
- * This function will add informations such as fps and buffer size on a picture
+ * This function will print informations such as fps and other picture
+ * dependant informations.
*******************************************************************************/
-static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic )
+static int RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic, boolean_t b_blank )
{
char psz_buffer[256]; /* string buffer */
-#ifdef DEBUG
- int i_ready_pic = 0; /* ready pictures */
- int i_reserved_pic = 0; /* reserved pictures */
- int i_picture; /* picture index */
-#endif
#ifdef STATS
/*
}
/*
- * Print statistics in upper left corner
+ * Print frames count and loop time in upper left corner
*/
- sprintf( psz_buffer, "gamma=%.2f %ld frames",
- p_vout->f_gamma, p_vout->c_fps_samples );
+ sprintf( psz_buffer, "%ld frames render time: %lu us",
+ p_vout->c_fps_samples, (long unsigned) p_vout->render_time );
vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer );
#endif
-
+
#ifdef DEBUG
- /*
- * Print heap state in lower left corner
+ /*
+ * Print picture information in lower right corner
*/
- for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
- {
- switch( p_vout->p_picture[i_picture].i_status )
- {
- case RESERVED_PICTURE:
- i_reserved_pic++;
- break;
- case READY_PICTURE:
- i_ready_pic++;
- break;
- }
- }
- sprintf( psz_buffer, "video heap: %d/%d/%d", i_reserved_pic, i_ready_pic,
- VOUT_MAX_PICTURES );
- vout_SysPrint( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer );
-#endif
-
-#ifdef DEBUG_VIDEO
- //??
+ sprintf( psz_buffer, "%s picture (mc=%d) %dx%d (%dx%d%+d%+d ar=%s)",
+ (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_444_PICTURE) ? "4:4:4" : "?")),
+ p_pic->i_matrix_coefficients, p_pic->i_width, p_pic->i_height,
+ p_pic->i_display_width, p_pic->i_display_height,
+ p_pic->i_display_horizontal_offset, p_pic->i_display_vertical_offset,
+ (p_pic->i_aspect_ratio == AR_SQUARE_PICTURE) ? "square" :
+ ((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_221_1_PICTURE) ? "2.21:1" : "?" ))));
+ vout_SysPrint( p_vout, p_vout->i_width, p_vout->i_height, 1, 1, psz_buffer );
#endif
+
+ return( 0 );
}
/*******************************************************************************
*******************************************************************************
* This function will clear the display or print a logo.
*******************************************************************************/
-static int RenderIdle( vout_thread_t *p_vout )
+static int RenderIdle( vout_thread_t *p_vout, boolean_t b_blank )
{
- //??
+ /* Blank screen if required */
+ if( (mdate() - p_vout->last_picture_date > VOUT_IDLE_DELAY) &&
+ (p_vout->last_picture_date > p_vout->last_display_date) &&
+ b_blank )
+ {
+ RenderBlank( p_vout );
+ p_vout->last_display_date = mdate();
+ vout_SysPrint( p_vout, p_vout->i_width / 2, p_vout->i_height / 2, 0, 0,
+ "no stream" );
+ return( 1 );
+ }
+
return( 0 );
}
/*******************************************************************************
* RenderInfo: render additionnal informations
*******************************************************************************
- * ??
+ * This function render informations which do not depend of the current picture
+ * rendered.
*******************************************************************************/
-static int RenderInfo( vout_thread_t *p_vout )
+static int RenderInfo( vout_thread_t *p_vout, boolean_t b_blank )
{
- //??
+ char psz_buffer[256]; /* string buffer */
+#ifdef DEBUG
+ int i_ready_pic = 0; /* ready pictures */
+ int i_reserved_pic = 0; /* reserved pictures */
+ int i_picture; /* picture index */
+#endif
+
+#ifdef DEBUG
+ /*
+ * Print thread state in lower left corner
+ */
+ for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
+ {
+ switch( p_vout->p_picture[i_picture].i_status )
+ {
+ case RESERVED_PICTURE:
+ i_reserved_pic++;
+ break;
+ case READY_PICTURE:
+ i_ready_pic++;
+ break;
+ }
+ }
+ sprintf( psz_buffer, "%s %dx%d:%d %.2f:%.2f g%+.2f pic: %d/%d/%d",
+ p_vout->b_grayscale ? "gray" : "rgb",
+ p_vout->i_width, p_vout->i_height,
+ p_vout->i_screen_depth, p_vout->f_x_ratio, p_vout->f_y_ratio, p_vout->f_gamma,
+ i_reserved_pic, i_ready_pic,
+ VOUT_MAX_PICTURES );
+ vout_SysPrint( p_vout, 0, p_vout->i_height, -1, 1, psz_buffer );
+#endif
return( 0 );
}
/*******************************************************************************
* Manage: manage thread
*******************************************************************************
- * ??
+ * This function will handle changes in thread configuration.
*******************************************************************************/
static int Manage( vout_thread_t *p_vout )
{
- //??
+ /* On gamma or grayscale change, rebuild tables */
+ if( p_vout->i_changes & (VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE) )
+ {
+ vout_ResetTables( p_vout );
+ }
+
+ /* Clear changes flags which does not need management or have been handled */
+ p_vout->i_changes &= ~(VOUT_INFO_CHANGE | VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE);
/* Detect unauthorized changes */
if( p_vout->i_changes )