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

📄 vout_subpictures.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 3 页
字号:
                int i_crop_y = p_spu->i_crop_y * i_scale_height / 1000;                int i_crop_width = p_spu->i_crop_width * i_scale_width / 1000;                int i_crop_height = p_spu->i_crop_height * i_scale_height/1000;                /* Find the intersection */                if( i_crop_x + i_crop_width <= i_x_offset ||                    i_x_offset + (int)p_fmt->i_visible_width < i_crop_x ||                    i_crop_y + i_crop_height <= i_y_offset ||                    i_y_offset + (int)p_fmt->i_visible_height < i_crop_y )                {                    /* No intersection */                    p_fmt->i_visible_width = p_fmt->i_visible_height = 0;                }                else                {                    int i_x, i_y, i_x_end, i_y_end;                    i_x = __MAX( i_crop_x, i_x_offset );                    i_y = __MAX( i_crop_y, i_y_offset );                    i_x_end = __MIN( i_crop_x + i_crop_width,                                   i_x_offset + (int)p_fmt->i_visible_width );                    i_y_end = __MIN( i_crop_y + i_crop_height,                                   i_y_offset + (int)p_fmt->i_visible_height );                    p_fmt->i_x_offset = i_x - i_x_offset;                    p_fmt->i_y_offset = i_y - i_y_offset;                    p_fmt->i_visible_width = i_x_end - i_x;                    p_fmt->i_visible_height = i_y_end - i_y;                    i_x_offset = i_x;                    i_y_offset = i_y;                }            }            /* Update the output picture size */            p_spu->p_blend->fmt_out.video.i_width =                p_spu->p_blend->fmt_out.video.i_visible_width =                    p_fmt->i_width;            p_spu->p_blend->fmt_out.video.i_height =                p_spu->p_blend->fmt_out.video.i_visible_height =                    p_fmt->i_height;            if( p_subpic->b_fade )            {                mtime_t i_fade_start = ( p_subpic->i_stop +                                         p_subpic->i_start ) / 2;                mtime_t i_now = mdate();                if( i_now >= i_fade_start && p_subpic->i_stop > i_fade_start )                {                    i_fade_alpha = 255 * ( p_subpic->i_stop - i_now ) /                                   ( p_subpic->i_stop - i_fade_start );                }            }            p_spu->p_blend->pf_video_blend( p_spu->p_blend, p_pic_dst,                p_pic_src, &p_region->picture, i_x_offset, i_y_offset,                i_fade_alpha * p_subpic->i_alpha / 255 );            p_region = p_region->p_next;        }        p_subpic = p_subpic->p_next;    }    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 ){    int i_index, i_channel;    subpicture_t *p_subpic = NULL;    subpicture_t *p_ephemer;    mtime_t      ephemer_date;    /* Run subpicture filters */    for( i_index = 0; i_index < p_spu->i_filter; i_index++ )    {        subpicture_t *p_subpic_filter;        p_subpic_filter = p_spu->pp_filter[i_index]->            pf_sub_filter( p_spu->pp_filter[i_index], display_date );        if( p_subpic_filter )        {            spu_DisplaySubpicture( p_spu, p_subpic_filter );        }    }    /* 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 ) )            {                /* 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 ){    int          i_subpic;                               /* subpicture index */    subpicture_t *p_subpic = NULL;                  /* first free subpicture */    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;        }    }    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++;        msg_Dbg( p_spu, "Registering subpicture channel, ID: %i",                 p_spu->i_channel - 1 );        break;    case SPU_CHANNEL_CLEAR:        i = (int)va_arg( args, int );        SpuClearChannel( p_spu, i );        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;    p_spu->b_force_palette = VLC_FALSE;    p_spu->b_force_crop = VLC_FALSE;    if( var_Get( p_object, "highlight", &val ) || !val.b_bool ) return;    p_spu->b_force_crop = VLC_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 = VLC_TRUE;    }    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 ){    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 ){    subpicture_t *p_subpic = (subpicture_t *)malloc(sizeof(subpicture_t));    memset( p_subpic, 0, sizeof(subpicture_t) );    p_subpic->b_absolute = VLC_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( 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 ){    if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );    if( p_pic ) free( p_pic );}

⌨️ 快捷键说明

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