📄 vout_subpictures.c
字号:
/***************************************************************************** * vout_subpictures.c : subpicture management functions ***************************************************************************** * Copyright (C) 2000-2007 the VideoLAN team * $Id: f171693c1c3b20eb5e38e9b8716ad4a37c066059 $ * * Authors: Vincent Seguin <seguin@via.ecp.fr> * Samuel Hocevar <sam@zoy.org> * Gildas Bazin <gbazin@videolan.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_vout.h>#include <vlc_block.h>#include <vlc_filter.h>#include <vlc_osd.h>#include "../libvlc.h"#include <assert.h>/***************************************************************************** * Local prototypes *****************************************************************************/static void UpdateSPU ( spu_t *, vlc_object_t * );static int CropCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static int spu_vaControlDefault( spu_t *, int, va_list );static subpicture_t *sub_new_buffer( filter_t * );static void sub_del_buffer( filter_t *, subpicture_t * );static subpicture_t *spu_new_buffer( filter_t * );static void spu_del_buffer( filter_t *, subpicture_t * );static picture_t *spu_new_video_buffer( filter_t * );static void spu_del_video_buffer( filter_t *, picture_t * );static int spu_ParseChain( spu_t * );static int SubFilterCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static int sub_filter_allocation_init( filter_t *, void * );static void sub_filter_allocation_clear( filter_t * );struct filter_owner_sys_t{ spu_t *p_spu; int i_channel;};enum { SCALE_DEFAULT, SCALE_TEXT, SCALE_SIZE};static void FilterRelease( filter_t *p_filter ){ if( p_filter->p_module ) module_Unneed( p_filter, p_filter->p_module ); vlc_object_detach( p_filter ); vlc_object_release( p_filter );}/** * Creates the subpicture unit * * \param p_this the parent object which creates the subpicture unit */spu_t *__spu_Create( vlc_object_t *p_this ){ int i_index; spu_t *p_spu = vlc_custom_create( p_this, sizeof( spu_t ), VLC_OBJECT_GENERIC, "subpicture" ); for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++) { p_spu->p_subpicture[i_index].i_status = FREE_SUBPICTURE; } p_spu->p_blend = NULL; p_spu->p_text = NULL; p_spu->p_scale = NULL; p_spu->p_scale_yuvp = NULL; p_spu->pf_control = spu_vaControlDefault; /* Register the default subpicture channel */ p_spu->i_channel = 2; vlc_mutex_init( &p_spu->subpicture_lock ); vlc_object_attach( p_spu, p_this ); p_spu->p_chain = filter_chain_New( p_spu, "sub filter", false, sub_filter_allocation_init, sub_filter_allocation_clear, p_spu ); return p_spu;}/** * Initialise the subpicture unit * * \param p_spu the subpicture unit object */int spu_Init( spu_t *p_spu ){ vlc_value_t val; /* If the user requested a sub margin, we force the position. */ var_Create( p_spu, "sub-margin", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_spu, "sub-margin", &val ); p_spu->i_margin = val.i_int; var_Create( p_spu, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_AddCallback( p_spu, "sub-filter", SubFilterCallback, p_spu ); spu_ParseChain( p_spu ); return VLC_SUCCESS;}int spu_ParseChain( spu_t *p_spu ){ char *psz_parser = var_GetString( p_spu, "sub-filter" ); if( filter_chain_AppendFromString( p_spu->p_chain, psz_parser ) < 0 ) { free( psz_parser ); return VLC_EGENERIC; } free( psz_parser ); return VLC_SUCCESS;}/** * Destroy the subpicture unit * * \param p_this the parent object which destroys the subpicture unit */void spu_Destroy( spu_t *p_spu ){ int i_index; /* Destroy all remaining subpictures */ for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ ) { if( p_spu->p_subpicture[i_index].i_status != FREE_SUBPICTURE ) { spu_DestroySubpicture( p_spu, &p_spu->p_subpicture[i_index] ); } } if( p_spu->p_blend ) FilterRelease( p_spu->p_blend ); if( p_spu->p_text ) FilterRelease( p_spu->p_text ); if( p_spu->p_scale_yuvp ) FilterRelease( p_spu->p_scale_yuvp ); if( p_spu->p_scale ) FilterRelease( p_spu->p_scale ); filter_chain_Delete( p_spu->p_chain ); vlc_mutex_destroy( &p_spu->subpicture_lock ); vlc_object_release( p_spu );}/** * Attach/Detach the SPU from any input * * \param p_this the object in which to destroy the subpicture unit * \param b_attach to select attach or detach */void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, bool b_attach ){ vlc_object_t *p_input; p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT ); if( !p_input ) return; if( b_attach ) { UpdateSPU( p_spu, VLC_OBJECT(p_input) ); var_AddCallback( p_input, "highlight", CropCallback, p_spu ); vlc_object_release( p_input ); } else { /* Delete callback */ var_DelCallback( p_input, "highlight", CropCallback, p_spu ); vlc_object_release( p_input ); }}/** * Create a subpicture region * * \param p_this vlc_object_t * \param p_fmt the format that this subpicture region should have */static void RegionPictureRelease( picture_t *p_pic ){ free( p_pic->p_data_orig ); /* We use pf_release nullity to know if the picture has already been released. */ p_pic->pf_release = NULL;}subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this, video_format_t *p_fmt ){ subpicture_region_t *p_region = malloc( sizeof(subpicture_region_t) ); if( !p_region ) return NULL; memset( p_region, 0, sizeof(subpicture_region_t) ); p_region->i_alpha = 0xff; p_region->p_next = NULL; p_region->p_cache = NULL; p_region->fmt = *p_fmt; p_region->psz_text = NULL; p_region->p_style = NULL; if( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') ) p_fmt->p_palette = p_region->fmt.p_palette = malloc( sizeof(video_palette_t) ); else p_fmt->p_palette = p_region->fmt.p_palette = NULL; p_region->picture.p_data_orig = NULL; if( p_fmt->i_chroma == VLC_FOURCC('T','E','X','T') ) return p_region; vout_AllocatePicture( p_this, &p_region->picture, p_fmt->i_chroma, p_fmt->i_width, p_fmt->i_height, p_fmt->i_aspect ); if( !p_region->picture.i_planes ) { free( p_region ); free( p_fmt->p_palette ); return NULL; } p_region->picture.pf_release = RegionPictureRelease; return p_region;}/** * Make a subpicture region from an existing picture_t * * \param p_this vlc_object_t * \param p_fmt the format that this subpicture region should have * \param p_pic a pointer to the picture creating the region (not freed) */subpicture_region_t *__spu_MakeRegion( vlc_object_t *p_this, video_format_t *p_fmt, picture_t *p_pic ){ subpicture_region_t *p_region = malloc( sizeof(subpicture_region_t) ); (void)p_this; if( !p_region ) return NULL; memset( p_region, 0, sizeof(subpicture_region_t) ); p_region->i_alpha = 0xff; p_region->p_next = 0; p_region->p_cache = 0; p_region->fmt = *p_fmt; p_region->psz_text = 0; p_region->p_style = NULL; if( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') ) p_fmt->p_palette = p_region->fmt.p_palette = malloc( sizeof(video_palette_t) ); else p_fmt->p_palette = p_region->fmt.p_palette = NULL; memcpy( &p_region->picture, p_pic, sizeof(picture_t) ); p_region->picture.pf_release = RegionPictureRelease; return p_region;}/** * Destroy a subpicture region * * \param p_this vlc_object_t * \param p_region the subpicture region to destroy */void __spu_DestroyRegion( vlc_object_t *p_this, subpicture_region_t *p_region ){ if( !p_region ) return; if( p_region->picture.pf_release ) p_region->picture.pf_release( &p_region->picture ); free( p_region->fmt.p_palette ); if( p_region->p_cache ) __spu_DestroyRegion( p_this, p_region->p_cache ); free( p_region->psz_text ); free( p_region->psz_html ); //free( p_region->p_style ); FIXME --fenrir plugin does not allocate the memory for it. I think it might lead to segfault, video renderer can live longer than the decoder free( p_region );}/** * Display a subpicture * * Remove the reservation flag of a subpicture, which will cause it to be * ready for display. * \param p_spu the subpicture unit object * \param p_subpic the subpicture to display */void spu_DisplaySubpicture( spu_t *p_spu, subpicture_t *p_subpic ){ /* Check if status is valid */ if( p_subpic->i_status != RESERVED_SUBPICTURE ) { msg_Err( p_spu, "subpicture %p has invalid status #%d", p_subpic, p_subpic->i_status ); } /* Remove reservation flag */ p_subpic->i_status = READY_SUBPICTURE; if( p_subpic->i_channel == DEFAULT_CHAN ) { p_subpic->i_channel = 0xFFFF; spu_Control( p_spu, SPU_CHANNEL_CLEAR, DEFAULT_CHAN ); p_subpic->i_channel = DEFAULT_CHAN; }}/** * Allocate a subpicture in the spu heap. * * This function create a reserved subpicture in the spu heap. * A null pointer is returned if the function fails. This method provides an * already allocated zone of memory in the spu data fields. It needs locking * since several pictures can be created by several producers threads. * \param p_spu the subpicture unit in which to create the subpicture * \return NULL on error, a reserved subpicture otherwise */subpicture_t *spu_CreateSubpicture( spu_t *p_spu ){ int i_subpic; /* subpicture index */ subpicture_t * p_subpic = NULL; /* first free subpicture */ /* Get lock */ vlc_mutex_lock( &p_spu->subpicture_lock ); /* * Look for an empty place */ p_subpic = NULL; for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ ) { if( p_spu->p_subpicture[i_subpic].i_status == FREE_SUBPICTURE ) { /* Subpicture is empty and ready for allocation */ p_subpic = &p_spu->p_subpicture[i_subpic]; p_spu->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -