]> git.sesse.net Git - vlc/blobdiff - src/video_output/video_output.c
No need to add a '\n' at the end of messages passed to msg_*
[vlc] / src / video_output / video_output.c
index 8d5b2542ea547246786fdd0319e31b2ca287b933..476eb4303e88e1d05c4bd2124c40aeba443cde18 100644 (file)
@@ -66,7 +66,7 @@
  * Local prototypes
  *****************************************************************************/
 static int      InitThread        ( vout_thread_t * );
-static void*    RunThread         ( vlc_object_t *  );
+static void*    RunThread         ( void *  );
 static void     ErrorThread       ( vout_thread_t * );
 static void     CleanThread       ( vout_thread_t * );
 static void     EndThread         ( vout_thread_t * );
@@ -153,7 +153,6 @@ static int video_filter_buffer_allocation_init( filter_t *p_filter, void *p_data
 vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
                                video_format_t *p_fmt )
 {
-    const bool b_vout_provided = p_vout != NULL;
     if( !p_fmt )
     {
         /* Video output is no longer used.
@@ -273,11 +272,6 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
 
             vlc_object_detach( p_vout );
             vlc_object_attach( p_vout, p_this );
-
-            /* Display title if we are not using the vout given to vout_Request.
-             * XXX for now b_vout_provided is always true at this stage */
-            if( p_vout->p->b_title_show && !b_vout_provided )
-                DisplayTitleOnOSD( p_vout );
         }
     }
 
@@ -380,7 +374,8 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
 
     /* 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;
@@ -391,7 +386,6 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
     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;
@@ -410,7 +404,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
     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 );
@@ -426,7 +420,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
 
     /* 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 )
+    if( vlc_internals( p_parent )->i_object_type != VLC_OBJECT_VOUT )
     {
         /* Look for the default filter configuration */
         p_vout->p->psz_filter_chain =
@@ -482,10 +476,11 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
         "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" );
-        vlc_object_set_destructor( p_vout, vout_Destructor );
         vlc_object_release( p_vout );
         return NULL;
     }
@@ -521,17 +516,24 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
     var_Change( p_vout, "vout-filter", VLC_VAR_SETTEXT, &text, NULL );
     var_AddCallback( p_vout, "vout-filter", FilterCallback, NULL );
 
-    if( vlc_thread_create( p_vout, "video output", RunThread,
-                           VLC_THREAD_PRIORITY_OUTPUT, true ) )
+    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;
-        vlc_object_set_destructor( p_vout, vout_Destructor );
         vlc_object_release( p_vout );
         return NULL;
     }
 
-    vlc_object_set_destructor( p_vout, vout_Destructor );
+    vlc_mutex_lock( &p_vout->change_lock );
+    while( !p_vout->p->b_ready )
+    {   /* We are (ab)using the same condition in opposite directions for
+         * b_ready and b_done. This works because of the strict ordering. */
+        assert( !p_vout->p->b_done );
+        vlc_cond_wait( &p_vout->p->change_wait, &p_vout->change_lock );
+    }
+    vlc_mutex_unlock( &p_vout->change_lock );
 
     if( p_vout->b_error )
     {
@@ -549,14 +551,17 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
  * You HAVE to call it on vout created by vout_Create before vlc_object_release.
  * You should NEVER call it on vout not obtained through vout_Create
  * (like with vout_Request or vlc_object_find.)
- * You can use vout_CloseAndRelease() as a convenient method.
+ * You can use vout_CloseAndRelease() as a convenience method.
  *****************************************************************************/
 void vout_Close( vout_thread_t *p_vout )
 {
     assert( p_vout );
 
-    vlc_object_kill( p_vout );
-    vlc_thread_join( p_vout );
+    vlc_mutex_lock( &p_vout->change_lock );
+    p_vout->p->b_done = true;
+    vlc_cond_signal( &p_vout->p->change_wait );
+    vlc_mutex_unlock( &p_vout->change_lock );
+    vlc_join( p_vout->p->thread, NULL );
     module_unneed( p_vout, p_vout->p_module );
     p_vout->p_module = NULL;
 }
@@ -573,12 +578,14 @@ static void vout_Destructor( vlc_object_t * p_this )
     spu_Destroy( p_vout->p_spu );
 
     /* Destroy the locks */
+    vlc_cond_destroy( &p_vout->p->change_wait );
     vlc_cond_destroy( &p_vout->p->picture_wait );
     vlc_mutex_destroy( &p_vout->picture_lock );
     vlc_mutex_destroy( &p_vout->change_lock );
     vlc_mutex_destroy( &p_vout->p->vfilter_lock );
 
     free( p_vout->p->psz_filter_chain );
+    free( p_vout->p->psz_title );
 
     config_ChainDestroy( p_vout->p_cfg );
 
@@ -604,7 +611,7 @@ static void vout_Destructor( vlc_object_t * p_this )
 /* */
 void vout_ChangePause( vout_thread_t *p_vout, bool b_paused, mtime_t i_date )
 {
-    vlc_object_lock( p_vout );
+    vlc_mutex_lock( &p_vout->change_lock );
 
     assert( !p_vout->p->b_paused || !b_paused );
 
@@ -635,11 +642,12 @@ void vout_ChangePause( vout_thread_t *p_vout, bool b_paused, mtime_t i_date )
     p_vout->p->b_paused = b_paused;
     p_vout->p->i_pause_date = i_date;
 
-    vlc_object_unlock( p_vout );
+    vlc_mutex_unlock( &p_vout->change_lock );
 }
+
 void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_lost )
 {
-    vlc_object_lock( p_vout );
+    vlc_mutex_lock( &p_vout->change_lock );
 
     *pi_displayed = p_vout->p->i_picture_displayed;
     *pi_lost = p_vout->p->i_picture_lost;
@@ -647,8 +655,9 @@ void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_l
     p_vout->p->i_picture_displayed = 0;
     p_vout->p->i_picture_lost = 0;
 
-    vlc_object_unlock( p_vout );
+    vlc_mutex_unlock( &p_vout->change_lock );
 }
+
 void vout_Flush( vout_thread_t *p_vout, mtime_t i_date )
 {
     vlc_mutex_lock( &p_vout->picture_lock );
@@ -669,6 +678,7 @@ void vout_Flush( vout_thread_t *p_vout, mtime_t i_date )
     vlc_cond_signal( &p_vout->p->picture_wait );
     vlc_mutex_unlock( &p_vout->picture_lock );
 }
+
 void vout_FixLeaks( vout_thread_t *p_vout, bool b_forced )
 {
     int i_pic, i_ready_pic;
@@ -716,7 +726,16 @@ void vout_FixLeaks( vout_thread_t *p_vout, bool b_forced )
 
         msg_Dbg( p_vout, "[%d] %d %d", i_pic, p_pic->i_status, p_pic->i_refcount );
         p_pic->i_refcount = 0;
-        vout_UsePictureLocked( p_vout, p_pic );
+
+        switch( p_pic->i_status )
+        {
+        case READY_PICTURE:
+        case DISPLAYED_PICTURE:
+        case RESERVED_PICTURE:
+            if( p_pic != p_vout->p->p_picture_displayed )
+                vout_UsePictureLocked( p_vout, p_pic );
+            break;
+        }
     }
     vlc_cond_signal( &p_vout->p->picture_wait );
     vlc_mutex_unlock( &p_vout->picture_lock );
@@ -745,6 +764,19 @@ void vout_NextPicture( vout_thread_t *p_vout, mtime_t *pi_duration )
     vlc_mutex_unlock( &p_vout->picture_lock );
 }
 
