Changeset 2121de2768caf997399ff534c0021e9204258fa1

Show
Ignore:
Timestamp:
20/07/08 22:20:19 (5 months ago)
Author:
Laurent Aimar <fenrir@videolan.org>
git-committer:
Laurent Aimar <fenrir@videolan.org> 1216585219 +0200
git-parent:

[a602c01e2e1b69dd1e7241d9d98686e25842ea41]

git-author:
Laurent Aimar <fenrir@videolan.org> 1216584993 +0200
Message:

Fixed a potential segfault when font builder thread try to release
itself.
Use the fontconfig the font builder thread created (Fixed a few past
broken commits).
Fixed fontconfig lock (a unique lock for all instances).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/misc/freetype.c

    re5ca236 r2121de2  
    7676#include <assert.h> 
    7777 
    78 typedef struct line_desc_t line_desc_t; 
    79  
    8078/***************************************************************************** 
    81  * Local prototypes 
     79 * Module descriptor 
    8280 *****************************************************************************/ 
    8381static int  Create ( vlc_object_t * ); 
    8482static void Destroy( vlc_object_t * ); 
    8583 
    86 static int LoadFontsFromAttachments( filter_t *p_filter ); 
    87  
    88 /* The RenderText call maps to pf_render_string, defined in vlc_filter.h */ 
    89 static int RenderText( filter_t *, subpicture_region_t *, 
    90                        subpicture_region_t * ); 
    91 #ifdef HAVE_FONTCONFIG 
    92 static int RenderHtml( filter_t *, subpicture_region_t *, 
    93                        subpicture_region_t * ); 
    94 static char *FontConfig_Select( FcConfig *, const char *, 
    95                                 bool, bool, int * ); 
    96 static int BuildDone( vlc_object_t*, const char *, vlc_value_t, vlc_value_t, 
    97                         void* ); 
    98 #endif 
    99 static line_desc_t *NewLine( int ); 
    100  
    101 static int GetFontSize( filter_t *p_filter ); 
    102 static int SetFontSize( filter_t *, int ); 
    103 static void YUVFromRGB( uint32_t i_argb, 
    104                         uint8_t *pi_y, uint8_t *pi_u, uint8_t *pi_v ); 
    105  
    106 /***************************************************************************** 
    107  * Module descriptor 
    108  *****************************************************************************/ 
    10984#define FONT_TEXT N_("Font") 
    11085#define FONT_LONGTEXT N_("Filename for the font you want to use") 
     
    190165vlc_module_end(); 
    191166 
     167 
     168 
     169/***************************************************************************** 
     170 * Local prototypes 
     171 *****************************************************************************/ 
     172 
     173/* The RenderText call maps to pf_render_string, defined in vlc_filter.h */ 
     174static int RenderText( filter_t *, subpicture_region_t *, 
     175                       subpicture_region_t * ); 
     176#ifdef HAVE_FONTCONFIG 
     177static int RenderHtml( filter_t *, subpicture_region_t *, 
     178                       subpicture_region_t * ); 
     179static char *FontConfig_Select( FcConfig *, const char *, 
     180                                bool, bool, int * ); 
     181static int BuildDone( vlc_object_t*, const char *, vlc_value_t, vlc_value_t, 
     182                        void* ); 
     183#endif 
     184 
     185 
     186static int LoadFontsFromAttachments( filter_t *p_filter ); 
     187 
     188static int GetFontSize( filter_t *p_filter ); 
     189static int SetFontSize( filter_t *, int ); 
     190static void YUVFromRGB( uint32_t i_argb, 
     191                        uint8_t *pi_y, uint8_t *pi_u, uint8_t *pi_v ); 
     192 
     193typedef struct line_desc_t line_desc_t; 
    192194struct line_desc_t 
    193195{ 
     
    215217    line_desc_t    *p_next; 
    216218}; 
     219static line_desc_t *NewLine( int ); 
    217220 
    218221typedef struct font_stack_t font_stack_t; 
     
    241244static void FreeLines( line_desc_t * ); 
    242245static void FreeLine( line_desc_t * ); 
     246 
    243247#ifdef HAVE_FONTCONFIG 
    244 static void FontBuilder( vlc_object_t *p_this); 
     248static vlc_object_t *FontBuilderAttach( filter_t *p_filter, vlc_mutex_t **pp_lock  ); 
     249static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder ); 
     250static void FontBuilderThread( vlc_object_t *p_this); 
     251static void FontBuilderDestructor( vlc_object_t *p_this ); 
    245252#endif 
    246253 
     
    264271    int            i_display_height; 
    265272#ifdef HAVE_FONTCONFIG 
     273    vlc_mutex_t   *p_fontconfig_lock; 
     274    bool           b_fontconfig_ok; 
    266275    FcConfig      *p_fontconfig; 
    267     bool     b_fontconfig_ok; 
    268     vlc_mutex_t    fontconfig_lock; 
    269276#endif 
    270277 
    271278    input_attachment_t **pp_font_attachments; 
    272279    int                  i_font_attachments; 
     280 
     281    vlc_object_t  *p_fontbuilder; 
    273282}; 
    274283 
     
    285294    int            i_error; 
    286295    vlc_value_t    val; 
    287     vlc_object_t  *p_fontbuilder; 
    288296 
    289297    /* Allocate structure */ 
     
    361369 
    362370#ifdef HAVE_FONTCONFIG 
    363     vlc_mutex_init( &p_sys->fontconfig_lock ); 
    364371    p_sys->b_fontconfig_ok = false; 
    365372    p_sys->p_fontconfig    = NULL; 
    366  
    367     /* Check for an existing Fontbuilder thread */ 
    368     vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); 
    369     p_fontbuilder = vlc_object_find_name( p_filter->p_libvlc, 
    370                                           "fontlist builder", 
    371                                           FIND_CHILD ); 
    372  
    373     if( ! p_fontbuilder ) 
    374     { 
    375         /* Create the FontBuilder thread as a child of a top-level 
    376          * object, so that it can survive the destruction of the 
    377          * freetype object - the fontlist only needs to be built once, 
    378          * and calling the fontbuild a second time while the first is 
    379          * still in progress can cause thread instabilities. 
    380          */ 
    381  
    382         p_fontbuilder = vlc_object_create( p_filter->p_libvlc, 
    383                                            sizeof(vlc_object_t) ); 
    384         if( p_fontbuilder ) 
    385         { 
    386             p_fontbuilder->psz_object_name = strdup( "fontlist builder" ); 
    387             vlc_object_attach( p_fontbuilder, p_filter->p_libvlc ); 
    388  
    389             var_Create( p_fontbuilder, "build-done", VLC_VAR_BOOL ); 
    390             var_SetBool( p_fontbuilder, "build-done", false ); 
    391             var_AddCallback( p_fontbuilder, "build-done", BuildDone, p_sys ); 
    392  
    393             if( vlc_thread_create( p_fontbuilder, 
    394                                    "fontlist builder", 
    395                                    FontBuilder, 
    396                                    VLC_THREAD_PRIORITY_LOW, 
    397                                    false ) ) 
    398             { 
    399                 /* Don't destroy the fontconfig object - we won't be able to do 
    400                  * italics or bold or change the font face, but we will still 
    401                  * be able to do underline and change the font size. 
    402                  */ 
    403                 msg_Warn( p_filter, "fontconfig database builder thread can't " 
    404                         "be launched. Font styling support will be limited." ); 
    405             } 
    406         } 
    407         else 
    408         { 
    409             vlc_object_release( p_fontbuilder ); 
    410         } 
    411     } 
    412     else 
    413     { 
    414         vlc_object_release( p_fontbuilder ); 
    415     } 
    416     vlc_mutex_unlock( lock ); 
    417  
     373    p_sys->p_fontbuilder   = FontBuilderAttach( p_filter, &p_sys->p_fontconfig_lock ); 
    418374#endif 
    419375 
     
    463419 
    464420        for( k = 0; k < p_sys->i_font_attachments; k++ ) 
    465         { 
    466421            vlc_input_attachment_Delete( p_sys->pp_font_attachments[k] ); 
    467         } 
    468422 
    469423        free( p_sys->pp_font_attachments ); 
     
    471425 
    472426#ifdef HAVE_FONTCONFIG 
    473     vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); 
    474     vlc_object_t *p_fontbuilder = vlc_object_find_name( p_filter->p_libvlc, 
    475                                     "fontlist builder", FIND_CHILD ); 
    476     if( p_fontbuilder ) 
    477     { 
    478         var_DelCallback( p_fontbuilder, "build-done", BuildDone, p_sys ); 
    479         vlc_object_release( p_fontbuilder ); 
    480     } 
    481     vlc_mutex_unlock( lock ); 
    482  
    483     vlc_mutex_destroy( &p_sys->fontconfig_lock ); 
    484  
    485     if( p_sys->p_fontconfig ) 
    486     { 
    487         FcConfigDestroy( p_sys->p_fontconfig ); 
    488         p_sys->p_fontconfig = NULL; 
    489     } 
     427    FontBuilderDetach( p_filter, p_sys->p_fontbuilder ); 
     428#endif 
     429 
    490430    /* FcFini asserts calling the subfunction FcCacheFini() 
    491431     * even if no other library functions have been made since FcInit(), 
    492432     * so don't call it. */ 
    493 #endif 
     433 
    494434    FT_Done_Face( p_sys->p_face ); 
    495435    FT_Done_FreeType( p_sys->p_library ); 
     
    498438 
    499439#ifdef HAVE_FONTCONFIG 
    500  
    501 static void FontBuilder( vlc_object_t *p_this ) 
     440static vlc_object_t *FontBuilderAttach( filter_t *p_filter, vlc_mutex_t **pp_lock ) 
     441
     442    /* Check for an existing Fontbuilder thread */ 
     443    vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); 
     444    vlc_object_t *p_fontbuilder = 
     445        vlc_object_find_name( p_filter->p_libvlc, 
     446                              "fontlist builder", FIND_CHILD ); 
     447 
     448    if( !p_fontbuilder ) 
     449    { 
     450        /* Create the FontBuilderThread thread as a child of a top-level 
     451         * object, so that it can survive the destruction of the 
     452         * freetype object - the fontlist only needs to be built once, 
     453         * and calling the fontbuild a second time while the first is 
     454         * still in progress can cause thread instabilities. 
     455         * 
     456         * XXX The fontbuilder will be destroy as soon as it is unused. 
     457         */ 
     458 
     459        p_fontbuilder = vlc_object_create( p_filter->p_libvlc, 
     460                                           sizeof(vlc_object_t) ); 
     461        if( p_fontbuilder ) 
     462        { 
     463            p_fontbuilder->psz_object_name = strdup( "fontlist builder" ); 
     464            p_fontbuilder->p_private = NULL; 
     465            vlc_object_set_destructor( p_fontbuilder, FontBuilderDestructor ); 
     466 
     467            vlc_object_attach( p_fontbuilder, p_filter->p_libvlc ); 
     468 
     469            var_Create( p_fontbuilder, "build-done", VLC_VAR_BOOL ); 
     470            var_SetBool( p_fontbuilder, "build-done", false ); 
     471 
     472            if( vlc_thread_create( p_fontbuilder, 
     473                                   "fontlist builder", 
     474                                   FontBuilderThread, 
     475                                   VLC_THREAD_PRIORITY_LOW, 
     476                                   false ) ) 
     477            { 
     478                msg_Warn( p_filter, "fontconfig database builder thread can't " 
     479                        "be launched. Font styling support will be limited." ); 
     480            } 
     481        } 
     482    } 
     483    if( p_fontbuilder ) 
     484    { 
     485        var_AddCallback( p_fontbuilder, "build-done", BuildDone, p_filter ); 
     486        var_TriggerCallback( p_fontbuilder, "build-done" ); 
     487    } 
     488    vlc_mutex_unlock( p_lock ); 
     489 
     490    *pp_lock = p_lock; 
     491    return p_fontbuilder; 
     492
     493static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder ) 
     494
     495    vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); 
     496    if( p_fontbuilder ) 
     497    { 
     498        var_DelCallback( p_fontbuilder, "build-done", BuildDone, p_filter ); 
     499 
     500        /* We wait for the thread on the first FontBuilderDetach */ 
     501        if( vlc_object_alive( p_fontbuilder ) ) 
     502        { 
     503            vlc_object_kill( p_fontbuilder ); 
     504            vlc_thread_join( p_fontbuilder ); 
     505        } 
     506        vlc_object_release( p_fontbuilder ); 
     507    } 
     508    vlc_mutex_unlock( lock ); 
     509
     510static void FontBuilderThread( vlc_object_t *p_this ) 
    502511{ 
    503512    FcConfig      *p_fontconfig = FcInitLoadConfig(); 
    504     vlc_mutex_t   *lock; 
    505513 
    506514    vlc_thread_ready( p_this ); 
     
    510518        mtime_t    t1, t2; 
    511519 
     520        //msg_Dbg( p_this, "Building font database..." ); 
    512521        msg_Dbg( p_this, "Building font database..." ); 
    513522        t1 = mdate(); 
     
    526535        msg_Dbg( p_this, "Took %ld seconds", (long)((t2 - t1)/1000000) ); 
    527536 
    528         lock = var_AcquireMutex( "fontbuilder" ); 
     537        vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); 
     538        p_this->p_private = p_fontconfig; 
     539        vlc_mutex_unlock( p_lock ); 
    529540 
    530541        var_SetBool( p_this, "build-done", true ); 
    531  
     542    } 
     543
     544static void FontBuilderDestructor( vlc_object_t *p_this ) 
     545
     546    FcConfig *p_fontconfig = p_this->p_private; 
     547 
     548    if( p_fontconfig ) 
    532549        FcConfigDestroy( p_fontconfig ); 
    533         vlc_mutex_unlock( lock ); 
    534     } 
    535     vlc_object_detach( p_this ); 
    536     vlc_object_release( p_this ); 
    537 
    538  
     550
    539551#endif 
    540552 
     
    21892201                       vlc_value_t oldval, vlc_value_t newval, void *param ) 
    21902202{ 
    2191     (void)p_this; 
    2192     (void)psz_var; 
    2193     (void)oldval; 
    2194     ((filter_sys_t*)param)->b_fontconfig_ok = newval.b_bool; 
    2195     assert( newval.b_bool ); 
     2203    filter_t *p_filter = param; 
     2204    filter_sys_t *p_sys = p_filter->p_sys; 
     2205 
     2206    if( newval.b_bool ) 
     2207    { 
     2208        vlc_mutex_lock( p_sys->p_fontconfig_lock ); 
     2209        p_sys->b_fontconfig_ok = true; 
     2210        p_sys->p_fontconfig = p_this->p_private; 
     2211        vlc_mutex_unlock( p_sys->p_fontconfig_lock ); 
     2212    } 
     2213 
     2214    VLC_UNUSED(psz_var); 
     2215    VLC_UNUSED(oldval); 
    21962216    return VLC_SUCCESS; 
    21972217} 
     
    24122432            CheckForEmbeddedFont( p_sys, &p_face, p_style ); 
    24132433 
    2414             if( ! p_face && p_sys->b_fontconfig_ok ) 
    2415             { 
    2416                 char *psz_fontfile; 
    2417                 vlc_mutex_lock( &p_sys->fontconfig_lock ); 
    2418  
    2419                 psz_fontfile = FontConfig_Select( p_sys->p_fontconfig, 
    2420                                                   p_style->psz_fontname, 
    2421                                                   p_style->b_bold, 
    2422                                                   p_style->b_italic, 
    2423                                                   &i_idx ); 
    2424                 vlc_mutex_unlock( &p_sys->fontconfig_lock ); 
     2434            if( ! p_face ) 
     2435            { 
     2436                char *psz_fontfile = NULL; 
     2437 
     2438                vlc_mutex_lock( p_sys->p_fontconfig_lock ); 
     2439                if( p_sys->b_fontconfig_ok ) 
     2440                { 
     2441                    /* FIXME Is there really a race condition between FontConfig_Select with default fontconfig(NULL) 
     2442                     * and FcConfigBuildFonts ? If not it would be better to remove the check on b_fontconfig_ok */ 
     2443                    psz_fontfile = FontConfig_Select( p_sys->p_fontconfig, 
     2444                                                      p_style->psz_fontname, 
     2445                                                      p_style->b_bold, 
     2446                                                      p_style->b_italic, 
     2447                                                      &i_idx ); 
     2448                } 
     2449                vlc_mutex_unlock( p_sys->p_fontconfig_lock ); 
    24252450 
    24262451                if( psz_fontfile && ! *psz_fontfile )