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

📄 vout_subpictures.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
            ( p_region->fmt.i_sar_den * p_fmt->i_sar_num ) )        {            for( k = 0; k < SCALE_SIZE; k++ )            {                pi_scale_width[k] = pi_scale_width[ k ] *                    (int64_t)p_region->fmt.i_sar_num * p_fmt->i_sar_den /                    p_region->fmt.i_sar_den / p_fmt->i_sar_num;                pi_subpic_x[k] = p_subpic->i_x * pi_scale_width[ k ] / 1000;            }        }        /* Load the scaling module when needed */        if( !p_spu->p_scale )        {            bool b_scale_used = false;            for( k = 0; k < SCALE_SIZE; k++ )            {                const int i_scale_w = pi_scale_width[k];                const int i_scale_h = pi_scale_height[k];                if( ( i_scale_w > 0 && i_scale_w != 1000 ) || ( i_scale_h > 0 && i_scale_h != 1000 ) )                    b_scale_used = true;            }            if( b_scale_used )                SpuRenderCreateAndLoadScale( p_spu );        }        for( ; p_region != NULL; p_region = p_region->p_next )            SpuRenderRegion( p_spu, p_pic_dst, p_pic_src,                             p_subpic, p_region, i_scale_width_orig, i_scale_height_orig,                             pi_subpic_x, pi_scale_width, pi_scale_height,                             p_fmt );    }    vlc_mutex_unlock( &p_spu->subpicture_lock );}/***************************************************************************** * spu_SortSubpictures: find the subpictures to display ***************************************************************************** * This function parses all subpictures and decides which ones need to be * displayed. This operation does not need lock, since only READY_SUBPICTURE * are handled. If no picture has been selected, display_date will depend on * the subpicture. * We also check for ephemer DVD subpictures (subpictures that have * to be removed if a newer one is available), which makes it a lot * more difficult to guess if a subpicture has to be rendered or not. *****************************************************************************/subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,                                   bool b_paused ){    int i_index, i_channel;    subpicture_t *p_subpic = NULL;    subpicture_t *p_ephemer;    mtime_t      ephemer_date;    /* Run subpicture filters */    filter_chain_SubFilter( p_spu->p_chain, display_date );    /* We get an easily parsable chained list of subpictures which     * ends with NULL since p_subpic was initialized to NULL. */    for( i_channel = 0; i_channel < p_spu->i_channel; i_channel++ )    {        p_ephemer = 0;        ephemer_date = 0;        for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )        {            if( p_spu->p_subpicture[i_index].i_channel != i_channel ||                p_spu->p_subpicture[i_index].i_status != READY_SUBPICTURE )            {                continue;            }            if( display_date &&                display_date < p_spu->p_subpicture[i_index].i_start )            {                /* Too early, come back next monday */                continue;            }            if( p_spu->p_subpicture[i_index].i_start > ephemer_date )                ephemer_date = p_spu->p_subpicture[i_index].i_start;            if( display_date > p_spu->p_subpicture[i_index].i_stop &&                ( !p_spu->p_subpicture[i_index].b_ephemer ||                  p_spu->p_subpicture[i_index].i_stop >                  p_spu->p_subpicture[i_index].i_start ) &&                !( p_spu->p_subpicture[i_index].b_pausable &&                   b_paused ) )            {                /* Too late, destroy the subpic */                spu_DestroySubpicture( p_spu, &p_spu->p_subpicture[i_index] );                continue;            }            /* If this is an ephemer subpic, add it to our list */            if( p_spu->p_subpicture[i_index].b_ephemer )            {                p_spu->p_subpicture[i_index].p_next = p_ephemer;                p_ephemer = &p_spu->p_subpicture[i_index];                continue;            }            p_spu->p_subpicture[i_index].p_next = p_subpic;            p_subpic = &p_spu->p_subpicture[i_index];        }        /* If we found ephemer subpictures, check if they have to be         * displayed or destroyed */        while( p_ephemer != NULL )        {            subpicture_t *p_tmp = p_ephemer;            p_ephemer = p_ephemer->p_next;            if( p_tmp->i_start < ephemer_date )            {                /* Ephemer subpicture has lived too long */                spu_DestroySubpicture( p_spu, p_tmp );            }            else            {                /* Ephemer subpicture can still live a bit */                p_tmp->p_next = p_subpic;                p_subpic = p_tmp;            }        }    }    return p_subpic;}/***************************************************************************** * SpuClearChannel: clear an spu channel ***************************************************************************** * This function destroys the subpictures which belong to the spu channel * corresponding to i_channel_id. *****************************************************************************/static void SpuClearChannel( spu_t *p_spu, int i_channel, bool b_locked ){    int          i_subpic;                               /* subpicture index */    subpicture_t *p_subpic = NULL;                  /* first free subpicture */    if( !b_locked )        vlc_mutex_lock( &p_spu->subpicture_lock );    for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )    {        p_subpic = &p_spu->p_subpicture[i_subpic];        if( p_subpic->i_status == FREE_SUBPICTURE            || ( p_subpic->i_status != RESERVED_SUBPICTURE                 && p_subpic->i_status != READY_SUBPICTURE ) )        {            continue;        }        if( p_subpic->i_channel == i_channel )        {            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;        }    }    if( !b_locked )        vlc_mutex_unlock( &p_spu->subpicture_lock );}/***************************************************************************** * spu_ControlDefault: default methods for the subpicture unit control. *****************************************************************************/static int spu_vaControlDefault( spu_t *p_spu, int i_query, va_list args ){    int *pi, i;    switch( i_query )    {    case SPU_CHANNEL_REGISTER:        pi = (int *)va_arg( args, int * );        if( pi ) *pi = p_spu->i_channel++;        break;    case SPU_CHANNEL_CLEAR:        i = (int)va_arg( args, int );        SpuClearChannel( p_spu, i, false );        break;    default:        msg_Dbg( p_spu, "control query not supported" );        return VLC_EGENERIC;    }    return VLC_SUCCESS;}/***************************************************************************** * Object variables callbacks *****************************************************************************//***************************************************************************** * UpdateSPU: update subpicture settings ***************************************************************************** * This function is called from CropCallback and at initialization time, to * retrieve crop information from the input. *****************************************************************************/static void UpdateSPU( spu_t *p_spu, vlc_object_t *p_object ){    vlc_value_t val;    vlc_mutex_lock( &p_spu->subpicture_lock );    p_spu->b_force_palette = false;    p_spu->b_force_crop = false;    if( var_Get( p_object, "highlight", &val ) || !val.b_bool )    {        vlc_mutex_unlock( &p_spu->subpicture_lock );        return;    }    p_spu->b_force_crop = true;    var_Get( p_object, "x-start", &val );    p_spu->i_crop_x = val.i_int;    var_Get( p_object, "y-start", &val );    p_spu->i_crop_y = val.i_int;    var_Get( p_object, "x-end", &val );    p_spu->i_crop_width = val.i_int - p_spu->i_crop_x;    var_Get( p_object, "y-end", &val );    p_spu->i_crop_height = val.i_int - p_spu->i_crop_y;    if( var_Get( p_object, "menu-palette", &val ) == VLC_SUCCESS )    {        memcpy( p_spu->palette, val.p_address, 16 );        p_spu->b_force_palette = true;    }    vlc_mutex_unlock( &p_spu->subpicture_lock );    msg_Dbg( p_object, "crop: %i,%i,%i,%i, palette forced: %i",             p_spu->i_crop_x, p_spu->i_crop_y,             p_spu->i_crop_width, p_spu->i_crop_height,             p_spu->b_force_palette );}/***************************************************************************** * CropCallback: called when the highlight properties are changed ***************************************************************************** * This callback is called from the input thread when we need cropping *****************************************************************************/static int CropCallback( vlc_object_t *p_object, char const *psz_var,                         vlc_value_t oldval, vlc_value_t newval, void *p_data ){    (void)psz_var; (void)oldval; (void)newval;    UpdateSPU( (spu_t *)p_data, p_object );    return VLC_SUCCESS;}/***************************************************************************** * Buffers allocation callbacks for the filters *****************************************************************************/static subpicture_t *sub_new_buffer( filter_t *p_filter ){    filter_owner_sys_t *p_sys = p_filter->p_owner;    subpicture_t *p_subpicture = spu_CreateSubpicture( p_sys->p_spu );    if( p_subpicture ) p_subpicture->i_channel = p_sys->i_channel;    return p_subpicture;}static void sub_del_buffer( filter_t *p_filter, subpicture_t *p_subpic ){    filter_owner_sys_t *p_sys = p_filter->p_owner;    spu_DestroySubpicture( p_sys->p_spu, p_subpic );}static subpicture_t *spu_new_buffer( filter_t *p_filter ){    (void)p_filter;    subpicture_t *p_subpic = (subpicture_t *)malloc(sizeof(subpicture_t));    if( !p_subpic ) return NULL;    memset( p_subpic, 0, sizeof(subpicture_t) );    p_subpic->b_absolute = true;    p_subpic->pf_create_region = __spu_CreateRegion;    p_subpic->pf_make_region = __spu_MakeRegion;    p_subpic->pf_destroy_region = __spu_DestroyRegion;    return p_subpic;}static void spu_del_buffer( filter_t *p_filter, 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;        p_subpic->pf_destroy_region( VLC_OBJECT(p_filter), p_region );    }    free( p_subpic );}static picture_t *spu_new_video_buffer( filter_t *p_filter ){    picture_t *p_picture = malloc( sizeof(picture_t) );    if( !p_picture ) return NULL;    if( vout_AllocatePicture( p_filter, p_picture,                              p_filter->fmt_out.video.i_chroma,                              p_filter->fmt_out.video.i_width,                              p_filter->fmt_out.video.i_height,                              p_filter->fmt_out.video.i_aspect )        != VLC_SUCCESS )    {        free( p_picture );        return NULL;    }    p_picture->pf_release = RegionPictureRelease;    return p_picture;}static void spu_del_video_buffer( filter_t *p_filter, picture_t *p_pic ){    (void)p_filter;    if( p_pic )    {        free( p_pic->p_data_orig );        free( p_pic );    }}static int SubFilterCallback( vlc_object_t *p_object, char const *psz_var,                         vlc_value_t oldval, vlc_value_t newval, void *p_data ){    VLC_UNUSED(p_object); VLC_UNUSED(oldval);    VLC_UNUSED(newval); VLC_UNUSED(psz_var);    spu_t *p_spu = (spu_t *)p_data;    vlc_mutex_lock( &p_spu->subpicture_lock );    filter_chain_Reset( p_spu->p_chain, NULL, NULL );    spu_ParseChain( p_spu );    vlc_mutex_unlock( &p_spu->subpicture_lock );    return VLC_SUCCESS;}static int sub_filter_allocation_init( filter_t *p_filter, void *p_data ){    spu_t *p_spu = (spu_t *)p_data;    p_filter->pf_sub_buffer_new = sub_new_buffer;    p_filter->pf_sub_buffer_del = sub_del_buffer;    filter_owner_sys_t *p_sys = malloc( sizeof(filter_owner_sys_t) );    if( !p_sys ) return VLC_EGENERIC;    p_filter->p_owner = p_sys;    spu_Control( p_spu, SPU_CHANNEL_REGISTER, &p_sys->i_channel );    p_sys->p_spu = p_spu;    return VLC_SUCCESS;}static void sub_filter_allocation_clear( filter_t *p_filter ){    filter_owner_sys_t *p_sys = p_filter->p_owner;    SpuClearChannel( p_sys->p_spu, p_sys->i_channel, true );    free( p_filter->p_owner );}

⌨️ 快捷键说明

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