+void vout_DisplayTitle( vout_thread_t *p_vout, const char *psz_title )
+{
+    assert( psz_title );
+
+    if( !config_GetInt( p_vout, "osd" ) )
+        return;
+
+    vlc_mutex_lock( &p_vout->change_lock );
+    free( p_vout->p->psz_title );
+    p_vout->p->psz_title = strdup( psz_title );
+    vlc_mutex_unlock( &p_vout->change_lock );
+}
+
 /*****************************************************************************
  * InitThread: initialize video output thread
  *****************************************************************************
@@ -947,15 +979,13 @@ static int InitThread( vout_thread_t *p_vout )
  * terminated. It handles the pictures arriving in the video heap and the
  * display device events.
  *****************************************************************************/
-static void* RunThread( vlc_object_t *p_this )
+static void* RunThread( void *p_this )
 {
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
+    vout_thread_t *p_vout = p_this;
     int             i_idle_loops = 0;  /* loops without displaying a picture */
 
     bool            b_drop_late;
 
-    int canc = vlc_savecancel();
-
     /*
      * Initialize thread
      */
@@ -965,26 +995,21 @@ static void* RunThread( vlc_object_t *p_this )
     b_drop_late = var_CreateGetBool( p_vout, "drop-late-frames" );
 
     /* signal the creation of the vout */
-    vlc_thread_ready( p_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 );
-        vlc_restorecancel( canc );
         return NULL;
     }
 
-    vlc_object_lock( p_vout );
-
-    if( p_vout->p->b_title_show )
-        DisplayTitleOnOSD( p_vout );
-
     /*
      * Main loop - it is not executed if an error occurred during
      * initialization
      */
