⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libass.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
        vlc_mutex_unlock( p_ass->p_lock );        return;    }    /* Allocate the regions and draw them */    subpicture_region_t *pp_region[i_max_region];    subpicture_region_t **pp_region_last = &p_subpic->p_region;    for( int i = 0; i < i_region; i++ )    {        subpicture_region_t *r;        video_format_t fmt_region;        /* */        fmt_region = fmt;        fmt_region.i_width =        fmt_region.i_visible_width  = region[i].x1 - region[i].x0;        fmt_region.i_height =        fmt_region.i_visible_height = region[i].y1 - region[i].y0;        pp_region[i] = r = p_subpic->pf_create_region( VLC_OBJECT(p_spu), &fmt_region );        if( !r )            break;        r->i_x = region[i].x0;        r->i_y = region[i].y0;        r->i_align = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT;        /* */        RegionDraw( r, p_img );        /* */        *pp_region_last = r;        pp_region_last = &r->p_next;    }    vlc_mutex_unlock( p_ass->p_lock );}static rectangle_t r_create( int x0, int y0, int x1, int y1 ){    rectangle_t r = { x0, y0, x1, y1 };    return r;}static rectangle_t r_img( const ass_image_t *p_img ){    return r_create( p_img->dst_x, p_img->dst_y, p_img->dst_x+p_img->w, p_img->dst_y+p_img->h );}static void r_add( rectangle_t *r, const rectangle_t *n ){    r->x0 = __MIN( r->x0, n->x0 );    r->y0 = __MIN( r->y0, n->y0 );    r->x1 = __MAX( r->x1, n->x1 );    r->y1 = __MAX( r->y1, n->y1 );}static int r_surface( const rectangle_t *r ){    return (r->x1-r->x0) * (r->y1-r->y0);}static bool r_overlap( const rectangle_t *a, const rectangle_t *b, int i_dx, int i_dy ){    return  __MAX(a->x0-i_dx, b->x0) < __MIN( a->x1+i_dx, b->x1 ) &&            __MAX(a->y0-i_dy, b->y0) < __MIN( a->y1+i_dy, b->y1 );}static int BuildRegions( spu_t *p_spu, rectangle_t *p_region, int i_max_region, ass_image_t *p_img_list, int i_width, int i_height ){    ass_image_t *p_tmp;    int i_count;    VLC_UNUSED(p_spu);#ifdef DEBUG_REGION    int64_t i_ck_start = mdate();#endif    for( p_tmp = p_img_list, i_count = 0; p_tmp != NULL; p_tmp = p_tmp->next )        i_count++;    if( i_count <= 0 )        return 0;    ass_image_t **pp_img = calloc( i_count, sizeof(*pp_img) );    if( !pp_img )        return 0;    for( p_tmp = p_img_list, i_count = 0; p_tmp != NULL; p_tmp = p_tmp->next, i_count++ )        pp_img[i_count] = p_tmp;    /* */    const int i_w_inc = __MAX( ( i_width + 49 ) / 50, 32 );    const int i_h_inc = __MAX( ( i_height + 99 ) / 100, 32 );    int i_maxh = i_w_inc;    int i_maxw = i_h_inc;    int i_region;    rectangle_t region[i_max_region+1];    i_region = 0;    for( int i_used = 0; i_used < i_count; )    {        int n;        for( n = 0; n < i_count; n++ )        {            if( pp_img[n] )                break;        }        assert( i_region < i_max_region + 1 );        region[i_region++] = r_img( pp_img[n] );        pp_img[n] = NULL; i_used++;        bool b_ok;        do {            b_ok = false;            for( n = 0; n < i_count; n++ )            {                ass_image_t *p_img = pp_img[n];                if( !p_img )                    continue;                rectangle_t r = r_img( p_img );                int k;                int i_best = -1;                int i_best_s = INT_MAX;                for( k = 0; k < i_region; k++ )                {                    if( !r_overlap( &region[k], &r, i_maxw, i_maxh ) )                        continue;                    int s = r_surface( &r );                    if( s < i_best_s )                    {                        i_best_s = s;                        i_best = k;                    }                }                if( i_best >= 0 )                {                    r_add( &region[i_best], &r );                    pp_img[n] = NULL; i_used++;                    b_ok = true;                }            }        } while( b_ok );        if( i_region > i_max_region )        {            int i_best_i = -1;            int i_best_j = -1;            int i_best_ds = INT_MAX;            /* merge best */            for( int i = 0; i < i_region; i++ )            {                for( int j = i+1; j < i_region; j++ )                {                    rectangle_t n = region[i];                    r_add( &n, &region[j] );                    int ds = r_surface( &n ) - r_surface( &region[i] ) - r_surface( &region[j] );                    if( ds < i_best_ds )                    {                        i_best_i = i;                        i_best_j = j;                        i_best_ds = ds;                    }                }            }#ifdef DEBUG_REGION            msg_Err( p_spu, "Merging %d and %d", i_best_i, i_best_j );#endif            r_add( &region[i_best_i], &region[i_best_j] );            if( i_best_j+1 < i_region )                memmove( &region[i_best_j], &region[i_best_j+1], sizeof(*region) * ( i_region - (i_best_j+1)  ) );            i_region--;        }    }    /* */    for( int n = 0; n < i_region; n++ )        p_region[n] = region[n];#ifdef DEBUG_REGION    int64_t i_ck_time = mdate() - i_ck_start;    msg_Err( p_spu, "ASS: %d objects merged into %d region in %d micros", i_count, i_region, (int)(i_ck_time) );#endif    free( pp_img );    return i_region;}static void RegionDraw( subpicture_region_t *p_region, ass_image_t *p_img ){    const plane_t *p = &p_region->picture.p[0];    const int i_x = p_region->i_x;    const int i_y = p_region->i_y;    const int i_width  = p_region->fmt.i_width;    const int i_height = p_region->fmt.i_height;    memset( p->p_pixels, 0x00, p->i_pitch * p->i_lines );    for( ; p_img != NULL; p_img = p_img->next )    {        if( p_img->dst_x < i_x || p_img->dst_x + p_img->w > i_x + i_width ||            p_img->dst_y < i_y || p_img->dst_y + p_img->h > i_y + i_height )            continue;        const int r = (p_img->color >> 24)&0xff;        const int g = (p_img->color >> 16)&0xff;        const int b = (p_img->color >>  8)&0xff;        const int a = (p_img->color      )&0xff;        int x, y;        for( y = 0; y < p_img->h; y++ )        {            for( x = 0; x < p_img->w; x++ )            {                const int alpha = p_img->bitmap[y*p_img->stride+x];                const int an = (255 - a) * alpha / 255;                uint8_t *p_rgba = &p->p_pixels[(y+p_img->dst_y-i_y) * p->i_pitch + 4 * (x+p_img->dst_x-i_x)];                /* Native endianness, but RGBA ordering */                p_rgba[0] = ( p_rgba[0] * (255-an) + r * an ) / 255;                p_rgba[1] = ( p_rgba[1] * (255-an) + g * an ) / 255;                p_rgba[2] = ( p_rgba[2] * (255-an) + b * an ) / 255;                p_rgba[3] = 255 - ( 255 - p_rgba[3] ) * ( 255 - an ) / 255;            }        }    }#ifdef DEBUG_REGION    /* XXX Draw a box for debug */#define P(x,y) ((uint32_t*)&p->p_pixels[(y)*p->i_pitch + 4*(x)])    for( int y = 0; y < p->i_lines; y++ )        *P(0,y) = *P(p->i_visible_pitch/4-1,y) = 0xff000000;    for( int x = 0; x < p->i_visible_pitch; x++ )        *P(x/4,0) = *P(x/4,p->i_visible_lines-1) = 0xff000000;#undef P#endif}static void SubpictureReleaseRegions( spu_t *p_spu, subpicture_t *p_subpic ){    while( p_subpic->p_region )    {        subpicture_region_t *p_region = p_subpic->p_region;        p_subpic->p_region = p_region->p_next;        spu_DestroyRegion( p_spu, p_region );    }    p_subpic->p_region = NULL;}/* */static ass_handle_t *AssHandleYield( decoder_t *p_dec ){    vlc_mutex_t *p_lock = var_AcquireMutex( "libass" );    if( !p_lock )        return NULL;    ass_handle_t *p_ass = NULL;    ass_library_t *p_library = NULL;    ass_renderer_t *p_renderer = NULL;    vlc_value_t val;    var_Create( p_dec->p_libvlc, "libass-handle", VLC_VAR_ADDRESS );    if( var_Get( p_dec->p_libvlc, "libass-handle", &val ) )        val.p_address = NULL;    if( val.p_address )    {        p_ass = val.p_address;        p_ass->i_refcount++;        vlc_mutex_unlock( p_lock );        return p_ass;    }    /* */    p_ass = malloc( sizeof(*p_ass) );    if( !p_ass )        goto error;    /* */    p_ass->p_libvlc = VLC_OBJECT(p_dec->p_libvlc);    p_ass->p_lock = p_lock;    p_ass->i_refcount = 1;    /* Create libass library */    p_ass->p_library = p_library = ass_library_init();    if( !p_library )        goto error;    /* load attachments */    input_attachment_t  **pp_attachments;    int                   i_attachments;    if( decoder_GetInputAttachments( p_dec, &pp_attachments, &i_attachments ))    {        i_attachments = 0;        pp_attachments = NULL;    }    for( int k = 0; k < i_attachments; k++ )    {        input_attachment_t *p_attach = pp_attachments[k];        if( !strcasecmp( p_attach->psz_mime, "application/x-truetype-font" ) )        {            msg_Dbg( p_dec, "adding embedded font %s", p_attach->psz_name );            ass_add_font( p_ass->p_library, p_attach->psz_name, p_attach->p_data, p_attach->i_data );        }        vlc_input_attachment_Delete( p_attach );    }    free( pp_attachments );    char *psz_font_dir = config_GetCacheDir();    if( !psz_font_dir )        goto error;    ass_set_fonts_dir( p_library, psz_font_dir );    free( psz_font_dir );    ass_set_extract_fonts( p_library, true );    ass_set_style_overrides( p_library, NULL );    /* Create the renderer */    p_ass->p_renderer = p_renderer = ass_renderer_init( p_library );    if( !p_renderer )        goto error;    ass_set_use_margins( p_renderer, false);    //if( false )    //    ass_set_margins( p_renderer, int t, int b, int l, int r);    ass_set_hinting( p_renderer, ASS_HINTING_NATIVE ); // No idea    ass_set_font_scale( p_renderer, 1.0 );    ass_set_line_spacing( p_renderer, 0.0 );    const char *psz_font = NULL; /* We don't ship a default font with VLC */    const char *psz_family = "Arial"; /* Use Arial if we can't find anything more suitable */#ifdef HAVE_FONTCONFIG    ass_set_fonts( p_renderer, psz_font, psz_family );  // setup default font/family#else    /* FIXME you HAVE to give him a font if no fontconfig */    ass_set_fonts_nofc( p_renderer, psz_font, psz_family );#endif    memset( &p_ass->fmt, 0, sizeof(p_ass->fmt) );    /* */    val.p_address = p_ass;    var_Set( p_dec->p_libvlc, "libass-handle", val );    /* */    vlc_mutex_unlock( p_ass->p_lock );    return p_ass;error:    if( p_renderer )        ass_renderer_done( p_renderer );    if( p_library )        ass_library_done( p_library );    free( p_ass );    vlc_mutex_unlock( p_lock );    return NULL;}static void AssHandleRelease( ass_handle_t *p_ass ){    vlc_mutex_lock( p_ass->p_lock );    p_ass->i_refcount--;    if( p_ass->i_refcount > 0 )    {        vlc_mutex_unlock( p_ass->p_lock );        return;    }    ass_renderer_done( p_ass->p_renderer );    ass_library_done( p_ass->p_library );    vlc_value_t val;    val.p_address = NULL;    var_Set( p_ass->p_libvlc, "libass-handle", val );    vlc_mutex_unlock( p_ass->p_lock );    free( p_ass );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -