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

📄 vout_subpictures.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
        }    }    /* If no free subpicture could be found */    if( p_subpic == NULL )    {        msg_Err( p_spu, "subpicture heap is full" );        vlc_mutex_unlock( &p_spu->subpicture_lock );        return NULL;    }    /* Copy subpicture information, set some default values */    memset( p_subpic, 0, sizeof(subpicture_t) );    p_subpic->i_status   = RESERVED_SUBPICTURE;    p_subpic->b_absolute = true;    p_subpic->b_pausable = false;    p_subpic->b_fade     = false;    p_subpic->i_alpha    = 0xFF;    p_subpic->p_region   = NULL;    p_subpic->pf_render  = NULL;    p_subpic->pf_destroy = NULL;    p_subpic->p_sys      = NULL;    vlc_mutex_unlock( &p_spu->subpicture_lock );    p_subpic->pf_create_region = __spu_CreateRegion;    p_subpic->pf_make_region = __spu_MakeRegion;    p_subpic->pf_destroy_region = __spu_DestroyRegion;    return p_subpic;}/** * Remove a subpicture from the heap * * This function frees a previously reserved subpicture. * It is meant to be used when the construction of a picture aborted. * This function does not need locking since reserved subpictures are ignored * by the spu. */void spu_DestroySubpicture( spu_t *p_spu, subpicture_t *p_subpic ){    /* Get lock */    vlc_mutex_lock( &p_spu->subpicture_lock );    /* There can be race conditions so we need to check the status */    if( p_subpic->i_status == FREE_SUBPICTURE )    {        vlc_mutex_unlock( &p_spu->subpicture_lock );        return;    }    /* Check if status is valid */    if( ( p_subpic->i_status != RESERVED_SUBPICTURE )           && ( p_subpic->i_status != READY_SUBPICTURE ) )    {        msg_Err( p_spu, "subpicture %p has invalid status %d",                         p_subpic, p_subpic->i_status );    }    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 );    }    if( p_subpic->pf_destroy )    {        p_subpic->pf_destroy( p_subpic );    }    p_subpic->i_status = FREE_SUBPICTURE;    vlc_mutex_unlock( &p_spu->subpicture_lock );}/***************************************************************************** * spu_RenderSubpictures: render a subpicture list ***************************************************************************** * This function renders all sub picture units in the list. *****************************************************************************/static void SpuRenderCreateBlend( spu_t *p_spu, vlc_fourcc_t i_chroma, int i_aspect ){    filter_t *p_blend;    assert( !p_spu->p_blend );    p_spu->p_blend =    p_blend        = vlc_custom_create( p_spu, sizeof(filter_t),                                        VLC_OBJECT_GENERIC, "blend" );    if( !p_blend )        return;    es_format_Init( &p_blend->fmt_in, VIDEO_ES, 0 );    es_format_Init( &p_blend->fmt_out, VIDEO_ES, 0 );    p_blend->fmt_out.video.i_x_offset = 0;    p_blend->fmt_out.video.i_y_offset = 0;    p_blend->fmt_out.video.i_chroma = i_chroma;    p_blend->fmt_out.video.i_aspect = i_aspect;    /* The blend module will be loaded when needed with the real    * input format */    p_blend->p_module = NULL;    /* */    vlc_object_attach( p_blend, p_spu );}static void SpuRenderUpdateBlend( spu_t *p_spu, int i_out_width, int i_out_height, const video_format_t *p_in_fmt ){    filter_t *p_blend = p_spu->p_blend;    assert( p_blend );    /* */    if( p_blend->p_module && p_blend->fmt_in.video.i_chroma != p_in_fmt->i_chroma )    {        /* The chroma is not the same, we need to reload the blend module         * XXX to match the old behaviour just test !p_blend->fmt_in.video.i_chroma */        module_Unneed( p_blend, p_blend->p_module );        p_blend->p_module = NULL;    }    /* */    p_blend->fmt_in.video = *p_in_fmt;    /* */    p_blend->fmt_out.video.i_width =    p_blend->fmt_out.video.i_visible_width = i_out_width;    p_blend->fmt_out.video.i_height =    p_blend->fmt_out.video.i_visible_height = i_out_height;    /* */    if( !p_blend->p_module )        p_blend->p_module = module_Need( p_blend, "video blending", 0, 0 );}static void SpuRenderCreateAndLoadText( spu_t *p_spu, int i_width, int i_height ){    filter_t *p_text;    assert( !p_spu->p_text );    p_spu->p_text =    p_text        = vlc_custom_create( p_spu, sizeof(filter_t),                                       VLC_OBJECT_GENERIC, "spu text" );    if( !p_text )        return;    es_format_Init( &p_text->fmt_in, VIDEO_ES, 0 );    es_format_Init( &p_text->fmt_out, VIDEO_ES, 0 );    p_text->fmt_out.video.i_width =    p_text->fmt_out.video.i_visible_width = i_width;    p_text->fmt_out.video.i_height =    p_text->fmt_out.video.i_visible_height = i_height;    p_text->pf_sub_buffer_new = spu_new_buffer;    p_text->pf_sub_buffer_del = spu_del_buffer;    vlc_object_attach( p_text, p_spu );    /* FIXME TOCHECK shouldn't module_Need( , , psz_modulename, false ) do the     * same than these 2 calls ? */    char *psz_modulename = var_CreateGetString( p_spu, "text-renderer" );    if( psz_modulename && *psz_modulename )    {        p_text->p_module = module_Need( p_text, "text renderer",                                        psz_modulename, true );    }    free( psz_modulename );    if( !p_text->p_module )        p_text->p_module = module_Need( p_text, "text renderer", NULL, false );}static filter_t *CreateAndLoadScale( vlc_object_t *p_obj, vlc_fourcc_t i_chroma ){    filter_t *p_scale;    p_scale = vlc_custom_create( p_obj, sizeof(filter_t),                                 VLC_OBJECT_GENERIC, "scale" );    if( !p_scale )        return NULL;    es_format_Init( &p_scale->fmt_in, VIDEO_ES, 0 );    p_scale->fmt_in.video.i_chroma = i_chroma;    p_scale->fmt_in.video.i_width =    p_scale->fmt_in.video.i_height = 32;    es_format_Init( &p_scale->fmt_out, VIDEO_ES, 0 );    p_scale->fmt_out.video.i_chroma = i_chroma;    p_scale->fmt_out.video.i_width =    p_scale->fmt_out.video.i_height = 16;    p_scale->pf_vout_buffer_new = spu_new_video_buffer;    p_scale->pf_vout_buffer_del = spu_del_video_buffer;    vlc_object_attach( p_scale, p_obj );    p_scale->p_module = module_Need( p_scale, "video filter2", 0, 0 );    return p_scale;}static void SpuRenderCreateAndLoadScale( spu_t *p_spu ){    /* FIXME: We'll also be using it for YUVA and RGBA blending ... */    assert( !p_spu->p_scale );    assert( !p_spu->p_scale_yuvp );    p_spu->p_scale = CreateAndLoadScale( VLC_OBJECT(p_spu), VLC_FOURCC('Y','U','V','A') );    p_spu->p_scale_yuvp = p_spu->p_scale_yuvp = CreateAndLoadScale( VLC_OBJECT(p_spu), VLC_FOURCC('Y','U','V','P') );}static void SpuRenderText( spu_t *p_spu, bool *pb_rerender_text,                           subpicture_t *p_subpic, subpicture_region_t *p_region, int i_min_scale_ratio ){    assert( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') );    if( !p_spu->p_text || !p_spu->p_text->p_module )        goto exit;    /* Setup 3 variables which can be used to render     * time-dependent text (and effects). The first indicates     * the total amount of time the text will be on screen,     * the second the amount of time it has already been on     * screen (can be a negative value as text is layed out     * before it is rendered) and the third is a feedback     * variable from the renderer - if the renderer sets it     * then this particular text is time-dependent, eg. the     * visual progress bar inside the text in karaoke and the     * text needs to be rendered multiple times in order for     * the effect to work - we therefore need to return the     * region to its original state at the end of the loop,     * instead of leaving it in YUVA or YUVP.     * Any renderer which is unaware of how to render     * time-dependent text can happily ignore the variables     * and render the text the same as usual - it should at     * least show up on screen, but the effect won't change     * the text over time.     */    /* FIXME why these variables are recreated every time and not     * when text renderer module was created ? */    var_Create( p_spu->p_text, "spu-duration", VLC_VAR_TIME );    var_Create( p_spu->p_text, "spu-elapsed", VLC_VAR_TIME );    var_Create( p_spu->p_text, "text-rerender", VLC_VAR_BOOL );    var_Create( p_spu->p_text, "scale", VLC_VAR_INTEGER );    var_SetTime( p_spu->p_text, "spu-duration", p_subpic->i_stop - p_subpic->i_start );    var_SetTime( p_spu->p_text, "spu-elapsed", mdate() - p_subpic->i_start );    var_SetBool( p_spu->p_text, "text-rerender", false );    var_SetInteger( p_spu->p_text, "scale", i_min_scale_ratio );    if( p_spu->p_text->pf_render_html && p_region->psz_html )    {        p_spu->p_text->pf_render_html( p_spu->p_text,                                       p_region, p_region );    }    else if( p_spu->p_text->pf_render_text )    {        p_spu->p_text->pf_render_text( p_spu->p_text,                                       p_region, p_region );    }    *pb_rerender_text = var_GetBool( p_spu->p_text, "text-rerender" );    var_Destroy( p_spu->p_text, "spu-duration" );    var_Destroy( p_spu->p_text, "spu-elapsed" );    var_Destroy( p_spu->p_text, "text-rerender" );    var_Destroy( p_spu->p_text, "scale" );exit:    p_region->i_align |= SUBPICTURE_RENDERED;}static void SpuRenderRegion( spu_t *p_spu,                             picture_t *p_pic_dst, picture_t *p_pic_src,                             subpicture_t *p_subpic, subpicture_region_t *p_region,                             const int i_scale_width_orig, const int i_scale_height_orig,                             const int pi_subpic_x[SCALE_SIZE],                             const int pi_scale_width[SCALE_SIZE],                             const int pi_scale_height[SCALE_SIZE],                             const video_format_t *p_fmt ){    video_format_t fmt_original;    bool b_rerender_text;    bool b_restore_format = false;    int i_fade_alpha;    int i_x_offset;    int i_y_offset;    int i_scale_idx;    int i_inv_scale_x;    int i_inv_scale_y;    filter_t *p_scale;    vlc_assert_locked( &p_spu->subpicture_lock );    fmt_original = p_region->fmt;    b_rerender_text = false;    if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )    {        SpuRenderText( p_spu, &b_rerender_text, p_subpic, p_region, __MIN(i_scale_width_orig, i_scale_height_orig) );        b_restore_format = b_rerender_text;        /* Check if the rendering has failed ... */        if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )            goto exit;    }    if( p_region->i_align & SUBPICTURE_RENDERED )    {        /* We are using a region which come from rendered text */        i_scale_idx   = SCALE_TEXT;        i_inv_scale_x = i_scale_width_orig;        i_inv_scale_y = i_scale_height_orig;    }    else    {        i_scale_idx   = SCALE_DEFAULT;        i_inv_scale_x = 1000;        i_inv_scale_y = 1000;    }    i_x_offset = (p_region->i_x + pi_subpic_x[ i_scale_idx ]) * i_inv_scale_x / 1000;    i_y_offset = (p_region->i_y + p_subpic->i_y) * i_inv_scale_y / 1000;    /* Force palette if requested     * FIXME b_force_palette and b_force_crop are applied to all subpictures using palette     * instead of only the right one (being the dvd spu).     */    const bool b_using_palette = p_region->fmt.i_chroma == VLC_FOURCC('Y','U','V','P');    const bool b_force_palette = b_using_palette && p_spu->b_force_palette;    const bool b_force_crop    = b_force_palette && p_spu->b_force_crop;    if( b_force_palette )    {        /* It looks so wrong I won't comment         * p_palette->palette is [256][4] with a int i_entries         * p_spu->palette is [4][4]         * */        p_region->fmt.p_palette->i_entries = 4;        memcpy( p_region->fmt.p_palette->palette, p_spu->palette, 4*sizeof(uint32_t) );    }    if( b_using_palette )        p_scale = p_spu->p_scale_yuvp;    else        p_scale = p_spu->p_scale;    if( p_scale &&        ( ( pi_scale_width[i_scale_idx]  > 0 && pi_scale_width[i_scale_idx]  != 1000 ) ||          ( pi_scale_height[i_scale_idx] > 0 && pi_scale_height[i_scale_idx] != 1000 ) ||          ( b_force_palette ) ) )    {        const unsigned i_dst_width  = p_region->fmt.i_width  * pi_scale_width[i_scale_idx] / 1000;        const unsigned i_dst_height = p_region->fmt.i_height * pi_scale_height[i_scale_idx] / 1000;        /* Destroy if cache is unusable */        if( p_region->p_cache )        {            if( p_region->p_cache->fmt.i_width  != i_dst_width ||                p_region->p_cache->fmt.i_height != i_dst_height ||                b_force_palette )            {                p_subpic->pf_destroy_region( VLC_OBJECT(p_spu),                                             p_region->p_cache );                p_region->p_cache = NULL;            }        }        /* Scale if needed into cache */        if( !p_region->p_cache )        {            picture_t *p_pic;            p_scale->fmt_in.video = p_region->fmt;            p_scale->fmt_out.video = p_region->fmt;            p_region->p_cache =                p_subpic->pf_create_region( VLC_OBJECT(p_spu),

⌨️ 快捷键说明

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