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 *****************************************************************************/
31 #include <stdlib.h> /* free() */
32 #include <string.h> /* strerror() */
33 #include <fcntl.h> /* open() */
34 #include <unistd.h> /* close() */
36 #include <sys/ioctl.h>
37 #include <sys/mman.h> /* mmap() */
41 #include <vlc_image.h>
42 #include <vlc_interface.h>
43 #include <vlc_input.h>
45 #include <vlc_filter.h>
47 #include <vlc_strings.h>
49 // #define FBOSD_BLENDING 1
51 /*****************************************************************************
53 *****************************************************************************/
54 static int Create ( vlc_object_t * );
55 static void Destroy ( vlc_object_t * );
56 static void Run ( intf_thread_t * );
58 static int Init ( intf_thread_t * );
59 static void End ( intf_thread_t * );
61 static int OpenDisplay ( intf_thread_t * );
62 static void CloseDisplay ( intf_thread_t * );
64 /* Load modules needed for rendering and blending */
66 static int OpenBlending ( intf_thread_t * );
67 static void CloseBlending ( intf_thread_t * );
69 static int OpenTextRenderer ( intf_thread_t * );
70 static void CloseTextRenderer( intf_thread_t * );
73 static int OpenScaling ( intf_thread_t * );
74 static int CloseScaling ( intf_thread_t * );
77 /* Manipulate the overlay buffer */
78 static int OverlayCallback( vlc_object_t *, char const *,
79 vlc_value_t, vlc_value_t, void * );
81 static picture_t *AllocatePicture( vlc_object_t *,
83 static void DeAllocatePicture( vlc_object_t *, picture_t *,
85 static void SetOverlayTransparency( intf_thread_t *,
87 static picture_t *LoadImage( intf_thread_t *, video_format_t *,
91 static int BlendPicture( intf_thread_t *, video_format_t *,
92 video_format_t *, picture_t *, picture_t * );
94 static picture_t *ConvertImage( intf_thread_t *, picture_t *,
95 video_format_t *, video_format_t * );
97 static int RenderPicture( intf_thread_t *, int, int,
98 picture_t *, picture_t * );
99 static picture_t *RenderText( intf_thread_t *, const char *,
102 #define DEVICE_TEXT N_("Framebuffer device")
103 #define DEVICE_LONGTEXT N_( \
104 "Framebuffer device to use for rendering (usually /dev/fb0).")
106 #define ASPECT_RATIO_TEXT N_("Video aspect ratio")
107 #define ASPECT_RATIO_LONGTEXT N_( \
108 "Aspect ratio of the video image (4:3, 16:9). Default is square pixels." )
110 #define FBOSD_IMAGE_TEXT N_("Image file")
111 #define FBOSD_IMAGE_LONGTEXT N_( \
112 "Filename of image file to use on the overlay framebuffer." )
114 #define ALPHA_TEXT N_("Transparency of the image")
115 #define ALPHA_LONGTEXT N_( "Transparency value of the new image " \
116 "used in blending. By default it set to fully opaque (255). " \
117 "(from 0 for full transparency to 255 for full opacity)" )
119 #define FBOSD_TEXT N_("Text")
120 #define FBOSD_LONGTEXT N_( "Text to display on the overlay framebuffer." )
122 #define POSX_TEXT N_("X coordinate")
123 #define POSX_LONGTEXT N_("X coordinate of the rendered image")
125 #define POSY_TEXT N_("Y coordinate")
126 #define POSY_LONGTEXT N_("Y coordinate of the rendered image")
128 #define POS_TEXT N_("Position")
129 #define POS_LONGTEXT N_( \
130 "You can enforce the picture position on the overlay " \
131 "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
132 "also use combinations of these values, e.g. 6=top-right).")
134 #define OPACITY_TEXT N_("Opacity")
135 #define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
136 "overlayed text. 0 = transparent, 255 = totally opaque. " )
138 #define SIZE_TEXT N_("Font size, pixels")
139 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
142 #define COLOR_TEXT N_("Color")
143 #define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
144 "the video. This must be an hexadecimal (like HTML colors). The first two "\
145 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
146 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
148 #define CLEAR_TEXT N_( "Clear overlay framebuffer" )
149 #define CLEAR_LONGTEXT N_( "The displayed overlay images is cleared by " \
150 "making the overlay completely transparent. All previously rendered " \
151 "images and text will be cleared from the cache." )
153 #define RENDER_TEXT N_( "Render text or image" )
154 #define RENDER_LONGTEXT N_( "Render the image or text in current overlay " \
157 #define DISPLAY_TEXT N_( "Display on overlay framebuffer" )
158 #define DISPLAY_LONGTEXT N_( "All rendered images and text will be " \
159 "displayed on the overlay framebuffer." )
161 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
162 static const char *ppsz_pos_descriptions[] =
163 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
164 N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
166 static int pi_color_values[] = { 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
167 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
168 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
169 0x00000080, 0x000000FF, 0x0000FFFF};
170 static const char *ppsz_color_descriptions[] = { N_("Default"), N_("Black"),
171 N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
172 N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
173 N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
177 set_shortname( "fbosd" );
178 set_category( CAT_INTERFACE );
179 set_subcategory( SUBCAT_INTERFACE_MAIN );
181 add_file( "fbosd-dev", "/dev/fb1", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
183 add_string( "fbosd-aspect-ratio", "", NULL, ASPECT_RATIO_TEXT,
184 ASPECT_RATIO_LONGTEXT, VLC_TRUE );
186 add_string( "fbosd-image", NULL, NULL, FBOSD_IMAGE_TEXT,
187 FBOSD_IMAGE_LONGTEXT, VLC_TRUE );
188 add_string( "fbosd-text", NULL, NULL, FBOSD_TEXT,
189 FBOSD_LONGTEXT, VLC_TRUE );
191 #ifdef FBOSD_BLENDING
192 add_integer_with_range( "fbosd-alpha", 255, 0, 255, NULL, ALPHA_TEXT,
193 ALPHA_LONGTEXT, VLC_TRUE );
197 set_section( N_("Position"), NULL );
198 add_integer( "fbosd-x", 0, NULL, POSX_TEXT,
199 POSX_LONGTEXT, VLC_FALSE );
200 add_integer( "fbosd-y", 0, NULL, POSY_TEXT,
201 POSY_LONGTEXT, VLC_FALSE );
202 add_integer( "fbosd-position", 8, NULL, POS_TEXT, POS_LONGTEXT, VLC_TRUE );
203 change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
205 set_section( N_("Font"), NULL );
206 add_integer_with_range( "fbosd-font-opacity", 255, 0, 255, NULL,
207 OPACITY_TEXT, OPACITY_LONGTEXT, VLC_FALSE );
208 add_integer( "fbosd-font-color", 0x00FFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT,
210 change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
211 add_integer( "fbosd-font-size", -1, NULL, SIZE_TEXT, SIZE_LONGTEXT,
214 set_section( N_("Commands"), NULL );
215 add_bool( "fbosd-clear", VLC_FALSE, NULL, CLEAR_TEXT, CLEAR_LONGTEXT, VLC_TRUE );
216 add_bool( "fbosd-render", VLC_FALSE, NULL, RENDER_TEXT, RENDER_LONGTEXT, VLC_TRUE );
217 add_bool( "fbosd-display", VLC_FALSE, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, VLC_TRUE );
219 set_description( _("GNU/Linux osd/overlay framebuffer interface") );
220 set_capability( "interface", 10 );
221 set_callbacks( Create, Destroy );
224 /*****************************************************************************
225 * intf_sys_t: interface framebuffer method descriptor
226 *****************************************************************************/
229 /* Framebuffer information */
230 int i_fd; /* device handle */
231 struct fb_var_screeninfo var_info; /* current mode information */
232 vlc_bool_t b_pan; /* does device supports panning ? */
233 struct fb_cmap fb_cmap; /* original colormap */
234 uint16_t *p_palette; /* original palette */
236 /* Overlay framebuffer format */
237 video_format_t fmt_out;
238 picture_t *p_overlay;
239 size_t i_page_size; /* page size */
243 int i_bytes_per_pixel;
245 /* Image and Picture rendering */
246 image_handler_t *p_image;
247 #ifdef FBOSD_BLENDING
248 filter_t *p_blend; /* alpha blending module */
250 filter_t *p_text; /* text renderer module */
252 filter_t *p_scale; /* scaling module */
254 vlc_bool_t b_force_crop; /* force cropping of picture */
255 int i_crop_x, i_crop_y, i_crop_width, i_crop_height; /* cropping */
265 text_style_t *p_style; /* font control */
267 /* Positon of image/text */
268 vlc_bool_t b_absolute;
273 int i_alpha; /* transparency for images */
275 /* commands control */
276 vlc_bool_t b_need_update; /* update display with \overlay buffer */
277 vlc_bool_t b_clear; /* clear overlay buffer make it tranparent */
278 vlc_bool_t b_render; /* render an image or text in overlay buffer */
281 /*****************************************************************************
282 * Create: allocates FB interface thread output method
283 *****************************************************************************/
284 static int Create( vlc_object_t *p_this )
286 intf_thread_t *p_intf = (intf_thread_t *)p_this;
290 /* Allocate instance and initialize some members */
291 p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) );
294 msg_Err( p_intf, "out of memory" );
297 memset( p_sys, 0, sizeof(intf_sys_t) );
299 p_sys->p_style = malloc( sizeof( text_style_t ) );
300 if( !p_sys->p_style )
302 free( p_intf->p_sys );
303 msg_Err( p_intf, "out of memory" );
306 p_intf->p_libvlc->pf_memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
308 p_intf->pf_run = Run;
310 p_sys->p_image = image_HandlerCreate( p_this );
311 if( !p_sys->p_image )
313 free( p_intf->p_sys->p_style );
314 free( p_intf->p_sys );
315 msg_Err( p_intf, "out of memory" );
319 #ifdef FBOSD_BLENDING
320 p_sys->i_alpha = var_CreateGetIntegerCommand( p_intf, "fbosd-alpha" );
321 var_AddCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
323 p_sys->i_alpha = 255;
325 p_sys->i_aspect = -1;
327 var_CreateGetNonEmptyString( p_intf, "fbosd-aspect-ratio" );
330 char *psz_parser = strchr( psz_aspect, ':' );
334 *psz_parser++ = '\0';
335 p_sys->i_aspect = ( atoi( psz_aspect )
336 * VOUT_ASPECT_FACTOR ) / atoi( psz_parser );
337 p_sys->fmt_out.i_aspect = p_sys->i_aspect;
339 msg_Dbg( p_intf, "using aspect ratio %d:%d",
340 atoi( psz_aspect ), atoi( psz_parser ) );
346 /* Use PAL by default */
347 p_sys->i_width = p_sys->fmt_out.i_width = 704;
348 p_sys->i_height = p_sys->fmt_out.i_height = 576;
351 var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-image" );
352 var_AddCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
353 if( p_sys->psz_file && *p_sys->psz_file )
354 p_sys->b_image = VLC_TRUE;
357 var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-text" );
358 var_AddCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
359 if( p_sys->psz_text && *p_sys->psz_text )
360 p_sys->b_text = VLC_TRUE;
362 p_sys->i_pos = var_CreateGetIntegerCommand( p_intf, "fbosd-position" );
363 p_sys->i_x = var_CreateGetIntegerCommand( p_intf, "fbosd-x" );
364 p_sys->i_y = var_CreateGetIntegerCommand( p_intf, "fbosd-y" );
366 var_AddCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
367 var_AddCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
368 var_AddCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
370 p_sys->p_style->i_font_size =
371 var_CreateGetIntegerCommand( p_intf, "fbosd-font-size" );
372 p_sys->p_style->i_font_color =
373 var_CreateGetIntegerCommand( p_intf, "fbosd-font-color" );
374 p_sys->p_style->i_font_alpha = 255 -
375 var_CreateGetIntegerCommand( p_intf, "fbosd-font-opacity" );
377 var_AddCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
378 var_AddCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
379 var_AddCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
381 p_sys->b_clear = var_CreateGetBoolCommand( p_intf, "fbosd-clear" );
382 p_sys->b_render = var_CreateGetBoolCommand( p_intf, "fbosd-render" );
383 p_sys->b_need_update = var_CreateGetBoolCommand( p_intf, "fbosd-display" );
385 var_AddCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
386 var_AddCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
387 var_AddCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
389 /* Check if picture position was overridden */
390 p_sys->b_absolute = VLC_TRUE;
391 if( ( p_sys->i_x >= 0 ) && ( p_sys->i_y >= 0 ) )
393 p_sys->b_absolute = VLC_FALSE;
394 p_sys->i_y = (p_sys->i_y < p_sys->i_height) ?
395 p_sys->i_y : p_sys->i_height;
396 p_sys->i_x = (p_sys->i_x < p_sys->i_width) ?
397 p_sys->i_x : p_sys->i_width;
400 /* Initialize framebuffer */
401 if( OpenDisplay( p_intf ) )
403 Destroy( VLC_OBJECT(p_intf) );
409 #ifdef FBOSD_BLENDING
410 /* Load the blending module */
411 if( OpenBlending( p_intf ) )
413 msg_Err( p_intf, "Unable to load image blending module" );
414 Destroy( VLC_OBJECT(p_intf) );
419 /* Load text renderer module */
420 if( OpenTextRenderer( p_intf ) )
422 msg_Err( p_intf, "Unable to load text rendering module" );
423 Destroy( VLC_OBJECT(p_intf) );
427 /* Load scaling module */
428 if( OpenScaling( p_intf ) )
430 msg_Err( p_intf, "Unable to load image scaling module" );
431 Destroy( VLC_OBJECT(p_intf) );
435 p_sys->b_render = VLC_TRUE;
436 p_sys->b_need_update = VLC_TRUE;
441 /*****************************************************************************
442 * Destroy: destroy FB interface thread output method
443 *****************************************************************************
444 * Terminate an output method created by Create
445 *****************************************************************************/
446 static void Destroy( vlc_object_t *p_this )
448 intf_thread_t *p_intf = (intf_thread_t *)p_this;
449 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
451 p_sys->b_need_update = VLC_FALSE;
452 p_sys->b_render = VLC_FALSE;
453 p_sys->b_clear = VLC_FALSE;
455 #ifdef FBOSD_BLENDING
456 var_DelCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
457 var_Destroy( p_intf, "fbosd-alpha" );
460 var_DelCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
461 var_DelCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
462 var_DelCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
463 var_DelCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
464 var_DelCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
465 var_DelCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
466 var_DelCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
467 var_DelCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
468 var_DelCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
469 var_DelCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
470 var_DelCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
472 var_Destroy( p_intf, "fbosd-x" );
473 var_Destroy( p_intf, "fbosd-y" );
474 var_Destroy( p_intf, "fbosd-position" );
475 var_Destroy( p_intf, "fbosd-image" );
476 var_Destroy( p_intf, "fbosd-text" );
477 var_Destroy( p_intf, "fbosd-font-size" );
478 var_Destroy( p_intf, "fbosd-font-color" );
479 var_Destroy( p_intf, "fbosd-font-opacity" );
480 var_Destroy( p_intf, "fbosd-clear" );
481 var_Destroy( p_intf, "fbosd-render" );
482 var_Destroy( p_intf, "fbosd-display" );
484 var_Destroy( p_intf, "fbosd-aspect-ratio" );
486 CloseDisplay( p_intf );
488 #ifdef FBOSD_BLENDING
489 if( p_sys->p_blend ) CloseBlending( p_intf );
491 if( p_sys->p_text ) CloseTextRenderer( p_intf );
493 if( p_sys->p_scale ) CloseScaling( p_intf );
496 image_HandlerDelete( p_sys->p_image );
497 if( p_sys->p_overlay )
498 p_sys->p_overlay->pf_release( p_sys->p_overlay );
500 free( p_sys->psz_file );
501 free( p_sys->psz_text );
502 free( p_sys->p_style );
506 #ifdef FBOSD_BLENDING
507 static int OpenBlending( intf_thread_t *p_intf )
509 if( p_intf->p_sys->p_blend ) return VLC_EGENERIC;
511 p_intf->p_sys->p_blend =
512 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
513 vlc_object_attach( p_intf->p_sys->p_blend, p_intf );
514 p_intf->p_sys->p_blend->fmt_out.video.i_x_offset =
515 p_intf->p_sys->p_blend->fmt_out.video.i_y_offset = 0;
516 p_intf->p_sys->p_blend->fmt_out.video.i_aspect =
517 p_intf->p_sys->fmt_out.i_aspect;
518 p_intf->p_sys->p_blend->fmt_out.video.i_chroma =
519 p_intf->p_sys->fmt_out.i_chroma;
520 if( config_GetInt( p_intf, "freetype-yuvp" ) )
521 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
522 VLC_FOURCC('Y','U','V','P');
524 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
525 VLC_FOURCC('Y','U','V','A');
527 p_intf->p_sys->p_blend->p_module =
528 module_Need( p_intf->p_sys->p_blend, "video blending", 0, 0 );
530 if( !p_intf->p_sys->p_blend->p_module )
536 static void CloseBlending( intf_thread_t *p_intf )
538 if( p_intf->p_sys->p_blend )
540 if( p_intf->p_sys->p_blend->p_module )
541 module_Unneed( p_intf->p_sys->p_blend,
542 p_intf->p_sys->p_blend->p_module );
544 vlc_object_detach( p_intf->p_sys->p_blend );
545 vlc_object_destroy( p_intf->p_sys->p_blend );
550 static int OpenTextRenderer( intf_thread_t *p_intf )
552 char *psz_modulename = NULL;
554 if( p_intf->p_sys->p_text ) return VLC_EGENERIC;
556 p_intf->p_sys->p_text =
557 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
558 vlc_object_attach( p_intf->p_sys->p_text, p_intf );
560 p_intf->p_sys->p_text->fmt_out.video.i_width =
561 p_intf->p_sys->p_text->fmt_out.video.i_visible_width =
562 p_intf->p_sys->i_width;
563 p_intf->p_sys->p_text->fmt_out.video.i_height =
564 p_intf->p_sys->p_text->fmt_out.video.i_visible_height =
565 p_intf->p_sys->i_height;
567 psz_modulename = var_CreateGetString( p_intf, "text-renderer" );
568 if( psz_modulename && *psz_modulename )
570 p_intf->p_sys->p_text->p_module =
571 module_Need( p_intf->p_sys->p_text, "text renderer",
572 psz_modulename, VLC_TRUE );
574 if( !p_intf->p_sys->p_text->p_module )
576 p_intf->p_sys->p_text->p_module =
577 module_Need( p_intf->p_sys->p_text, "text renderer", 0, 0 );
579 if( psz_modulename ) free( psz_modulename );
581 if( !p_intf->p_sys->p_text->p_module )
587 static void CloseTextRenderer( intf_thread_t *p_intf )
589 if( p_intf->p_sys->p_text )
591 if( p_intf->p_sys->p_text->p_module )
592 module_Unneed( p_intf->p_sys->p_text,
593 p_intf->p_sys->p_text->p_module );
595 vlc_object_detach( p_intf->p_sys->p_text );
596 vlc_object_destroy( p_intf->p_sys->p_text );
600 static int OpenScaling( intf_thread_t *p_intf )
602 if( p_intf->p_sys->p_scale ) return VLC_EGENERIC;
604 p_intf->p_sys->p_scale =
605 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
606 vlc_object_attach( p_intf->p_sys->p_scale, p_intf );
607 p_intf->p_sys->p_scale->fmt_out.video.i_chroma =
608 p_intf->p_sys->p_scale->fmt_in.video.i_chroma =
609 p_intf->p_sys->fmt_out.i_chroma;
611 /* XXX: We'll also be using it for YUVA and RGBA blending ... */
612 p_intf->p_sys->p_scale->fmt_in.video.i_width =
613 p_intf->p_sys->p_scale->fmt_in.video.i_height = 32;
614 p_intf->p_sys->p_scale->fmt_out.video.i_width =
615 p_intf->p_sys->p_scale->fmt_out.video.i_height = 16;
617 p_intf->p_sys->p_scale->p_module =
618 module_Need( p_intf->p_sys->p_scale, "video filter2", 0, 0 );
620 if( !p_intf->p_sys->p_scale->p_module )
626 static int CloseScaling( intf_thread_t *p_intf )
628 if( p_intf->p_sys->p_scale )
630 if( p_intf->p_sys->p_scale->p_module )
631 module_Unneed( p_intf->p_sys->p_scale,
632 p_intf->p_sys->p_scale->p_module );
634 vlc_object_detach( p_intf->p_sys->p_scale );
635 vlc_object_destroy( p_intf->p_sys->p_scale );
640 /*****************************************************************************
642 * allocate a picture buffer for use with the overlay fb.
643 *****************************************************************************/
644 static picture_t *AllocatePicture( vlc_object_t *p_this,
645 video_format_t *p_fmt )
647 picture_t *p_pic = malloc( sizeof( picture_t ) );
648 if( !p_pic ) return NULL;
650 if( !p_fmt->p_palette &&
651 ( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') ) )
653 p_fmt->p_palette = malloc( sizeof(video_palette_t) );
654 if( !p_fmt->p_palette )
660 else p_fmt->p_palette = NULL;
662 p_pic->p_data_orig = NULL;
664 vout_AllocatePicture( p_this, p_pic, p_fmt->i_chroma,
665 p_fmt->i_width, p_fmt->i_height, p_fmt->i_aspect );
667 if( !p_pic->i_planes )
670 free( p_fmt->p_palette );
676 /*****************************************************************************
678 * Deallocate a picture buffer and free all associated memory.
679 *****************************************************************************/
680 static void DeAllocatePicture( vlc_object_t *p_this, picture_t *p_pic,
681 video_format_t *p_fmt )
683 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
684 if( p_pic && p_pic->pf_release ) p_pic->pf_release( p_pic );
685 if( p_fmt && p_fmt->p_palette )
687 free( p_fmt->p_palette );
688 p_fmt->p_palette = NULL;
693 /*****************************************************************************
694 * SetOverlayTransparency: Set the transparency for this overlay fb,
695 * - VLC_TRUE is make transparent
696 * - VLC_FALSE is make non tranparent
697 *****************************************************************************/
698 static void SetOverlayTransparency( intf_thread_t *p_intf,
699 vlc_bool_t b_transparent )
701 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
702 size_t i_size = p_sys->fmt_out.i_width * p_sys->fmt_out.i_height
703 * p_sys->i_bytes_per_pixel;
704 size_t i_page_size = (p_sys->i_page_size > i_size) ?
705 i_size : p_sys->i_page_size;
707 if( p_sys->p_overlay )
709 msg_Dbg( p_intf, "Make overlay %s",
710 b_transparent ? "transparent" : "opaque" );
711 memset( p_sys->p_overlay->p[0].p_pixels, 0x00, i_page_size );
713 memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, i_page_size );
717 #ifdef FBOSD_BLENDING
718 /*****************************************************************************
719 * BlendPicture: Blend two pictures together..
720 *****************************************************************************/
721 static int BlendPicture( intf_thread_t *p_intf, video_format_t *p_fmt_src,
722 video_format_t *p_fmt_dst, picture_t *p_pic_src,
723 picture_t *p_pic_dst )
725 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
726 if( p_sys->p_blend && p_sys->p_blend->p_module )
728 int i_x_offset = p_sys->i_x;
729 int i_y_offset = p_sys->i_y;
731 memcpy( &p_sys->p_blend->fmt_in.video, p_fmt_src, sizeof( video_format_t ) );
733 msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
734 p_pic_src, (char*)&p_fmt_src->i_chroma,
735 p_sys->p_blend->fmt_in.video.i_width, p_sys->p_blend->fmt_in.video.i_height,
736 p_fmt_src->i_bits_per_pixel,
738 p_pic_src->p[0].p_pixels, p_pic_src->p[1].p_pixels,
739 p_pic_src->p[2].p_pixels, p_pic_src->p[3].p_pixels );
740 msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
741 p_pic_dst, (char*)&p_fmt_dst->i_chroma,
742 p_fmt_dst->i_width, p_fmt_dst->i_height,
743 p_fmt_dst->i_bits_per_pixel,
745 p_pic_dst->p[0].p_pixels, p_pic_dst->p[1].p_pixels,
746 p_pic_dst->p[2].p_pixels, p_pic_dst->p[3].p_pixels );
748 /* Update the output picture size */
749 p_sys->p_blend->fmt_out.video.i_width =
750 p_sys->p_blend->fmt_out.video.i_visible_width =
752 p_sys->p_blend->fmt_out.video.i_height =
753 p_sys->p_blend->fmt_out.video.i_visible_height =
756 i_x_offset = __MAX( i_x_offset, 0 );
757 i_y_offset = __MAX( i_y_offset, 0 );
759 p_sys->p_blend->pf_video_blend( p_sys->p_blend, p_pic_dst,
760 p_pic_src, p_pic_dst, i_x_offset, i_y_offset,
769 /*****************************************************************************
770 * RenderPicture: Render the picture into the p_dest buffer.
771 * We don't take transparent pixels into account, so we don't have to blend
772 * the two images together.
773 *****************************************************************************/
774 static int RenderPicture( intf_thread_t *p_intf, int i_x_offset, int i_y_offset,
775 picture_t *p_src, picture_t *p_dest )
779 if( !p_dest && !p_src ) return VLC_EGENERIC;
781 for( i = 0; i < p_src->i_planes ; i++ )
783 if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
785 /* There are margins, but with the same width : perfect ! */
786 p_intf->p_libvlc->pf_memcpy(
787 p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
788 p_src->p[i].i_pitch * p_src->p[i].i_visible_lines );
792 /* We need to proceed line by line */
793 uint8_t *p_in = p_src->p[i].p_pixels;
794 uint8_t *p_out = p_dest->p[i].p_pixels;
796 int i_x = i_x_offset * p_src->p[i].i_pixel_pitch;
797 int i_x_clip, i_y_clip;
799 /* Check boundaries, clip the image if necessary */
800 i_x_clip = ( i_x + p_src->p[i].i_visible_pitch ) - p_dest->p[i].i_visible_pitch;
801 i_x_clip = ( i_x_clip > 0 ) ? i_x_clip : 0;
803 i_y_clip = ( i_y_offset + p_src->p[i].i_visible_lines ) - p_dest->p[i].i_visible_lines;
804 i_y_clip = ( i_y_clip > 0 ) ? i_y_clip : 0;
806 msg_Dbg( p_intf, "i_pitch (%d,%d), (%d,%d)/(%d,%d)",
807 p_dest->p[i].i_visible_pitch, p_src->p[i].i_visible_pitch,
808 i_x_offset, i_y_offset, i_x, i_x_clip );
810 if( ( i_y_offset <= p_dest->p[i].i_visible_lines ) &&
811 ( i_x <= p_dest->p[i].i_visible_pitch ) )
815 p_out += ( i_y_offset * p_dest->p[i].i_pitch );
816 for( i_line = 0; i_line < ( p_src->p[i].i_visible_lines - i_y_clip ); i_line++ )
818 p_intf->p_libvlc->pf_memcpy( p_out + i_x, p_in,
819 p_src->p[i].i_visible_pitch - i_x_clip );
820 p_in += p_src->p[i].i_pitch;
821 p_out += p_dest->p[i].i_pitch;
829 /*****************************************************************************
830 * RenderText - Render text to the desired picture format
831 *****************************************************************************/
832 static picture_t *RenderText( intf_thread_t *p_intf, const char *psz_text,
833 video_format_t *p_fmt )
835 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
836 subpicture_region_t *p_region;
837 picture_t *p_dest = NULL;
839 if( !psz_text ) return p_dest;
841 if( p_sys->p_text && p_sys->p_text->p_module )
843 p_region = (subpicture_region_t *) malloc( sizeof(subpicture_region_t) );
847 memset( p_region, 0, sizeof(subpicture_region_t) );
849 p_region->psz_text = strdup( p_sys->psz_text );
850 p_region->p_style = p_sys->p_style;
852 p_region->fmt.i_chroma = VLC_FOURCC('T','E','X','T');
853 p_region->fmt.i_aspect = 0;
854 p_region->fmt.i_width = p_region->fmt.i_visible_width = 0;
855 p_region->fmt.i_height = p_region->fmt.i_visible_height = 0;
856 p_region->fmt.i_x_offset = 0;
857 p_region->fmt.i_y_offset = 0;
859 p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
861 if( p_sys->p_text->pf_render_text )
863 video_format_t fmt_out;
865 memset( &fmt_out, 0, sizeof(video_format_t) );
867 p_sys->p_text->pf_render_text( p_sys->p_text,
868 p_region, p_region );
870 #ifndef FBOSD_BLENDING
871 fmt_out.i_chroma = p_fmt->i_chroma;
872 p_dest = ConvertImage( p_intf, &p_region->picture,
873 &p_region->fmt, &fmt_out );
875 fmt_out = p_region->fmt;
876 fmt_out.i_bits_per_pixel = 32;
877 memcpy( p_fmt, &fmt_out, sizeof(video_format_t) );
878 p_dest = AllocatePicture( VLC_OBJECT(p_intf), &fmt_out );
881 if( p_region->picture.pf_release )
882 p_region->picture.pf_release( &p_region->picture );
883 free( p_region->psz_text );
887 vout_CopyPicture( VLC_OBJECT(p_intf), p_dest, &p_region->picture );
889 if( p_region->picture.pf_release )
890 p_region->picture.pf_release( &p_region->picture );
891 free( p_region->psz_text );
895 free( p_region->psz_text );
901 /*****************************************************************************
902 * LoadImage: Load an image from file into a picture buffer.
903 *****************************************************************************/
904 static picture_t *LoadImage( intf_thread_t *p_intf, video_format_t *p_fmt,
907 picture_t *p_pic = NULL;
909 if( psz_file && p_intf->p_sys->p_image )
911 video_format_t fmt_in, fmt_out;
913 memset( &fmt_in, 0, sizeof(fmt_in) );
914 memset( &fmt_out, 0, sizeof(fmt_out) );
916 fmt_out.i_chroma = p_fmt->i_chroma;
917 p_pic = image_ReadUrl( p_intf->p_sys->p_image, psz_file,
920 msg_Dbg( p_intf, "image size %dx%d chroma %4.4s",
921 fmt_out.i_width, fmt_out.i_height,
922 (char *)&p_fmt->i_chroma );
927 #ifndef FBOSD_BLENDING
928 /*****************************************************************************
929 * Convertmage: Convert image to another fourcc
930 *****************************************************************************/
931 static picture_t *ConvertImage( intf_thread_t *p_intf, picture_t *p_pic,
932 video_format_t *p_fmt_in, video_format_t *p_fmt_out )
934 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
935 picture_t *p_old = NULL;
939 p_old = image_Convert( p_sys->p_image, p_pic, p_fmt_in, p_fmt_out );
941 msg_Dbg( p_intf, "converted image size %dx%d chroma %4.4s",
942 p_fmt_out->i_width, p_fmt_out->i_height,
943 (char *)&p_fmt_out->i_chroma );
949 /*****************************************************************************
950 * Init: initialize framebuffer video thread output method
951 *****************************************************************************/
952 static int Init( intf_thread_t *p_intf )
954 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
956 /* Initialize the output structure: RGB with square pixels, whatever
957 * the input format is, since it's the only format we know */
958 switch( p_sys->var_info.bits_per_pixel )
960 case 8: /* FIXME: set the palette */
961 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','G','B','2'); break;
963 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','5'); break;
965 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','6'); break;
967 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','2','4'); break;
969 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','3','2'); break;
971 msg_Err( p_intf, "unknown screen depth %i",
972 p_sys->var_info.bits_per_pixel );
976 p_sys->fmt_out.i_bits_per_pixel = p_sys->var_info.bits_per_pixel;
977 p_sys->fmt_out.i_width = p_sys->i_width;
978 p_sys->fmt_out.i_height = p_sys->i_height;
980 /* Assume we have square pixels */
981 if( p_sys->i_aspect < 0 )
983 p_sys->fmt_out.i_aspect = ( p_sys->i_width
984 * VOUT_ASPECT_FACTOR ) / p_sys->i_height;
986 else p_sys->fmt_out.i_aspect = p_sys->i_aspect;
988 p_sys->fmt_out.i_sar_num = p_sys->fmt_out.i_sar_den = 1;
990 /* Allocate overlay buffer */
991 p_sys->p_overlay = AllocatePicture( VLC_OBJECT(p_intf),
993 if( !p_sys->p_overlay ) return VLC_EGENERIC;
995 SetOverlayTransparency( p_intf, VLC_TRUE );
997 /* We know the chroma, allocate a buffer which will be used
998 * to write to the overlay framebuffer */
999 p_sys->p_overlay->p->i_pixel_pitch = p_sys->i_bytes_per_pixel;
1000 p_sys->p_overlay->p->i_lines = p_sys->var_info.yres;
1001 p_sys->p_overlay->p->i_visible_lines = p_sys->var_info.yres;
1003 if( p_sys->var_info.xres_virtual )
1005 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres_virtual
1006 * p_sys->i_bytes_per_pixel;
1010 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres
1011 * p_sys->i_bytes_per_pixel;
1014 p_sys->p_overlay->p->i_visible_pitch = p_sys->var_info.xres
1015 * p_sys->i_bytes_per_pixel;
1017 p_sys->p_overlay->i_planes = 1;
1022 /*****************************************************************************
1023 * End: terminate framebuffer interface
1024 *****************************************************************************/
1025 static void End( intf_thread_t *p_intf )
1027 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1030 SetOverlayTransparency( p_intf, VLC_FALSE );
1031 if( p_sys->p_overlay )
1033 write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels, p_sys->i_page_size );
1036 DeAllocatePicture( VLC_OBJECT(p_intf), p_intf->p_sys->p_overlay,
1037 &p_intf->p_sys->fmt_out );
1038 p_intf->p_sys->p_overlay = NULL;
1041 /*****************************************************************************
1042 * OpenDisplay: initialize framebuffer
1043 *****************************************************************************/
1044 static int OpenDisplay( intf_thread_t *p_intf )
1046 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1047 char *psz_device; /* framebuffer device path */
1048 struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
1050 /* Open framebuffer device */
1051 if( !(psz_device = config_GetPsz( p_intf, "fbosd-dev" )) )
1053 msg_Err( p_intf, "don't know which fb osd/overlay device to open" );
1054 return VLC_EGENERIC;
1057 p_sys->i_fd = open( psz_device, O_RDWR );
1058 if( p_sys->i_fd == -1 )
1060 msg_Err( p_intf, "cannot open %s (%s)", psz_device, strerror(errno) );
1062 return VLC_EGENERIC;
1066 /* Get framebuffer device information */
1067 if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) )
1069 msg_Err( p_intf, "cannot get fb info (%s)", strerror(errno) );
1070 close( p_sys->i_fd );
1071 return VLC_EGENERIC;
1074 /* Get some info on the framebuffer itself */
1075 if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) == 0 )
1077 p_sys->i_width = p_sys->fmt_out.i_width = p_sys->var_info.xres;
1078 p_sys->i_height = p_sys->fmt_out.i_height = p_sys->var_info.yres;
1081 /* FIXME: if the image is full-size, it gets cropped on the left
1082 * because of the xres / xres_virtual slight difference */
1083 msg_Dbg( p_intf, "%ix%i (virtual %ix%i)",
1084 p_sys->var_info.xres, p_sys->var_info.yres,
1085 p_sys->var_info.xres_virtual,
1086 p_sys->var_info.yres_virtual );
1088 p_sys->fmt_out.i_width = p_sys->i_width;
1089 p_sys->fmt_out.i_height = p_sys->i_height;
1091 p_sys->p_palette = NULL;
1092 p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
1094 switch( p_sys->var_info.bits_per_pixel )
1097 p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) );
1098 if( !p_sys->p_palette )
1100 msg_Err( p_intf, "out of memory" );
1101 close( p_sys->i_fd );
1104 p_sys->fb_cmap.start = 0;
1105 p_sys->fb_cmap.len = 256;
1106 p_sys->fb_cmap.red = p_sys->p_palette;
1107 p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t );
1108 p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t );
1109 p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t );
1111 /* Save the colormap */
1112 ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap );
1114 p_sys->i_bytes_per_pixel = 1;
1119 p_sys->i_bytes_per_pixel = 2;
1123 p_sys->i_bytes_per_pixel = 3;
1127 p_sys->i_bytes_per_pixel = 4;
1131 msg_Err( p_intf, "screen depth %d is not supported",
1132 p_sys->var_info.bits_per_pixel );
1134 close( p_sys->i_fd );
1135 return VLC_EGENERIC;
1138 p_sys->i_page_size = p_sys->i_width * p_sys->i_height
1139 * p_sys->i_bytes_per_pixel;
1141 msg_Dbg( p_intf, "framebuffer type=%d, visual=%d, ypanstep=%d, "
1142 "ywrap=%d, accel=%d", fix_info.type, fix_info.visual,
1143 fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
1147 /*****************************************************************************
1148 * CloseDisplay: terminate FB interface thread
1149 *****************************************************************************/
1150 static void CloseDisplay( intf_thread_t *p_intf )
1152 intf_sys_t *p_sys = (intf_sys_t *) p_intf;
1154 /* Restore palette */
1155 if( p_sys->var_info.bits_per_pixel == 8 )
1157 ioctl( p_sys->i_fd, FBIOPUTCMAP, &p_sys->fb_cmap );
1158 free( p_sys->p_palette );
1159 p_sys->p_palette = NULL;
1163 close( p_sys->i_fd );
1166 /*****************************************************************************
1168 *****************************************************************************
1169 * This part of the interface is in a separate thread so that we can call
1170 * exec() from within it without annoying the rest of the program.
1171 *****************************************************************************/
1172 static void Run( intf_thread_t *p_intf )
1174 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1176 while( !intf_ShouldDie( p_intf ) )
1178 if( p_sys->b_render )
1180 if( p_sys->b_image )
1183 p_pic = LoadImage( p_intf, &p_sys->fmt_out, p_sys->psz_file );
1186 RenderPicture( p_intf, p_sys->i_x, p_sys->i_y,
1187 p_pic, p_sys->p_overlay );
1188 p_pic->pf_release( p_pic );
1190 var_SetString( p_intf, "fbosd-image", "" );
1191 p_sys->b_image = VLC_FALSE;
1197 #ifndef FBOSD_BLENDING
1198 p_text = RenderText( p_intf, p_sys->psz_text, &p_sys->fmt_out );
1201 RenderPicture( p_intf, p_sys->i_x, p_sys->i_y,
1202 p_text, p_sys->p_overlay );
1203 p_text->pf_release( p_text );
1206 video_format_t fmt_in;
1207 memset( &fmt_in, 0, sizeof(video_format_t) );
1208 p_text = RenderText( p_intf, p_sys->psz_text, &fmt_in );
1211 BlendPicture( p_intf, &fmt_in, &p_sys->fmt_out,
1212 p_text, p_sys->p_overlay );
1213 msg_Dbg( p_intf, "releasing picture" );
1214 DeAllocatePicture( VLC_OBJECT( p_intf ), p_text, &fmt_in );
1217 var_SetString( p_intf, "fbosd-text", "" );
1218 p_sys->b_text = VLC_FALSE;
1220 p_sys->b_render = VLC_FALSE;
1223 if( p_sys->b_clear )
1225 SetOverlayTransparency( p_intf, VLC_TRUE );
1227 var_SetString( p_intf, "fbosd-image", "" );
1228 var_SetString( p_intf, "fbosd-text", "" );
1230 p_sys->b_image = VLC_FALSE;
1231 p_sys->b_text = VLC_FALSE;
1232 p_sys->b_clear = VLC_FALSE;
1233 p_sys->b_need_update = VLC_TRUE;
1236 if( p_sys->b_need_update && p_sys->p_overlay )
1238 write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels,
1239 p_sys->i_page_size );
1240 lseek( p_sys->i_fd, 0, SEEK_SET );
1241 p_sys->b_need_update = VLC_FALSE;
1244 if( vlc_CPU() & CPU_CAPABILITY_FPU )
1245 msleep( INTF_IDLE_SLEEP );
1253 static int OverlayCallback( vlc_object_t *p_this, char const *psz_cmd,
1254 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1256 intf_thread_t *p_intf = (intf_thread_t *) p_this;
1257 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1259 if( !strncmp( psz_cmd, "fbosd-image", 11 ) )
1261 free( p_sys->psz_file );
1262 p_sys->psz_file = strdup( newval.psz_string );
1263 p_sys->b_image = VLC_TRUE;
1265 else if( !strncmp( psz_cmd, "fbosd-text", 10 ) )
1267 free( p_sys->psz_text );
1268 p_sys->psz_text = strdup( newval.psz_string );
1269 p_sys->b_text = VLC_TRUE;
1271 else if( !strncmp( psz_cmd, "fbosd-x", 7 ) )
1273 p_sys->b_absolute = VLC_FALSE;
1274 p_sys->i_x = (newval.i_int < p_sys->i_width) ?
1275 newval.i_int : p_sys->i_width;
1277 else if( !strncmp( psz_cmd, "fbosd-y", 7 ) )
1279 p_sys->b_absolute = VLC_FALSE;
1280 p_sys->i_y = (newval.i_int < p_sys->i_height) ?
1281 newval.i_int : p_sys->i_height;
1283 else if( !strncmp( psz_cmd, "fbosd-position", 14 ) )
1285 p_sys->b_absolute = VLC_TRUE;
1286 p_sys->i_pos = newval.i_int;
1288 else if( !strncmp( psz_cmd, "fbosd-font-size", 15 ) )
1290 p_sys->p_style->i_font_size = newval.i_int;
1292 else if( !strncmp( psz_cmd, "fbosd-font-color", 16 ) )
1294 p_sys->p_style->i_font_color = newval.i_int;
1296 else if( !strncmp( psz_cmd, "fbosd-font-opacity", 18 ) )
1298 p_sys->p_style->i_font_alpha = 255 - newval.i_int;
1300 else if( !strncmp( psz_cmd, "fbosd-display", 13 ) )
1302 p_sys->b_need_update = VLC_TRUE;
1304 else if( !strncmp( psz_cmd, "fbosd-render", 12 ) )
1306 p_sys->b_render = VLC_TRUE;
1308 else if( !strncmp( psz_cmd, "fbosd-clear", 11 ) )
1310 p_sys->b_clear = VLC_TRUE;
1312 #ifdef FBOSD_BLENDING
1313 else if( !strncmp( psz_cmd, "fbosd-alpha", 11 ) )
1315 p_sys->i_alpha = newval.i_int;