]> git.sesse.net Git - vlc/blobdiff - src/video_output/video_output.c
* src/video_output/video_output.c: another fix for on-the-fly deinterlacing switch.
[vlc] / src / video_output / video_output.c
index 0dcfd2a38ada322bbfb63f5736aeb23a4e38317c..6e5dd3714cbc2ca8056883da85ea24433370e6a4 100644 (file)
@@ -1,5 +1,6 @@
 /*****************************************************************************
  * video_output.c : video output thread
+ *
  * This module describes the programming interface for video output threads.
  * It includes functions allowing to open a new thread, send pictures to a
  * thread, and destroy a previously oppened video output thread.
@@ -136,12 +137,14 @@ vout_thread_t * __vout_Request ( vlc_object_t *p_this, vout_thread_t *p_vout,
     if( p_vout )
     {
         char *psz_filter_chain;
+        vlc_value_t val;
 
         /* We don't directly check for the "filter" variable for obvious
          * performance reasons. */
         if( p_vout->b_filter_change )
         {
-            psz_filter_chain = config_GetPsz( p_this, "filter" );
+            var_Get( p_vout, "filter", &val );
+            psz_filter_chain = val.psz_string;
 
             if( psz_filter_chain && !*psz_filter_chain )
             {
@@ -154,9 +157,7 @@ vout_thread_t * __vout_Request ( vlc_object_t *p_this, vout_thread_t *p_vout,
                 p_vout->psz_filter_chain = NULL;
             }
 
-            if( ( !psz_filter_chain && !p_vout->psz_filter_chain ) ||
-                ( psz_filter_chain && p_vout->psz_filter_chain &&
-                  !strcmp( psz_filter_chain, p_vout->psz_filter_chain ) ) )
+            if( !psz_filter_chain && !p_vout->psz_filter_chain )
             {
                 p_vout->b_filter_change = VLC_FALSE;
             }
@@ -420,15 +421,9 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent,
     var_AddCallback( p_vout, "deinterlace", DeinterlaceCallback, NULL );
 
 
-    var_Create( p_vout, "filter", VLC_VAR_STRING );
+    var_Create( p_vout, "filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     text.psz_string = _("Filters");
     var_Change( p_vout, "filter", VLC_VAR_SETTEXT, &text, NULL );
-    var_Change( p_vout, "filter", VLC_VAR_INHERITVALUE, &val, NULL );
-    if( val.psz_string )
-    {
-        var_Set( p_vout, "filter", val );
-        free( val.psz_string );
-    }
     var_AddCallback( p_vout, "filter", FilterCallback, NULL );
 
     /* Calculate delay created by internal caching */
@@ -560,30 +555,6 @@ static int InitThread( vout_thread_t *p_vout )
 
     msg_Dbg( p_vout, "got %i direct buffer(s)", I_OUTPUTPICTURES );
 
-#if 0
-    if( !p_vout->psz_filter_chain )
-    {
-        char *psz_aspect = config_GetPsz( p_vout, "pixel-ratio" );
-
-        if( psz_aspect )
-        {
-            int i_new_aspect = p_vout->output.i_width * VOUT_ASPECT_FACTOR
-                                                      * atof( psz_aspect )
-                                                      / p_vout->output.i_height;
-            free( psz_aspect );
-
-            if( i_new_aspect && i_new_aspect != p_vout->output.i_aspect )
-            {
-                AspectRatio( i_new_aspect, &i_aspect_x, &i_aspect_y );
-
-                msg_Dbg( p_vout, "output ratio forced to %i:%i\n",
-                         i_aspect_x, i_aspect_y );
-                p_vout->output.i_aspect = i_new_aspect;
-            }
-        }
-    }
-#endif
-
     AspectRatio( p_vout->render.i_aspect, &i_aspect_x, &i_aspect_y );
     msg_Dbg( p_vout,
              "picture in %ix%i, chroma 0x%.8x (%4.4s), aspect ratio %i:%i",
@@ -1297,6 +1268,40 @@ int vout_VarCallback( vlc_object_t * p_this, const char * psz_variable,
     return VLC_SUCCESS;
 }
 
+/*****************************************************************************
+ * Helper thread for object variables callbacks.
+ * Only used to avoid deadlocks when using the video embedded mode.
+ *****************************************************************************/
+typedef struct suxor_thread_t
+{
+    VLC_COMMON_MEMBERS
+    input_thread_t *p_input;
+
+} suxor_thread_t;
+
+static void SuxorRestartVideoES( suxor_thread_t *p_this )
+{
+    vlc_value_t val;
+
+    /* Now restart current video stream */
+    var_Get( p_this->p_input, "video-es", &val );
+    if( val.i_int >= 0 )
+    {
+        vlc_value_t val_es;
+        val_es.i_int = -VIDEO_ES;
+        var_Set( p_this->p_input, "video-es", val_es );
+        var_Set( p_this->p_input, "video-es", val );
+    }
+
+    vlc_object_release( p_this->p_input );
+
+#ifdef WIN32
+    CloseHandle( p_this->thread_id );
+#endif
+
+    vlc_object_destroy( p_this );
+}
+
 /*****************************************************************************
  * object variables callbacks: a bunch of object variables are used by the
  * interfaces to interact with the vout.
@@ -1309,33 +1314,28 @@ static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd,
     vlc_value_t val;
 
     char *psz_mode = newval.psz_string;
-    char *psz_filter;
+    char *psz_filter, *psz_deinterlace = NULL;
 
-    psz_filter = config_GetPsz( p_vout, "filter" );
+    var_Get( p_vout, "filter", &val );
+    psz_filter = val.psz_string;
+    if( psz_filter ) psz_deinterlace = strstr( psz_filter, "deinterlace" );
 
     if( !psz_mode || !*psz_mode )
     {
-        config_PutPsz( p_vout, "filter", "" );
-    }
-    else
-    {
-        if( !psz_filter || !*psz_filter )
-        {
-            config_PutPsz( p_vout, "filter", "deinterlace" );
-        }
-        else
+        if( psz_deinterlace )
         {
-            if( strstr( psz_filter, "deinterlace" ) == NULL )
-            {
-                psz_filter = realloc( psz_filter, strlen( psz_filter ) + 20 );
-                strcat( psz_filter, ",deinterlace" );
-            }
-            config_PutPsz( p_vout, "filter", psz_filter );
+            char *psz_src = psz_deinterlace + sizeof("deinterlace") - 1;
+            if( psz_src[0] == ',' ) psz_src++;
+            memmove( psz_deinterlace, psz_src, strlen(psz_src) + 1 );
         }
     }
-
-    if( psz_filter ) free( psz_filter );
-
+    else if( !psz_deinterlace )
+    {
+        psz_filter = realloc( psz_filter, strlen( psz_filter ) +
+                              sizeof(",deinterlace") );
+        if( psz_filter && *psz_filter ) strcat( psz_filter, "," );
+        strcat( psz_filter, "deinterlace" );
+    }
 
     p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT,
                                                  FIND_PARENT );
@@ -1343,28 +1343,20 @@ static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd,
 
     if( psz_mode && *psz_mode )
     {
-        val.psz_string = psz_mode;
-        var_Set( p_vout, "deinterlace-mode", val );
         /* Modify input as well because the vout might have to be restarted */
+        val.psz_string = psz_mode;
         var_Create( p_input, "deinterlace-mode", VLC_VAR_STRING );
         var_Set( p_input, "deinterlace-mode", val );
     }
-
-    /* Now restart current video stream */
-    var_Get( p_input, "video-es", &val );
-    if( val.i_int >= 0 )
-    {
-        vlc_value_t val_es;
-        val_es.i_int = -VIDEO_ES;
-        p_vout->b_filter_change = VLC_TRUE;
-        var_Set( p_input, "video-es", val_es );
-        var_Set( p_input, "video-es", val );
-    }
-
     vlc_object_release( p_input );
 
     val.b_bool = VLC_TRUE;
     var_Set( p_vout, "intf-change", val );
+
+    val.psz_string = psz_filter;
+    var_Set( p_vout, "filter", val );
+    if( psz_filter ) free( psz_filter );
+
     return VLC_SUCCESS;
 }
 
@@ -1377,27 +1369,34 @@ static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd,
 
     p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT,
                                                  FIND_PARENT );
-
     if (!p_input)
     {
         msg_Err( p_vout, "Input not found" );
         return( VLC_EGENERIC );
     }
 
+    val.b_bool = VLC_TRUE;
+    var_Set( p_vout, "intf-change", val );
+
+    /* Modify input as well because the vout might have to be restarted */
+    val.psz_string = newval.psz_string;
+    var_Create( p_input, "filter", VLC_VAR_STRING );
+    var_Set( p_input, "filter", val );
+
     /* Now restart current video stream */
     var_Get( p_input, "video-es", &val );
     if( val.i_int >= 0 )
     {
-        vlc_value_t val_es;
-        val_es.i_int = -VIDEO_ES;
         p_vout->b_filter_change = VLC_TRUE;
-        var_Set( p_input, "video-es", val_es );
-        var_Set( p_input, "video-es", val );
+        suxor_thread_t *p_suxor =
+            vlc_object_create( p_vout, sizeof(suxor_thread_t) );
+        p_suxor->p_input = p_input;
+        vlc_object_yield( p_input );
+        vlc_thread_create( p_suxor, "suxor", SuxorRestartVideoES,
+                           VLC_THREAD_PRIORITY_LOW, VLC_FALSE );
     }
 
     vlc_object_release( p_input );
 
-    val.b_bool = VLC_TRUE;
-    var_Set( p_vout, "intf-change", val );
     return VLC_SUCCESS;
 }