p_vout->i_alignment = 0;
p_vout->p->render_time = 10;
p_vout->p->c_fps_samples = 0;
- p_vout->p->i_picture_lost = 0;
- p_vout->p->i_picture_displayed = 0;
+ vout_statistic_Init( &p_vout->p->statistic );
p_vout->p->b_filter_change = 0;
p_vout->p->b_paused = false;
p_vout->p->i_pause_date = 0;
p_vout->p->b_picture_empty = false;
p_vout->p->i_picture_qtype = QTYPE_NONE;
- p_vout->p->snapshot.b_available = true;
- p_vout->p->snapshot.i_request = 0;
- p_vout->p->snapshot.p_picture = NULL;
- vlc_mutex_init( &p_vout->p->snapshot.lock );
- vlc_cond_init( &p_vout->p->snapshot.wait );
+ vlc_mouse_Init( &p_vout->p->mouse );
+
+ vout_snapshot_Init( &p_vout->p->snapshot );
/* Initialize locks */
vlc_mutex_init( &p_vout->picture_lock );
free( psz_parser );
free( psz_tmp );
p_vout->p_cfg = p_cfg;
- p_vout->p_module = module_need( p_vout,
- ( p_vout->p->psz_filter_chain && *p_vout->p->psz_filter_chain ) ?
- "video filter" : "video output", psz_name, p_vout->p->psz_filter_chain && *p_vout->p->psz_filter_chain );
- free( psz_name );
-
- vlc_object_set_destructor( p_vout, vout_Destructor );
-
- if( p_vout->p_module == NULL )
- {
- msg_Err( p_vout, "no suitable vout module" );
- spu_Attach( p_vout->p_spu, VLC_OBJECT(p_vout), false );
- spu_Destroy( p_vout->p_spu );
- p_vout->p_spu = NULL;
- vlc_object_release( p_vout );
- return NULL;
- }
/* Create a few object variables for interface interaction */
var_Create( p_vout, "vout-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
/* */
DeinterlaceEnable( p_vout );
+ if( p_vout->p->psz_filter_chain && *p_vout->p->psz_filter_chain )
+ p_vout->p->psz_module_type = "video filter";
+ else
+ p_vout->p->psz_module_type = "video output";
+ p_vout->p->psz_module_name = psz_name;
+ p_vout->p_module = NULL;
+
+ /* */
+ vlc_object_set_destructor( p_vout, vout_Destructor );
+
/* */
vlc_cond_init( &p_vout->p->change_wait );
if( vlc_clone( &p_vout->p->thread, RunThread, p_vout,
VLC_THREAD_PRIORITY_OUTPUT ) )
{
- module_unneed( p_vout, p_vout->p_module );
- p_vout->p_module = NULL;
spu_Attach( p_vout->p_spu, VLC_OBJECT(p_vout), false );
spu_Destroy( p_vout->p_spu );
p_vout->p_spu = NULL;
vlc_cond_signal( &p_vout->p->change_wait );
vlc_mutex_unlock( &p_vout->change_lock );
- vlc_mutex_lock( &p_vout->p->snapshot.lock );
- p_vout->p->snapshot.b_available = false;
- vlc_cond_broadcast( &p_vout->p->snapshot.wait );
- vlc_mutex_unlock( &p_vout->p->snapshot.lock );
+ vout_snapshot_End( &p_vout->p->snapshot );
vlc_join( p_vout->p->thread, NULL );
- module_unneed( p_vout, p_vout->p_module );
- p_vout->p_module = NULL;
}
/* */
/* Make sure the vout was stopped first */
assert( !p_vout->p_module );
+ free( p_vout->p->psz_module_name );
+
/* */
if( p_vout->p_spu )
spu_Destroy( p_vout->p_spu );
vlc_mutex_destroy( &p_vout->p->vfilter_lock );
/* */
- for( ;; )
- {
- picture_t *p_picture = p_vout->p->snapshot.p_picture;
- if( !p_picture )
- break;
-
- p_vout->p->snapshot.p_picture = p_picture->p_next;
+ vout_statistic_Clean( &p_vout->p->statistic );
- picture_Release( p_picture );
- }
- vlc_cond_destroy( &p_vout->p->snapshot.wait );
- vlc_mutex_destroy( &p_vout->p->snapshot.lock );
+ /* */
+ vout_snapshot_Clean( &p_vout->p->snapshot );
/* */
free( p_vout->p->psz_filter_chain );
void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_lost )
{
- vlc_mutex_lock( &p_vout->change_lock );
-
- *pi_displayed = p_vout->p->i_picture_displayed;
- *pi_lost = p_vout->p->i_picture_lost;
-
- p_vout->p->i_picture_displayed = 0;
- p_vout->p->i_picture_lost = 0;
-
- vlc_mutex_unlock( &p_vout->change_lock );
+ vout_statistic_GetReset( &p_vout->p->statistic,
+ pi_displayed, pi_lost );
}
void vout_Flush( vout_thread_t *p_vout, mtime_t i_date )
vlc_mutex_unlock( &p_vout->change_lock );
}
+spu_t *vout_GetSpu( vout_thread_t *p_vout )
+{
+ return p_vout->p_spu;
+}
+
/*****************************************************************************
* InitThread: initialize video output thread
*****************************************************************************
}
}
- /* Link pictures back to their heap */
- for( i = 0 ; i < I_RENDERPICTURES ; i++ )
- {
- PP_RENDERPICTURE[ i ]->p_heap = &p_vout->render;
- }
-
- for( i = 0 ; i < I_OUTPUTPICTURES ; i++ )
- {
- PP_OUTPUTPICTURE[ i ]->p_heap = &p_vout->output;
- }
-
return VLC_SUCCESS;
}
int i_idle_loops = 0; /* loops without displaying a picture */
int i_picture_qtype_last = QTYPE_NONE;
- bool b_drop_late;
+
+ vlc_mutex_lock( &p_vout->change_lock );
/*
* Initialize thread
*/
- vlc_mutex_lock( &p_vout->change_lock );
- p_vout->b_error = InitThread( p_vout );
-
- b_drop_late = var_CreateGetBool( p_vout, "drop-late-frames" );
+ p_vout->p_module = module_need( p_vout,
+ p_vout->p->psz_module_type,
+ p_vout->p->psz_module_name,
+ !strcmp(p_vout->p->psz_module_type, "video filter") );
+ if( p_vout->p_module )
+ p_vout->b_error = InitThread( p_vout );
+ else
+ p_vout->b_error = true;
/* signal the creation of the vout */
p_vout->p->b_ready = true;
vlc_cond_signal( &p_vout->p->change_wait );
if( p_vout->b_error )
- {
- EndThread( p_vout );
- vlc_mutex_unlock( &p_vout->change_lock );
- return NULL;
- }
+ goto exit_thread;
+
+ /* */
+ const bool b_drop_late = var_CreateGetBool( p_vout, "drop-late-frames" );
/*
* Main loop - it is not executed if an error occurred during
/* Picture is late: it will be destroyed and the thread
* will directly choose the next picture */
vout_UsePictureLocked( p_vout, p_pic );
- p_vout->p->i_picture_lost++;
+ vout_statistic_Update( &p_vout->p->statistic, 0, 1 );
msg_Warn( p_vout, "late picture skipped (%"PRId64" > %d)",
current_date - p_pic->date, - p_vout->p->render_time );
p_filtered_picture = filter_chain_VideoFilter( p_vout->p->p_vf2_chain,
p_picture );
- bool b_snapshot = false;
- if( vlc_mutex_trylock( &p_vout->p->snapshot.lock ) == 0 )
- {
- b_snapshot = p_vout->p->snapshot.i_request > 0
- && p_picture != NULL;
- vlc_mutex_unlock( &p_vout->p->snapshot.lock );
- }
+ const bool b_snapshot = vout_snapshot_IsRequested( &p_vout->p->snapshot );
/*
* Check for subpictures to display
*/
- subpicture_t *p_subpic = NULL;
- if( display_date > 0 )
- p_subpic = spu_SortSubpictures( p_vout->p_spu, display_date,
- p_vout->p->b_paused, b_snapshot );
+ mtime_t spu_render_time;
+ if( p_vout->p->b_paused )
+ spu_render_time = p_vout->p->i_pause_date;
+ else if( p_picture )
+ spu_render_time = p_picture->date > 1 ? p_picture->date : mdate();
+ else
+ spu_render_time = 0;
+ subpicture_t *p_subpic = spu_SortSubpictures( p_vout->p_spu,
+ spu_render_time,
+ b_snapshot );
/*
* Perform rendering
*/
- p_vout->p->i_picture_displayed++;
- p_directbuffer = vout_RenderPicture( p_vout, p_filtered_picture,
- p_subpic, p_vout->p->b_paused );
+ vout_statistic_Update( &p_vout->p->statistic, 1, 0 );
+ p_directbuffer = vout_RenderPicture( p_vout,
+ p_filtered_picture, p_subpic,
+ spu_render_time );
/*
* Take a snapshot if requested
*/
if( p_directbuffer && b_snapshot )
- {
- vlc_mutex_lock( &p_vout->p->snapshot.lock );
- assert( p_vout->p->snapshot.i_request > 0 );
- while( p_vout->p->snapshot.i_request > 0 )
- {
- picture_t *p_pic = picture_New( p_vout->fmt_out.i_chroma,
- p_vout->fmt_out.i_width,
- p_vout->fmt_out.i_height,
- p_vout->fmt_out.i_aspect );
- if( !p_pic )
- break;
-
- picture_Copy( p_pic, p_directbuffer );
-
- p_pic->p_next = p_vout->p->snapshot.p_picture;
- p_vout->p->snapshot.p_picture = p_pic;
- p_vout->p->snapshot.i_request--;
- }
- vlc_cond_broadcast( &p_vout->p->snapshot.wait );
- vlc_mutex_unlock( &p_vout->p->snapshot.lock );
- }
+ vout_snapshot_Set( &p_vout->p->snapshot,
+ &p_vout->fmt_out, p_directbuffer );
/*
* Call the plugin-specific rendering method if there is one
if( p_vout->pf_init( p_vout ) )
{
msg_Err( p_vout, "cannot resize display" );
- /* FIXME: pf_end will be called again in EndThread() */
+ /* FIXME: pf_end will be called again in CleanThread()? */
p_vout->b_error = 1;
}
if( p_vout->b_error )
ErrorThread( p_vout );
- /* End of thread */
+ /* Clean thread */
CleanThread( p_vout );
+
+exit_thread:
+ /* End of thread */
EndThread( p_vout );
vlc_mutex_unlock( &p_vout->change_lock );
+ if( p_vout->p_module )
+ module_unneed( p_vout, p_vout->p_module );
+ p_vout->p_module = NULL;
+
return NULL;
}
}
static void PostProcessEnable( vout_thread_t *p_vout )
{
+ vlc_value_t text;
msg_Dbg( p_vout, "Post-processing available" );
var_Create( p_vout, "postprocess", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
+ text.psz_string = _("Post processing");
+ var_Change( p_vout, "postprocess", VLC_VAR_SETTEXT, &text, NULL );
+
for( int i = 0; i <= 6; i++ )
{
vlc_value_t val;
const mtime_t i_stop = i_start + INT64_C(1000) * p_vout->p->i_title_timeout;
if( i_stop <= i_start )
- return
+ return;
vlc_assert_locked( &p_vout->change_lock );
typedef struct
{
const char *psz_mode;
- const char *psz_description;
bool b_vout_filter;
} deinterlace_mode_t;
* same (width/height/chroma/fps), at least for now.
*/
static const deinterlace_mode_t p_deinterlace_mode[] = {
- { "", "Disable", false },
- { "discard", "Discard", true },
- { "blend", "Blend", false },
- { "mean", "Mean", true },
- { "bob", "Bob", true },
- { "linear", "Linear", true },
- { "x", "X", false },
- { NULL, NULL, true }
+ { "", false },
+ { "discard", true },
+ { "blend", false },
+ { "mean", true },
+ { "bob", true },
+ { "linear", true },
+ { "x", false },
+ { "yadif", true },
+ { "yadif2x", true },
+ { NULL, true }
};
static char *FilterFind( char *psz_filter_base, const char *psz_module )
const deinterlace_mode_t *p_mode;
for( p_mode = &p_deinterlace_mode[0]; p_mode->psz_mode; p_mode++ )
{
- if( !strcmp( p_mode->psz_mode, newval.psz_string ?: "" ) )
+ if( !strcmp( p_mode->psz_mode,
+ newval.psz_string ? newval.psz_string : "" ) )
break;
}
if( !p_mode->psz_mode )
input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
if( p_input )
{
- var_Create( p_input, "vout-deinterlace", VLC_VAR_STRING );
- var_SetString( p_input, "vout-deinterlace", p_mode->psz_mode );
-
var_Create( p_input, "deinterlace-mode", VLC_VAR_STRING );
- var_SetString( p_input, "deinterlace-mode", p_mode->psz_mode );
+ var_SetString( p_input, "deinterlace-mode", *p_mode->psz_mode ? p_mode->psz_mode : "disable" );
+
+ var_Create( p_input, "filter-deinterlace-mode", VLC_VAR_STRING );
+ var_SetString( p_input, "filter-deinterlace-mode", p_mode->psz_mode );
var_Create( p_input, "sout-deinterlace-mode", VLC_VAR_STRING );
var_SetString( p_input, "sout-deinterlace-mode", p_mode->psz_mode );
if( p_mode->b_vout_filter )
{
- psz_old = var_CreateGetString( p_vout, "deinterlace-mode" );
+ psz_old = var_CreateGetString( p_vout, "filter-deinterlace-mode" );
}
else
{
msg_Dbg( p_vout, "Deinterlacing available" );
/* Create the configuration variable */
- var_Create( p_vout, "deinterlace", VLC_VAR_STRING | VLC_VAR_HASCHOICE );
- text.psz_string = _("Deinterlace");
- var_Change( p_vout, "deinterlace", VLC_VAR_SETTEXT, &text, NULL );
+ var_Create( p_vout, "deinterlace-mode", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_HASCHOICE );
+ char *psz_deinterlace = var_GetNonEmptyString( p_vout, "deinterlace-mode" );
+
+ text.psz_string = _("Deinterlace mode");
+ var_Change( p_vout, "deinterlace-mode", VLC_VAR_SETTEXT, &text, NULL );
- for( int i = 0; p_deinterlace_mode[i].psz_mode; i++ )
+ const module_config_t *p_opt = config_FindConfig( VLC_OBJECT(p_vout), "deinterlace-mode" );
+ var_Change( p_vout, "deinterlace-mode", VLC_VAR_CLEARCHOICES, NULL, NULL );
+ for( int i = 0; p_opt && i < p_opt->i_list; i++ )
{
- val.psz_string = (char*)p_deinterlace_mode[i].psz_mode;
- text.psz_string = (char*)vlc_gettext(p_deinterlace_mode[i].psz_description);
- var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );
+ val.psz_string = p_opt->ppsz_list[i];
+ text.psz_string = (char*)vlc_gettext(p_opt->ppsz_list_text[i]);
+ var_Change( p_vout, "deinterlace-mode", VLC_VAR_ADDCHOICE, &val, &text );
}
- var_AddCallback( p_vout, "deinterlace", DeinterlaceCallback, NULL );
+ var_AddCallback( p_vout, "deinterlace-mode", DeinterlaceCallback, NULL );
/* */
- char *psz_mode = NULL;
- if( var_Type( p_vout, "vout-deinterlace" ) != 0 )
- psz_mode = var_CreateGetNonEmptyString( p_vout, "vout-deinterlace" );
+ char *psz_mode = psz_deinterlace;
+ if( psz_mode && !strcmp( psz_mode, "disable" ) )
+ {
+ free( psz_mode );
+ psz_mode = strdup( "" );
+ }
if( !psz_mode )
{
- /* Get the initial value */
+ /* Get the initial value from filters if present */
if( DeinterlaceIsPresent( p_vout, true ) )
- psz_mode = var_CreateGetNonEmptyString( p_vout, "deinterlace-mode" );
+ psz_mode = var_CreateGetNonEmptyString( p_vout, "filter-deinterlace-mode" );
else if( DeinterlaceIsPresent( p_vout, false ) )
psz_mode = var_CreateGetNonEmptyString( p_vout, "sout-deinterlace-mode" );
}
- var_SetString( p_vout, "deinterlace", psz_mode ?: "" );
+ var_SetString( p_vout, "deinterlace-mode", psz_mode ? psz_mode : "" );
free( psz_mode );
}