vlc_value_t, vlc_value_t, void * );
static int VideoFilter2Callback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
+static void PostProcessEnable( vout_thread_t * );
+static void PostProcessDisable( vout_thread_t * );
+static void PostProcessSetFilterQuality( vout_thread_t *p_vout );
+static int PostProcessCallback( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
/* From vout_intf.c */
int vout_Snapshot( vout_thread_t *, picture_t * );
/* Initialize misc stuff */
p_vout->i_changes = 0;
- p_vout->b_scale = 1;
+ p_vout->b_autoscale = 1;
+ p_vout->i_zoom = ZOOM_FP_FACTOR;
p_vout->b_fullscreen = 0;
p_vout->i_alignment = 0;
p_vout->p->render_time = 10;
p_vout->p->b_paused = false;
p_vout->p->i_pause_date = 0;
p_vout->pf_control = NULL;
- p_vout->p_window = NULL;
p_vout->p->i_par_num =
p_vout->p->i_par_den = 1;
p_vout->p->p_picture_displayed = NULL;
p_vout->p->i_picture_displayed_date = 0;
p_vout->p->b_picture_displayed = false;
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 );
/* Initialize locks */
vlc_mutex_init( &p_vout->picture_lock );
var_Create( p_vout, "mouse-y", VLC_VAR_INTEGER );
var_Create( p_vout, "mouse-button-down", VLC_VAR_INTEGER );
var_Create( p_vout, "mouse-moved", VLC_VAR_BOOL );
- var_Create( p_vout, "mouse-clicked", VLC_VAR_INTEGER );
+ var_Create( p_vout, "mouse-clicked", VLC_VAR_BOOL );
/* Initialize subpicture unit */
p_vout->p_spu = spu_Create( p_vout );
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 */
+ /* Deinterlacing */
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_AddCallback( p_vout, "deinterlace", DeinterlaceCallback, NULL );
+ /* */
var_Create( p_vout, "vout-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
text.psz_string = _("Filters");
var_Change( p_vout, "vout-filter", VLC_VAR_SETTEXT, &text, NULL );
{
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_object_release( p_vout );
return NULL;
}
p_vout->p->b_done = true;
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 );
+
vlc_join( p_vout->p->thread, NULL );
module_unneed( p_vout, p_vout->p_module );
p_vout->p_module = NULL;
assert( !p_vout->p_module );
/* */
- spu_Destroy( p_vout->p_spu );
+ if( p_vout->p_spu )
+ spu_Destroy( p_vout->p_spu );
/* Destroy the locks */
vlc_cond_destroy( &p_vout->p->change_wait );
vlc_mutex_destroy( &p_vout->change_lock );
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;
+
+ picture_Release( p_picture );
+ }
+ vlc_cond_destroy( &p_vout->p->snapshot.wait );
+ vlc_mutex_destroy( &p_vout->p->snapshot.lock );
+
+ /* */
free( p_vout->p->psz_filter_chain );
free( p_vout->p->psz_title );
AspectRatio( p_vout->fmt_render.i_aspect, &i_aspect_x, &i_aspect_y );
- msg_Dbg( p_vout, "picture in %ix%i (%i,%i,%ix%i), "
- "chroma %4.4s, ar %i:%i, sar %i:%i",
- p_vout->fmt_render.i_width, p_vout->fmt_render.i_height,
- p_vout->fmt_render.i_x_offset, p_vout->fmt_render.i_y_offset,
- p_vout->fmt_render.i_visible_width,
- p_vout->fmt_render.i_visible_height,
- (char*)&p_vout->fmt_render.i_chroma,
- i_aspect_x, i_aspect_y,
- p_vout->fmt_render.i_sar_num, p_vout->fmt_render.i_sar_den );
-
AspectRatio( p_vout->fmt_in.i_aspect, &i_aspect_x, &i_aspect_y );
- msg_Dbg( p_vout, "picture user %ix%i (%i,%i,%ix%i), "
- "chroma %4.4s, ar %i:%i, sar %i:%i",
- p_vout->fmt_in.i_width, p_vout->fmt_in.i_height,
- p_vout->fmt_in.i_x_offset, p_vout->fmt_in.i_y_offset,
- p_vout->fmt_in.i_visible_width,
- p_vout->fmt_in.i_visible_height,
- (char*)&p_vout->fmt_in.i_chroma,
- i_aspect_x, i_aspect_y,
- p_vout->fmt_in.i_sar_num, p_vout->fmt_in.i_sar_den );
-
if( !p_vout->fmt_out.i_width || !p_vout->fmt_out.i_height )
{
p_vout->fmt_out.i_width = p_vout->fmt_out.i_visible_width =
AspectRatio( p_vout->fmt_out.i_aspect, &i_aspect_x, &i_aspect_y );
- msg_Dbg( p_vout, "picture out %ix%i (%i,%i,%ix%i), "
- "chroma %4.4s, ar %i:%i, sar %i:%i",
- p_vout->fmt_out.i_width, p_vout->fmt_out.i_height,
- p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset,
- p_vout->fmt_out.i_visible_width,
- p_vout->fmt_out.i_visible_height,
- (char*)&p_vout->fmt_out.i_chroma,
- i_aspect_x, i_aspect_y,
- p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den );
-
/* FIXME removed the need of both fmt_* and heap infos */
/* Calculate shifts from system-updated masks */
PictureHeapFixRgb( &p_vout->render );
PictureHeapFixRgb( &p_vout->output );
VideoFormatImportRgb( &p_vout->fmt_out, &p_vout->output );
+ /* print some usefull debug info about different vout formats
+ */
+ msg_Dbg( p_vout, "pic render sz %ix%i, of (%i,%i), vsz %ix%i, 4cc %4.4s, ar %i:%i, sar %i:%i, msk r0x%x g0x%x b0x%x",
+ p_vout->fmt_render.i_width, p_vout->fmt_render.i_height,
+ p_vout->fmt_render.i_x_offset, p_vout->fmt_render.i_y_offset,
+ p_vout->fmt_render.i_visible_width,
+ p_vout->fmt_render.i_visible_height,
+ (char*)&p_vout->fmt_render.i_chroma,
+ i_aspect_x, i_aspect_y,
+ p_vout->fmt_render.i_sar_num, p_vout->fmt_render.i_sar_den,
+ p_vout->fmt_render.i_rmask, p_vout->fmt_render.i_gmask, p_vout->fmt_render.i_bmask );
+
+ msg_Dbg( p_vout, "pic in sz %ix%i, of (%i,%i), vsz %ix%i, 4cc %4.4s, ar %i:%i, sar %i:%i, msk r0x%x g0x%x b0x%x",
+ p_vout->fmt_in.i_width, p_vout->fmt_in.i_height,
+ p_vout->fmt_in.i_x_offset, p_vout->fmt_in.i_y_offset,
+ p_vout->fmt_in.i_visible_width,
+ p_vout->fmt_in.i_visible_height,
+ (char*)&p_vout->fmt_in.i_chroma,
+ i_aspect_x, i_aspect_y,
+ p_vout->fmt_in.i_sar_num, p_vout->fmt_in.i_sar_den,
+ p_vout->fmt_in.i_rmask, p_vout->fmt_in.i_gmask, p_vout->fmt_in.i_bmask );
+
+ msg_Dbg( p_vout, "pic out sz %ix%i, of (%i,%i), vsz %ix%i, 4cc %4.4s, ar %i:%i, sar %i:%i, msk r0x%x g0x%x b0x%x",
+ p_vout->fmt_out.i_width, p_vout->fmt_out.i_height,
+ p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset,
+ p_vout->fmt_out.i_visible_width,
+ p_vout->fmt_out.i_visible_height,
+ (char*)&p_vout->fmt_out.i_chroma,
+ i_aspect_x, i_aspect_y,
+ p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den,
+ p_vout->fmt_out.i_rmask, p_vout->fmt_out.i_gmask, p_vout->fmt_out.i_bmask );
+
/* Check whether we managed to create direct buffers similar to
* the render buffers, ie same size and chroma */
if( ( p_vout->output.i_width == p_vout->render.i_width )
{
vout_thread_t *p_vout = p_this;
int i_idle_loops = 0; /* loops without displaying a picture */
+ int i_picture_qtype_last = QTYPE_NONE;
bool b_drop_late;
vout_UsePictureLocked( p_vout, p_pic );
p_vout->p->i_picture_lost++;
- msg_Warn( p_vout, "late picture skipped (%"PRId64")",
- current_date - p_pic->date );
+ msg_Warn( p_vout, "late picture skipped (%"PRId64" > %d)",
+ current_date - p_pic->date, - p_vout->p->render_time );
}
else if( ( !p_last || p_last->date < p_pic->date ) &&
( p_picture == NULL || p_pic->date < p_picture->date ) )
p_vout->p->p_picture_displayed = p_picture;
}
}
+
+ /* */
+ const int i_postproc_type = p_vout->p->i_picture_qtype;
+ const int i_postproc_state = (p_vout->p->i_picture_qtype != QTYPE_NONE) - (i_picture_qtype_last != QTYPE_NONE);
+
vlc_mutex_unlock( &p_vout->picture_lock );
if( p_picture == NULL )
/* FIXME it is ugly that b_snapshot is not locked but I do not
* know which lock to use (here and in the snapshot callback) */
- const bool b_snapshot = p_vout->p->b_snapshot && p_picture != NULL;
+ vlc_mutex_lock( &p_vout->p->snapshot.lock );
+ const bool b_snapshot = p_vout->p->snapshot.i_request > 0 && p_picture != NULL;
+ vlc_mutex_unlock( &p_vout->p->snapshot.lock );
/*
* Check for subpictures to display
*/
if( p_directbuffer && b_snapshot )
{
- /* FIXME lock (see b_snapshot) */
- p_vout->p->b_snapshot = false;
-
- vout_Snapshot( p_vout, p_directbuffer );
+ 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 );
}
/*
p_vout->p->render_time += current_render_time;
p_vout->p->render_time >>= 2;
}
+ else
+ msg_Dbg( p_vout, "skipped big render time %d > %d", (int) current_render_time,
+ (int) (p_vout->p->render_time +VOUT_DISPLAY_DELAY ) ) ;
}
/* Give back change lock */
break;
}
+ while( p_vout->i_changes & VOUT_ON_TOP_CHANGE )
+ {
+ p_vout->i_changes &= ~VOUT_ON_TOP_CHANGE;
+ vlc_mutex_unlock( &p_vout->change_lock );
+ vout_Control( p_vout, VOUT_SET_STAY_ON_TOP, p_vout->b_on_top );
+ vlc_mutex_lock( &p_vout->change_lock );
+ }
+
if( p_vout->i_changes & VOUT_SIZE_CHANGE )
{
/* this must only happen when the vout plugin is incapable of
p_vout->b_error = InitThread( p_vout );
if( p_vout->b_error )
- msg_Err( p_vout, "InitThread after VOUT_PICTURE_BUFFERS_CHANGE failed\n" );
+ msg_Err( p_vout, "InitThread after VOUT_PICTURE_BUFFERS_CHANGE failed" );
vlc_cond_signal( &p_vout->p->picture_wait );
vlc_mutex_unlock( &p_vout->picture_lock );
break;
}
+ /* Post processing */
+ if( i_postproc_state == 1 )
+ PostProcessEnable( p_vout );
+ else if( i_postproc_state == -1 )
+ PostProcessDisable( p_vout );
+ if( i_postproc_state != 0 )
+ i_picture_qtype_last = i_postproc_type;
+
/* Check for "video filter2" changes */
vlc_mutex_lock( &p_vout->p->vfilter_lock );
if( p_vout->p->psz_vf2 )
free( p_vout->p->psz_vf2 );
p_vout->p->psz_vf2 = NULL;
+
+ if( i_picture_qtype_last != QTYPE_NONE )
+ PostProcessSetFilterQuality( p_vout );
}
vlc_mutex_unlock( &p_vout->p->vfilter_lock );
}
return VLC_SUCCESS;
}
+/*****************************************************************************
+ * Post-processing
+ *****************************************************************************/
+static bool PostProcessIsPresent( const char *psz_filter )
+{
+ const char *psz_pp = "postproc";
+ const size_t i_pp = strlen(psz_pp);
+ return psz_filter &&
+ !strncmp( psz_filter, psz_pp, strlen(psz_pp) ) &&
+ ( psz_filter[i_pp] == '\0' || psz_filter[i_pp] == ':' );
+}
+
+static int PostProcessCallback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
+
+ static const char *psz_pp = "postproc";
+
+ char *psz_vf2 = var_GetString( p_vout, "video-filter" );
+
+ if( newval.i_int <= 0 )
+ {
+ if( PostProcessIsPresent( psz_vf2 ) )
+ {
+ strcpy( psz_vf2, &psz_vf2[strlen(psz_pp)] );
+ if( *psz_vf2 == ':' )
+ strcpy( psz_vf2, &psz_vf2[1] );
+ }
+ }
+ else
+ {
+ if( !PostProcessIsPresent( psz_vf2 ) )
+ {
+ if( psz_vf2 )
+ {
+ char *psz_tmp = psz_vf2;
+ if( asprintf( &psz_vf2, "%s:%s", psz_pp, psz_tmp ) < 0 )
+ psz_vf2 = psz_tmp;
+ else
+ free( psz_tmp );
+ }
+ else
+ {
+ psz_vf2 = strdup( psz_pp );
+ }
+ }
+ }
+ if( psz_vf2 )
+ var_SetString( p_vout, "video-filter", psz_vf2 );
+
+ return VLC_SUCCESS;
+}
+static void PostProcessEnable( vout_thread_t *p_vout )
+{
+ msg_Dbg( p_vout, "Post-processing available" );
+ var_Create( p_vout, "postprocess", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
+ for( int i = 0; i <= 6; i++ )
+ {
+ vlc_value_t val;
+ vlc_value_t text;
+ char psz_text[1+1];
+
+ val.i_int = i;
+ snprintf( psz_text, sizeof(psz_text), "%d", i );
+ if( i == 0 )
+ text.psz_string = _("Disable");
+ else
+ text.psz_string = psz_text;
+ var_Change( p_vout, "postprocess", VLC_VAR_ADDCHOICE, &val, &text );
+ }
+ var_AddCallback( p_vout, "postprocess", PostProcessCallback, NULL );
+
+ /* */
+ char *psz_filter = var_GetNonEmptyString( p_vout, "video-filter" );
+ int i_postproc_q = 0;
+ if( PostProcessIsPresent( psz_filter ) )
+ i_postproc_q = var_CreateGetInteger( p_vout, "postproc-q" );
+
+ var_SetInteger( p_vout, "postprocess", i_postproc_q );
+
+ free( psz_filter );
+}
+static void PostProcessDisable( vout_thread_t *p_vout )
+{
+ msg_Dbg( p_vout, "Post-processing no more available" );
+ var_Destroy( p_vout, "postprocess" );
+}
+static void PostProcessSetFilterQuality( vout_thread_t *p_vout )
+{
+ vlc_object_t *p_pp = vlc_object_find_name( p_vout, "postproc", FIND_CHILD );
+ if( !p_pp )
+ return;
+
+ var_SetInteger( p_pp, "postproc-q", var_GetInteger( p_vout, "postprocess" ) );
+ vlc_object_release( p_pp );
+}
+
+
static void DisplayTitleOnOSD( vout_thread_t *p_vout )
{
const mtime_t i_start = mdate();