1 /*****************************************************************************
2 * fbosd.c : framebuffer osd plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2007, the VideoLAN team
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_release( 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 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_release( 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_release( 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 )
689 free( p_pic->p_data_orig );
690 if( p_pic->pf_release ) p_pic->pf_release( p_pic );
694 free( p_fmt->p_palette );
695 p_fmt->p_palette = NULL;
700 /*****************************************************************************
701 * SetOverlayTransparency: Set the transparency for this overlay fb,
702 * - VLC_TRUE is make transparent
703 * - VLC_FALSE is make non tranparent
704 *****************************************************************************/
705 static void SetOverlayTransparency( intf_thread_t *p_intf,
706 vlc_bool_t b_transparent )
708 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
709 size_t i_size = p_sys->fmt_out.i_width * p_sys->fmt_out.i_height
710 * p_sys->i_bytes_per_pixel;
711 size_t i_page_size = (p_sys->i_page_size > i_size) ?
712 i_size : p_sys->i_page_size;
714 if( p_sys->p_overlay )
716 msg_Dbg( p_intf, "Make overlay %s",
717 b_transparent ? "transparent" : "opaque" );
718 memset( p_sys->p_overlay->p[0].p_pixels, 0x00, i_page_size );
720 memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, i_page_size );
724 #ifdef FBOSD_BLENDING
725 /*****************************************************************************
726 * BlendPicture: Blend two pictures together..
727 *****************************************************************************/
728 static int BlendPicture( intf_thread_t *p_intf, video_format_t *p_fmt_src,
729 video_format_t *p_fmt_dst, picture_t *p_pic_src,
730 picture_t *p_pic_dst )
732 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
733 if( p_sys->p_blend && p_sys->p_blend->p_module )
735 int i_x_offset = p_sys->i_x;
736 int i_y_offset = p_sys->i_y;
738 memcpy( &p_sys->p_blend->fmt_in.video, p_fmt_src, sizeof( video_format_t ) );
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_src, (char*)&p_fmt_src->i_chroma,
742 p_sys->p_blend->fmt_in.video.i_width, p_sys->p_blend->fmt_in.video.i_height,
743 p_fmt_src->i_bits_per_pixel,
745 p_pic_src->p[0].p_pixels, p_pic_src->p[1].p_pixels,
746 p_pic_src->p[2].p_pixels, p_pic_src->p[3].p_pixels );
747 msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
748 p_pic_dst, (char*)&p_fmt_dst->i_chroma,
749 p_fmt_dst->i_width, p_fmt_dst->i_height,
750 p_fmt_dst->i_bits_per_pixel,
752 p_pic_dst->p[0].p_pixels, p_pic_dst->p[1].p_pixels,
753 p_pic_dst->p[2].p_pixels, p_pic_dst->p[3].p_pixels );
755 /* Update the output picture size */
756 p_sys->p_blend->fmt_out.video.i_width =
757 p_sys->p_blend->fmt_out.video.i_visible_width =
759 p_sys->p_blend->fmt_out.video.i_height =
760 p_sys->p_blend->fmt_out.video.i_visible_height =
763 i_x_offset = __MAX( i_x_offset, 0 );
764 i_y_offset = __MAX( i_y_offset, 0 );
766 p_sys->p_blend->pf_video_blend( p_sys->p_blend, p_pic_dst,
767 p_pic_src, p_pic_dst, i_x_offset, i_y_offset,
776 /*****************************************************************************
777 * RenderPicture: Render the picture into the p_dest buffer.
778 * We don't take transparent pixels into account, so we don't have to blend
779 * the two images together.
780 *****************************************************************************/
781 static int RenderPicture( intf_thread_t *p_intf, int i_x_offset, int i_y_offset,
782 picture_t *p_src, picture_t *p_dest )
786 if( !p_dest && !p_src ) return VLC_EGENERIC;
788 for( i = 0; i < p_src->i_planes ; i++ )
790 if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
792 /* There are margins, but with the same width : perfect ! */
793 p_intf->p_libvlc->pf_memcpy(
794 p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
795 p_src->p[i].i_pitch * p_src->p[i].i_visible_lines );
799 /* We need to proceed line by line */
800 uint8_t *p_in = p_src->p[i].p_pixels;
801 uint8_t *p_out = p_dest->p[i].p_pixels;
803 int i_x = i_x_offset * p_src->p[i].i_pixel_pitch;
804 int i_x_clip, i_y_clip;
806 /* Check boundaries, clip the image if necessary */
807 i_x_clip = ( i_x + p_src->p[i].i_visible_pitch ) - p_dest->p[i].i_visible_pitch;
808 i_x_clip = ( i_x_clip > 0 ) ? i_x_clip : 0;
810 i_y_clip = ( i_y_offset + p_src->p[i].i_visible_lines ) - p_dest->p[i].i_visible_lines;
811 i_y_clip = ( i_y_clip > 0 ) ? i_y_clip : 0;
813 msg_Dbg( p_intf, "i_pitch (%d,%d), (%d,%d)/(%d,%d)",
814 p_dest->p[i].i_visible_pitch, p_src->p[i].i_visible_pitch,
815 i_x_offset, i_y_offset, i_x, i_x_clip );
817 if( ( i_y_offset <= p_dest->p[i].i_visible_lines ) &&
818 ( i_x <= p_dest->p[i].i_visible_pitch ) )
822 p_out += ( i_y_offset * p_dest->p[i].i_pitch );
823 for( i_line = 0; i_line < ( p_src->p[i].i_visible_lines - i_y_clip ); i_line++ )
825 p_intf->p_libvlc->pf_memcpy( p_out + i_x, p_in,
826 p_src->p[i].i_visible_pitch - i_x_clip );
827 p_in += p_src->p[i].i_pitch;
828 p_out += p_dest->p[i].i_pitch;
836 /*****************************************************************************
837 * RenderText - Render text to the desired picture format
838 *****************************************************************************/
839 static picture_t *RenderText( intf_thread_t *p_intf, const char *psz_text,
840 video_format_t *p_fmt )
842 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
843 subpicture_region_t *p_region;
844 picture_t *p_dest = NULL;
846 if( !psz_text ) return p_dest;
848 if( p_sys->p_text && p_sys->p_text->p_module )
850 p_region = (subpicture_region_t *) malloc( sizeof(subpicture_region_t) );
854 memset( p_region, 0, sizeof(subpicture_region_t) );
856 p_region->psz_text = strdup( p_sys->psz_text );
857 p_region->p_style = p_sys->p_style;
859 p_region->fmt.i_chroma = VLC_FOURCC('T','E','X','T');
860 p_region->fmt.i_aspect = 0;
861 p_region->fmt.i_width = p_region->fmt.i_visible_width = 0;
862 p_region->fmt.i_height = p_region->fmt.i_visible_height = 0;
863 p_region->fmt.i_x_offset = 0;
864 p_region->fmt.i_y_offset = 0;
866 p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
868 if( p_sys->p_text->pf_render_text )
870 video_format_t fmt_out;
872 memset( &fmt_out, 0, sizeof(video_format_t) );
874 p_sys->p_text->pf_render_text( p_sys->p_text,
875 p_region, p_region );
877 #ifndef FBOSD_BLENDING
878 fmt_out.i_chroma = p_fmt->i_chroma;
879 p_dest = ConvertImage( p_intf, &p_region->picture,
880 &p_region->fmt, &fmt_out );
882 fmt_out = p_region->fmt;
883 fmt_out.i_bits_per_pixel = 32;
884 memcpy( p_fmt, &fmt_out, sizeof(video_format_t) );
885 p_dest = AllocatePicture( VLC_OBJECT(p_intf), &fmt_out );
888 if( p_region->picture.pf_release )
889 p_region->picture.pf_release( &p_region->picture );
890 free( p_region->psz_text );
894 vout_CopyPicture( VLC_OBJECT(p_intf), p_dest, &p_region->picture );
896 if( p_region->picture.pf_release )
897 p_region->picture.pf_release( &p_region->picture );
898 free( p_region->psz_text );
902 free( p_region->psz_text );
908 /*****************************************************************************
909 * LoadImage: Load an image from file into a picture buffer.
910 *****************************************************************************/
911 static picture_t *LoadImage( intf_thread_t *p_intf, video_format_t *p_fmt,
914 picture_t *p_pic = NULL;
916 if( psz_file && p_intf->p_sys->p_image )
918 video_format_t fmt_in, fmt_out;
920 memset( &fmt_in, 0, sizeof(fmt_in) );
921 memset( &fmt_out, 0, sizeof(fmt_out) );
923 fmt_out.i_chroma = p_fmt->i_chroma;
924 p_pic = image_ReadUrl( p_intf->p_sys->p_image, psz_file,
927 msg_Dbg( p_intf, "image size %dx%d chroma %4.4s",
928 fmt_out.i_width, fmt_out.i_height,
929 (char *)&p_fmt->i_chroma );
934 #ifndef FBOSD_BLENDING
935 /*****************************************************************************
936 * Convertmage: Convert image to another fourcc
937 *****************************************************************************/
938 static picture_t *ConvertImage( intf_thread_t *p_intf, picture_t *p_pic,
939 video_format_t *p_fmt_in, video_format_t *p_fmt_out )
941 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
942 picture_t *p_old = NULL;
946 p_old = image_Convert( p_sys->p_image, p_pic, p_fmt_in, p_fmt_out );
948 msg_Dbg( p_intf, "converted image size %dx%d chroma %4.4s",
949 p_fmt_out->i_width, p_fmt_out->i_height,
950 (char *)&p_fmt_out->i_chroma );
956 /*****************************************************************************
957 * Init: initialize framebuffer video thread output method
958 *****************************************************************************/
959 static int Init( intf_thread_t *p_intf )
961 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
963 /* Initialize the output structure: RGB with square pixels, whatever
964 * the input format is, since it's the only format we know */
965 switch( p_sys->var_info.bits_per_pixel )
967 case 8: /* FIXME: set the palette */
968 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','G','B','2'); break;
970 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','5'); break;
972 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','6'); break;
974 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','2','4'); break;
976 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','3','2'); break;
978 msg_Err( p_intf, "unknown screen depth %i",
979 p_sys->var_info.bits_per_pixel );
983 p_sys->fmt_out.i_bits_per_pixel = p_sys->var_info.bits_per_pixel;
984 p_sys->fmt_out.i_width = p_sys->i_width;
985 p_sys->fmt_out.i_height = p_sys->i_height;
987 /* Assume we have square pixels */
988 if( p_sys->i_aspect < 0 )
990 p_sys->fmt_out.i_aspect = ( p_sys->i_width
991 * VOUT_ASPECT_FACTOR ) / p_sys->i_height;
993 else p_sys->fmt_out.i_aspect = p_sys->i_aspect;
995 p_sys->fmt_out.i_sar_num = p_sys->fmt_out.i_sar_den = 1;
997 /* Allocate overlay buffer */
998 p_sys->p_overlay = AllocatePicture( VLC_OBJECT(p_intf),
1000 if( !p_sys->p_overlay ) return VLC_EGENERIC;
1002 SetOverlayTransparency( p_intf, VLC_TRUE );
1004 /* We know the chroma, allocate a buffer which will be used
1005 * to write to the overlay framebuffer */
1006 p_sys->p_overlay->p->i_pixel_pitch = p_sys->i_bytes_per_pixel;
1007 p_sys->p_overlay->p->i_lines = p_sys->var_info.yres;
1008 p_sys->p_overlay->p->i_visible_lines = p_sys->var_info.yres;
1010 if( p_sys->var_info.xres_virtual )
1012 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres_virtual
1013 * p_sys->i_bytes_per_pixel;
1017 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres
1018 * p_sys->i_bytes_per_pixel;
1021 p_sys->p_overlay->p->i_visible_pitch = p_sys->var_info.xres
1022 * p_sys->i_bytes_per_pixel;
1024 p_sys->p_overlay->i_planes = 1;
1029 /*****************************************************************************
1030 * End: terminate framebuffer interface
1031 *****************************************************************************/
1032 static void End( intf_thread_t *p_intf )
1034 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1037 SetOverlayTransparency( p_intf, VLC_FALSE );
1038 if( p_sys->p_overlay )
1040 write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels, p_sys->i_page_size );
1043 DeAllocatePicture( VLC_OBJECT(p_intf), p_intf->p_sys->p_overlay,
1044 &p_intf->p_sys->fmt_out );
1045 p_intf->p_sys->p_overlay = NULL;
1048 /*****************************************************************************
1049 * OpenDisplay: initialize framebuffer
1050 *****************************************************************************/
1051 static int OpenDisplay( intf_thread_t *p_intf )
1053 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1054 char *psz_device; /* framebuffer device path */
1055 struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
1057 /* Open framebuffer device */
1058 if( !(psz_device = config_GetPsz( p_intf, "fbosd-dev" )) )
1060 msg_Err( p_intf, "don't know which fb osd/overlay device to open" );
1061 return VLC_EGENERIC;
1064 p_sys->i_fd = open( psz_device, O_RDWR );
1065 if( p_sys->i_fd == -1 )
1067 msg_Err( p_intf, "cannot open %s (%s)", psz_device, strerror(errno) );
1069 return VLC_EGENERIC;
1073 /* Get framebuffer device information */
1074 if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) )
1076 msg_Err( p_intf, "cannot get fb info (%s)", strerror(errno) );
1077 close( p_sys->i_fd );
1078 return VLC_EGENERIC;
1081 /* Get some info on the framebuffer itself */
1082 if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) == 0 )
1084 p_sys->i_width = p_sys->fmt_out.i_width = p_sys->var_info.xres;
1085 p_sys->i_height = p_sys->fmt_out.i_height = p_sys->var_info.yres;
1088 /* FIXME: if the image is full-size, it gets cropped on the left
1089 * because of the xres / xres_virtual slight difference */
1090 msg_Dbg( p_intf, "%ix%i (virtual %ix%i)",
1091 p_sys->var_info.xres, p_sys->var_info.yres,
1092 p_sys->var_info.xres_virtual,
1093 p_sys->var_info.yres_virtual );
1095 p_sys->fmt_out.i_width = p_sys->i_width;
1096 p_sys->fmt_out.i_height = p_sys->i_height;
1098 p_sys->p_palette = NULL;
1099 p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
1101 switch( p_sys->var_info.bits_per_pixel )
1104 p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) );
1105 if( !p_sys->p_palette )
1107 msg_Err( p_intf, "out of memory" );
1108 close( p_sys->i_fd );
1111 p_sys->fb_cmap.start = 0;
1112 p_sys->fb_cmap.len = 256;
1113 p_sys->fb_cmap.red = p_sys->p_palette;
1114 p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t );
1115 p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t );
1116 p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t );
1118 /* Save the colormap */
1119 ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap );
1121 p_sys->i_bytes_per_pixel = 1;
1126 p_sys->i_bytes_per_pixel = 2;
1130 p_sys->i_bytes_per_pixel = 3;
1134 p_sys->i_bytes_per_pixel = 4;
1138 msg_Err( p_intf, "screen depth %d is not supported",
1139 p_sys->var_info.bits_per_pixel );
1141 close( p_sys->i_fd );
1142 return VLC_EGENERIC;
1145 p_sys->i_page_size = p_sys->i_width * p_sys->i_height
1146 * p_sys->i_bytes_per_pixel;
1148 msg_Dbg( p_intf, "framebuffer type=%d, visual=%d, ypanstep=%d, "
1149 "ywrap=%d, accel=%d", fix_info.type, fix_info.visual,
1150 fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
1154 /*****************************************************************************
1155 * CloseDisplay: terminate FB interface thread
1156 *****************************************************************************/
1157 static void CloseDisplay( intf_thread_t *p_intf )
1159 intf_sys_t *p_sys = (intf_sys_t *) p_intf;
1161 /* Restore palette */
1162 if( p_sys->var_info.bits_per_pixel == 8 )
1164 ioctl( p_sys->i_fd, FBIOPUTCMAP, &p_sys->fb_cmap );
1165 free( p_sys->p_palette );
1166 p_sys->p_palette = NULL;
1170 close( p_sys->i_fd );
1173 /*****************************************************************************
1175 *****************************************************************************
1176 * This part of the interface is in a separate thread so that we can call
1177 * exec() from within it without annoying the rest of the program.
1178 *****************************************************************************/
1179 static void Run( intf_thread_t *p_intf )
1181 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1183 while( !intf_ShouldDie( p_intf ) )
1185 if( p_sys->b_render )
1187 if( p_sys->b_image )
1190 p_pic = LoadImage( p_intf, &p_sys->fmt_out, p_sys->psz_file );
1193 RenderPicture( p_intf, p_sys->i_x, p_sys->i_y,
1194 p_pic, p_sys->p_overlay );
1195 p_pic->pf_release( p_pic );
1197 var_SetString( p_intf, "fbosd-image", "" );
1198 p_sys->b_image = VLC_FALSE;
1204 #ifndef FBOSD_BLENDING
1205 p_text = RenderText( p_intf, p_sys->psz_text, &p_sys->fmt_out );
1208 RenderPicture( p_intf, p_sys->i_x, p_sys->i_y,
1209 p_text, p_sys->p_overlay );
1210 p_text->pf_release( p_text );
1213 video_format_t fmt_in;
1214 memset( &fmt_in, 0, sizeof(video_format_t) );
1215 p_text = RenderText( p_intf, p_sys->psz_text, &fmt_in );
1218 BlendPicture( p_intf, &fmt_in, &p_sys->fmt_out,
1219 p_text, p_sys->p_overlay );
1220 msg_Dbg( p_intf, "releasing picture" );
1221 DeAllocatePicture( VLC_OBJECT( p_intf ), p_text, &fmt_in );
1224 var_SetString( p_intf, "fbosd-text", "" );
1225 p_sys->b_text = VLC_FALSE;
1227 p_sys->b_render = VLC_FALSE;
1230 if( p_sys->b_clear )
1232 SetOverlayTransparency( p_intf, VLC_TRUE );
1234 var_SetString( p_intf, "fbosd-image", "" );
1235 var_SetString( p_intf, "fbosd-text", "" );
1237 p_sys->b_image = VLC_FALSE;
1238 p_sys->b_text = VLC_FALSE;
1239 p_sys->b_clear = VLC_FALSE;
1240 p_sys->b_need_update = VLC_TRUE;
1243 if( p_sys->b_need_update && p_sys->p_overlay )
1245 write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels,
1246 p_sys->i_page_size );
1247 lseek( p_sys->i_fd, 0, SEEK_SET );
1248 p_sys->b_need_update = VLC_FALSE;
1251 if( vlc_CPU() & CPU_CAPABILITY_FPU )
1252 msleep( INTF_IDLE_SLEEP );
1260 static int OverlayCallback( vlc_object_t *p_this, char const *psz_cmd,
1261 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1263 intf_thread_t *p_intf = (intf_thread_t *) p_this;
1264 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1266 if( !strncmp( psz_cmd, "fbosd-image", 11 ) )
1268 free( p_sys->psz_file );
1269 p_sys->psz_file = strdup( newval.psz_string );
1270 p_sys->b_image = VLC_TRUE;
1272 else if( !strncmp( psz_cmd, "fbosd-text", 10 ) )
1274 free( p_sys->psz_text );
1275 p_sys->psz_text = strdup( newval.psz_string );
1276 p_sys->b_text = VLC_TRUE;
1278 else if( !strncmp( psz_cmd, "fbosd-x", 7 ) )
1280 p_sys->b_absolute = VLC_FALSE;
1281 p_sys->i_x = (newval.i_int < p_sys->i_width) ?
1282 newval.i_int : p_sys->i_width;
1284 else if( !strncmp( psz_cmd, "fbosd-y", 7 ) )
1286 p_sys->b_absolute = VLC_FALSE;
1287 p_sys->i_y = (newval.i_int < p_sys->i_height) ?
1288 newval.i_int : p_sys->i_height;
1290 else if( !strncmp( psz_cmd, "fbosd-position", 14 ) )
1292 p_sys->b_absolute = VLC_TRUE;
1293 p_sys->i_pos = newval.i_int;
1295 else if( !strncmp( psz_cmd, "fbosd-font-size", 15 ) )
1297 p_sys->p_style->i_font_size = newval.i_int;
1299 else if( !strncmp( psz_cmd, "fbosd-font-color", 16 ) )
1301 p_sys->p_style->i_font_color = newval.i_int;
1303 else if( !strncmp( psz_cmd, "fbosd-font-opacity", 18 ) )
1305 p_sys->p_style->i_font_alpha = 255 - newval.i_int;
1307 else if( !strncmp( psz_cmd, "fbosd-display", 13 ) )
1309 p_sys->b_need_update = VLC_TRUE;
1311 else if( !strncmp( psz_cmd, "fbosd-render", 12 ) )
1313 p_sys->b_render = VLC_TRUE;
1315 else if( !strncmp( psz_cmd, "fbosd-clear", 11 ) )
1317 p_sys->b_clear = VLC_TRUE;
1319 #ifdef FBOSD_BLENDING
1320 else if( !strncmp( psz_cmd, "fbosd-alpha", 11 ) )
1322 p_sys->i_alpha = newval.i_int;