-    while( vlc_object_alive( p_vout ) && !p_vout->b_error )
+    while( !p_vout->p->b_done && !p_vout->b_error )
     {
         /* Initialize loop variables */
         const mtime_t current_date = mdate();
@@ -994,6 +1019,9 @@ static void* RunThread( vlc_object_t *p_this )
         picture_t *p_directbuffer;
         int i_index;
 
+        if( p_vout->p->b_title_show && p_vout->p->psz_title )
+            DisplayTitleOnOSD( p_vout );
+
         vlc_mutex_lock( &p_vout->picture_lock );
 
         /* Look for the earliest picture but after the last displayed one */
@@ -1173,8 +1201,6 @@ static void* RunThread( vlc_object_t *p_this )
         /* Give back change lock */
         vlc_mutex_unlock( &p_vout->change_lock );
 
-        vlc_object_unlock( p_vout );
-
         /* Sleep a while or until a given date */
         if( display_date != 0 )
         {
@@ -1195,9 +1221,7 @@ static void* RunThread( vlc_object_t *p_this )
 
         /* On awakening, take back lock and send immediately picture
          * to display. */
-        vlc_object_lock( p_vout );
-        /* Note: vlc_object_alive() could be false here, and we
-         * could be dead */
+        /* Note: p_vout->p->b_done could be true here and now */
         vlc_mutex_lock( &p_vout->change_lock );
 
         /*
@@ -1308,7 +1332,7 @@ static void* RunThread( vlc_object_t *p_this )
 
             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 );
@@ -1348,8 +1372,6 @@ static void* RunThread( vlc_object_t *p_this )
     EndThread( p_vout );
     vlc_mutex_unlock( &p_vout->change_lock );
 
-    vlc_object_unlock( p_vout );
-    vlc_restorecancel( canc );
     return NULL;
 }
 
@@ -1362,9 +1384,9 @@ static void* RunThread( vlc_object_t *p_this )
  *****************************************************************************/
 static void ErrorThread( vout_thread_t *p_vout )
 {
-    /* Wait until a `die' order */
-    while( vlc_object_alive( p_vout ) )
-        vlc_object_wait( p_vout );
+    /* Wait until a `close' order */
+    while( !p_vout->p->b_done )
+        vlc_cond_wait( &p_vout->p->change_wait, &p_vout->change_lock );
 }
 
 /*****************************************************************************
@@ -1450,7 +1472,7 @@ static int ChromaCreate( vout_thread_t *p_vout )
     VideoFormatImportRgb( &p_chroma->fmt_in.video, &p_vout->render );
     VideoFormatImportRgb( &p_chroma->fmt_out.video, &p_vout->output );
 
-    p_chroma->p_module = module_need( p_chroma, "video filter2", NULL, 0 );
+    p_chroma->p_module = module_need( p_chroma, "video filter2", NULL, false );
 
     if( p_chroma->p_module == NULL )
     {
@@ -1693,68 +1715,22 @@ static int VideoFilter2Callback( vlc_object_t *p_this, char const *psz_cmd,
 
 static void DisplayTitleOnOSD( vout_thread_t *p_vout )
 {
-    input_thread_t *p_input;
-    mtime_t i_now, i_stop;
+    const mtime_t i_start = mdate();
+    const mtime_t i_stop = i_start + INT64_C(1000) * p_vout->p->i_title_timeout;
 
-    if( !config_GetInt( p_vout, "osd" ) ) return;
+    vlc_assert_locked( &p_vout->change_lock );
 
-    p_input = (input_thread_t *)vlc_object_find( p_vout,
-              VLC_OBJECT_INPUT, FIND_ANYWHERE );
-    if( p_input )
-    {
-        i_now = mdate();
-        i_stop = i_now + (mtime_t)(p_vout->p->i_title_timeout * 1000);
-        char *psz_nowplaying =
-            input_item_GetNowPlaying( input_GetItem( p_input ) );
-        char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
-        char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
-        if( EMPTY_STR( psz_name ) )
-        {
-            free( psz_name );
-            psz_name = input_item_GetName( input_GetItem( p_input ) );
-        }
-        if( !EMPTY_STR( psz_nowplaying ) )
-        {
-            vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
-                                   psz_nowplaying, NULL,
-                                   p_vout->p->i_title_position,
-                                   30 + p_vout->fmt_in.i_width
-                                      - p_vout->fmt_in.i_visible_width
-                                      - p_vout->fmt_in.i_x_offset,
-                                   20 + p_vout->fmt_in.i_y_offset,
-                                   i_now, i_stop );
-        }
-        else if( !EMPTY_STR( psz_artist ) )
-        {
-            char *psz_string = NULL;
-            if( asprintf( &psz_string, "%s - %s", psz_name, psz_artist ) != -1 )
-            {
-                vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
-                                       psz_string, NULL,
-                                       p_vout->p->i_title_position,
-                                       30 + p_vout->fmt_in.i_width
-                                          - p_vout->fmt_in.i_visible_width
-                                          - p_vout->fmt_in.i_x_offset,
-                                       20 + p_vout->fmt_in.i_y_offset,
-                                       i_now, i_stop );
-                free( psz_string );
-            }
-        }
-        else
-        {
-            vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
-                                   psz_name, NULL,
-                                   p_vout->p->i_title_position,
-                                   30 + p_vout->fmt_in.i_width
-                                      - p_vout->fmt_in.i_visible_width
-                                      - p_vout->fmt_in.i_x_offset,
-                                   20 + p_vout->fmt_in.i_y_offset,
-                                   i_now, i_stop );
-        }
-        vlc_object_release( p_input );
-        free( psz_artist );
-        free( psz_name );
-        free( psz_nowplaying );
-    }
+    vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
+                           p_vout->p->psz_title, NULL,
+                           p_vout->p->i_title_position,
+                           30 + p_vout->fmt_in.i_width
+                              - p_vout->fmt_in.i_visible_width
+                              - p_vout->fmt_in.i_x_offset,
+                           20 + p_vout->fmt_in.i_y_offset,
+                           i_start, i_stop );
+
+    free( p_vout->p->psz_title );
+
+    p_vout->p->psz_title = NULL;
 }