>From 37755774b4bb3f1e31d81982b7446612c20b53e9 Mon Sep 17 00:00:00 2001
From: Joseph Tulou <brezhoneg1@yahoo.fr>
Date: Fri, 30 Jan 2009 18:21:09 +0100
Subject: [PATCH] vout reuse (corrects ugly transitions between items)

---
 include/vlc_vout.h              |    1 +
 src/video_output/video_output.c |  194 +++++++++++++++++++--------------------
 src/video_output/vout_intf.c    |   19 ++--
 3 files changed, 106 insertions(+), 108 deletions(-)

diff --git a/include/vlc_vout.h b/include/vlc_vout.h
index 034f0be..efd677b 100644
--- a/include/vlc_vout.h
+++ b/include/vlc_vout.h
@@ -676,6 +676,7 @@ VLC_EXPORT( void,            vout_PlacePicture,   ( const vout_thread_t *, unsig
 
 VLC_EXPORT( int, vout_vaControlDefault, ( vout_thread_t *, int, va_list ) );
 void vout_IntfInit( vout_thread_t * );
+void vout_InitWindowSize( vout_thread_t *, unsigned *, unsigned * );
 VLC_EXPORT( int, vout_Snapshot, ( vout_thread_t *p_vout, picture_t *p_pic ) );
 VLC_EXPORT( void, vout_EnableFilter, ( vout_thread_t *, char *,bool , bool  ) );
 
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 39b6e78..704e752 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -77,6 +77,7 @@ static void VideoFormatImportRgb( video_format_t *, const picture_heap_t * );
 static void PictureHeapFixRgb( picture_heap_t * );
 
 static void     vout_Destructor   ( vlc_object_t * p_this );
+static void vout_Reset( vout_thread_t* p_vout, video_format_t *p_fmt );
 
 /* Object variables callbacks */
 static int DeinterlaceCallback( vlc_object_t *, char const *,
@@ -155,127 +156,44 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
 {
     if( !p_fmt )
     {
-        /* Video output is no longer used.
-         * TODO: support for reusing video outputs with proper _thread-safe_
-         * reference handling. */
         if( p_vout )
             vout_CloseAndRelease( p_vout );
         return NULL;
     }
 
-    /* If a video output was provided, lock it, otherwise look for one. */
     if( p_vout )
     {
-        vlc_object_hold( p_vout );
-    }
-
-    /* TODO: find a suitable unused video output */
-
-    /* If we now have a video output, check it has the right properties */
-    if( p_vout )
-    {
-        char *psz_filter_chain;
-        vlc_value_t val;
-
         vlc_mutex_lock( &p_vout->change_lock );
 
-        /* We don't directly check for the "vout-filter" variable for obvious
-         * performance reasons. */
-        if( p_vout->p->b_filter_change )
-        {
-            var_Get( p_vout, "vout-filter", &val );
-            psz_filter_chain = val.psz_string;
-
-            if( psz_filter_chain && !*psz_filter_chain )
-            {
-                free( psz_filter_chain );
-                psz_filter_chain = NULL;
-            }
-            if( p_vout->p->psz_filter_chain && !*p_vout->p->psz_filter_chain )
-            {
-                free( p_vout->p->psz_filter_chain );
-                p_vout->p->psz_filter_chain = NULL;
-            }
-
-            if( !psz_filter_chain && !p_vout->p->psz_filter_chain )
-            {
-                p_vout->p->b_filter_change = false;
-            }
-
-            free( psz_filter_chain );
-        }
-
-        if( p_vout->fmt_render.i_chroma != p_fmt->i_chroma ||
-            p_vout->fmt_render.i_width != p_fmt->i_width ||
-            p_vout->fmt_render.i_height != p_fmt->i_height ||
-            p_vout->p->b_filter_change )
+        /* restriction to vout resue : vout-filter */
+        if( p_vout->p->psz_filter_chain && *p_vout->p->psz_filter_chain )
         {
+            free( p_vout->p->psz_filter_chain );
+            p_vout->p->psz_filter_chain = NULL;
+    
             vlc_mutex_unlock( &p_vout->change_lock );
 
-            /* We are not interested in this format, close this vout */
             vout_CloseAndRelease( p_vout );
-            vlc_object_release( p_vout );
             p_vout = NULL;
         }
         else
         {
-            /* This video output is cool! Hijack it. */
-            if( p_vout->fmt_render.i_aspect != p_fmt->i_aspect )
-            {
-                /* Correct aspect ratio on change
-                 * FIXME factorize this code with other aspect ration related code */
-                unsigned int i_sar_num;
-                unsigned int i_sar_den;
-                unsigned int i_aspect;
-
-                i_aspect = p_fmt->i_aspect;
-                vlc_ureduce( &i_sar_num, &i_sar_den,
-                             p_fmt->i_sar_num, p_fmt->i_sar_den, 50000 );
-#if 0
-                /* What's that, it does not seems to be used correcly everywhere
-                 * beside the previous p_vout->fmt_render.i_aspect != p_fmt->i_aspect
-                 * should be fixed to use it too then */
-                if( p_vout->i_par_num > 0 && p_vout->i_par_den > 0 )
-                {
-                    i_sar_num *= p_vout->i_par_den;
-                    i_sar_den *= p_vout->i_par_num;
-                    i_aspect = i_aspect * p_vout->i_par_den / p_vout->i_par_num;
-                }
-#endif
-
-                if( i_sar_num > 0 && i_sar_den > 0 && i_aspect > 0 )
-                {
-                    p_vout->fmt_in.i_sar_num = i_sar_num;
-                    p_vout->fmt_in.i_sar_den = i_sar_den;
-                    p_vout->fmt_in.i_aspect  = i_aspect;
-
-                    p_vout->fmt_render.i_sar_num = i_sar_num;
-                    p_vout->fmt_render.i_sar_den = i_sar_den;
-                    p_vout->fmt_render.i_aspect  = i_aspect;
-
-                    p_vout->render.i_aspect   = i_aspect;
-
-                    p_vout->i_changes |= VOUT_ASPECT_CHANGE;
-
-                }
-            }
             vlc_mutex_unlock( &p_vout->change_lock );
-
-            vlc_object_release( p_vout );
         }
+    }
 
-        if( p_vout )
-        {
-            msg_Dbg( p_this, "reusing provided vout" );
+    if( p_vout )
+    {
+        msg_Dbg( p_this, "reusing provided vout" );
 
-            spu_Attach( p_vout->p_spu, p_this, true );
+        vout_Reset( p_vout, p_fmt );
 
-            vlc_object_detach( p_vout );
-            vlc_object_attach( p_vout, p_this );
-        }
-    }
+        spu_Attach( p_vout->p_spu, p_this, true );
 
-    if( !p_vout )
+        vlc_object_detach( p_vout );
+        vlc_object_attach( p_vout, p_this );
+    }
+    else
     {
         msg_Dbg( p_this, "no usable vout present, spawning one" );
 
@@ -1734,3 +1652,83 @@ static void DisplayTitleOnOSD( vout_thread_t *p_vout )
     p_vout->p->psz_title = NULL;
 }
 
+/*
+ * Reset a previous vout and take new input format into account
+ */
+void vout_Reset( vout_thread_t* p_vout, video_format_t *p_fmt )
+{
+    vlc_mutex_lock( &p_vout->change_lock );
+    
+    /* clean up data from previous use of vout */
+    CleanThread( p_vout );
+
+    /* set data from new input */
+    unsigned int i_width = p_fmt->i_width;
+    unsigned int i_height = p_fmt->i_height;
+    vlc_fourcc_t i_chroma = p_fmt->i_chroma;
+    unsigned int i_aspect = p_fmt->i_aspect;
+
+    if( i_width <= 0 || i_height <= 0 || i_aspect <= 0 )
+        return;
+
+    vlc_ureduce( &p_fmt->i_sar_num, &p_fmt->i_sar_den,
+                 p_fmt->i_sar_num, p_fmt->i_sar_den, 50000 );
+    if( p_fmt->i_sar_num <= 0 || p_fmt->i_sar_den <= 0 )
+        return;
+
+    /* Initialize pictures - translation tables and functions
+     * will be initialized later in InitThread */
+    for( int i_index = 0; i_index < 2 * VOUT_MAX_PICTURES + 1; i_index++)
+    {
+        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].b_slow   = 0;
+    }
+
+    /* No images in the heap */
+    p_vout->i_heap_size = 0;
+
+    /* Initialize the rendering heap */
+    I_RENDERPICTURES = 0;
+
+    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;
+    p_vout->render.i_aspect   = i_aspect;
+
+    p_vout->render.i_rmask    = p_fmt->i_rmask;
+    p_vout->render.i_gmask    = p_fmt->i_gmask;
+    p_vout->render.i_bmask    = p_fmt->i_bmask;
+
+    p_vout->render.i_last_used_pic = -1;
+    p_vout->render.b_allow_modify_pics = 1;
+
+    /* Zero the output heap */
+    I_OUTPUTPICTURES = 0;
+    p_vout->output.i_width    = 0;
+    p_vout->output.i_height   = 0;
+    // p_vout->output.i_chroma   = 0;
+    p_vout->output.i_aspect   = 0;
+
+    //p_vout->output.i_rmask    = 0;
+    //p_vout->output.i_gmask    = 0;
+    //p_vout->output.i_bmask    = 0;
+
+    /* Reset window size */
+    vout_InitWindowSize( p_vout, &p_vout->i_window_width,
+                         &p_vout->i_window_height );
+    vout_Control( p_vout, VOUT_SET_SIZE, p_vout->i_window_width,
+                  p_vout->i_window_height );
+
+    /* re-start vout */
+    InitThread( p_vout );
+
+    vlc_mutex_unlock( &p_vout->change_lock );
+
+    /* reset aspect_ratio */
+    var_SetString( p_vout, "aspect-ratio", "" );
+}
+
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index 4aa3094..8c20b85 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -56,7 +56,6 @@
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static void InitWindowSize( vout_thread_t *, unsigned *, unsigned * );
 
 /* Object variables callbacks */
 static int ZoomCallback( vlc_object_t *, char const *,
@@ -417,8 +416,8 @@ void vout_IntfInit( vout_thread_t *p_vout )
     p_vout->ll_zoom = (uint64_t) ( ZOOM_FP_FACTOR * val.f_float );
 
     /* Initialize the dimensions of the video window */
-    InitWindowSize( p_vout, &p_vout->i_window_width,
-                    &p_vout->i_window_height );
+    vout_InitWindowSize( p_vout, &p_vout->i_window_width,
+                         &p_vout->i_window_height );
 
     /* Add a variable to indicate if the window should be on top of others */
     var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
@@ -922,13 +921,13 @@ int vout_vaControlDefault( vout_thread_t *p_vout, int i_query, va_list args )
 }
 
 /*****************************************************************************
- * InitWindowSize: find the initial dimensions the video window should have.
+ * vout_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, unsigned *pi_width,
-                            unsigned *pi_height )
+void vout_InitWindowSize( vout_thread_t *p_vout, unsigned *pi_width,
+                          unsigned *pi_height )
 {
     vlc_value_t val;
     int i_width, i_height;
@@ -1001,8 +1000,8 @@ static int ZoomCallback( vlc_object_t *p_this, char const *psz_cmd,
 {
     vout_thread_t *p_vout = (vout_thread_t *)p_this;
     (void)psz_cmd; (void)oldval; (void)newval; (void)p_data;
-    InitWindowSize( p_vout, &p_vout->i_window_width,
-                    &p_vout->i_window_height );
+    vout_InitWindowSize( p_vout, &p_vout->i_window_width,
+                         &p_vout->i_window_height );
     vout_Control( p_vout, VOUT_SET_SIZE, p_vout->i_window_width,
                   p_vout->i_window_height );
     return VLC_SUCCESS;
@@ -1144,8 +1143,8 @@ static int CropCallback( vlc_object_t *p_this, char const *psz_cmd,
     }
 
  crop_end:
-    InitWindowSize( p_vout, &p_vout->i_window_width,
-                    &p_vout->i_window_height );
+    vout_InitWindowSize( p_vout, &p_vout->i_window_width,
+                         &p_vout->i_window_height );
 
     p_vout->i_changes |= VOUT_CROP_CHANGE;
 
-- 
1.5.2.5

