]> git.sesse.net Git - vlc/blobdiff - src/video_output/video_output.c
Some more stats preliminary work
[vlc] / src / video_output / video_output.c
index ac977bae7bbd1d7b3a42aef85c2e53e41934fc4c..6960d8601df2d8106ece04eb10eb4f21e24a5f0e 100644 (file)
@@ -5,7 +5,7 @@
  * It includes functions allowing to open a new thread, send pictures to a
  * thread, and destroy a previously oppened video output thread.
  *****************************************************************************
- * Copyright (C) 2000-2004 VideoLAN
+ * Copyright (C) 2000-2004 the VideoLAN team
  * $Id$
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
@@ -41,6 +41,7 @@
 #include "video_output.h"
 #include "vlc_spu.h"
 #include <vlc/input.h>                 /* for input_thread_t and i_pts_delay */
+#include "vlc_playlist.h"
 
 #if defined( SYS_DARWIN )
 #include "darwin_specific.h"
@@ -58,7 +59,6 @@ static void     DestroyThread     ( vout_thread_t * );
 static void     AspectRatio       ( int, int *, int * );
 static int      BinaryLog         ( uint32_t );
 static void     MaskToShift       ( int *, int *, uint32_t );
-static void     InitWindowSize    ( vout_thread_t *, int *, int * );
 
 /* Object variables callbacks */
 static int DeinterlaceCallback( vlc_object_t *, char const *,
@@ -117,20 +117,22 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
 
         if( !p_vout )
         {
-            vlc_object_t *p_playlist;
+            playlist_t *p_playlist;
 
             p_playlist = vlc_object_find( p_this,
                                           VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
             if( p_playlist )
             {
+                vlc_mutex_lock( &p_playlist->gc_lock );
                 p_vout = vlc_object_find( p_playlist,
                                           VLC_OBJECT_VOUT, FIND_CHILD );
                 /* only first children of p_input for unused vout */
-                if( p_vout && p_vout->p_parent != p_playlist )
+                if( p_vout && p_vout->p_parent != (vlc_object_t *)p_playlist )
                 {
                     vlc_object_release( p_vout );
                     p_vout = NULL;
                 }
+                vlc_mutex_unlock( &p_playlist->gc_lock );
                 vlc_object_release( p_playlist );
             }
         }
@@ -171,8 +173,7 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
         if( ( p_vout->fmt_render.i_width != p_fmt->i_width ) ||
             ( p_vout->fmt_render.i_height != p_fmt->i_height ) ||
             ( p_vout->fmt_render.i_chroma != p_fmt->i_chroma ) ||
-            ( p_vout->fmt_render.i_aspect != p_fmt->i_aspect
-                    && !p_vout->b_override_aspect ) ||
+            ( p_vout->fmt_render.i_aspect != p_fmt->i_aspect ) ||
             p_vout->b_filter_change )
         {
             /* We are not interested in this format, close this vout */
@@ -228,6 +229,10 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
         return NULL;
     }
 
+    stats_Create( p_vout, "displayed_pictures", VLC_VAR_INTEGER,
+                                                 STATS_COUNTER );
+    stats_Create( p_vout, "lost_pictures", VLC_VAR_INTEGER, STATS_COUNTER );
+
     /* Initialize pictures - translation tables and functions
      * will be initialized later in InitThread */
     for( i_index = 0; i_index < 2 * VOUT_MAX_PICTURES + 1; i_index++)
@@ -244,8 +249,12 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
 
     /* Initialize the rendering heap */
     I_RENDERPICTURES = 0;
+
+    vlc_ureduce( &p_fmt->i_sar_num, &p_fmt->i_sar_den,
+                 p_fmt->i_sar_num, p_fmt->i_sar_den, 50000 );
     p_vout->fmt_render        = *p_fmt;   /* FIXME palette */
     p_vout->fmt_in            = *p_fmt;   /* FIXME palette */
+
     p_vout->render.i_width    = i_width;
     p_vout->render.i_height   = i_height;
     p_vout->render.i_chroma   = i_chroma;
@@ -283,6 +292,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
     p_vout->b_filter_change = 0;
     p_vout->pf_control = 0;
     p_vout->p_parent_intf = 0;
+    p_vout->i_par_num = p_vout->i_par_den = 1;
 
     /* Initialize locks */
     vlc_mutex_init( p_vout, &p_vout->picture_lock );
@@ -307,50 +317,10 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
     /* Take care of some "interface/control" related initialisations */
     vout_IntfInit( p_vout );
 
-    p_vout->b_override_aspect = VLC_FALSE;
-
     /* If the parent is not a VOUT object, that means we are at the start of
      * the video output pipe */
     if( p_parent->i_object_type != VLC_OBJECT_VOUT )
     {
-        var_Get( p_vout, "aspect-ratio", &val );
-
-        /* Check whether the user tried to override aspect ratio */
-        if( val.psz_string )
-        {
-            unsigned int i_new_aspect = i_aspect;
-            char *psz_parser = strchr( val.psz_string, ':' );
-
-            if( psz_parser )
-            {
-                *psz_parser++ = '\0';
-                i_new_aspect = atoi( val.psz_string ) * VOUT_ASPECT_FACTOR
-                                                      / atoi( psz_parser );
-            }
-            else
-            {
-                i_new_aspect = i_width * VOUT_ASPECT_FACTOR
-                                       * atof( val.psz_string )
-                                       / i_height;
-            }
-
-            free( val.psz_string );
-
-            if( i_new_aspect && i_new_aspect != i_aspect )
-            {
-                int i_aspect_x, i_aspect_y;
-
-                AspectRatio( i_new_aspect, &i_aspect_x, &i_aspect_y );
-
-                msg_Dbg( p_vout, "overriding source aspect ratio to %i:%i",
-                         i_aspect_x, i_aspect_y );
-
-                p_vout->render.i_aspect = i_new_aspect;
-
-                p_vout->b_override_aspect = VLC_TRUE;
-            }
-        }
-
         /* Look for the default filter configuration */
         var_Create( p_vout, "vout-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
         var_Get( p_vout, "vout-filter", &val );
@@ -361,7 +331,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
         /* continue the parent's filter chain */
         char *psz_end;
 
-        psz_end = strchr( ((vout_thread_t *)p_parent)->psz_filter_chain, ',' );
+        psz_end = strchr( ((vout_thread_t *)p_parent)->psz_filter_chain, ':' );
         if( psz_end && *(psz_end+1) )
             p_vout->psz_filter_chain = strdup( psz_end+1 );
         else p_vout->psz_filter_chain = NULL;
@@ -380,17 +350,13 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
          * colons */
         char *psz_end;
 
-        psz_end = strchr( p_vout->psz_filter_chain, ',' );
+        psz_end = strchr( p_vout->psz_filter_chain, ':' );
         if( psz_end )
             psz_plugin = strndup( p_vout->psz_filter_chain,
                                   psz_end - p_vout->psz_filter_chain );
         else psz_plugin = strdup( p_vout->psz_filter_chain );
     }
 
-    /* Initialize the dimensions of the video window */
-    InitWindowSize( p_vout, &p_vout->i_window_width,
-                    &p_vout->i_window_height );
-
     /* Create the vout thread */
     p_vout->p_module = module_Need( p_vout,
         ( p_vout->psz_filter_chain && *p_vout->psz_filter_chain ) ?
@@ -421,6 +387,9 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
     var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );
     val.psz_string = "linear"; text.psz_string = _("Linear");
     var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );
+    val.psz_string = "x"; text.psz_string = "X";
+    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );
+
     if( var_Get( p_vout, "deinterlace-mode", &val ) == VLC_SUCCESS )
     {
         var_Set( p_vout, "deinterlace", val );
@@ -606,14 +575,18 @@ static int InitThread( vout_thread_t *p_vout )
             p_vout->fmt_out.i_width;
     }
 
-    vlc_reduce( &p_vout->fmt_out.i_sar_num, &p_vout->fmt_out.i_sar_den,
-                p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den, 0 );
+    vlc_ureduce( &p_vout->fmt_out.i_sar_num, &p_vout->fmt_out.i_sar_den,
+                 p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den, 0 );
 
     AspectRatio( p_vout->fmt_out.i_aspect, &i_aspect_x, &i_aspect_y );
 
-    msg_Dbg( p_vout, "picture out %ix%i, chroma %4.4s, ar %i:%i, sar %i:%i",
-             p_vout->output.i_width, p_vout->output.i_height,
-             (char*)&p_vout->output.i_chroma,
+    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 );
 
@@ -725,7 +698,7 @@ static void RunThread( vout_thread_t *p_vout)
     picture_t *     p_last_picture = NULL;                   /* last picture */
     picture_t *     p_directbuffer;              /* direct buffer to display */
 
-    subpicture_t *  p_subpic;                          /* subpicture pointer */
+    subpicture_t *  p_subpic = NULL;                   /* subpicture pointer */
 
     /*
      * Initialize thread
@@ -817,9 +790,12 @@ static void RunThread( vout_thread_t *p_vout)
             p_vout->p_fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ]
                 = display_date;
 
+            /* XXX: config_GetInt is slow, but this kind of frame dropping
+             * should not happen that often. */
             if( !p_picture->b_force &&
                 p_picture != p_last_picture &&
-                display_date < current_date + p_vout->render_time )
+                display_date < current_date + p_vout->render_time &&
+                config_GetInt( p_vout, "skip-frames" ) )
             {
                 /* Picture is late: it will be destroyed and the thread
                  * will directly choose the next picture */
@@ -838,6 +814,7 @@ static void RunThread( vout_thread_t *p_vout)
                 }
                 msg_Warn( p_vout, "late picture skipped ("I64Fd")",
                                   current_date - display_date );
+                stats_UpdateInteger( p_vout, "lost_pictures", 1 );
                 vlc_mutex_unlock( &p_vout->picture_lock );
 
                 continue;
@@ -860,6 +837,7 @@ static void RunThread( vout_thread_t *p_vout)
                     p_picture->i_status = DESTROYED_PICTURE;
                     p_vout->i_heap_size--;
                 }
+                stats_UpdateInteger( p_vout, "lost_pictures", 1 );
                 msg_Warn( p_vout, "vout warning: early picture skipped "
                           "("I64Fd")", display_date - current_date
                           - p_vout->i_pts_delay );
@@ -909,11 +887,15 @@ static void RunThread( vout_thread_t *p_vout)
         /*
          * Check for subpictures to display
          */
-        p_subpic = spu_SortSubpictures( p_vout->p_spu, display_date );
+        if( display_date > 0 )
+        {
+            p_subpic = spu_SortSubpictures( p_vout->p_spu, display_date );
+        }
 
         /*
          * Perform rendering
          */
+        stats_UpdateInteger( p_vout, "displayed_pictures", 1 );
         p_directbuffer = vout_RenderPicture( p_vout, p_picture, p_subpic );
 
         /*
@@ -1245,69 +1227,6 @@ static void MaskToShift( int *pi_left, int *pi_right, uint32_t i_mask )
     *pi_right = (8 - i_high + i_low);
 }
 
-/*****************************************************************************
- * InitWindowSize: find the initial dimensions the video window should have.
- *****************************************************************************
- * This function will check the "width", "height" and "zoom" config options and
- * will calculate the size that the video window should have.
- *****************************************************************************/
-static void InitWindowSize( vout_thread_t *p_vout, int *pi_width,
-                            int *pi_height )
-{
-    vlc_value_t val;
-    int i_width, i_height;
-    uint64_t ll_zoom;
-
-#define FP_FACTOR 1000                             /* our fixed point factor */
-
-    var_Get( p_vout, "align", &val );
-    p_vout->i_alignment = val.i_int;
-
-    var_Get( p_vout, "width", &val );
-    i_width = val.i_int;
-    var_Get( p_vout, "height", &val );
-    i_height = val.i_int;
-    var_Get( p_vout, "zoom", &val );
-    ll_zoom = (uint64_t)( FP_FACTOR * val.f_float );
-
-    if( i_width > 0 && i_height > 0)
-    {
-        *pi_width = (int)( i_width * ll_zoom / FP_FACTOR );
-        *pi_height = (int)( i_height * ll_zoom / FP_FACTOR );
-        return;
-    }
-    else if( i_width > 0 )
-    {
-        *pi_width = (int)( i_width * ll_zoom / FP_FACTOR );
-        *pi_height = (int)( i_width * ll_zoom * VOUT_ASPECT_FACTOR /
-                            p_vout->render.i_aspect / FP_FACTOR );
-        return;
-    }
-    else if( i_height > 0 )
-    {
-        *pi_height = (int)( i_height * ll_zoom / FP_FACTOR );
-        *pi_width = (int)( i_height * ll_zoom * p_vout->render.i_aspect /
-                           VOUT_ASPECT_FACTOR / FP_FACTOR );
-        return;
-    }
-
-    if( p_vout->render.i_height * p_vout->render.i_aspect
-        >= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
-    {
-        *pi_width = (int)( p_vout->render.i_height * ll_zoom
-          * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR / FP_FACTOR );
-        *pi_height = (int)( p_vout->render.i_height * ll_zoom / FP_FACTOR );
-    }
-    else
-    {
-        *pi_width = (int)( p_vout->render.i_width * ll_zoom / FP_FACTOR );
-        *pi_height = (int)( p_vout->render.i_width * ll_zoom
-          * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect / FP_FACTOR );
-    }
-
-#undef FP_FACTOR
-}
-
 /*****************************************************************************
  * vout_VarCallback: generic callback for intf variables
  *****************************************************************************/
@@ -1381,15 +1300,15 @@ static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd,
         if( psz_deinterlace )
         {
             char *psz_src = psz_deinterlace + sizeof("deinterlace") - 1;
-            if( psz_src[0] == ',' ) psz_src++;
+            if( psz_src[0] == ':' ) psz_src++;
             memmove( psz_deinterlace, psz_src, strlen(psz_src) + 1 );
         }
     }
     else if( !psz_deinterlace )
     {
         psz_filter = realloc( psz_filter, strlen( psz_filter ) +
-                              sizeof(",deinterlace") );
-        if( psz_filter && *psz_filter ) strcat( psz_filter, "," );
+                              sizeof(":deinterlace") );
+        if( psz_filter && *psz_filter ) strcat( psz_filter, ":" );
         strcat( psz_filter, "deinterlace" );
     }