Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

logo.c

00001 /*****************************************************************************
00002  * logo.c : logo video plugin for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2003-2004 the VideoLAN team
00005  * $Id: logo.c 12968 2005-10-25 19:24:21Z gbazin $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *          Simon Latapie <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <stdlib.h>                                      /* malloc(), free() */
00029 #include <string.h>
00030 
00031 #include <vlc/vlc.h>
00032 #include <vlc/vout.h>
00033 
00034 #include "vlc_filter.h"
00035 #include "filter_common.h"
00036 #include "vlc_image.h"
00037 #include "vlc_osd.h"
00038 
00039 #ifdef LoadImage
00040 #   undef LoadImage
00041 #endif
00042 
00043 /*****************************************************************************
00044  * Local prototypes
00045  *****************************************************************************/
00046 static int  Create    ( vlc_object_t * );
00047 static void Destroy   ( vlc_object_t * );
00048 
00049 static int  Init      ( vout_thread_t * );
00050 static void End       ( vout_thread_t * );
00051 static void Render    ( vout_thread_t *, picture_t * );
00052 
00053 static int  SendEvents( vlc_object_t *, char const *,
00054                         vlc_value_t, vlc_value_t, void * );
00055 static int  MouseEvent( vlc_object_t *, char const *,
00056                         vlc_value_t , vlc_value_t , void * );
00057 static int  Control   ( vout_thread_t *, int, va_list );
00058 
00059 static int  CreateFilter ( vlc_object_t * );
00060 static void DestroyFilter( vlc_object_t * );
00061 
00062 static int LogoCallback( vlc_object_t *, char const *,
00063                          vlc_value_t, vlc_value_t, void * );
00064 
00065 /*****************************************************************************
00066  * Module descriptor
00067  *****************************************************************************/
00068 #define FILE_TEXT N_("Logo filename")
00069 #define FILE_LONGTEXT N_("Full path of the PNG file to use.")
00070 #define POSX_TEXT N_("X coordinate of the logo")
00071 #define POSX_LONGTEXT N_("You can move the logo by left-clicking on it." )
00072 #define POSY_TEXT N_("Y coordinate of the logo")
00073 #define POSY_LONGTEXT N_("You can move the logo by left-clicking on it." )
00074 #define TRANS_TEXT N_("Transparency of the logo")
00075 #define TRANS_LONGTEXT N_("You can set the logo transparency value here " \
00076   "(from 0 for full transparency to 255 for full opacity)." )
00077 #define POS_TEXT N_("Logo position")
00078 #define POS_LONGTEXT N_( \
00079   "You can enforce the logo position on the video " \
00080   "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
00081   "also use combinations of these values).")
00082 
00083 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
00084 static char *ppsz_pos_descriptions[] =
00085 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
00086   N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
00087 
00088 vlc_module_begin();
00089     set_description( _("Logo video filter") );
00090     set_capability( "video filter", 0 );
00091     set_shortname( N_("Logo overlay") );
00092     set_category( CAT_VIDEO );
00093     set_subcategory( SUBCAT_VIDEO_SUBPIC );
00094     add_shortcut( "logo" );
00095     set_callbacks( Create, Destroy );
00096 
00097     add_file( "logo-file", NULL, NULL, FILE_TEXT, FILE_LONGTEXT, VLC_FALSE );
00098     add_integer( "logo-x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_TRUE );
00099     add_integer( "logo-y", 0, NULL, POSY_TEXT, POSY_LONGTEXT, VLC_TRUE );
00100     add_integer_with_range( "logo-transparency", 255, 0, 255, NULL,
00101         TRANS_TEXT, TRANS_LONGTEXT, VLC_FALSE );
00102     add_integer( "logo-position", 6, NULL, POS_TEXT, POS_LONGTEXT, VLC_FALSE );
00103         change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
00104 
00105     /* subpicture filter submodule */
00106     add_submodule();
00107     set_capability( "sub filter", 0 );
00108     set_callbacks( CreateFilter, DestroyFilter );
00109     set_description( _("Logo sub filter") );
00110     add_shortcut( "logo" );
00111 vlc_module_end();
00112 
00113 /*****************************************************************************
00114  * LoadImage: loads the logo image into memory
00115  *****************************************************************************/
00116 static picture_t *LoadImage( vlc_object_t *p_this, char *psz_filename )
00117 {
00118     picture_t *p_pic;
00119     image_handler_t *p_image;
00120     video_format_t fmt_in = {0}, fmt_out = {0};
00121 
00122     fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
00123     p_image = image_HandlerCreate( p_this );
00124     p_pic = image_ReadUrl( p_image, psz_filename, &fmt_in, &fmt_out );
00125     image_HandlerDelete( p_image );
00126 
00127     return p_pic;
00128 }
00129 
00130 /*****************************************************************************
00131  * vout_sys_t: logo video output method descriptor
00132  *****************************************************************************
00133  * This structure is part of the video output thread descriptor.
00134  * It describes the Invert specific properties of an output thread.
00135  *****************************************************************************/
00136 struct vout_sys_t
00137 {
00138     vout_thread_t *p_vout;
00139 
00140     filter_t *p_blend;
00141     picture_t *p_pic;
00142 
00143     int i_width, i_height;
00144     int pos, posx, posy;
00145     char *psz_filename;
00146     int i_trans;
00147 };
00148 
00149 /*****************************************************************************
00150  * Create: allocates logo video thread output method
00151  *****************************************************************************/
00152 static int Create( vlc_object_t *p_this )
00153 {
00154     vout_thread_t *p_vout = (vout_thread_t *)p_this;
00155     vout_sys_t *p_sys;
00156     vlc_value_t val;
00157 
00158     /* Allocate structure */
00159     p_sys = p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00160     if( p_sys == NULL )
00161     {
00162         msg_Err( p_vout, "out of memory" );
00163         return VLC_ENOMEM;
00164     }
00165 
00166     p_vout->pf_init = Init;
00167     p_vout->pf_end = End;
00168     p_vout->pf_manage = NULL;
00169     p_vout->pf_render = Render;
00170     p_vout->pf_display = NULL;
00171     p_vout->pf_control = Control;
00172 
00173     p_sys->psz_filename = var_CreateGetString( p_this , "logo-file" );
00174     if( !p_sys->psz_filename || !*p_sys->psz_filename )
00175     {
00176         msg_Err( p_this, "logo file not specified" );
00177         return 0;
00178     }
00179 
00180     var_Create( p_this, "logo-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00181     var_Get( p_this, "logo-position", &val );
00182     p_sys->pos = val.i_int;
00183     var_Create( p_this, "logo-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00184     var_Get( p_this, "logo-x", &val );
00185     p_sys->posx = val.i_int;
00186     var_Create( p_this, "logo-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00187     var_Get( p_this, "logo-y", &val );
00188     p_sys->posy = val.i_int;
00189     var_Create(p_this, "logo-transparency", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT);
00190     var_Get( p_this, "logo-transparency", &val );
00191     p_sys->i_trans = __MAX( __MIN( val.i_int, 255 ), 0 );
00192 
00193     p_sys->p_pic = LoadImage( p_this, p_sys->psz_filename );
00194     if( !p_sys->p_pic )
00195     {
00196         free( p_sys );
00197         return VLC_EGENERIC;
00198     }
00199 
00200     p_sys->i_width = p_sys->p_pic->p[Y_PLANE].i_visible_pitch;
00201     p_sys->i_height = p_sys->p_pic->p[Y_PLANE].i_visible_lines;
00202 
00203     return VLC_SUCCESS;
00204 }
00205 
00206 /*****************************************************************************
00207  * Init: initialize logo video thread output method
00208  *****************************************************************************/
00209 static int Init( vout_thread_t *p_vout )
00210 {
00211     vout_sys_t *p_sys = p_vout->p_sys;
00212     picture_t *p_pic;
00213     int i_index;
00214     video_format_t fmt = {0};
00215 
00216     I_OUTPUTPICTURES = 0;
00217 
00218     /* Initialize the output structure */
00219     p_vout->output.i_chroma = p_vout->render.i_chroma;
00220     p_vout->output.i_width  = p_vout->render.i_width;
00221     p_vout->output.i_height = p_vout->render.i_height;
00222     p_vout->output.i_aspect = p_vout->render.i_aspect;
00223     p_vout->fmt_out = p_vout->fmt_in;
00224     fmt = p_vout->fmt_out;
00225 
00226     /* Load the video blending filter */
00227     p_sys->p_blend = vlc_object_create( p_vout, sizeof(filter_t) );
00228     vlc_object_attach( p_sys->p_blend, p_vout );
00229     p_sys->p_blend->fmt_out.video.i_x_offset =
00230         p_sys->p_blend->fmt_out.video.i_y_offset = 0;
00231     p_sys->p_blend->fmt_in.video.i_x_offset =
00232         p_sys->p_blend->fmt_in.video.i_y_offset = 0;
00233     p_sys->p_blend->fmt_out.video.i_aspect = p_vout->render.i_aspect;
00234     p_sys->p_blend->fmt_out.video.i_chroma = p_vout->output.i_chroma;
00235     p_sys->p_blend->fmt_in.video.i_chroma = VLC_FOURCC('Y','U','V','A');
00236     p_sys->p_blend->fmt_in.video.i_aspect = VOUT_ASPECT_FACTOR;
00237     p_sys->p_blend->fmt_in.video.i_width =
00238         p_sys->p_blend->fmt_in.video.i_visible_width =
00239             p_sys->p_pic->p[Y_PLANE].i_visible_pitch;
00240     p_sys->p_blend->fmt_in.video.i_height =
00241         p_sys->p_blend->fmt_in.video.i_visible_height =
00242             p_sys->p_pic->p[Y_PLANE].i_visible_lines;
00243     p_sys->p_blend->fmt_out.video.i_width =
00244         p_sys->p_blend->fmt_out.video.i_visible_width =
00245            p_vout->output.i_width;
00246     p_sys->p_blend->fmt_out.video.i_height =
00247         p_sys->p_blend->fmt_out.video.i_visible_height =
00248             p_vout->output.i_height;
00249 
00250     p_sys->p_blend->p_module =
00251         module_Need( p_sys->p_blend, "video blending", 0, 0 );
00252     if( !p_sys->p_blend->p_module )
00253     {
00254         msg_Err( p_vout, "can't open blending filter, aborting" );
00255         vlc_object_detach( p_sys->p_blend );
00256         vlc_object_destroy( p_sys->p_blend );
00257         return VLC_EGENERIC;
00258     }
00259 
00260     if( p_sys->posx < 0 || p_sys->posy < 0 )
00261     {
00262         p_sys->posx = 0; p_sys->posy = 0;
00263 
00264         if( p_sys->pos & SUBPICTURE_ALIGN_BOTTOM )
00265         {
00266             p_sys->posy = p_vout->render.i_height - p_sys->i_height;
00267         }
00268         else if ( !(p_sys->pos & SUBPICTURE_ALIGN_TOP) )
00269         {
00270             p_sys->posy = p_vout->render.i_height / 2 - p_sys->i_height / 2;
00271         }
00272 
00273         if( p_sys->pos & SUBPICTURE_ALIGN_RIGHT )
00274         {
00275             p_sys->posx = p_vout->render.i_width - p_sys->i_width;
00276         }
00277         else if ( !(p_sys->pos & SUBPICTURE_ALIGN_LEFT) )
00278         {
00279             p_sys->posx = p_vout->render.i_width / 2 - p_sys->i_width / 2;
00280         }
00281     }
00282 
00283     /* Try to open the real video output */
00284     msg_Dbg( p_vout, "spawning the real video output" );
00285 
00286     p_sys->p_vout = vout_Create( p_vout, &fmt );
00287 
00288     /* Everything failed */
00289     if( p_sys->p_vout == NULL )
00290     {
00291         msg_Err( p_vout, "can't open vout, aborting" );
00292         return VLC_EGENERIC;
00293     }
00294 
00295     var_AddCallback( p_sys->p_vout, "mouse-x", MouseEvent, p_vout);
00296     var_AddCallback( p_sys->p_vout, "mouse-y", MouseEvent, p_vout);
00297 
00298     ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
00299     ADD_CALLBACKS( p_sys->p_vout, SendEvents );
00300     ADD_PARENT_CALLBACKS( SendEventsToChild );
00301 
00302     return VLC_SUCCESS;
00303 }
00304 
00305 /*****************************************************************************
00306  * End: terminate logo video thread output method
00307  *****************************************************************************/
00308 static void End( vout_thread_t *p_vout )
00309 {
00310     vout_sys_t *p_sys = p_vout->p_sys;
00311     int i_index;
00312 
00313     /* Free the fake output buffers we allocated */
00314     for( i_index = I_OUTPUTPICTURES ; i_index ; )
00315     {
00316         i_index--;
00317         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
00318     }
00319 
00320     var_DelCallback( p_sys->p_vout, "mouse-x", MouseEvent, p_vout);
00321     var_DelCallback( p_sys->p_vout, "mouse-y", MouseEvent, p_vout);
00322 
00323     if( p_sys->p_vout )
00324     {
00325         DEL_CALLBACKS( p_sys->p_vout, SendEvents );
00326         vlc_object_detach( p_sys->p_vout );
00327         vout_Destroy( p_sys->p_vout );
00328     }
00329 
00330     if( p_sys->p_blend->p_module )
00331         module_Unneed( p_sys->p_blend, p_sys->p_blend->p_module );
00332     vlc_object_detach( p_sys->p_blend );
00333     vlc_object_destroy( p_sys->p_blend );
00334 }
00335 
00336 /*****************************************************************************
00337  * Destroy: destroy logo video thread output method
00338  *****************************************************************************/
00339 static void Destroy( vlc_object_t *p_this )
00340 {
00341     vout_thread_t *p_vout = (vout_thread_t *)p_this;
00342     vout_sys_t *p_sys = p_vout->p_sys;
00343 
00344     DEL_PARENT_CALLBACKS( SendEventsToChild );
00345 
00346     if( p_sys->p_pic ) p_sys->p_pic->pf_release( p_sys->p_pic );
00347     free( p_sys );
00348 }
00349 
00350 /*****************************************************************************
00351  * Render: render the logo onto the video
00352  *****************************************************************************/
00353 static void Render( vout_thread_t *p_vout, picture_t *p_pic )
00354 {
00355     vout_sys_t *p_sys = p_vout->p_sys;
00356     picture_t *p_outpic;
00357 
00358     /* This is a new frame. Get a structure from the video_output. */
00359     while( !(p_outpic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 )) )
00360     {
00361         if( p_vout->b_die || p_vout->b_error ) return;
00362         msleep( VOUT_OUTMEM_SLEEP );
00363     }
00364 
00365     vout_CopyPicture( p_vout, p_outpic, p_pic );
00366     vout_DatePicture( p_sys->p_vout, p_outpic, p_pic->date );
00367 
00368     p_sys->p_blend->pf_video_blend( p_sys->p_blend, p_outpic, p_outpic,
00369                                     p_sys->p_pic, p_sys->posx, p_sys->posy,
00370                                     p_sys->i_trans );
00371 
00372     vout_DisplayPicture( p_sys->p_vout, p_outpic );
00373 }
00374 
00375 /*****************************************************************************
00376  * SendEvents: forward mouse and keyboard events to the parent p_vout
00377  *****************************************************************************/
00378 static int SendEvents( vlc_object_t *p_this, char const *psz_var,
00379                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
00380 {
00381     var_Set( (vlc_object_t *)p_data, psz_var, newval );
00382     return VLC_SUCCESS;
00383 }
00384 
00385 /*****************************************************************************
00386  * MouseEvent: callback for mouse events
00387  *****************************************************************************/
00388 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
00389                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
00390 {
00391     vout_thread_t *p_vout = (vout_thread_t*)p_data;
00392     vout_sys_t *p_sys = p_vout->p_sys;
00393     vlc_value_t valb;
00394     int i_delta;
00395 
00396     var_Get( p_vout->p_sys->p_vout, "mouse-button-down", &valb );
00397 
00398     i_delta = newval.i_int - oldval.i_int;
00399 
00400     if( (valb.i_int & 0x1) == 0 )
00401     {
00402         return VLC_SUCCESS;
00403     }
00404 
00405     if( psz_var[6] == 'x' )
00406     {
00407         vlc_value_t valy;
00408         var_Get( p_vout->p_sys->p_vout, "mouse-y", &valy );
00409         if( newval.i_int >= (int)p_sys->posx &&
00410             valy.i_int >= (int)p_sys->posy &&
00411             newval.i_int <= (int)(p_sys->posx + p_sys->i_width) &&
00412             valy.i_int <= (int)(p_sys->posy + p_sys->i_height) )
00413         {
00414             p_sys->posx = __MIN( __MAX( p_sys->posx + i_delta, 0 ),
00415                           p_vout->output.i_width - p_sys->i_width );
00416         }
00417     }
00418     else if( psz_var[6] == 'y' )
00419     {
00420         vlc_value_t valx;
00421         var_Get( p_vout->p_sys->p_vout, "mouse-x", &valx );
00422         if( valx.i_int >= (int)p_sys->posx &&
00423             newval.i_int >= (int)p_sys->posy &&
00424             valx.i_int <= (int)(p_sys->posx + p_sys->i_width) &&
00425             newval.i_int <= (int)(p_sys->posy + p_sys->i_height) )
00426         {
00427             p_sys->posy = __MIN( __MAX( p_sys->posy + i_delta, 0 ),
00428                           p_vout->output.i_height - p_sys->i_height );
00429         }
00430     }
00431 
00432     return VLC_SUCCESS;
00433 }
00434 
00435 /*****************************************************************************
00436  * Control: control facility for the vout (forwards to child vout)
00437  *****************************************************************************/
00438 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
00439 {
00440     return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
00441 }
00442 
00443 /*****************************************************************************
00444  * SendEventsToChild: forward events to the child/children vout
00445  *****************************************************************************/
00446 static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
00447                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
00448 {
00449     vout_thread_t *p_vout = (vout_thread_t *)p_this;
00450     var_Set( p_vout->p_sys->p_vout, psz_var, newval );
00451     return VLC_SUCCESS;
00452 }
00453 
00454 /*****************************************************************************
00455  * filter_sys_t: logo filter descriptor
00456  *****************************************************************************/
00457 struct filter_sys_t
00458 {
00459     picture_t *p_pic;
00460 
00461     int i_width, i_height;
00462     int pos, posx, posy;
00463     char *psz_filename;
00464     int i_trans;
00465 
00466     vlc_bool_t b_absolute;
00467 
00468     mtime_t i_last_date;
00469 
00470     /* On the fly control variable */
00471     vlc_bool_t b_need_update;
00472     vlc_bool_t b_new_image;
00473 };
00474 
00475 static subpicture_t *Filter( filter_t *, mtime_t );
00476 
00477 /*****************************************************************************
00478  * CreateFilter: allocates logo video filter
00479  *****************************************************************************/
00480 static int CreateFilter( vlc_object_t *p_this )
00481 {
00482     filter_t *p_filter = (filter_t *)p_this;
00483     filter_sys_t *p_sys;
00484     vlc_object_t *p_input;
00485 
00486     /* Allocate structure */
00487     p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
00488     if( p_sys == NULL )
00489     {
00490         msg_Err( p_filter, "out of memory" );
00491         return VLC_ENOMEM;
00492     }
00493 
00494     /* Hook used for callback variables */
00495     p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
00496     if( !p_input )
00497     {
00498         free( p_sys );
00499         return VLC_ENOOBJ;
00500     }
00501 
00502     p_sys->psz_filename =
00503         var_CreateGetString( p_input->p_libvlc , "logo-file" );
00504     if( !p_sys->psz_filename || !*p_sys->psz_filename )
00505     {
00506         msg_Err( p_this, "logo file not specified" );
00507         vlc_object_release( p_input );
00508         if( p_sys->psz_filename ) free( p_sys->psz_filename );
00509         free( p_sys );
00510         return VLC_EGENERIC;
00511     }
00512 
00513     p_sys->posx = var_CreateGetInteger( p_input->p_libvlc , "logo-x" );
00514     p_sys->posy = var_CreateGetInteger( p_input->p_libvlc , "logo-y" );
00515     p_sys->pos = var_CreateGetInteger( p_input->p_libvlc , "logo-position" );
00516     p_sys->i_trans =
00517         var_CreateGetInteger( p_input->p_libvlc, "logo-transparency");
00518     p_sys->i_trans = __MAX( __MIN( p_sys->i_trans, 255 ), 0 );
00519 
00520     var_AddCallback( p_input->p_libvlc, "logo-file", LogoCallback, p_sys );
00521     var_AddCallback( p_input->p_libvlc, "logo-x", LogoCallback, p_sys );
00522     var_AddCallback( p_input->p_libvlc, "logo-y", LogoCallback, p_sys );
00523     var_AddCallback( p_input->p_libvlc, "logo-position", LogoCallback, p_sys );
00524     var_AddCallback( p_input->p_libvlc, "logo-transparency", LogoCallback, p_sys );
00525     vlc_object_release( p_input );
00526 
00527     p_sys->p_pic = LoadImage( p_this, p_sys->psz_filename );
00528     if( !p_sys->p_pic )
00529     {
00530         free( p_sys );
00531         msg_Err( p_this, "couldn't load logo file" );
00532         return VLC_EGENERIC;
00533     }
00534 
00535     /* Misc init */
00536     p_filter->pf_sub_filter = Filter;
00537     p_sys->i_width = p_sys->p_pic->p[Y_PLANE].i_visible_pitch;
00538     p_sys->i_height = p_sys->p_pic->p[Y_PLANE].i_visible_lines;
00539     p_sys->b_need_update = VLC_TRUE;
00540     p_sys->b_new_image = VLC_FALSE;
00541     p_sys->i_last_date = 0;
00542 
00543     return VLC_SUCCESS;
00544 }
00545 
00546 /*****************************************************************************
00547  * DestroyFilter: destroy logo video filter
00548  *****************************************************************************/
00549 static void DestroyFilter( vlc_object_t *p_this )
00550 {
00551     filter_t *p_filter = (filter_t *)p_this;
00552     filter_sys_t *p_sys = p_filter->p_sys;
00553     vlc_object_t *p_input;
00554 
00555     if( p_sys->p_pic ) p_sys->p_pic->pf_release( p_sys->p_pic );
00556     if( p_sys->psz_filename ) free( p_sys->psz_filename );
00557     free( p_sys );
00558 
00559     /* Delete the logo variables from INPUT */
00560     p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
00561     if( !p_input ) return;
00562 
00563     var_Destroy( p_input->p_libvlc , "logo-file" );
00564     var_Destroy( p_input->p_libvlc , "logo-x" );
00565     var_Destroy( p_input->p_libvlc , "logo-y" );
00566     var_Destroy( p_input->p_libvlc , "logo-position" );
00567     var_Destroy( p_input->p_libvlc , "logo-transparency" );
00568     vlc_object_release( p_input );
00569 }
00570 
00571 /*****************************************************************************
00572  * Filter: the whole thing
00573  *****************************************************************************
00574  * This function outputs subpictures at regular time intervals.
00575  *****************************************************************************/
00576 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
00577 {
00578     filter_sys_t *p_sys = p_filter->p_sys;
00579     subpicture_t *p_spu;
00580     subpicture_region_t *p_region;
00581     video_format_t fmt;
00582 
00583     if( !p_sys->b_need_update && p_sys->i_last_date +5000000 > date ) return 0;
00584 
00585     if( p_sys->b_new_image )
00586     {
00587         if( p_sys->p_pic ) p_sys->p_pic->pf_release( p_sys->p_pic );
00588 
00589         p_sys->p_pic = LoadImage( VLC_OBJECT(p_filter), p_sys->psz_filename );
00590         if( p_sys->p_pic )
00591         {
00592             p_sys->i_width = p_sys->p_pic->p[Y_PLANE].i_visible_pitch;
00593             p_sys->i_height = p_sys->p_pic->p[Y_PLANE].i_visible_lines;
00594         }
00595 
00596         p_sys->b_new_image = VLC_FALSE;
00597     }
00598 
00599     p_sys->b_need_update = VLC_FALSE;
00600 
00601     /* Allocate the subpicture internal data. */
00602     p_spu = p_filter->pf_sub_buffer_new( p_filter );
00603     if( !p_spu ) return NULL;
00604 
00605     p_spu->b_absolute = p_sys->b_absolute;
00606     p_spu->i_start = p_sys->i_last_date = date;
00607     p_spu->i_stop = 0;
00608     p_spu->b_ephemer = VLC_TRUE;
00609 
00610     p_sys->b_need_update = VLC_FALSE;
00611 
00612     if( !p_sys->p_pic || !p_sys->i_trans )
00613     {
00614         /* Send an empty subpicture to clear the display */
00615         return p_spu;
00616     }
00617 
00618     /* Create new SPU region */
00619     memset( &fmt, 0, sizeof(video_format_t) );
00620     fmt.i_chroma = VLC_FOURCC('Y','U','V','A');
00621     fmt.i_aspect = VOUT_ASPECT_FACTOR;
00622     fmt.i_sar_num = fmt.i_sar_den = 1;
00623     fmt.i_width = fmt.i_visible_width = p_sys->i_width;
00624     fmt.i_height = fmt.i_visible_height = p_sys->i_height;
00625     fmt.i_x_offset = fmt.i_y_offset = 0;
00626     p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
00627     if( !p_region )
00628     {
00629         msg_Err( p_filter, "cannot allocate SPU region" );
00630         p_filter->pf_sub_buffer_del( p_filter, p_spu );
00631         return NULL;
00632     }
00633 
00634     vout_CopyPicture( p_filter, &p_region->picture, p_sys->p_pic );
00635 
00636     /*  where to locate the logo: */
00637     if( p_sys->posx < 0 || p_sys->posy < 0 )
00638     {   /* set to one of the 9 relative locations */
00639         p_spu->i_flags = p_sys->pos;
00640         p_spu->i_x = 0;
00641         p_spu->i_y = 0;
00642         p_spu->b_absolute = VLC_FALSE;
00643     }
00644     else
00645     {   /*  set to an absolute xy, referenced to upper left corner */
00646         p_spu->i_flags = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
00647         p_spu->i_x = p_sys->posx;
00648         p_spu->i_y = p_sys->posy;
00649         p_spu->b_absolute = VLC_TRUE;
00650     }
00651 
00652     p_spu->p_region = p_region;
00653     p_spu->i_alpha = p_sys->i_trans;
00654 
00655     return p_spu;
00656 }
00657 
00658 /*****************************************************************************
00659  * Callback to update params on the fly
00660  *****************************************************************************/
00661 static int LogoCallback( vlc_object_t *p_this, char const *psz_var,
00662                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
00663 {
00664     filter_sys_t *p_sys = (filter_sys_t *)p_data;
00665 
00666     if( !strncmp( psz_var, "logo-file", 6 ) )
00667     {
00668         if( p_sys->psz_filename ) free( p_sys->psz_filename );
00669         p_sys->psz_filename = strdup( newval.psz_string );
00670         p_sys->b_new_image = VLC_TRUE;
00671     }
00672     else if ( !strncmp( psz_var, "logo-x", 6 ) )
00673     {
00674         p_sys->posx = newval.i_int;
00675     }
00676     else if ( !strncmp( psz_var, "logo-y", 6 ) )
00677     {
00678         p_sys->posy = newval.i_int;
00679     }
00680     else if ( !strncmp( psz_var, "logo-position", 12 ) )
00681     {
00682         p_sys->pos = newval.i_int;
00683     }
00684     else if ( !strncmp( psz_var, "logo-transparency", 9 ) )
00685     {
00686         p_sys->i_trans = __MAX( __MIN( newval.i_int, 255 ), 0 );
00687     }
00688     p_sys->b_need_update = VLC_TRUE;
00689     return VLC_SUCCESS;
00690 }

Generated on Tue Dec 20 10:14:52 2005 for vlc-0.8.4a by  doxygen 1.4.2