1 /*****************************************************************************
2 * fbosd.c : framebuffer osd plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2007, the VideoLAN team
5 * $Id: vlc-fb-overlay.patch,v 1.8 2007/10/19 14:33:23 jeanpaul.saman Exp $
7 * Authors: Jean-Paul Saman
8 * Copied from modules/video_output/fb.c by Samuel Hocevar <sam@zoy.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
35 #include <stdlib.h> /* free() */
36 #include <string.h> /* strerror() */
37 #include <fcntl.h> /* open() */
38 #include <unistd.h> /* close() */
40 #include <sys/ioctl.h>
41 #include <sys/mman.h> /* mmap() */
45 #include <vlc_image.h>
46 #include <vlc_interface.h>
47 #include <vlc_input.h>
49 #include <vlc_filter.h>
51 #include <vlc_strings.h>
53 // #define FBOSD_BLENDING 1
55 /*****************************************************************************
57 *****************************************************************************/
58 static int Create ( vlc_object_t * );
59 static void Destroy ( vlc_object_t * );
60 static void Run ( intf_thread_t * );
62 static int Init ( intf_thread_t * );
63 static void End ( intf_thread_t * );
65 static int OpenDisplay ( intf_thread_t * );
66 static void CloseDisplay ( intf_thread_t * );
68 /* Load modules needed for rendering and blending */
70 static int OpenBlending ( intf_thread_t * );
71 static void CloseBlending ( intf_thread_t * );
73 static int OpenTextRenderer ( intf_thread_t * );
74 static void CloseTextRenderer( intf_thread_t * );
77 static int OpenScaling ( intf_thread_t * );
78 static int CloseScaling ( intf_thread_t * );
81 /* Manipulate the overlay buffer */
82 static int OverlayCallback( vlc_object_t *, char const *,
83 vlc_value_t, vlc_value_t, void * );
85 static picture_t *AllocatePicture( vlc_object_t *,
87 static void DeAllocatePicture( vlc_object_t *, picture_t *,
89 static void SetOverlayTransparency( intf_thread_t *,
91 static picture_t *LoadImage( intf_thread_t *, video_format_t *,
95 static int BlendPicture( intf_thread_t *, video_format_t *,
96 video_format_t *, picture_t *, picture_t * );
98 static picture_t *ConvertImage( intf_thread_t *, picture_t *,
99 video_format_t *, video_format_t * );
101 static int RenderPicture( intf_thread_t *, int, int,
102 picture_t *, picture_t * );
103 static picture_t *RenderText( intf_thread_t *, const char *,
106 #define DEVICE_TEXT N_("Framebuffer device")
107 #define DEVICE_LONGTEXT N_( \
108 "Framebuffer device to use for rendering (usually /dev/fb0).")
110 #define ASPECT_RATIO_TEXT N_("Video aspect ratio")
111 #define ASPECT_RATIO_LONGTEXT N_( \
112 "Aspect ratio of the video image (4:3, 16:9). Default is square pixels." )
114 #define FBOSD_IMAGE_TEXT N_("Image file")
115 #define FBOSD_IMAGE_LONGTEXT N_( \
116 "Filename of image file to use on the overlay framebuffer." )
118 #define ALPHA_TEXT N_("Transparency of the image")
119 #define ALPHA_LONGTEXT N_( "Transparency value of the new image " \
120 "used in blending. By default it set to fully opaque (255). " \
121 "(from 0 for full transparency to 255 for full opacity)" )
123 #define FBOSD_TEXT N_("Text")
124 #define FBOSD_LONGTEXT N_( "Text to display on the overlay framebuffer." )
126 #define POSX_TEXT N_("X coordinate")
127 #define POSX_LONGTEXT N_("X coordinate of the rendered image")
129 #define POSY_TEXT N_("Y coordinate")
130 #define POSY_LONGTEXT N_("Y coordinate of the rendered image")
132 #define POS_TEXT N_("Position")
133 #define POS_LONGTEXT N_( \
134 "You can enforce the picture position on the overlay " \
135 "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
136 "also use combinations of these values, e.g. 6=top-right).")
138 #define OPACITY_TEXT N_("Opacity")
139 #define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
140 "overlayed text. 0 = transparent, 255 = totally opaque. " )
142 #define SIZE_TEXT N_("Font size, pixels")
143 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
146 #define COLOR_TEXT N_("Color")
147 #define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
148 "the video. This must be an hexadecimal (like HTML colors). The first two "\
149 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
150 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
152 #define CLEAR_TEXT N_( "Clear overlay framebuffer" )
153 #define CLEAR_LONGTEXT N_( "The displayed overlay images is cleared by " \
154 "making the overlay completely transparent. All previously rendered " \
155 "images and text will be cleared from the cache." )
157 #define RENDER_TEXT N_( "Render text or image" )
158 #define RENDER_LONGTEXT N_( "Render the image or text in current overlay " \
161 #define DISPLAY_TEXT N_( "Display on overlay framebuffer" )
162 #define DISPLAY_LONGTEXT N_( "All rendered images and text will be " \
163 "displayed on the overlay framebuffer." )
165 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
166 static const char *ppsz_pos_descriptions[] =
167 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
168 N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
170 static int pi_color_values[] = { 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
171 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
172 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
173 0x00000080, 0x000000FF, 0x0000FFFF};
174 static const char *ppsz_color_descriptions[] = { N_("Default"), N_("Black"),
175 N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
176 N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
177 N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
181 set_shortname( "fbosd" );
182 set_category( CAT_INTERFACE );
183 set_subcategory( SUBCAT_INTERFACE_MAIN );
185 add_file( "fbosd-dev", "/dev/fb1", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
187 add_string( "fbosd-aspect-ratio", "", NULL, ASPECT_RATIO_TEXT,
188 ASPECT_RATIO_LONGTEXT, VLC_TRUE );
190 add_string( "fbosd-image", NULL, NULL, FBOSD_IMAGE_TEXT,
191 FBOSD_IMAGE_LONGTEXT, VLC_TRUE );
192 add_string( "fbosd-text", NULL, NULL, FBOSD_TEXT,
193 FBOSD_LONGTEXT, VLC_TRUE );
195 #ifdef FBOSD_BLENDING
196 add_integer_with_range( "fbosd-alpha", 255, 0, 255, NULL, ALPHA_TEXT,
197 ALPHA_LONGTEXT, VLC_TRUE );
201 set_section( N_("Position"), NULL );
202 add_integer( "fbosd-x", 0, NULL, POSX_TEXT,
203 POSX_LONGTEXT, VLC_FALSE );
204 add_integer( "fbosd-y", 0, NULL, POSY_TEXT,
205 POSY_LONGTEXT, VLC_FALSE );
206 add_integer( "fbosd-position", 8, NULL, POS_TEXT, POS_LONGTEXT, VLC_TRUE );
207 change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
209 set_section( N_("Font"), NULL );
210 add_integer_with_range( "fbosd-font-opacity", 255, 0, 255, NULL,
211 OPACITY_TEXT, OPACITY_LONGTEXT, VLC_FALSE );
212 add_integer( "fbosd-font-color", 0x00FFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT,
214 change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
215 add_integer( "fbosd-font-size", -1, NULL, SIZE_TEXT, SIZE_LONGTEXT,
218 set_section( N_("Commands"), NULL );
219 add_bool( "fbosd-clear", VLC_FALSE, NULL, CLEAR_TEXT, CLEAR_LONGTEXT, VLC_TRUE );
220 add_bool( "fbosd-render", VLC_FALSE, NULL, RENDER_TEXT, RENDER_LONGTEXT, VLC_TRUE );
221 add_bool( "fbosd-display", VLC_FALSE, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, VLC_TRUE );
223 set_description( _("GNU/Linux osd/overlay framebuffer interface") );
224 set_capability( "interface", 10 );
225 set_callbacks( Create, Destroy );
228 /*****************************************************************************
229 * intf_sys_t: interface framebuffer method descriptor
230 *****************************************************************************/
233 /* Framebuffer information */
234 int i_fd; /* device handle */
235 struct fb_var_screeninfo var_info; /* current mode information */
236 vlc_bool_t b_pan; /* does device supports panning ? */
237 struct fb_cmap fb_cmap; /* original colormap */
238 uint16_t *p_palette; /* original palette */
240 /* Overlay framebuffer format */
241 video_format_t fmt_out;
242 picture_t *p_overlay;
243 size_t i_page_size; /* page size */
247 int i_bytes_per_pixel;
249 /* Image and Picture rendering */
250 image_handler_t *p_image;
251 #ifdef FBOSD_BLENDING
252 filter_t *p_blend; /* alpha blending module */
254 filter_t *p_text; /* text renderer module */
256 filter_t *p_scale; /* scaling module */
258 vlc_bool_t b_force_crop; /* force cropping of picture */
259 int i_crop_x, i_crop_y, i_crop_width, i_crop_height; /* cropping */
269 text_style_t *p_style; /* font control */
271 /* Positon of image/text */
272 vlc_bool_t b_absolute;
277 int i_alpha; /* transparency for images */
279 /* commands control */
280 vlc_bool_t b_need_update; /* update display with \overlay buffer */
281 vlc_bool_t b_clear; /* clear overlay buffer make it tranparent */
282 vlc_bool_t b_render; /* render an image or text in overlay buffer */
285 /*****************************************************************************
286 * Create: allocates FB interface thread output method
287 *****************************************************************************/
288 static int Create( vlc_object_t *p_this )
290 intf_thread_t *p_intf = (intf_thread_t *)p_this;
294 /* Allocate instance and initialize some members */
295 p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) );
298 msg_Err( p_intf, "out of memory" );
301 memset( p_sys, 0, sizeof(intf_sys_t) );
303 p_sys->p_style = malloc( sizeof( text_style_t ) );
304 if( !p_sys->p_style )
306 free( p_intf->p_sys );
307 msg_Err( p_intf, "out of memory" );
310 p_intf->p_libvlc->pf_memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
312 p_intf->pf_run = Run;
314 p_sys->p_image = image_HandlerCreate( p_this );
315 if( !p_sys->p_image )
317 free( p_intf->p_sys->p_style );
318 free( p_intf->p_sys );
319 msg_Err( p_intf, "out of memory" );
323 #ifdef FBOSD_BLENDING
324 p_sys->i_alpha = var_CreateGetIntegerCommand( p_intf, "fbosd-alpha" );
325 var_AddCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
327 p_sys->i_alpha = 255;
329 p_sys->i_aspect = -1;
331 var_CreateGetNonEmptyString( p_intf, "fbosd-aspect-ratio" );
334 char *psz_parser = strchr( psz_aspect, ':' );
338 *psz_parser++ = '\0';
339 p_sys->i_aspect = ( atoi( psz_aspect )
340 * VOUT_ASPECT_FACTOR ) / atoi( psz_parser );
341 p_sys->fmt_out.i_aspect = p_sys->i_aspect;
343 msg_Dbg( p_intf, "using aspect ratio %d:%d",
344 atoi( psz_aspect ), atoi( psz_parser ) );
350 /* Use PAL by default */
351 p_sys->i_width = p_sys->fmt_out.i_width = 704;
352 p_sys->i_height = p_sys->fmt_out.i_height = 576;
355 var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-image" );
356 var_AddCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
357 if( p_sys->psz_file && *p_sys->psz_file )
358 p_sys->b_image = VLC_TRUE;
361 var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-text" );
362 var_AddCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
363 if( p_sys->psz_text && *p_sys->psz_text )
364 p_sys->b_text = VLC_TRUE;
366 p_sys->i_pos = var_CreateGetIntegerCommand( p_intf, "fbosd-position" );
367 p_sys->i_x = var_CreateGetIntegerCommand( p_intf, "fbosd-x" );
368 p_sys->i_y = var_CreateGetIntegerCommand( p_intf, "fbosd-y" );
370 var_AddCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
371 var_AddCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
372 var_AddCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
374 p_sys->p_style->i_font_size =
375 var_CreateGetIntegerCommand( p_intf, "fbosd-font-size" );
376 p_sys->p_style->i_font_color =
377 var_CreateGetIntegerCommand( p_intf, "fbosd-font-color" );
378 p_sys->p_style->i_font_alpha = 255 -
379 var_CreateGetIntegerCommand( p_intf, "fbosd-font-opacity" );
381 var_AddCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
382 var_AddCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
383 var_AddCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
385 p_sys->b_clear = var_CreateGetBoolCommand( p_intf, "fbosd-clear" );
386 p_sys->b_render = var_CreateGetBoolCommand( p_intf, "fbosd-render" );
387 p_sys->b_need_update = var_CreateGetBoolCommand( p_intf, "fbosd-display" );
389 var_AddCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
390 var_AddCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
391 var_AddCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
393 /* Check if picture position was overridden */
394 p_sys->b_absolute = VLC_TRUE;
395 if( ( p_sys->i_x >= 0 ) && ( p_sys->i_y >= 0 ) )
397 p_sys->b_absolute = VLC_FALSE;
398 p_sys->i_y = (p_sys->i_y < p_sys->i_height) ?
399 p_sys->i_y : p_sys->i_height;
400 p_sys->i_x = (p_sys->i_x < p_sys->i_width) ?
401 p_sys->i_x : p_sys->i_width;
404 /* Initialize framebuffer */
405 if( OpenDisplay( p_intf ) )
407 Destroy( VLC_OBJECT(p_intf) );
413 #ifdef FBOSD_BLENDING
414 /* Load the blending module */
415 if( OpenBlending( p_intf ) )
417 msg_Err( p_intf, "Unable to load image blending module" );
418 Destroy( VLC_OBJECT(p_intf) );
423 /* Load text renderer module */
424 if( OpenTextRenderer( p_intf ) )
426 msg_Err( p_intf, "Unable to load text rendering module" );
427 Destroy( VLC_OBJECT(p_intf) );
431 /* Load scaling module */
432 if( OpenScaling( p_intf ) )
434 msg_Err( p_intf, "Unable to load image scaling module" );
435 Destroy( VLC_OBJECT(p_intf) );
439 p_sys->b_render = VLC_TRUE;
440 p_sys->b_need_update = VLC_TRUE;
445 /*****************************************************************************
446 * Destroy: destroy FB interface thread output method
447 *****************************************************************************
448 * Terminate an output method created by Create
449 *****************************************************************************/
450 static void Destroy( vlc_object_t *p_this )
452 intf_thread_t *p_intf = (intf_thread_t *)p_this;
453 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
455 p_sys->b_need_update = VLC_FALSE;
456 p_sys->b_render = VLC_FALSE;
457 p_sys->b_clear = VLC_FALSE;
459 #ifdef FBOSD_BLENDING
460 var_DelCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
461 var_Destroy( p_intf, "fbosd-alpha" );
464 var_DelCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
465 var_DelCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
466 var_DelCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
467 var_DelCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
468 var_DelCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
469 var_DelCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
470 var_DelCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
471 var_DelCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
472 var_DelCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
473 var_DelCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
474 var_DelCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
476 var_Destroy( p_intf, "fbosd-x" );
477 var_Destroy( p_intf, "fbosd-y" );
478 var_Destroy( p_intf, "fbosd-position" );
479 var_Destroy( p_intf, "fbosd-image" );
480 var_Destroy( p_intf, "fbosd-text" );
481 var_Destroy( p_intf, "fbosd-font-size" );
482 var_Destroy( p_intf, "fbosd-font-color" );
483 var_Destroy( p_intf, "fbosd-font-opacity" );
484 var_Destroy( p_intf, "fbosd-clear" );
485 var_Destroy( p_intf, "fbosd-render" );
486 var_Destroy( p_intf, "fbosd-display" );
488 var_Destroy( p_intf, "fbosd-aspect-ratio" );
490 CloseDisplay( p_intf );
492 #ifdef FBOSD_BLENDING
493 if( p_sys->p_blend ) CloseBlending( p_intf );
495 if( p_sys->p_text ) CloseTextRenderer( p_intf );
497 if( p_sys->p_scale ) CloseScaling( p_intf );
500 image_HandlerDelete( p_sys->p_image );
501 if( p_sys->p_overlay )
502 p_sys->p_overlay->pf_release( p_sys->p_overlay );
504 free( p_sys->psz_file );
505 free( p_sys->psz_text );
506 free( p_sys->p_style );
510 #ifdef FBOSD_BLENDING
511 static int OpenBlending( intf_thread_t *p_intf )
513 if( p_intf->p_sys->p_blend ) return VLC_EGENERIC;
515 p_intf->p_sys->p_blend =
516 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
517 vlc_object_attach( p_intf->p_sys->p_blend, p_intf );
518 p_intf->p_sys->p_blend->fmt_out.video.i_x_offset =
519 p_intf->p_sys->p_blend->fmt_out.video.i_y_offset = 0;
520 p_intf->p_sys->p_blend->fmt_out.video.i_aspect =
521 p_intf->p_sys->fmt_out.i_aspect;
522 p_intf->p_sys->p_blend->fmt_out.video.i_chroma =
523 p_intf->p_sys->fmt_out.i_chroma;
524 if( config_GetInt( p_intf, "freetype-yuvp" ) )
525 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
526 VLC_FOURCC('Y','U','V','P');
528 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
529 VLC_FOURCC('Y','U','V','A');
531 p_intf->p_sys->p_blend->p_module =
532 module_Need( p_intf->p_sys->p_blend, "video blending", 0, 0 );
534 if( !p_intf->p_sys->p_blend->p_module )
540 static void CloseBlending( intf_thread_t *p_intf )
542 if( p_intf->p_sys->p_blend )
544 if( p_intf->p_sys->p_blend->p_module )
545 module_Unneed( p_intf->p_sys->p_blend,
546 p_intf->p_sys->p_blend->p_module );
548 vlc_object_detach( p_intf->p_sys->p_blend );
549 vlc_object_destroy( p_intf->p_sys->p_blend );
554 static int OpenTextRenderer( intf_thread_t *p_intf )
556 char *psz_modulename = NULL;
558 if( p_intf->p_sys->p_text ) return VLC_EGENERIC;
560 p_intf->p_sys->p_text =
561 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
562 vlc_object_attach( p_intf->p_sys->p_text, p_intf );
564 p_intf->p_sys->p_text->fmt_out.video.i_width =
565 p_intf->p_sys->p_text->fmt_out.video.i_visible_width =
566 p_intf->p_sys->i_width;
567 p_intf->p_sys->p_text->fmt_out.video.i_height =
568 p_intf->p_sys->p_text->fmt_out.video.i_visible_height =
569 p_intf->p_sys->i_height;
571 psz_modulename = var_CreateGetString( p_intf, "text-renderer" );
572 if( psz_modulename && *psz_modulename )
574 p_intf->p_sys->p_text->p_module =
575 module_Need( p_intf->p_sys->p_text, "text renderer",
576 psz_modulename, VLC_TRUE );
578 if( !p_intf->p_sys->p_text->p_module )
580 p_intf->p_sys->p_text->p_module =
581 module_Need( p_intf->p_sys->p_text, "text renderer", 0, 0 );
583 if( psz_modulename ) free( psz_modulename );
585 if( !p_intf->p_sys->p_text->p_module )
591 static void CloseTextRenderer( intf_thread_t *p_intf )
593 if( p_intf->p_sys->p_text )
595 if( p_intf->p_sys->p_text->p_module )
596 module_Unneed( p_intf->p_sys->p_text,
597 p_intf->p_sys->p_text->p_module );
599 vlc_object_detach( p_intf->p_sys->p_text );
600 vlc_object_destroy( p_intf->p_sys->p_text );
604 static int OpenScaling( intf_thread_t *p_intf )
606 if( p_intf->p_sys->p_scale ) return VLC_EGENERIC;
608 p_intf->p_sys->p_scale =
609 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
610 vlc_object_attach( p_intf->p_sys->p_scale, p_intf );
611 p_intf->p_sys->p_scale->fmt_out.video.i_chroma =
612 p_intf->p_sys->p_scale->fmt_in.video.i_chroma =
613 p_intf->p_sys->fmt_out.i_chroma;
615 /* XXX: We'll also be using it for YUVA and RGBA blending ... */
616 p_intf->p_sys->p_scale->fmt_in.video.i_width =
617 p_intf->p_sys->p_scale->fmt_in.video.i_height = 32;
618 p_intf->p_sys->p_scale->fmt_out.video.i_width =
619 p_intf->p_sys->p_scale->fmt_out.video.i_height = 16;
621 p_intf->p_sys->p_scale->p_module =
622 module_Need( p_intf->p_sys->p_scale, "video filter2", 0, 0 );
624 if( !p_intf->p_sys->p_scale->p_module )
630 static int CloseScaling( intf_thread_t *p_intf )
632 if( p_intf->p_sys->p_scale )
634 if( p_intf->p_sys->p_scale->p_module )
635 module_Unneed( p_intf->p_sys->p_scale,
636 p_intf->p_sys->p_scale->p_module );
638 vlc_object_detach( p_intf->p_sys->p_scale );
639 vlc_object_destroy( p_intf->p_sys->p_scale );
644 /*****************************************************************************
646 * allocate a picture buffer for use with the overlay fb.
647 *****************************************************************************/
648 static picture_t *AllocatePicture( vlc_object_t *p_this,
649 video_format_t *p_fmt )
651 picture_t *p_pic = malloc( sizeof( picture_t ) );
652 if( !p_pic ) return NULL;
654 if( !p_fmt->p_palette &&
655 ( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') ) )
657 p_fmt->p_palette = malloc( sizeof(video_palette_t) );
658 if( !p_fmt->p_palette )
664 else p_fmt->p_palette = NULL;
666 p_pic->p_data_orig = NULL;
668 vout_AllocatePicture( p_this, p_pic, p_fmt->i_chroma,
669 p_fmt->i_width, p_fmt->i_height, p_fmt->i_aspect );
671 if( !p_pic->i_planes )
674 free( p_fmt->p_palette );
680 /*****************************************************************************
682 * Deallocate a picture buffer and free all associated memory.
683 *****************************************************************************/
684 static void DeAllocatePicture( vlc_object_t *p_this, picture_t *p_pic,
685 video_format_t *p_fmt )
687 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
688 if( p_pic && p_pic->pf_release ) p_pic->pf_release( p_pic );
689 if( p_fmt && p_fmt->p_palette )
691 free( p_fmt->p_palette );
692 p_fmt->p_palette = NULL;
697 /*****************************************************************************
698 * SetOverlayTransparency: Set the transparency for this overlay fb,
699 * - VLC_TRUE is make transparent
700 * - VLC_FALSE is make non tranparent
701 *****************************************************************************/
702 static void SetOverlayTransparency( intf_thread_t *p_intf,
703 vlc_bool_t b_transparent )
705 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
706 size_t i_size = p_sys->fmt_out.i_width * p_sys->fmt_out.i_height
707 * p_sys->i_bytes_per_pixel;
708 size_t i_page_size = (p_sys->i_page_size > i_size) ?
709 i_size : p_sys->i_page_size;
711 if( p_sys->p_overlay )
713 msg_Dbg( p_intf, "Make overlay %s",
714 b_transparent ? "transparent" : "opaque" );
715 memset( p_sys->p_overlay->p[0].p_pixels, 0x00, i_page_size );
717 memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, i_page_size );
721 #ifdef FBOSD_BLENDING
722 /*****************************************************************************
723 * BlendPicture: Blend two pictures together..
724 *****************************************************************************/
725 static int BlendPicture( intf_thread_t *p_intf, video_format_t *p_fmt_src,
726 video_format_t *p_fmt_dst, picture_t *p_pic_src,
727 picture_t *p_pic_dst )
729 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
730 if( p_sys->p_blend && p_sys->p_blend->p_module )
732 int i_x_offset = p_sys->i_x;
733 int i_y_offset = p_sys->i_y;
735 memcpy( &p_sys->p_blend->fmt_in.video, p_fmt_src, sizeof( video_format_t ) );
737 msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
738 p_pic_src, (char*)&p_fmt_src->i_chroma,
739 p_sys->p_blend->fmt_in.video.i_width, p_sys->p_blend->fmt_in.video.i_height,
740 p_fmt_src->i_bits_per_pixel,
742 p_pic_src->p[0].p_pixels, p_pic_src->p[1].p_pixels,
743 p_pic_src->p[2].p_pixels, p_pic_src->p[3].p_pixels );
744 msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
745 p_pic_dst, (char*)&p_fmt_dst->i_chroma,
746 p_fmt_dst->i_width, p_fmt_dst->i_height,
747 p_fmt_dst->i_bits_per_pixel,
749 p_pic_dst->p[0].p_pixels, p_pic_dst->p[1].p_pixels,
750 p_pic_dst->p[2].p_pixels, p_pic_dst->p[3].p_pixels );
752 /* Update the output picture size */
753 p_sys->p_blend->fmt_out.video.i_width =
754 p_sys->p_blend->fmt_out.video.i_visible_width =
756 p_sys->p_blend->fmt_out.video.i_height =
757 p_sys->p_blend->fmt_out.video.i_visible_height =
760 i_x_offset = __MAX( i_x_offset, 0 );
761 i_y_offset = __MAX( i_y_offset, 0 );
763 p_sys->p_blend->pf_video_blend( p_sys->p_blend, p_pic_dst,
764 p_pic_src, p_pic_dst, i_x_offset, i_y_offset,
773 /*****************************************************************************
774 * RenderPicture: Render the picture into the p_dest buffer.
775 * We don't take transparent pixels into account, so we don't have to blend
776 * the two images together.
777 *****************************************************************************/
778 static int RenderPicture( intf_thread_t *p_intf, int i_x_offset, int i_y_offset,
779 picture_t *p_src, picture_t *p_dest )
783 if( !p_dest && !p_src ) return VLC_EGENERIC;
785 for( i = 0; i < p_src->i_planes ; i++ )
787 if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
789 /* There are margins, but with the same width : perfect ! */
790 p_intf->p_libvlc->pf_memcpy(
791 p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
792 p_src->p[i].i_pitch * p_src->p[i].i_visible_lines );
796 /* We need to proceed line by line */
797 uint8_t *p_in = p_src->p[i].p_pixels;
798 uint8_t *p_out = p_dest->p[i].p_pixels;
800 int i_x = i_x_offset * p_src->p[i].i_pixel_pitch;
801 int i_x_clip, i_y_clip;
803 /* Check boundaries, clip the image if necessary */
804 i_x_clip = ( i_x + p_src->p[i].i_visible_pitch ) - p_dest->p[i].i_visible_pitch;
805 i_x_clip = ( i_x_clip > 0 ) ? i_x_clip : 0;
807 i_y_clip = ( i_y_offset + p_src->p[i].i_visible_lines ) - p_dest->p[i].i_visible_lines;
808 i_y_clip = ( i_y_clip > 0 ) ? i_y_clip : 0;
810 msg_Dbg( p_intf, "i_pitch (%d,%d), (%d,%d)/(%d,%d)",
811 p_dest->p[i].i_visible_pitch, p_src->p[i].i_visible_pitch,
812 i_x_offset, i_y_offset, i_x, i_x_clip );
814 if( ( i_y_offset <= p_dest->p[i].i_visible_lines ) &&
815 ( i_x <= p_dest->p[i].i_visible_pitch ) )
819 p_out += ( i_y_offset * p_dest->p[i].i_pitch );
820 for( i_line = 0; i_line < ( p_src->p[i].i_visible_lines - i_y_clip ); i_line++ )
822 p_intf->p_libvlc->pf_memcpy( p_out + i_x, p_in,
823 p_src->p[i].i_visible_pitch - i_x_clip );
824 p_in += p_src->p[i].i_pitch;
825 p_out += p_dest->p[i].i_pitch;
833 /*****************************************************************************
834 * RenderText - Render text to the desired picture format
835 *****************************************************************************/
836 static picture_t *RenderText( intf_thread_t *p_intf, const char *psz_text,
837 video_format_t *p_fmt )
839 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
840 subpicture_region_t *p_region;
841 picture_t *p_dest = NULL;
843 if( !psz_text ) return p_dest;
845 if( p_sys->p_text && p_sys->p_text->p_module )
847 p_region = (subpicture_region_t *) malloc( sizeof(subpicture_region_t) );
851 memset( p_region, 0, sizeof(subpicture_region_t) );
853 p_region->psz_text = strdup( p_sys->psz_text );
854 p_region->p_style = p_sys->p_style;
856 p_region->fmt.i_chroma = VLC_FOURCC('T','E','X','T');
857 p_region->fmt.i_aspect = 0;
858 p_region->fmt.i_width = p_region->fmt.i_visible_width = 0;
859 p_region->fmt.i_height = p_region->fmt.i_visible_height = 0;
860 p_region->fmt.i_x_offset = 0;
861 p_region->fmt.i_y_offset = 0;
863 p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
865 if( p_sys->p_text->pf_render_text )
867 video_format_t fmt_out;
869 memset( &fmt_out, 0, sizeof(video_format_t) );
871 p_sys->p_text->pf_render_text( p_sys->p_text,
872 p_region, p_region );
874 #ifndef FBOSD_BLENDING
875 fmt_out.i_chroma = p_fmt->i_chroma;
876 p_dest = ConvertImage( p_intf, &p_region->picture,
877 &p_region->fmt, &fmt_out );
879 fmt_out = p_region->fmt;
880 fmt_out.i_bits_per_pixel = 32;
881 memcpy( p_fmt, &fmt_out, sizeof(video_format_t) );
882 p_dest = AllocatePicture( VLC_OBJECT(p_intf), &fmt_out );
885 if( p_region->picture.pf_release )
886 p_region->picture.pf_release( &p_region->picture );
887 free( p_region->psz_text );
891 vout_CopyPicture( VLC_OBJECT(p_intf), p_dest, &p_region->picture );
893 if( p_region->picture.pf_release )
894 p_region->picture.pf_release( &p_region->picture );
895 free( p_region->psz_text );
899 free( p_region->psz_text );
905 /*****************************************************************************
906 * LoadImage: Load an image from file into a picture buffer.
907 *****************************************************************************/
908 static picture_t *LoadImage( intf_thread_t *p_intf, video_format_t *p_fmt,
911 picture_t *p_pic = NULL;
913 if( psz_file && p_intf->p_sys->p_image )
915 video_format_t fmt_in, fmt_out;
917 memset( &fmt_in, 0, sizeof(fmt_in) );
918 memset( &fmt_out, 0, sizeof(fmt_out) );
920 fmt_out.i_chroma = p_fmt->i_chroma;
921 p_pic = image_ReadUrl( p_intf->p_sys->p_image, psz_file,
924 msg_Dbg( p_intf, "image size %dx%d chroma %4.4s",
925 fmt_out.i_width, fmt_out.i_height,
926 (char *)&p_fmt->i_chroma );
931 #ifndef FBOSD_BLENDING
932 /*****************************************************************************
933 * Convertmage: Convert image to another fourcc
934 *****************************************************************************/
935 static picture_t *ConvertImage( intf_thread_t *p_intf, picture_t *p_pic,
936 video_format_t *p_fmt_in, video_format_t *p_fmt_out )
938 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
939 picture_t *p_old = NULL;
943 p_old = image_Convert( p_sys->p_image, p_pic, p_fmt_in, p_fmt_out );
945 msg_Dbg( p_intf, "converted image size %dx%d chroma %4.4s",
946 p_fmt_out->i_width, p_fmt_out->i_height,
947 (char *)&p_fmt_out->i_chroma );
953 /*****************************************************************************
954 * Init: initialize framebuffer video thread output method
955 *****************************************************************************/
956 static int Init( intf_thread_t *p_intf )
958 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
960 /* Initialize the output structure: RGB with square pixels, whatever
961 * the input format is, since it's the only format we know */
962 switch( p_sys->var_info.bits_per_pixel )
964 case 8: /* FIXME: set the palette */
965 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','G','B','2'); break;
967 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','5'); break;
969 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','6'); break;
971 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','2','4'); break;
973 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','3','2'); break;
975 msg_Err( p_intf, "unknown screen depth %i",
976 p_sys->var_info.bits_per_pixel );
980 p_sys->fmt_out.i_bits_per_pixel = p_sys->var_info.bits_per_pixel;
981 p_sys->fmt_out.i_width = p_sys->i_width;
982 p_sys->fmt_out.i_height = p_sys->i_height;
984 /* Assume we have square pixels */
985 if( p_sys->i_aspect < 0 )
987 p_sys->fmt_out.i_aspect = ( p_sys->i_width
988 * VOUT_ASPECT_FACTOR ) / p_sys->i_height;
990 else p_sys->fmt_out.i_aspect = p_sys->i_aspect;
992 p_sys->fmt_out.i_sar_num = p_sys->fmt_out.i_sar_den = 1;
994 /* Allocate overlay buffer */
995 p_sys->p_overlay = AllocatePicture( VLC_OBJECT(p_intf),
997 if( !p_sys->p_overlay ) return VLC_EGENERIC;
999 SetOverlayTransparency( p_intf, VLC_TRUE );
1001 /* We know the chroma, allocate a buffer which will be used
1002 * to write to the overlay framebuffer */
1003 p_sys->p_overlay->p->i_pixel_pitch = p_sys->i_bytes_per_pixel;
1004 p_sys->p_overlay->p->i_lines = p_sys->var_info.yres;
1005 p_sys->p_overlay->p->i_visible_lines = p_sys->var_info.yres;
1007 if( p_sys->var_info.xres_virtual )
1009 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres_virtual
1010 * p_sys->i_bytes_per_pixel;
1014 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres
1015 * p_sys->i_bytes_per_pixel;
1018 p_sys->p_overlay->p->i_visible_pitch = p_sys->var_info.xres
1019 * p_sys->i_bytes_per_pixel;
1021 p_sys->p_overlay->i_planes = 1;
1026 /*****************************************************************************
1027 * End: terminate framebuffer interface
1028 *****************************************************************************/
1029 static void End( intf_thread_t *p_intf )
1031 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1034 SetOverlayTransparency( p_intf, VLC_FALSE );
1035 if( p_sys->p_overlay )
1037 write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels, p_sys->i_page_size );
1040 DeAllocatePicture( VLC_OBJECT(p_intf), p_intf->p_sys->p_overlay,
1041 &p_intf->p_sys->fmt_out );
1042 p_intf->p_sys->p_overlay = NULL;
1045 /*****************************************************************************
1046 * OpenDisplay: initialize framebuffer
1047 *****************************************************************************/
1048 static int OpenDisplay( intf_thread_t *p_intf )
1050 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1051 char *psz_device; /* framebuffer device path */
1052 struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
1054 /* Open framebuffer device */
1055 if( !(psz_device = config_GetPsz( p_intf, "fbosd-dev" )) )
1057 msg_Err( p_intf, "don't know which fb osd/overlay device to open" );
1058 return VLC_EGENERIC;
1061 p_sys->i_fd = open( psz_device, O_RDWR );
1062 if( p_sys->i_fd == -1 )
1064 msg_Err( p_intf, "cannot open %s (%s)", psz_device, strerror(errno) );
1066 return VLC_EGENERIC;
1070 /* Get framebuffer device information */
1071 if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) )
1073 msg_Err( p_intf, "cannot get fb info (%s)", strerror(errno) );
1074 close( p_sys->i_fd );
1075 return VLC_EGENERIC;
1078 /* Get some info on the framebuffer itself */
1079 if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) == 0 )
1081 p_sys->i_width = p_sys->fmt_out.i_width = p_sys->var_info.xres;
1082 p_sys->i_height = p_sys->fmt_out.i_height = p_sys->var_info.yres;
1085 /* FIXME: if the image is full-size, it gets cropped on the left
1086 * because of the xres / xres_virtual slight difference */
1087 msg_Dbg( p_intf, "%ix%i (virtual %ix%i)",
1088 p_sys->var_info.xres, p_sys->var_info.yres,
1089 p_sys->var_info.xres_virtual,
1090 p_sys->var_info.yres_virtual );
1092 p_sys->fmt_out.i_width = p_sys->i_width;
1093 p_sys->fmt_out.i_height = p_sys->i_height;
1095 p_sys->p_palette = NULL;
1096 p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
1098 switch( p_sys->var_info.bits_per_pixel )
1101 p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) );
1102 if( !p_sys->p_palette )
1104 msg_Err( p_intf, "out of memory" );
1105 close( p_sys->i_fd );
1108 p_sys->fb_cmap.start = 0;
1109 p_sys->fb_cmap.len = 256;
1110 p_sys->fb_cmap.red = p_sys->p_palette;
1111 p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t );
1112 p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t );
1113 p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t );
1115 /* Save the colormap */
1116 ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap );
1118 p_sys->i_bytes_per_pixel = 1;
1123 p_sys->i_bytes_per_pixel = 2;
1127 p_sys->i_bytes_per_pixel = 3;
1131 p_sys->i_bytes_per_pixel = 4;
1135 msg_Err( p_intf, "screen depth %d is not supported",
1136 p_sys->var_info.bits_per_pixel );
1138 close( p_sys->i_fd );
1139 return VLC_EGENERIC;
1142 p_sys->i_page_size = p_sys->i_width * p_sys->i_height
1143 * p_sys->i_bytes_per_pixel;
1145 msg_Dbg( p_intf, "framebuffer type=%d, visual=%d, ypanstep=%d, "
1146 "ywrap=%d, accel=%d", fix_info.type, fix_info.visual,
1147 fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
1151 /*****************************************************************************
1152 * CloseDisplay: terminate FB interface thread
1153 *****************************************************************************/
1154 static void CloseDisplay( intf_thread_t *p_intf )
1156 intf_sys_t *p_sys = (intf_sys_t *) p_intf;
1158 /* Restore palette */
1159 if( p_sys->var_info.bits_per_pixel == 8 )
1161 ioctl( p_sys->i_fd, FBIOPUTCMAP, &p_sys->fb_cmap );
1162 free( p_sys->p_palette );
1163 p_sys->p_palette = NULL;
1167 close( p_sys->i_fd );
1170 /*****************************************************************************
1172 *****************************************************************************
1173 * This part of the interface is in a separate thread so that we can call
1174 * exec() from within it without annoying the rest of the program.
1175 *****************************************************************************/
1176 static void Run( intf_thread_t *p_intf )
1178 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1180 while( !intf_ShouldDie( p_intf ) )
1182 if( p_sys->b_render )
1184 if( p_sys->b_image )
1187 p_pic = LoadImage( p_intf, &p_sys->fmt_out, p_sys->psz_file );
1190 RenderPicture( p_intf, p_sys->i_x, p_sys->i_y,
1191 p_pic, p_sys->p_overlay );
1192 p_pic->pf_release( p_pic );
1194 var_SetString( p_intf, "fbosd-image", "" );
1195 p_sys->b_image = VLC_FALSE;
1201 #ifndef FBOSD_BLENDING
1202 p_text = RenderText( p_intf, p_sys->psz_text, &p_sys->fmt_out );
1205 RenderPicture( p_intf, p_sys->i_x, p_sys->i_y,
1206 p_text, p_sys->p_overlay );
1207 p_text->pf_release( p_text );
1210 video_format_t fmt_in;
1211 memset( &fmt_in, 0, sizeof(video_format_t) );
1212 p_text = RenderText( p_intf, p_sys->psz_text, &fmt_in );
1215 BlendPicture( p_intf, &fmt_in, &p_sys->fmt_out,
1216 p_text, p_sys->p_overlay );
1217 msg_Dbg( p_intf, "releasing picture" );
1218 DeAllocatePicture( VLC_OBJECT( p_intf ), p_text, &fmt_in );
1221 var_SetString( p_intf, "fbosd-text", "" );
1222 p_sys->b_text = VLC_FALSE;
1224 p_sys->b_render = VLC_FALSE;
1227 if( p_sys->b_clear )
1229 SetOverlayTransparency( p_intf, VLC_TRUE );
1231 var_SetString( p_intf, "fbosd-image", "" );
1232 var_SetString( p_intf, "fbosd-text", "" );
1234 p_sys->b_image = VLC_FALSE;
1235 p_sys->b_text = VLC_FALSE;
1236 p_sys->b_clear = VLC_FALSE;
1237 p_sys->b_need_update = VLC_TRUE;
1240 if( p_sys->b_need_update && p_sys->p_overlay )
1242 write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels,
1243 p_sys->i_page_size );
1244 lseek( p_sys->i_fd, 0, SEEK_SET );
1245 p_sys->b_need_update = VLC_FALSE;
1248 if( vlc_CPU() & CPU_CAPABILITY_FPU )
1249 msleep( INTF_IDLE_SLEEP );
1257 static int OverlayCallback( vlc_object_t *p_this, char const *psz_cmd,
1258 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1260 intf_thread_t *p_intf = (intf_thread_t *) p_this;
1261 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1263 if( !strncmp( psz_cmd, "fbosd-image", 11 ) )
1265 free( p_sys->psz_file );
1266 p_sys->psz_file = strdup( newval.psz_string );
1267 p_sys->b_image = VLC_TRUE;
1269 else if( !strncmp( psz_cmd, "fbosd-text", 10 ) )
1271 free( p_sys->psz_text );
1272 p_sys->psz_text = strdup( newval.psz_string );
1273 p_sys->b_text = VLC_TRUE;
1275 else if( !strncmp( psz_cmd, "fbosd-x", 7 ) )
1277 p_sys->b_absolute = VLC_FALSE;
1278 p_sys->i_x = (newval.i_int < p_sys->i_width) ?
1279 newval.i_int : p_sys->i_width;
1281 else if( !strncmp( psz_cmd, "fbosd-y", 7 ) )
1283 p_sys->b_absolute = VLC_FALSE;
1284 p_sys->i_y = (newval.i_int < p_sys->i_height) ?
1285 newval.i_int : p_sys->i_height;
1287 else if( !strncmp( psz_cmd, "fbosd-position", 14 ) )
1289 p_sys->b_absolute = VLC_TRUE;
1290 p_sys->i_pos = newval.i_int;
1292 else if( !strncmp( psz_cmd, "fbosd-font-size", 15 ) )
1294 p_sys->p_style->i_font_size = newval.i_int;
1296 else if( !strncmp( psz_cmd, "fbosd-font-color", 16 ) )
1298 p_sys->p_style->i_font_color = newval.i_int;
1300 else if( !strncmp( psz_cmd, "fbosd-font-opacity", 18 ) )
1302 p_sys->p_style->i_font_alpha = 255 - newval.i_int;
1304 else if( !strncmp( psz_cmd, "fbosd-display", 13 ) )
1306 p_sys->b_need_update = VLC_TRUE;
1308 else if( !strncmp( psz_cmd, "fbosd-render", 12 ) )
1310 p_sys->b_render = VLC_TRUE;
1312 else if( !strncmp( psz_cmd, "fbosd-clear", 11 ) )
1314 p_sys->b_clear = VLC_TRUE;
1316 #ifdef FBOSD_BLENDING
1317 else if( !strncmp( psz_cmd, "fbosd-alpha", 11 ) )
1319 p_sys->i_alpha = newval.i_int;