All: My shot at improving subtitle rendering in vlc. Now each vout uses a...

All: My shot at improving subtitle rendering in vlc. Now each vout uses a "text renderer" module to render text on the video when needed. I decieded to make this a module type, because other api's (win32 and macosx) is supposed to do better than freetype under some circumstances.

include/video_output.h: added some members needed by text renderer modules
src/video_output/video_output.c: load and unload text renderer module when needed
src/video_output/video_text.c: implemented some functions to show text on the video
include/osd.h: exported the functions to show text
modules/misc/Modules.am, module/misc/freetype.c: new text renderer module, largly based on the old osdtext module.
modules/video_filter/Modules.am, modules/video_filter/osd_text.c: removed the osdtext module
configure.ac: changes "osdtext" to "freetype" some places
modules/codec/spudec/*: when iconv is available, use it to convert textual subtitles from the encoding given by --sub-encoding to utf8. Use new code to render subtitles
modules/control/lirc/lirc.c: use new code to give feedback on buttons pressed. untested.
modules/demux/util/sub.c: remove all traces of the ugly old osdtext module
modules/misc/dummy/*: added a "text renderer" submodule in the dummy module
src/misc/modules.c: included osd.h as it seems to be needed to export symbols


final notes: you need to give a proper value to --freetype-font. This should be the path to a font file freetype2 can handle (almost any format afaik) with a unicode translation table in it. Windows ttf files will do. In linux at least openoffice distributes some fonts that work. I think macosx and beos also has useable fonts.
parent 371148d3
dnl Autoconf settings for vlc dnl Autoconf settings for vlc
dnl $Id: configure.ac,v 1.29 2003/07/14 16:10:20 gbazin Exp $ dnl $Id: configure.ac,v 1.30 2003/07/14 21:32:58 sigmunau Exp $
AC_INIT(vlc,0.6.0) AC_INIT(vlc,0.6.0)
...@@ -2129,9 +2129,9 @@ then ...@@ -2129,9 +2129,9 @@ then
if test "${FREETYPE_CONFIG}" != "no" if test "${FREETYPE_CONFIG}" != "no"
then then
AX_ADD_PLUGINS([osdtext]) AX_ADD_PLUGINS([freetype])
AX_ADD_CFLAGS([osdtext],[`${FREETYPE_CONFIG} --cflags`]) AX_ADD_CFLAGS([freetype],[`${FREETYPE_CONFIG} --cflags`])
AX_ADD_LDFLAGS([osdtext],[`${FREETYPE_CONFIG} --libs`]) AX_ADD_LDFLAGS([freetype],[`${FREETYPE_CONFIG} --libs`])
CPPFLAGS="${CPPFLAGS_save} ${CFLAGS_freetype}" CPPFLAGS="${CPPFLAGS_save} ${CFLAGS_freetype}"
elif test "${enable_freetype}" = "yes" elif test "${enable_freetype}" = "yes"
then then
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* osd.h : Constants for use with osd modules * osd.h : Constants for use with osd modules
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: osd.h,v 1.1 2003/03/23 16:38:40 sigmunau Exp $ * $Id: osd.h,v 1.2 2003/07/14 21:32:58 sigmunau Exp $
* *
* Authors: Sigmund Augdal <sigmunau@idi.ntnu.no> * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
* *
...@@ -25,3 +25,15 @@ ...@@ -25,3 +25,15 @@
#define OSD_ALIGN_RIGHT 0x1 #define OSD_ALIGN_RIGHT 0x1
#define OSD_ALIGN_TOP 0 #define OSD_ALIGN_TOP 0
#define OSD_ALIGN_BOTTOM 0x2 #define OSD_ALIGN_BOTTOM 0x2
struct text_style_t
{
int i_size;
uint32_t i_color;
vlc_bool_t b_italic;
vlc_bool_t b_bold;
vlc_bool_t b_underline;
};
static const text_style_t default_text_style = { 22, 0xffffff, VLC_FALSE, VLC_FALSE, VLC_FALSE };
VLC_EXPORT( void, vout_ShowTextRelative, ( vout_thread_t *, char *, text_style_t *, int, int, int, mtime_t ) );
VLC_EXPORT( void, vout_ShowTextAbsolute, ( vout_thread_t *, char *, text_style_t *, int, int, int, mtime_t, mtime_t ) );
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* thread, and destroy a previously opened video output thread. * thread, and destroy a previously opened video output thread.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: video_output.h,v 1.95 2003/06/09 00:33:34 massiot Exp $ * $Id: video_output.h,v 1.96 2003/07/14 21:32:58 sigmunau Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr> * Samuel Hocevar <sam@via.ecp.fr>
...@@ -50,76 +50,91 @@ typedef struct vout_chroma_t ...@@ -50,76 +50,91 @@ typedef struct vout_chroma_t
} vout_chroma_t; } vout_chroma_t;
/***************************************************************************** /**
* vout_thread_t: video output thread descriptor * \brief video output thread descriptor
***************************************************************************** *
* Any independant video output device, such as an X11 window or a GGI device, * Any independant video output device, such as an X11 window or a GGI device,
* is represented by a video output thread, and described using the following * is represented by a video output thread, and described using the following
* structure. * structure.
*****************************************************************************/ */
struct vout_thread_t struct vout_thread_t
{ {
VLC_COMMON_MEMBERS VLC_COMMON_MEMBERS
/* Thread properties and lock */ /** \name Thread properties and locks */
vlc_mutex_t picture_lock; /* picture heap lock */ /**@{*/
vlc_mutex_t subpicture_lock; /* subpicture heap lock */ vlc_mutex_t picture_lock; /**< picture heap lock */
vlc_mutex_t change_lock; /* thread change lock */ vlc_mutex_t subpicture_lock; /**< subpicture heap lock */
vout_sys_t * p_sys; /* system output method */ vlc_mutex_t change_lock; /**< thread change lock */
vout_sys_t * p_sys; /**< system output method */
/* Current display properties */ /**@}*/
uint16_t i_changes; /* changes made to the thread */
float f_gamma; /* gamma */ /** \name Current display properties */
vlc_bool_t b_grayscale; /* color or grayscale display */ /**@{*/
vlc_bool_t b_info; /* print additional information */ uint16_t i_changes; /**< changes made to the thread */
vlc_bool_t b_interface; /* render interface */ float f_gamma; /**< gamma */
vlc_bool_t b_scale; /* allow picture scaling */ vlc_bool_t b_grayscale; /**< color or grayscale display */
vlc_bool_t b_fullscreen; /* toogle fullscreen display */ vlc_bool_t b_info; /**< print additional information */
vlc_bool_t b_override_aspect; /* aspect ratio overriden */ vlc_bool_t b_interface; /**< render interface */
mtime_t render_time; /* last picture render time */ vlc_bool_t b_scale; /**< allow picture scaling */
unsigned int i_window_width; /* video window width */ vlc_bool_t b_fullscreen; /**< toogle fullscreen display */
unsigned int i_window_height; /* video window height */ vlc_bool_t b_override_aspect; /**< aspect ratio overriden */
mtime_t render_time; /**< last picture render time */
/* Plugin used and shortcuts to access its capabilities */ unsigned int i_window_width; /**< video window width */
unsigned int i_window_height; /**< video window height */
/**@}*/
/** \name Plugin used and shortcuts to access its capabilities */
/**@{*/
module_t * p_module; module_t * p_module;
int ( *pf_init ) ( vout_thread_t * ); int ( *pf_init ) ( vout_thread_t * );
void ( *pf_end ) ( vout_thread_t * ); void ( *pf_end ) ( vout_thread_t * );
int ( *pf_manage ) ( vout_thread_t * ); int ( *pf_manage ) ( vout_thread_t * );
void ( *pf_render ) ( vout_thread_t *, picture_t * ); void ( *pf_render ) ( vout_thread_t *, picture_t * );
void ( *pf_display ) ( vout_thread_t *, picture_t * ); void ( *pf_display ) ( vout_thread_t *, picture_t * );
/**@}*/
/* Statistics - these numbers are not supposed to be accurate, but are a /** \name Statistics
* These numbers are not supposed to be accurate, but are a
* good indication of the thread status */ * good indication of the thread status */
count_t c_fps_samples; /* picture counts */ /**@{*/
mtime_t p_fps_sample[VOUT_FPS_SAMPLES]; /* FPS samples dates */ count_t c_fps_samples; /**< picture counts */
mtime_t p_fps_sample[VOUT_FPS_SAMPLES]; /**< FPS samples dates */
/* Video heap and translation tables */ /**@}*/
int i_heap_size; /* heap size */
picture_heap_t render; /* rendered pictures */ /** \name Video heap and translation tables */
picture_heap_t output; /* direct buffers */ /**@{*/
vlc_bool_t b_direct; /* rendered are like direct ? */ int i_heap_size; /**< heap size */
vout_chroma_t chroma; /* translation tables */ picture_heap_t render; /**< rendered pictures */
picture_heap_t output; /**< direct buffers */
vlc_bool_t b_direct; /**< rendered are like direct ? */
vout_chroma_t chroma; /**< translation tables */
/**@}*/
/* Picture and subpicture heaps */ /* Picture and subpicture heaps */
picture_t p_picture[2*VOUT_MAX_PICTURES]; /* pictures */ picture_t p_picture[2*VOUT_MAX_PICTURES]; /**< pictures */
subpicture_t p_subpicture[VOUT_MAX_PICTURES]; /* subpictures */ subpicture_t p_subpicture[VOUT_MAX_PICTURES]; /**< subpictures */
/* Bitmap fonts */
vout_font_t * p_default_font; /* default font */
vout_font_t * p_large_font; /* large font */
/* Statistics */ /* Statistics */
count_t c_loops; count_t c_loops;
count_t c_pictures, c_late_pictures; count_t c_pictures, c_late_pictures;
mtime_t display_jitter; /* average deviation from the PTS */ mtime_t display_jitter; /**< average deviation from the PTS */
count_t c_jitter_samples; /* number of samples used for the * count_t c_jitter_samples; /**< number of samples used
* calculation of the jitter */ for the calculation of the
/* delay created by internal caching */ jitter */
/** delay created by internal caching */
int i_pts_delay; int i_pts_delay;
/* Filter chain */ /* Filter chain */
char *psz_filter_chain; char *psz_filter_chain;
vlc_bool_t b_filter_change; vlc_bool_t b_filter_change;
/* text renderer data */
text_renderer_sys_t * p_text_renderer_data; /**< private data for
the text renderer */
module_t * p_text_renderer_module; /**< text renderer module */
int ( *pf_add_string ) ( vout_thread_t *, char *, text_style_t *, int,
int, int, mtime_t, mtime_t ); /**< callback used when a new string needs to be shown on the vout */
}; };
#define I_OUTPUTPICTURES p_vout->output.i_pictures #define I_OUTPUTPICTURES p_vout->output.i_pictures
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* spudec.c : SPU decoder thread * spudec.c : SPU decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: spudec.c,v 1.19 2003/06/12 22:27:35 massiot Exp $ * $Id: spudec.c,v 1.20 2003/07/14 21:32:58 sigmunau Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -52,6 +52,9 @@ static vout_thread_t *FindVout( spudec_thread_t * ); ...@@ -52,6 +52,9 @@ static vout_thread_t *FindVout( spudec_thread_t * );
#define DEFAULT_FONT "font-eutopiabold21.rle" #define DEFAULT_FONT "font-eutopiabold21.rle"
#define ENCODING_TEXT N_("subtitle text encoding")
#define ENCODING_LONGTEXT N_("change the encoding used in text subtitles")
vlc_module_begin(); vlc_module_begin();
add_category_hint( N_("subtitles"), NULL, VLC_TRUE ); add_category_hint( N_("subtitles"), NULL, VLC_TRUE );
#if defined(SYS_DARWIN) || defined(SYS_BEOS) \ #if defined(SYS_DARWIN) || defined(SYS_BEOS) \
...@@ -61,6 +64,10 @@ vlc_module_begin(); ...@@ -61,6 +64,10 @@ vlc_module_begin();
#else #else
add_file( "spudec-font", "share/" DEFAULT_FONT, NULL, add_file( "spudec-font", "share/" DEFAULT_FONT, NULL,
FONT_TEXT, FONT_LONGTEXT, VLC_TRUE ); FONT_TEXT, FONT_LONGTEXT, VLC_TRUE );
#endif
#if defined(HAVE_ICONV)
add_string( "spudec-encoding", "ISO-8859-1", NULL, ENCODING_TEXT,
ENCODING_LONGTEXT, VLC_FALSE );
#endif #endif
set_description( _("subtitles decoder") ); set_description( _("subtitles decoder") );
set_capability( "decoder", 50 ); set_capability( "decoder", 50 );
...@@ -151,7 +158,13 @@ static int RunDecoder( decoder_fifo_t * p_fifo ) ...@@ -151,7 +158,13 @@ static int RunDecoder( decoder_fifo_t * p_fifo )
p_spudec->p_fifo->b_error = VLC_TRUE; p_spudec->p_fifo->b_error = VLC_TRUE;
} }
#endif #endif
#if defined(HAVE_ICONV)
p_spudec->iconv_handle = iconv_open( "UTF-8", config_GetPsz( p_spudec->p_fifo, "spudec-encoding" ) );
if( p_spudec->iconv_handle == (iconv_t)-1 )
{
msg_Warn( p_spudec->p_fifo, "Unable to do requested conversion" );
}
#endif
while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) ) while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
{ {
/* Find/Wait for a video output */ /* Find/Wait for a video output */
...@@ -324,7 +337,12 @@ static void EndThread( spudec_thread_t *p_spudec ) ...@@ -324,7 +337,12 @@ static void EndThread( spudec_thread_t *p_spudec )
} }
} }
} }
#if defined(HAVE_ICONV)
if( p_spudec->iconv_handle != (iconv_t)-1 )
{
iconv_close( p_spudec->iconv_handle );
}
#endif
CloseBitstream( &p_spudec->bit_stream ); CloseBitstream( &p_spudec->bit_stream );
free( p_spudec ); free( p_spudec );
} }
/***************************************************************************** /*****************************************************************************
* spudec.h : sub picture unit decoder thread interface * spudec.h : sub picture unit decoder thread interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: spudec.h,v 1.5 2002/12/06 16:34:05 sam Exp $ * $Id: spudec.h,v 1.6 2003/07/14 21:32:58 sigmunau Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -21,6 +22,11 @@ ...@@ -21,6 +22,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#if defined(HAVE_ICONV)
#include <iconv.h>
#endif
typedef struct spudec_thread_t spudec_thread_t; typedef struct spudec_thread_t spudec_thread_t;
struct subpicture_sys_t struct subpicture_sys_t
...@@ -83,6 +89,9 @@ struct spudec_thread_t ...@@ -83,6 +89,9 @@ struct spudec_thread_t
*/ */
unsigned int i_spu_size; /* size of current SPU packet */ unsigned int i_spu_size; /* size of current SPU packet */
unsigned int i_rle_size; /* size of the RLE part */ unsigned int i_rle_size; /* size of the RLE part */
#if defined(HAVE_ICONV)
iconv_t iconv_handle; /* handle to iconv instance */
#endif
}; };
/***************************************************************************** /*****************************************************************************
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* text.c: text subtitles parser * text.c: text subtitles parser
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: text.c,v 1.5 2003/05/11 14:33:32 sigmunau Exp $ * $Id: text.c,v 1.6 2003/07/14 21:32:58 sigmunau Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
/* define USE_FREETYPE here to disable the old style subtitles */
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
...@@ -32,6 +31,7 @@ ...@@ -32,6 +31,7 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/vout.h> #include <vlc/vout.h>
#include <vlc/decoder.h> #include <vlc/decoder.h>
#include <osd.h>
#include "spudec.h" #include "spudec.h"
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
*****************************************************************************/ *****************************************************************************/
void E_(ParseText)( spudec_thread_t *p_spudec, subtitler_font_t *p_font ) void E_(ParseText)( spudec_thread_t *p_spudec, subtitler_font_t *p_font )
{ {
#if !defined(USE_FREETYPE)
char * psz_subtitle; char * psz_subtitle;
mtime_t i_pts, i_dts; mtime_t i_pts, i_dts;
/* We cannot display a subpicture with no date */ /* We cannot display a subpicture with no date */
...@@ -74,17 +73,43 @@ void E_(ParseText)( spudec_thread_t *p_spudec, subtitler_font_t *p_font ) ...@@ -74,17 +73,43 @@ void E_(ParseText)( spudec_thread_t *p_spudec, subtitler_font_t *p_font )
if( psz_subtitle[0] != '\0' ) if( psz_subtitle[0] != '\0' )
{ {
#if defined(HAVE_ICONV)
char *psz_new_subtitle, *psz_convert_buffer_out, *psz_convert_buffer_in;
size_t ret, inbytes_left, outbytes_left;
psz_new_subtitle = malloc( 6 * strlen( psz_subtitle ) * sizeof(char) );
psz_convert_buffer_out = psz_new_subtitle;
psz_convert_buffer_in = psz_subtitle;
inbytes_left = strlen( psz_subtitle );
outbytes_left = 6 * inbytes_left;
ret = iconv( p_spudec->iconv_handle, &psz_convert_buffer_in, &inbytes_left, &psz_convert_buffer_out, &outbytes_left );
*psz_convert_buffer_out = '\0';
if( inbytes_left )
{
msg_Warn( p_spudec->p_fifo, "Something fishy happened during conversion" );
}
else
{
msg_Dbg( p_spudec->p_fifo, "reencoded \"%s\" into \"%s\"", psz_subtitle, psz_new_subtitle );
vout_ShowTextAbsolute( p_spudec->p_vout, psz_new_subtitle, NULL,
OSD_ALIGN_BOTTOM|OSD_ALIGN_LEFT, 20, 20,
i_pts, i_dts );
}
free( psz_new_subtitle );
#else
vout_ShowTextAbsolute( p_spudec->p_vout, psz_subtitle, NULL,
OSD_ALIGN_BOTTOM|OSD_ALIGN_LEFT, 20, 20,
i_pts, i_dts );
#endif
#if 0
subtitler_PlotSubtitle( p_spudec->p_vout, subtitler_PlotSubtitle( p_spudec->p_vout,
psz_subtitle, p_font, psz_subtitle, p_font,
i_pts, i_pts,
i_dts ); i_dts );
#endif
} }
/* Prepare for next time. No need to check that /* Prepare for next time. No need to check that
* p_spudec->bit_stream->p_data is valid since we check later on * p_spudec->bit_stream->p_data is valid since we check later on
* for b_die and b_error */ * for b_die and b_error */
NextDataPacket( p_spudec->p_fifo, &p_spudec->bit_stream ); NextDataPacket( p_spudec->p_fifo, &p_spudec->bit_stream );
#else
msleep(10);
#endif
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* lirc.c : lirc plugin for vlc * lirc.c : lirc plugin for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: lirc.c,v 1.6 2003/03/30 18:14:37 gbazin Exp $ * $Id: lirc.c,v 1.7 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Sigmund Augdal <sigmunau@idi.ntnu.no> * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
* *
...@@ -370,25 +370,9 @@ static void Run( intf_thread_t *p_intf ) ...@@ -370,25 +370,9 @@ static void Run( intf_thread_t *p_intf )
static void Feedback( intf_thread_t *p_intf, char *psz_string ) static void Feedback( intf_thread_t *p_intf, char *psz_string )
{ {
vlc_value_t val, lockval; if ( p_intf->p_sys->p_vout )
if ( p_intf->p_sys->p_vout
&& var_Get( p_intf->p_sys->p_vout, "lock", &lockval ) == VLC_SUCCESS )
{
vlc_mutex_lock( lockval.p_address );
val.i_int = OSD_ALIGN_RIGHT|OSD_ALIGN_BOTTOM;
var_Set( p_intf->p_sys->p_vout, "flags", val );
val.i_int = 400000;
var_Set( p_intf->p_sys->p_vout, "duration", val );
val.i_int = 30;
var_Set( p_intf->p_sys->p_vout, "x-margin", val );
val.i_int = 20;
var_Set( p_intf->p_sys->p_vout, "y-margin", val );
val.psz_string = psz_string;
var_Set( p_intf->p_sys->p_vout, "string", val );
vlc_mutex_unlock( lockval.p_address );
}
else
{ {
msg_Dbg( p_intf, psz_string ); vout_ShowTextRelative( p_intf->p_sys->p_vout, psz_string, NULL,
OSD_ALIGN_TOP|OSD_ALIGN_RIGHT, 30,20,400000 );
} }
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* sub.c * sub.c
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: sub.c,v 1.16 2003/06/26 18:14:56 sam Exp $ * $Id: sub.c,v 1.17 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
/* define USE_FREETYPE to use freetype for subtitles */
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
...@@ -33,9 +31,6 @@ ...@@ -33,9 +31,6 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/input.h> #include <vlc/input.h>
#if defined(USE_FREETYPE)
#include <osd.h>
#endif
#include "vlc_video.h" #include "vlc_video.h"
#include "sub.h" #include "sub.h"
...@@ -447,9 +442,6 @@ static int sub_open ( subtitle_demux_t *p_sub, ...@@ -447,9 +442,6 @@ static int sub_open ( subtitle_demux_t *p_sub,
*****************************************************************************/ *****************************************************************************/
static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate ) static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
{ {
#if defined(USE_FREETYPE)
vlc_object_t *p_vout = NULL;
#endif
if( p_sub->p_es->p_decoder_fifo && !p_sub->i_previously_selected ) if( p_sub->p_es->p_decoder_fifo && !p_sub->i_previously_selected )
{ {
p_sub->i_previously_selected = 1; p_sub->i_previously_selected = 1;
...@@ -469,9 +461,6 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate ) ...@@ -469,9 +461,6 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
data_packet_t *p_data; data_packet_t *p_data;
int i_len; int i_len;
#if defined(USE_FREETYPE)
p_vout = vlc_object_find( p_sub, VLC_OBJECT_VOUT, FIND_ANYWHERE );
#endif
i_len = strlen( p_sub->subtitle[p_sub->i_subtitle].psz_text ) + 1; i_len = strlen( p_sub->subtitle[p_sub->i_subtitle].psz_text ) + 1;
...@@ -514,35 +503,7 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate ) ...@@ -514,35 +503,7 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
{ {
p_pes->i_dts = 0; p_pes->i_dts = 0;
} }
#if defined(USE_FREETYPE)
if( p_vout )
{
vlc_value_t val, lockval;
if( var_Get( p_vout, "lock", &lockval ) == VLC_SUCCESS )
{
int64_t i_tmp;
vlc_mutex_lock( lockval.p_address );
msg_Dbg( p_sub, "pts "I64Fd" dts " I64Fd, p_pes->i_pts,
p_pes->i_dts );
i_tmp = p_pes->i_dts - p_pes->i_pts;
val.i_int = OSD_ALIGN_LEFT|OSD_ALIGN_BOTTOM;
var_Set( p_vout, "flags", val );
val.time.i_low = (int)(p_pes->i_pts+p_sub->p_input->i_pts_delay);
val.time.i_high = (int)( p_pes->i_pts >> 32 );
var_Set( p_vout, "start-date", val );
val.time.i_low = (int)(p_pes->i_dts + p_sub->p_input->i_pts_delay);
val.time.i_high = (int)( p_pes->i_dts >> 32 );
var_Set( p_vout, "stop-date", val );
val.i_int = 20;
var_Set( p_vout, "x-margin", val );
val.i_int = 20;
var_Set( p_vout, "y-margin", val );
val.psz_string = p_sub->subtitle[p_sub->i_subtitle].psz_text;
var_Set( p_vout, "string", val );
vlc_mutex_unlock( lockval.p_address );
}
}
#endif
p_pes->i_nb_data = 1; p_pes->i_nb_data = 1;
p_pes->p_first = p_pes->p_first =
p_pes->p_last = p_data; p_pes->p_last = p_data;
...@@ -563,12 +524,6 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate ) ...@@ -563,12 +524,6 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
p_sub->i_subtitle++; p_sub->i_subtitle++;
} }
#if defined(USE_FREETYPE)
if ( p_vout )
{
vlc_object_release( p_vout );
}
#endif
return( 0 ); return( 0 );
} }
......
...@@ -5,4 +5,5 @@ SOURCES_gnome2_main = gtk_main.c ...@@ -5,4 +5,5 @@ SOURCES_gnome2_main = gtk_main.c
SOURCES_sap = sap.c SOURCES_sap = sap.c
SOURCES_screensaver = screensaver.c SOURCES_screensaver = screensaver.c
SOURCES_qte_main = qte_main.cpp SOURCES_qte_main = qte_main.cpp
SOURCES_freetype = freetype.c
SOURCES_httpd = httpd.c SOURCES_httpd = httpd.c
...@@ -6,5 +6,6 @@ SOURCES_dummy = \ ...@@ -6,5 +6,6 @@ SOURCES_dummy = \
interface.c \ interface.c \
input.c \ input.c \
decoder.c \ decoder.c \
renderer.c \
$(NULL) $(NULL)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dummy.c : dummy plugin for vlc * dummy.c : dummy plugin for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN * Copyright (C) 2000, 2001 VideoLAN
* $Id: dummy.c,v 1.8 2003/06/17 16:09:16 gbazin Exp $ * $Id: dummy.c,v 1.9 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -80,5 +80,9 @@ vlc_module_begin(); ...@@ -80,5 +80,9 @@ vlc_module_begin();
set_callbacks( E_(OpenVideo), NULL ); set_callbacks( E_(OpenVideo), NULL );
add_category_hint( N_("Video"), NULL, VLC_FALSE ); add_category_hint( N_("Video"), NULL, VLC_FALSE );
add_string( "dummy-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, VLC_FALSE ); add_string( "dummy-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, VLC_FALSE );
add_submodule();
set_description( _("dummy font renderer function") );
set_capability( "text renderer", 1 );
set_callbacks( E_(OpenRenderer), NULL );
vlc_module_end(); vlc_module_end();
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dummy.h : dummy plugin for vlc * dummy.h : dummy plugin for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2000, 2001, 2002 VideoLAN * Copyright (C) 2000, 2001, 2002 VideoLAN
* $Id: dummy.h,v 1.1 2002/08/04 17:23:43 sam Exp $ * $Id: dummy.h,v 1.2 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -37,3 +37,4 @@ int E_(OpenAudio) ( vlc_object_t * ); ...@@ -37,3 +37,4 @@ int E_(OpenAudio) ( vlc_object_t * );
int E_(OpenVideo) ( vlc_object_t * ); int E_(OpenVideo) ( vlc_object_t * );
int E_(OpenRenderer) ( vlc_object_t * );
/***************************************************************************** /*****************************************************************************
* osd_text.c : Filter to put text on the video, using freetype2 * freetype.c : Put text on the video, using freetype2
***************************************************************************** *****************************************************************************
* Copyright (C) 2002, 2003 VideoLAN * Copyright (C) 2002, 2003 VideoLAN
* $Id: osd_text.c,v 1.5 2003/06/11 20:36:22 gbazin Exp $ * $Id: freetype.c,v 1.1 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Sigmund Augdal <sigmunau@idi.ntnu.no> * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
* *
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include <osd.h> #include <osd.h>
#include <math.h> #include <math.h>
#include "filter_common.h"
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_GLYPH_H #include FT_GLYPH_H
...@@ -46,17 +44,11 @@ ...@@ -46,17 +44,11 @@
static int Create ( vlc_object_t * ); static int Create ( vlc_object_t * );
static void Destroy ( vlc_object_t * ); static void Destroy ( vlc_object_t * );
static int Init ( vout_thread_t * ); static void Render ( vout_thread_t *, picture_t *,
static void End ( vout_thread_t * ); const subpicture_t * );
static void Render ( vout_thread_t *, picture_t * ); static int AddText ( vout_thread_t *, byte_t *, text_style_t *, int,
int, int, mtime_t, mtime_t );
static int SendEvents( vlc_object_t *, char const *, static int GetUnicodeCharFromUTF8( byte_t ** );
vlc_value_t, vlc_value_t, void * );
static int SetMargin ( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int AddText ( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -67,11 +59,11 @@ static int AddText ( vlc_object_t *, char const *, ...@@ -67,11 +59,11 @@ static int AddText ( vlc_object_t *, char const *,
#define FONTSIZE_LONGTEXT N_("The size of the fonts used by the osd module" ) #define FONTSIZE_LONGTEXT N_("The size of the fonts used by the osd module" )
vlc_module_begin(); vlc_module_begin();
add_category_hint( N_("OSD"), NULL, VLC_FALSE ); add_category_hint( N_("Fonts"), NULL, VLC_FALSE );
add_file( "osd-font", "", NULL, FONT_TEXT, FONT_LONGTEXT, VLC_FALSE ); add_file( "freetype-font", "", NULL, FONT_TEXT, FONT_LONGTEXT, VLC_FALSE );
add_integer( "osd-fontsize", 16, NULL, FONTSIZE_TEXT, FONTSIZE_LONGTEXT, VLC_FALSE ); add_integer( "freetype-fontsize", 16, NULL, FONTSIZE_TEXT, FONTSIZE_LONGTEXT, VLC_FALSE );
set_description( _("osd text filter") ); set_description( _("freetype2 font renderer") );
set_capability( "video filter", 0 ); set_capability( "text renderer", 100 );
add_shortcut( "text" ); add_shortcut( "text" );
set_callbacks( Create, Destroy ); set_callbacks( Create, Destroy );
vlc_module_end(); vlc_module_end();
...@@ -80,19 +72,18 @@ vlc_module_end(); ...@@ -80,19 +72,18 @@ vlc_module_end();
Describes a string to be displayed on the video, or a linked list of Describes a string to be displayed on the video, or a linked list of
such such
*/ */
typedef struct string_info_s string_info_t; struct subpicture_sys_t
struct string_info_s
{ {
string_info_t *p_next;
int i_x_margin; int i_x_margin;
int i_y_margin; int i_y_margin;
int i_width; int i_width;
int i_height; int i_height;
int i_flags; int i_flags;
mtime_t i_start_date; /** The string associated with this subpicture */
mtime_t i_end_date; byte_t *psz_text;
char *psz_text; /** NULL-terminated list of glyphs making the string */
FT_Glyph *pp_glyphs; FT_Glyph *pp_glyphs;
/** list of relative positions for the glyphs */
FT_Vector *p_glyph_pos; FT_Vector *p_glyph_pos;
}; };
...@@ -102,26 +93,17 @@ struct string_info_s ...@@ -102,26 +93,17 @@ struct string_info_s
* This structure is part of the video output thread descriptor. * This structure is part of the video output thread descriptor.
* It describes the osd-text specific properties of an output thread. * It describes the osd-text specific properties of an output thread.
*****************************************************************************/ *****************************************************************************/
struct vout_sys_t struct text_renderer_sys_t
{ {
int i_clones;
vout_thread_t *p_vout;
FT_Library p_library; /* handle to library */ FT_Library p_library; /* handle to library */
FT_Face p_face; /* handle to face object */ FT_Face p_face; /* handle to face object */
string_info_t *p_strings;
int i_x_margin;
int i_y_margin;
int i_flags;
int i_duration;
mtime_t i_start_date;
mtime_t i_end_date;
vlc_mutex_t *lock; vlc_mutex_t *lock;
vlc_bool_t i_use_kerning; vlc_bool_t i_use_kerning;
uint8_t pi_gamma[256]; uint8_t pi_gamma[256];
}; };
/* more prototypes */ /* more prototypes */
static void ComputeBoundingBox( string_info_t * ); //static void ComputeBoundingBox( subpicture_sys_t * );
static void FreeString( string_info_t * ); static void FreeString( subpicture_t * );
/***************************************************************************** /*****************************************************************************
* Create: allocates osd-text video thread output method * Create: allocates osd-text video thread output method
...@@ -134,277 +116,111 @@ static int Create( vlc_object_t *p_this ) ...@@ -134,277 +116,111 @@ static int Create( vlc_object_t *p_this )
vout_thread_t *p_vout = (vout_thread_t *)p_this; vout_thread_t *p_vout = (vout_thread_t *)p_this;
char *psz_fontfile; char *psz_fontfile;
int i, i_error; int i, i_error;
vlc_value_t val;
double gamma_inv = 1.0f / gamma_value; double gamma_inv = 1.0f / gamma_value;
/* Allocate structure */ /* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); p_vout->p_text_renderer_data = malloc( sizeof( text_renderer_sys_t ) );
if( p_vout->p_sys == NULL ) if( p_vout->p_text_renderer_data == NULL )
{ {
msg_Err( p_vout, "out of memory" ); msg_Err( p_vout, "out of memory" );
return VLC_ENOMEM; return VLC_ENOMEM;
} }
p_vout->p_sys->p_strings = NULL;
p_vout->p_sys->i_x_margin = 50;
p_vout->p_sys->i_y_margin = 50;
p_vout->p_sys->i_flags = 0;
p_vout->p_sys->i_duration = 2000000;
p_vout->p_sys->i_start_date = 0;
p_vout->p_sys->i_end_date = 0;
p_vout->p_sys->lock = malloc( sizeof(vlc_mutex_t));
if( p_vout->p_sys->lock == NULL )
{
msg_Err( p_vout, "out of memory" );
return VLC_ENOMEM;
}
vlc_mutex_init( p_vout, p_vout->p_sys->lock);
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
p_vout->p_sys->pi_gamma[i] = p_vout->p_text_renderer_data->pi_gamma[i] =
(uint8_t)( pow( (double)i / 255.0f, gamma_inv) * 255.0f ); (uint8_t)( pow( (double)i / 255.0f, gamma_inv) * 255.0f );
msg_Dbg( p_vout, "%d", p_vout->p_sys->pi_gamma[i]); //msg_Dbg( p_vout, "%d", p_vout->p_text_renderer_data->pi_gamma[i]);
} }
p_vout->pf_init = Init;
p_vout->pf_end = End;
p_vout->pf_manage = NULL;
p_vout->pf_render = Render;
p_vout->pf_display = NULL;
/* Look what method was requested */ /* Look what method was requested */
psz_fontfile = config_GetPsz( p_vout, "osd-font" ); psz_fontfile = config_GetPsz( p_vout, "freetype-font" );
i_error = FT_Init_FreeType( &p_vout->p_sys->p_library ); i_error = FT_Init_FreeType( &p_vout->p_text_renderer_data->p_library );
if( i_error ) if( i_error )
{ {
msg_Err( p_vout, "couldn't initialize freetype" ); msg_Err( p_vout, "couldn't initialize freetype" );
free( p_vout->p_sys ); free( p_vout->p_text_renderer_data );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
i_error = FT_New_Face( p_vout->p_sys->p_library, psz_fontfile, 0, i_error = FT_New_Face( p_vout->p_text_renderer_data->p_library,
&p_vout->p_sys->p_face ); psz_fontfile, 0,
&p_vout->p_text_renderer_data->p_face );
if( i_error == FT_Err_Unknown_File_Format ) if( i_error == FT_Err_Unknown_File_Format )
{ {
msg_Err( p_vout, "file %s have unknown format", psz_fontfile ); msg_Err( p_vout, "file %s have unknown format", psz_fontfile );
free( p_vout->p_sys ); FT_Done_FreeType( p_vout->p_text_renderer_data->p_library );
free( p_vout->p_text_renderer_data );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
else if( i_error ) else if( i_error )
{ {
msg_Err( p_vout, "failed to load font file" ); msg_Err( p_vout, "failed to load font file" );
free( p_vout->p_sys ); FT_Done_FreeType( p_vout->p_text_renderer_data->p_library );
free( p_vout->p_text_renderer_data );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_vout->p_sys->i_use_kerning = FT_HAS_KERNING(p_vout->p_sys->p_face); i_error = FT_Select_Charmap( p_vout->p_text_renderer_data->p_face,
FT_ENCODING_UNICODE );
i_error = FT_Set_Pixel_Sizes( p_vout->p_sys->p_face, 0, config_GetInt( p_vout, "osd-fontsize" ) ); if ( i_error )
if( i_error )
{ {
msg_Err( p_vout, "couldn't set font size to %d", msg_Err( p_vout, "Font has no unicode translation table" );
config_GetInt( p_vout, "osd-fontsize" ) ); FT_Done_Face( p_vout->p_text_renderer_data->p_face );
free( p_vout->p_sys ); FT_Done_FreeType( p_vout->p_text_renderer_data->p_library );
free( p_vout->p_text_renderer_data );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
var_Create( p_vout, "lock", VLC_VAR_MUTEX );
var_Create( p_vout, "flags", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "flags", SetMargin, NULL );
var_Create( p_vout, "x-margin", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "x-margin", SetMargin, NULL );
var_Create( p_vout, "y-margin", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "y-margin", SetMargin, NULL );
var_Create( p_vout, "duration", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "duration", SetMargin, NULL );
var_Create( p_vout, "start-date", VLC_VAR_TIME | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "start-date", SetMargin, NULL );
var_Create( p_vout, "end-date", VLC_VAR_TIME | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "end-date", SetMargin, NULL );
var_Create( p_vout, "string", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "string", AddText, NULL );
val.psz_string = "Videolan";
// var_Set( p_vout, "string", val );
// p_vout->p_sys->p_strings->i_end_date = 0xFFFFFFFFFFFFFFF;
return VLC_SUCCESS;
}
/*****************************************************************************
* Init: initialize the video thread output method
*****************************************************************************/
static int Init( vout_thread_t *p_vout )
{
int i_index;
picture_t *p_pic;
I_OUTPUTPICTURES = 0; p_vout->p_text_renderer_data->i_use_kerning = FT_HAS_KERNING(p_vout->p_text_renderer_data->p_face);
/* Initialize the output structure */ i_error = FT_Set_Pixel_Sizes( p_vout->p_text_renderer_data->p_face, 0,
p_vout->output.i_chroma = p_vout->render.i_chroma; config_GetInt( p_vout, "freetype-fontsize" ) );
p_vout->output.i_width = p_vout->render.i_width; if( i_error )
p_vout->output.i_height = p_vout->render.i_height;
p_vout->output.i_aspect = p_vout->render.i_aspect;
/* Try to open the real video output */
msg_Dbg( p_vout, "spawning the real video output" );
p_vout->p_sys->p_vout = vout_Create( p_vout,
p_vout->render.i_width, p_vout->render.i_height,
p_vout->render.i_chroma, p_vout->render.i_aspect );
if( p_vout->p_sys->p_vout == NULL )
{ {
msg_Err( p_vout, "failed to start vout" ); msg_Err( p_vout, "couldn't set font size to %d",
config_GetInt( p_vout, "osd-fontsize" ) );
free( p_vout->p_text_renderer_data );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_vout->pf_add_string = AddText;
ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/*****************************************************************************
* End: terminate Clone video thread output method
*****************************************************************************/
static void End( vout_thread_t *p_vout )
{
int i_index;
/* Free the fake output buffers we allocated */
for( i_index = I_OUTPUTPICTURES ; i_index ; )
{
i_index--;
free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
}
}
/***************************************************************************** /*****************************************************************************
* Destroy: destroy Clone video thread output method * Destroy: destroy Clone video thread output method
***************************************************************************** *****************************************************************************
* Terminate an output method created by CloneCreateOutputMethod * Clean up all data and library connections
*****************************************************************************/ *****************************************************************************/
static void Destroy( vlc_object_t *p_this ) static void Destroy( vlc_object_t *p_this )
{ {
vout_thread_t *p_vout = (vout_thread_t *)p_this; vout_thread_t *p_vout = (vout_thread_t *)p_this;
string_info_t *p_string1, *p_string2; FT_Done_Face( p_vout->p_text_renderer_data->p_face );
DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); FT_Done_FreeType( p_vout->p_text_renderer_data->p_library );
vlc_object_detach( p_vout->p_sys->p_vout ); free( p_vout->p_text_renderer_data );
vout_Destroy( p_vout->p_sys->p_vout );
vlc_mutex_destroy( p_vout->p_sys->lock );
p_string1 = p_vout->p_sys->p_strings;
while( p_string1 )
{
p_string2 = p_string1->p_next;
FreeString( p_string1 );
p_string1 = p_string2;
}
FT_Done_Face( p_vout->p_sys->p_face );
FT_Done_FreeType( p_vout->p_sys->p_library );
free( p_vout->p_sys );
}
/*****************************************************************************
* SendEvents: forward mouse and keyboard events to the parent p_vout
*****************************************************************************/
static int SendEvents( vlc_object_t *p_this, char const *psz_var,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
var_Set( (vlc_object_t *)p_data, psz_var, newval );
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* Render: displays previously rendered output * Render: place string in picture
***************************************************************************** *****************************************************************************
* This function send the currently rendered image to Clone image, waits * This function merges the previously rendered freetype glyphs into a picture
* until it is displayed and switch the two rendering buffers, preparing next
* frame.
*****************************************************************************/ *****************************************************************************/
static void Render( vout_thread_t *p_vout, picture_t *p_pic ) static void Render( vout_thread_t *p_vout, picture_t *p_pic,
const subpicture_t *p_subpic )
{ {
picture_t *p_outpic = NULL; subpicture_sys_t *p_string = p_subpic->p_sys;
int i_plane, i_error,x,y,pen_x, pen_y; int i_plane, i_error,x,y,pen_x, pen_y;
unsigned int i; unsigned int i;
string_info_t *p_string;
mtime_t date;
while( ( p_outpic =
vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 )
) == NULL )
{
if( p_vout->b_die || p_vout->b_error )
{
vout_DestroyPicture(
p_vout->p_sys->p_vout, p_outpic );
return;
}
msleep( VOUT_OUTMEM_SLEEP );
}
vout_DatePicture( p_vout->p_sys->p_vout,
p_outpic, p_pic->date );
if( p_vout->i_changes )
{
p_vout->p_sys->p_vout->i_changes = p_vout->i_changes;
p_vout->i_changes = 0;
}
date = mdate();
/* trash old strings */
while( p_vout->p_sys->p_strings &&
p_vout->p_sys->p_strings->i_end_date < date )
{
p_string = p_vout->p_sys->p_strings;
p_vout->p_sys->p_strings = p_string->p_next;
msg_Dbg( p_vout, "trashing string "I64Fd" < "I64Fd, p_string->i_end_date, date );
FreeString( p_string );
}
vlc_mutex_lock( p_vout->p_sys->lock );
for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ ) for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
{ {
uint8_t *p_in, *p_in_end, *p_out; uint8_t *p_in;
int i_in_pitch = p_pic->p[i_plane].i_pitch; int i_pitch = p_pic->p[i_plane].i_pitch;
const int i_out_pitch = p_outpic->p[i_plane].i_pitch;
const int i_copy_pitch = p_outpic->p[i_plane].i_visible_pitch;
p_in = p_pic->p[i_plane].p_pixels; p_in = p_pic->p[i_plane].p_pixels;
p_out = p_outpic->p[i_plane].p_pixels;
if( i_in_pitch == i_copy_pitch
&& i_out_pitch == i_copy_pitch )
{
p_vout->p_vlc->pf_memcpy( p_out, p_in, i_in_pitch
* p_outpic->p[i_plane].i_lines );
}
else
{
p_in_end = p_in + i_in_pitch * p_outpic->p[i_plane].i_lines;
while( p_in < p_in_end )
{
p_vout->p_vlc->pf_memcpy( p_out, p_in, i_copy_pitch );
p_in += i_in_pitch;
p_out += i_out_pitch;
}
}
/* pen_x = 20;
pen_y = 100;*/
if ( i_plane == 0 ) if ( i_plane == 0 )
{ {
for( p_string = p_vout->p_sys->p_strings; p_string != NULL;
p_string = p_string->p_next )
{
if( p_string->i_start_date > date )
{
continue;
}
if ( p_string->i_flags & OSD_ALIGN_BOTTOM ) if ( p_string->i_flags & OSD_ALIGN_BOTTOM )
{ {
pen_y = p_outpic->p[i_plane].i_lines - p_string->i_height - pen_y = p_pic->p[i_plane].i_lines - p_string->i_height -
p_string->i_y_margin; p_string->i_y_margin;
} }
else else
...@@ -413,7 +229,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -413,7 +229,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
} }
if ( p_string->i_flags & OSD_ALIGN_RIGHT ) if ( p_string->i_flags & OSD_ALIGN_RIGHT )
{ {
pen_x = i_out_pitch - p_string->i_width pen_x = i_pitch - p_string->i_width
- p_string->i_x_margin; - p_string->i_x_margin;
} }
else else
...@@ -421,7 +237,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -421,7 +237,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
pen_x = p_string->i_x_margin; pen_x = p_string->i_x_margin;
} }
for( i = 0; i < strlen( p_string->psz_text ); i++ ) for( i = 0; p_string->pp_glyphs[i] != NULL; i++ )
{ {
if( p_string->pp_glyphs[i] ) if( p_string->pp_glyphs[i] )
{ {
...@@ -433,14 +249,14 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -433,14 +249,14 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
0 ); 0 );
if ( i_error ) continue; if ( i_error ) continue;
p_image = (FT_BitmapGlyph)p_glyph; p_image = (FT_BitmapGlyph)p_glyph;
#define alpha p_vout->p_sys->pi_gamma[p_image->bitmap.buffer[x+ y*p_image->bitmap.width]] #define alpha p_vout->p_text_renderer_data->pi_gamma[p_image->bitmap.buffer[x+ y*p_image->bitmap.width]]
#define pixel p_out[(p_string->p_glyph_pos[i].y + pen_y + y - p_image->top)*i_out_pitch+x+pen_x+p_string->p_glyph_pos[i].x+p_image->left] #define pixel p_in[(p_string->p_glyph_pos[i].y + pen_y + y - p_image->top)*i_pitch+x+pen_x+p_string->p_glyph_pos[i].x+p_image->left]
for(y = 0; y < p_image->bitmap.rows; y++ ) for(y = 0; y < p_image->bitmap.rows; y++ )
{ {
for( x = 0; x < p_image->bitmap.width; x++ ) for( x = 0; x < p_image->bitmap.width; x++ )
{ {
// pixel = alpha; // pixel = alpha;
// pixel = (pixel^alpha)^pixel; // pixel = (pixel^alpha)^pixel;
pixel = ((pixel*(255-alpha))>>8) + (255*alpha>>8); pixel = ((pixel*(255-alpha))>>8) + (255*alpha>>8);
} }
} }
...@@ -449,109 +265,104 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -449,109 +265,104 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
} }
} }
} }
}
vlc_mutex_unlock( p_vout->p_sys->lock );
vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
} }
static int SetMargin ( vlc_object_t *p_this, char const *psz_command, /**
vlc_value_t oldval, vlc_value_t newval, void *p_data ) * This function receives a string and creates a subpicture for it. It
* also calculates the size needed for this string, and renders the
* needed glyphs into memory. It is used as pf_add_string callback in
* the vout method by this module
*/
static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
text_style_t *p_style, int i_flags, int i_hmargin,
int i_vmargin, mtime_t i_start, mtime_t i_stop )
{ {
vout_thread_t *p_vout = (vout_thread_t*)p_this; subpicture_sys_t *p_string;
if( !strcmp( psz_command, "x-margin" ) ) int i, i_pen_y, i_pen_x, i_error, i_glyph_index, i_previous, i_char;
{ subpicture_t *p_subpic;
p_vout->p_sys->i_x_margin = newval.i_int; FT_BBox line;
} FT_BBox glyph_size;
else if( !strcmp( psz_command, "y-margin" ) ) FT_Vector result;
{
p_vout->p_sys->i_y_margin = newval.i_int; result.x = 0;
} result.y = 0;
else if( !strcmp( psz_command, "duration" ) ) line.xMin = 0;
{ line.xMax = 0;
p_vout->p_sys->i_duration = newval.i_int; line.yMin = 0;
msg_Dbg( p_vout, "setting duration %d", p_vout->p_sys->i_duration ); line.yMax = 0;
}
else if( !strcmp( psz_command, "start-date" ) ) /* Create and initialize a subpicture */
{ p_subpic = vout_CreateSubPicture( p_vout, MEMORY_SUBPICTURE );
p_vout->p_sys->i_start_date = ( (mtime_t) newval.time.i_high << 32 ) if ( p_subpic == NULL )
+ newval.time.i_low;
}
else if( !strcmp( psz_command, "end-date" ) )
{ {
p_vout->p_sys->i_end_date = ( (mtime_t) newval.time.i_high << 32 ) return VLC_EGENERIC;
+ newval.time.i_low;
} }
else if( !strcmp( psz_command, "flags" ) ) p_subpic->pf_render = Render;
p_subpic->pf_destroy = FreeString;
p_subpic->i_start = i_start;
p_subpic->i_stop = i_stop;
if( i_stop == 0 )
{ {
p_vout->p_sys->i_flags = newval.i_int; p_subpic->b_ephemer = VLC_TRUE;
} }
else else
{ {
msg_Err( p_vout, "Invalid command" ); p_subpic->b_ephemer = VLC_FALSE;
return VLC_EGENERIC;
} }
return VLC_SUCCESS;
}
static int AddText ( vlc_object_t *p_this, char const *psz_command,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
vout_thread_t *p_vout = (vout_thread_t*)p_this;
string_info_t **pp_string;
string_info_t *p_string;
char *psz_string;
int i, i_pen_x, i_error, i_glyph_index, i_previous;
p_string = malloc( sizeof(string_info_t) ); /* Create and initialize private data for the subpicture */
p_string->i_flags = p_vout->p_sys->i_flags; p_string = malloc( sizeof(subpicture_sys_t) );
p_string->i_x_margin = p_vout->p_sys->i_x_margin; if ( p_string == NULL )
p_string->i_y_margin = p_vout->p_sys->i_y_margin;
if( p_vout->p_sys->i_start_date && p_vout->p_sys->i_end_date )
{ {
p_string->i_end_date = p_vout->p_sys->i_end_date; vout_DestroySubPicture( p_vout, p_subpic );
p_string->i_start_date = p_vout->p_sys->i_start_date; return VLC_ENOMEM;
}
else
{
p_string->i_end_date = mdate() + p_vout->p_sys->i_duration;
p_string->i_start_date = 0;
} }
p_vout->p_sys->i_end_date = 0; p_subpic->p_sys = p_string;
p_vout->p_sys->i_start_date = 0; p_string->i_flags = i_flags;
p_string->psz_text = strdup( newval.psz_string ); p_string->i_x_margin = i_hmargin;
p_string->i_y_margin = i_vmargin;
p_string->psz_text = strdup( psz_string );
p_string->pp_glyphs = malloc( sizeof(FT_GlyphSlot) p_string->pp_glyphs = malloc( sizeof(FT_GlyphSlot)
* strlen( p_string->psz_text ) ); * ( strlen( p_string->psz_text ) + 1 ) );
if( p_string->pp_glyphs == NULL ) if( p_string->pp_glyphs == NULL )
{ {
msg_Err( p_this, "Out of memory" ); msg_Err( p_vout, "Out of memory" );
return VLC_ENOMEM; return VLC_ENOMEM;
} }
p_string->p_glyph_pos = malloc( sizeof( FT_Vector ) p_string->p_glyph_pos = malloc( sizeof( FT_Vector )
* strlen( p_string->psz_text ) ); * strlen( p_string->psz_text ) );
if( p_string->p_glyph_pos == NULL ) if( p_string->p_glyph_pos == NULL )
{ {
msg_Err( p_this, "Out of memory" ); msg_Err( p_vout, "Out of memory" );
return VLC_ENOMEM; return VLC_ENOMEM;
} }
/* Calculate relative glyph positions and a bounding box for the /* Calculate relative glyph positions and a bounding box for the
* entire string */ * entire string */
i_pen_x = 0; i_pen_x = 0;
i_pen_y = 0;
i_previous = 0; i_previous = 0;
psz_string = p_string->psz_text; i = 0;
for( i = 0; *psz_string; i++, psz_string++ ) while( *psz_string )
{ {
#define face p_vout->p_sys->p_face i_char = GetUnicodeCharFromUTF8( &psz_string );
#define face p_vout->p_text_renderer_data->p_face
#define glyph face->glyph #define glyph face->glyph
if ( *psz_string == '\n' ) if ( i_char == '\n' )
{ {
i_pen_x = 0; i_pen_x = 0;
p_string->pp_glyphs[ i ] = NULL; result.x = __MAX( result.x, line.xMax );
result.y += line.yMax - line.yMin;
line.xMin = 0;
line.xMax = 0;
line.yMin = 0;
line.yMax = 0;
i_pen_y = result.y + 1;
continue; continue;
} }
i_glyph_index = FT_Get_Char_Index( face, *psz_string); i_glyph_index = FT_Get_Char_Index( face, i_char );
if ( p_vout->p_sys->i_use_kerning && i_glyph_index if ( p_vout->p_text_renderer_data->i_use_kerning && i_glyph_index
&& i_previous ) && i_previous )
{ {
FT_Vector delta; FT_Vector delta;
...@@ -561,111 +372,97 @@ static int AddText ( vlc_object_t *p_this, char const *psz_command, ...@@ -561,111 +372,97 @@ static int AddText ( vlc_object_t *p_this, char const *psz_command,
} }
p_string->p_glyph_pos[ i ].x = i_pen_x; p_string->p_glyph_pos[ i ].x = i_pen_x;
p_string->p_glyph_pos[ i ].y = 0; p_string->p_glyph_pos[ i ].y = i_pen_y;
i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_DEFAULT ); i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_DEFAULT );
if ( i_error ) if ( i_error )
{ {
msg_Err( p_this, "FT_Load_Glyph returned %d", i_error ); msg_Err( p_vout, "FT_Load_Glyph returned %d", i_error );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
i_error = FT_Get_Glyph( glyph, &p_string->pp_glyphs[ i ] ); i_error = FT_Get_Glyph( glyph, &p_string->pp_glyphs[ i ] );
if ( i_error ) if ( i_error )
{ {
msg_Err( p_this, "FT_Get_Glyph returned %d", i_error ); msg_Err( p_vout, "FT_Get_Glyph returned %d", i_error );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
i_previous = i_glyph_index;
i_pen_x += glyph->advance.x >> 6;
}
ComputeBoundingBox( p_string );
msg_Dbg( p_this, "string height is %d width is %d", p_string->i_height, p_string->i_width );
p_string->p_next = NULL;
msg_Dbg( p_this, "adding string \"%s\" at (%d,%d) start_date "I64Fd
" end_date" I64Fd, p_string->psz_text, p_string->i_x_margin,
p_string->i_y_margin, p_string->i_start_date,
p_string->i_end_date );
vlc_mutex_lock( p_vout->p_sys->lock );
pp_string = &p_vout->p_sys->p_strings;
while( *pp_string && (*pp_string)->i_end_date < p_string->i_end_date )
{
pp_string = &(*pp_string)->p_next;
}
p_string->p_next = (*pp_string);
*pp_string = p_string;
vlc_mutex_unlock( p_vout->p_sys->lock );
return VLC_SUCCESS;
}
static void ComputeBoundingBox( string_info_t *p_string )
{
unsigned int i;
int i_pen_y = 0;
int i_firstline_height = 0;
FT_Vector result;
FT_BBox line;
FT_BBox glyph_size;
result.x = 0;
result.y = 0;
line.xMin = 0;
line.xMax = 0;
line.yMin = 0;
line.yMax = 0;
for ( i = 0; i < strlen( p_string->psz_text ); i++ )
{
if ( p_string->psz_text[i] == '\n' )
{
result.x = __MAX( result.x, line.xMax );
result.y += line.yMax - line.yMin;
if ( !i_firstline_height )
{
i_firstline_height = result.y;
}
line.xMin = 0;
line.xMax = 0;
line.yMin = 0;
line.yMax = 0;
i_pen_y = result.y + 1;
continue;
}
p_string->p_glyph_pos[ i ].y = i_pen_y;
FT_Glyph_Get_CBox( p_string->pp_glyphs[i], FT_Glyph_Get_CBox( p_string->pp_glyphs[i],
ft_glyph_bbox_pixels, &glyph_size ); ft_glyph_bbox_pixels, &glyph_size );
/* Do rest */ /* Do rest */
line.xMax = p_string->p_glyph_pos[i].x + glyph_size.xMax - glyph_size.xMin; line.xMax = p_string->p_glyph_pos[i].x + glyph_size.xMax - glyph_size.xMin;
line.yMax = __MAX( line.yMax, glyph_size.yMax ); line.yMax = __MAX( line.yMax, glyph_size.yMax );
line.yMin = __MIN( line.yMin, glyph_size.yMin ); line.yMin = __MIN( line.yMin, glyph_size.yMin );
i_previous = i_glyph_index;
i_pen_x += glyph->advance.x >> 6;
i++;
} }
p_string->pp_glyphs[i] = NULL;
result.x = __MAX( result.x, line.xMax ); result.x = __MAX( result.x, line.xMax );
result.y += line.yMax - line.yMin; result.y += line.yMax - line.yMin;
p_string->i_height = result.y; p_string->i_height = result.y;
p_string->i_width = result.x; p_string->i_width = result.x;
if ( !i_firstline_height ) msg_Dbg( p_vout, "string height is %d, width is %d", p_string->i_height, p_string->i_width );
{ msg_Dbg( p_vout, "adding string \"%s\" at (%d,%d) start_date "I64Fd
i_firstline_height = result.y; " end_date" I64Fd, p_string->psz_text, p_string->i_x_margin,
} p_string->i_y_margin, i_start, i_stop );
for ( i = 0; i < strlen( p_string->psz_text ); i++ ) vout_DisplaySubPicture( p_vout, p_subpic );
{ return VLC_SUCCESS;
p_string->p_glyph_pos[ i ].y += i_firstline_height;
}
return;
} }
static void FreeString( string_info_t *p_string ) static void FreeString( subpicture_t *p_subpic )
{ {
unsigned int i; unsigned int i;
for ( i = 0; i < strlen( p_string->psz_text ); i++ ) subpicture_sys_t *p_string = p_subpic->p_sys;
{ for ( i = 0; p_string->pp_glyphs[ i ] != NULL; i++ )
if ( p_string->pp_glyphs[ i ] )
{ {
FT_Done_Glyph( p_string->pp_glyphs[ i ] ); FT_Done_Glyph( p_string->pp_glyphs[ i ] );
} }
}
free( p_string->psz_text ); free( p_string->psz_text );
free( p_string->p_glyph_pos ); free( p_string->p_glyph_pos );
free( p_string->pp_glyphs ); free( p_string->pp_glyphs );
free( p_string ); free( p_string );
} }
/* convert one or more utf8 bytes into a unicode character */
static int GetUnicodeCharFromUTF8( byte_t **ppsz_utf8_string )
{
int i_remaining_bytes, i_char = 0;
if( ( **ppsz_utf8_string & 0xFC ) == 0xFC )
{
i_char = **ppsz_utf8_string & 1;
i_remaining_bytes = 5;
}
else if( ( **ppsz_utf8_string & 0xF8 ) == 0xF8 )
{
i_char = **ppsz_utf8_string & 3;
i_remaining_bytes = 4;
}
else if( ( **ppsz_utf8_string & 0xF0 ) == 0xF0 )
{
i_char = **ppsz_utf8_string & 7;
i_remaining_bytes = 3;
}
else if( ( **ppsz_utf8_string & 0xE0 ) == 0xE0 )
{
i_char = **ppsz_utf8_string & 15;
i_remaining_bytes = 2;
}
else if( ( **ppsz_utf8_string & 0xC0 ) == 0xC0 )
{
i_char = **ppsz_utf8_string & 31;
i_remaining_bytes = 1;
}
else
{
i_char = **ppsz_utf8_string;
i_remaining_bytes = 0;
}
while( i_remaining_bytes )
{
(*ppsz_utf8_string)++;
i_remaining_bytes--;
i_char = ( i_char << 6 ) + ( **ppsz_utf8_string & 0x3F );
}
(*ppsz_utf8_string)++;
return i_char;
}
...@@ -6,6 +6,5 @@ SOURCES_wall = wall.c ...@@ -6,6 +6,5 @@ SOURCES_wall = wall.c
SOURCES_clone = clone.c SOURCES_clone = clone.c
SOURCES_crop = crop.c SOURCES_crop = crop.c
SOURCES_motionblur = motionblur.c SOURCES_motionblur = motionblur.c
SOURCES_osdtext = osd_text.c
SOURCES_logo = logo.c SOURCES_logo = logo.c
noinst_HEADERS += filter_common.h noinst_HEADERS += filter_common.h
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* modules.c : Builtin and plugin modules management functions * modules.c : Builtin and plugin modules management functions
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: modules.c,v 1.124 2003/07/01 12:56:47 sam Exp $ * $Id: modules.c,v 1.125 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* Ethan C. Baldridge <BaldridgeE@cadmus.com> * Ethan C. Baldridge <BaldridgeE@cadmus.com>
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
#include "stream_output.h" #include "stream_output.h"
#include "announce.h" #include "announce.h"
#include "osd.h"
#include "iso_lang.h" #include "iso_lang.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread. * thread, and destroy a previously oppened video output thread.
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: video_output.c,v 1.228 2003/06/28 21:18:58 fenrir Exp $ * $Id: video_output.c,v 1.229 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* *
...@@ -382,7 +382,13 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, ...@@ -382,7 +382,13 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent,
vlc_object_destroy( p_vout ); vlc_object_destroy( p_vout );
return NULL; return NULL;
} }
p_vout->p_text_renderer_module = module_Need( p_vout, "text renderer",
NULL );
if( p_vout->p_text_renderer_module == NULL )
{
msg_Warn( p_vout, "no suitable text renderer module" );
p_vout->pf_add_string = NULL;
}
/* Create a few object variables for interface interaction */ /* Create a few object variables for interface interaction */
var_Create( p_vout, "fullscreen", VLC_VAR_BOOL ); var_Create( p_vout, "fullscreen", VLC_VAR_BOOL );
text.psz_string = _("Fullscreen"); text.psz_string = _("Fullscreen");
...@@ -1030,6 +1036,8 @@ static void EndThread( vout_thread_t *p_vout ) ...@@ -1030,6 +1036,8 @@ static void EndThread( vout_thread_t *p_vout )
} }
} }
module_Unneed( p_vout, p_vout->p_text_renderer_module );
/* Destroy translation tables */ /* Destroy translation tables */
p_vout->pf_end( p_vout ); p_vout->pf_end( p_vout );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* video_text.c : text manipulation functions * video_text.c : text manipulation functions
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: video_text.c,v 1.43 2003/06/26 12:19:59 sam Exp $ * $Id: video_text.c,v 1.44 2003/07/14 21:32:59 sigmunau Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -21,6 +21,66 @@ ...@@ -21,6 +21,66 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#include <vlc/vout.h>
/**
* \brief Show text on the video for some time
* \param p_vout pointer to the vout the text is to be showed on
* \param psz_string The text to be shown
* \param p_style Pointer to a struct with text style info
* \param i_flags flags for alignment and such
* \param i_hmargin horizontal margin in pixels
* \param i_vmargin vertical margin in pixels
* \param i_duration Amount of time the text is to be shown.
*/
void vout_ShowTextRelative( vout_thread_t *p_vout, char *psz_string,
text_style_t *p_style, int i_flags,
int i_hmargin, int i_vmargin,
mtime_t i_duration )
{
mtime_t i_now = mdate();
if ( p_vout->pf_add_string )
{
p_vout->pf_add_string( p_vout, psz_string, p_style, i_flags, i_hmargin,
i_vmargin, i_now, i_now + i_duration );
}
else
{
msg_Warn( p_vout, "No text renderer found" );
}
}
/**
* \brief Show text on the video from a given start date to a given end date
* \param p_vout pointer to the vout the text is to be showed on
* \param psz_string The text to be shown
* \param p_style Pointer to a struct with text style info
* \param i_flags flags for alignment and such
* \param i_hmargin horizontal margin in pixels
* \param i_vmargin vertical margin in pixels
* \param i_start the time when this string is to appear on the video
* \param i_stop the time when this string should stop to be displayed
* if this is 0 the string will be shown untill the next string
* is about to be shown
*/
void vout_ShowTextAbsolute( vout_thread_t *p_vout, char *psz_string,
text_style_t *p_style, int i_flags,
int i_hmargin, int i_vmargin, mtime_t i_start,
mtime_t i_stop )
{
if ( p_vout->pf_add_string )
{
p_vout->pf_add_string( p_vout, psz_string, p_style, i_flags, i_hmargin,
i_vmargin, i_start, i_stop );
}
else
{
msg_Warn( p_vout, "No text renderer found" );
}
}
/* XXX: unused */ /* XXX: unused */
#if 0 #if 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment