📄 vout_subpictures.c
字号:
/***************************************************************************** * vout_subpictures.c : subpicture management functions ***************************************************************************** * Copyright (C) 2000-2005 VideoLAN * $Id: vout_subpictures.c 11305 2005-06-05 17:05:20Z gbazin $ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h> /* free() */#include <stdio.h> /* sprintf() */#include <string.h> /* strerror() */#include <vlc/vlc.h>#include "vlc_block.h"#include "vlc_video.h"#include "video_output.h"#include "vlc_spu.h"#include "vlc_filter.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 * );struct filter_owner_sys_t{ spu_t *p_spu; int i_channel;};/** * 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_object_create( p_this, VLC_OBJECT_SPU ); 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->i_filter = 0; p_spu->pf_control = spu_vaControlDefault; /* Register the default subpicture channel */ p_spu->i_channel = 2; vlc_mutex_init( p_this, &p_spu->subpicture_lock ); vlc_object_attach( p_spu, p_this ); return p_spu;}/** * Initialise the subpicture unit * * \param p_spu the subpicture unit object */int spu_Init( spu_t *p_spu ){ char *psz_filter, *psz_filter_orig; 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_Get( p_spu, "sub-filter", &val ); psz_filter = psz_filter_orig = val.psz_string; while( psz_filter && *psz_filter ) { char *psz_parser = strchr( psz_filter, ':' ); if( psz_parser ) *psz_parser++ = 0; p_spu->pp_filter[p_spu->i_filter] = vlc_object_create( p_spu, VLC_OBJECT_FILTER ); vlc_object_attach( p_spu->pp_filter[p_spu->i_filter], p_spu ); p_spu->pp_filter[p_spu->i_filter]->pf_sub_buffer_new = sub_new_buffer; p_spu->pp_filter[p_spu->i_filter]->pf_sub_buffer_del = sub_del_buffer; p_spu->pp_filter[p_spu->i_filter]->p_module = module_Need( p_spu->pp_filter[p_spu->i_filter], "sub filter", psz_filter, 0 ); if( p_spu->pp_filter[p_spu->i_filter]->p_module ) { filter_owner_sys_t *p_sys = malloc( sizeof(filter_owner_sys_t) ); p_spu->pp_filter[p_spu->i_filter]->p_owner = p_sys; spu_Control( p_spu, SPU_CHANNEL_REGISTER, &p_sys->i_channel ); p_sys->p_spu = p_spu; p_spu->i_filter++; } else { msg_Dbg( p_spu, "no sub filter found" ); vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] ); vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] ); } if( p_spu->i_filter >= 10 ) { msg_Dbg( p_spu, "can't add anymore filters" ); } psz_filter = psz_parser; } if( psz_filter_orig ) free( psz_filter_orig ); return VLC_EGENERIC;}/** * 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; vlc_object_detach( p_spu ); /* 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 ) { if( p_spu->p_blend->p_module ) module_Unneed( p_spu->p_blend, p_spu->p_blend->p_module ); vlc_object_detach( p_spu->p_blend ); vlc_object_destroy( p_spu->p_blend ); } if( p_spu->p_text ) { if( p_spu->p_text->p_module ) module_Unneed( p_spu->p_text, p_spu->p_text->p_module ); vlc_object_detach( p_spu->p_text ); vlc_object_destroy( p_spu->p_text ); } if( p_spu->p_scale ) { if( p_spu->p_scale->p_module ) module_Unneed( p_spu->p_scale, p_spu->p_scale->p_module ); vlc_object_detach( p_spu->p_scale ); vlc_object_destroy( p_spu->p_scale ); } while( p_spu->i_filter-- ) { module_Unneed( p_spu->pp_filter[p_spu->i_filter], p_spu->pp_filter[p_spu->i_filter]->p_module ); free( p_spu->pp_filter[p_spu->i_filter]->p_owner ); vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] ); vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] ); } vlc_mutex_destroy( &p_spu->subpicture_lock ); vlc_object_destroy( 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, vlc_bool_t 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 ){ if( p_pic->p_data_orig ) free( p_pic->p_data_orig );}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) ); memset( p_region, 0, sizeof(subpicture_region_t) ); p_region->p_next = 0; p_region->p_cache = 0; p_region->fmt = *p_fmt; p_region->psz_text = 0; p_region->i_text_color = 0xFFFFFF; 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 = 0; 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) ); memset( p_region, 0, sizeof(subpicture_region_t) ); p_region->p_next = 0; p_region->p_cache = 0; p_region->fmt = *p_fmt; p_region->psz_text = 0; p_region->i_text_color = 0xFFFFFF; 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 ); if( p_region->fmt.p_palette ) free( p_region->fmt.p_palette ); if( p_region->psz_text ) free( p_region->psz_text ); if( p_region->p_cache ) __spu_DestroyRegion( p_this, p_region->p_cache ); 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -