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 *,
104 text_style_t *, video_format_t * );
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, true );
190 add_string( "fbosd-image", NULL, NULL, FBOSD_IMAGE_TEXT,
191 FBOSD_IMAGE_LONGTEXT, true );
192 add_string( "fbosd-text", NULL, NULL, FBOSD_TEXT,
193 FBOSD_LONGTEXT, true );
195 #ifdef FBOSD_BLENDING
196 add_integer_with_range( "fbosd-alpha", 255, 0, 255, NULL, ALPHA_TEXT,
197 ALPHA_LONGTEXT, true );
201 set_section( N_("Position"), NULL );
202 add_integer( "fbosd-x", 0, NULL, POSX_TEXT,
203 POSX_LONGTEXT, false );
204 add_integer( "fbosd-y", 0, NULL, POSY_TEXT,
205 POSY_LONGTEXT, false );
206 add_integer( "fbosd-position", 8, NULL, POS_TEXT, POS_LONGTEXT, 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, 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", false, NULL, CLEAR_TEXT, CLEAR_LONGTEXT, true );
220 add_bool( "fbosd-render", false, NULL, RENDER_TEXT, RENDER_LONGTEXT, true );
221 add_bool( "fbosd-display", false, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, true );
223 set_description( _("GNU/Linux osd/overlay framebuffer interface") );
224 set_capability( "interface", 10 );
225 set_callbacks( Create, Destroy );
228 /*****************************************************************************
229 * fbosd_render_t: render descriptor
230 *****************************************************************************/
231 struct fbosd_render_t
233 #define FBOSD_RENDER_IMAGE 0
234 #define FBOSD_RENDER_TEXT 1
237 #define FBOSD_STATE_FREE 0
238 #define FBOSD_STATE_RESERVED 1
239 #define FBOSD_STATE_RENDER 2
243 text_style_t text_style; /* font control */
251 int i_alpha; /* transparency for images */
253 #define FBOSD_RENDER_MAX 10
255 /*****************************************************************************
256 * intf_sys_t: interface framebuffer method descriptor
257 *****************************************************************************/
260 /* Framebuffer information */
261 int i_fd; /* device handle */
262 struct fb_var_screeninfo var_info; /* current mode information */
263 bool b_pan; /* does device supports panning ? */
264 struct fb_cmap fb_cmap; /* original colormap */
265 uint16_t *p_palette; /* original palette */
267 /* Overlay framebuffer format */
268 video_format_t fmt_out;
269 picture_t *p_overlay;
270 size_t i_page_size; /* page size */
274 int i_bytes_per_pixel;
276 /* Image and Picture rendering */
277 image_handler_t *p_image;
278 #ifdef FBOSD_BLENDING
279 filter_t *p_blend; /* alpha blending module */
281 filter_t *p_text; /* text renderer module */
283 filter_t *p_scale; /* scaling module */
287 struct fbosd_render_t render[FBOSD_RENDER_MAX];
290 text_style_t *p_style; /* font control */
298 int i_alpha; /* transparency for images */
300 /* commands control */
301 bool b_need_update; /* update display with \overlay buffer */
302 bool b_clear; /* clear overlay buffer make it tranparent */
303 bool b_render; /* render an image or text in overlay buffer */
306 /*****************************************************************************
307 * Create: allocates FB interface thread output method
308 *****************************************************************************/
309 static int Create( vlc_object_t *p_this )
311 intf_thread_t *p_intf = (intf_thread_t *)p_this;
318 /* Allocate instance and initialize some members */
319 p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) );
322 msg_Err( p_intf, "out of memory" );
325 memset( p_sys, 0, sizeof(intf_sys_t) );
327 p_sys->p_style = malloc( sizeof( text_style_t ) );
328 if( !p_sys->p_style )
330 free( p_intf->p_sys );
331 msg_Err( p_intf, "out of memory" );
334 vlc_memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
336 p_intf->pf_run = Run;
338 p_sys->p_image = image_HandlerCreate( p_this );
339 if( !p_sys->p_image )
341 free( p_intf->p_sys->p_style );
342 free( p_intf->p_sys );
343 msg_Err( p_intf, "out of memory" );
347 #ifdef FBOSD_BLENDING
348 p_sys->i_alpha = var_CreateGetIntegerCommand( p_intf, "fbosd-alpha" );
349 var_AddCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
351 p_sys->i_alpha = 255;
353 p_sys->i_aspect = -1;
355 var_CreateGetNonEmptyString( p_intf, "fbosd-aspect-ratio" );
358 char *psz_parser = strchr( psz_aspect, ':' );
362 *psz_parser++ = '\0';
363 p_sys->i_aspect = ( atoi( psz_aspect )
364 * VOUT_ASPECT_FACTOR ) / atoi( psz_parser );
365 p_sys->fmt_out.i_aspect = p_sys->i_aspect;
367 msg_Dbg( p_intf, "using aspect ratio %d:%d",
368 atoi( psz_aspect ), atoi( psz_parser ) );
374 /* Use PAL by default */
375 p_sys->i_width = p_sys->fmt_out.i_width = 704;
376 p_sys->i_height = p_sys->fmt_out.i_height = 576;
378 psz_tmp = var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-image" );
379 var_AddCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
380 if( psz_tmp && *psz_tmp )
382 p_sys->render[0].i_type = FBOSD_RENDER_IMAGE;
383 p_sys->render[0].i_state = FBOSD_STATE_RENDER;
384 p_sys->render[0].psz_string = strdup( psz_tmp );
388 psz_tmp = var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-text" );
389 var_AddCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
390 if( psz_tmp && *psz_tmp )
392 p_sys->render[1].i_type = FBOSD_RENDER_TEXT;
393 p_sys->render[1].i_state = FBOSD_STATE_RENDER;
394 p_sys->render[1].psz_string = strdup( psz_tmp );
398 p_sys->i_pos = var_CreateGetIntegerCommand( p_intf, "fbosd-position" );
399 p_sys->i_x = var_CreateGetIntegerCommand( p_intf, "fbosd-x" );
400 p_sys->i_y = var_CreateGetIntegerCommand( p_intf, "fbosd-y" );
402 var_AddCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
403 var_AddCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
404 var_AddCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
406 p_sys->p_style->i_font_size =
407 var_CreateGetIntegerCommand( p_intf, "fbosd-font-size" );
408 p_sys->p_style->i_font_color =
409 var_CreateGetIntegerCommand( p_intf, "fbosd-font-color" );
410 p_sys->p_style->i_font_alpha = 255 -
411 var_CreateGetIntegerCommand( p_intf, "fbosd-font-opacity" );
413 var_AddCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
414 var_AddCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
415 var_AddCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
417 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
419 vlc_memcpy( &p_sys->render[i].text_style, &default_text_style,
420 sizeof( text_style_t ) );
423 p_sys->b_clear = var_CreateGetBoolCommand( p_intf, "fbosd-clear" );
424 p_sys->b_render = var_CreateGetBoolCommand( p_intf, "fbosd-render" );
425 p_sys->b_need_update = var_CreateGetBoolCommand( p_intf, "fbosd-display" );
427 var_AddCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
428 var_AddCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
429 var_AddCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
431 /* Check if picture position was overridden */
432 p_sys->b_absolute = true;
433 if( ( p_sys->i_x >= 0 ) && ( p_sys->i_y >= 0 ) )
435 p_sys->b_absolute = false;
436 p_sys->i_y = (p_sys->i_y < p_sys->i_height) ?
437 p_sys->i_y : p_sys->i_height;
438 p_sys->i_x = (p_sys->i_x < p_sys->i_width) ?
439 p_sys->i_x : p_sys->i_width;
442 p_sys->render[0].i_x = p_sys->render[1].i_x = p_sys->i_x;
443 p_sys->render[0].i_y = p_sys->render[1].i_y = p_sys->i_y;
444 p_sys->render[0].i_pos = p_sys->render[1].i_pos = p_sys->i_pos;
445 p_sys->render[0].i_alpha = p_sys->render[1].i_alpha = p_sys->i_alpha;
447 /* Initialize framebuffer */
448 if( OpenDisplay( p_intf ) )
450 Destroy( VLC_OBJECT(p_intf) );
456 #ifdef FBOSD_BLENDING
457 /* Load the blending module */
458 if( OpenBlending( p_intf ) )
460 msg_Err( p_intf, "Unable to load image blending module" );
461 Destroy( VLC_OBJECT(p_intf) );
466 /* Load text renderer module */
467 if( OpenTextRenderer( p_intf ) )
469 msg_Err( p_intf, "Unable to load text rendering module" );
470 Destroy( VLC_OBJECT(p_intf) );
474 /* Load scaling module */
475 if( OpenScaling( p_intf ) )
477 msg_Err( p_intf, "Unable to load image scaling module" );
478 Destroy( VLC_OBJECT(p_intf) );
482 p_sys->b_render = true;
483 p_sys->b_need_update = true;
488 /*****************************************************************************
489 * Destroy: destroy FB interface thread output method
490 *****************************************************************************
491 * Terminate an output method created by Create
492 *****************************************************************************/
493 static void Destroy( vlc_object_t *p_this )
495 intf_thread_t *p_intf = (intf_thread_t *)p_this;
496 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
499 p_sys->b_need_update = false;
500 p_sys->b_render = false;
501 p_sys->b_clear = false;
503 #ifdef FBOSD_BLENDING
504 var_DelCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
505 var_Destroy( p_intf, "fbosd-alpha" );
508 var_DelCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
509 var_DelCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
510 var_DelCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
511 var_DelCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
512 var_DelCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
513 var_DelCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
514 var_DelCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
515 var_DelCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
516 var_DelCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
517 var_DelCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
518 var_DelCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
520 var_Destroy( p_intf, "fbosd-x" );
521 var_Destroy( p_intf, "fbosd-y" );
522 var_Destroy( p_intf, "fbosd-position" );
523 var_Destroy( p_intf, "fbosd-image" );
524 var_Destroy( p_intf, "fbosd-text" );
525 var_Destroy( p_intf, "fbosd-font-size" );
526 var_Destroy( p_intf, "fbosd-font-color" );
527 var_Destroy( p_intf, "fbosd-font-opacity" );
528 var_Destroy( p_intf, "fbosd-clear" );
529 var_Destroy( p_intf, "fbosd-render" );
530 var_Destroy( p_intf, "fbosd-display" );
532 var_Destroy( p_intf, "fbosd-aspect-ratio" );
534 CloseDisplay( p_intf );
536 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
538 free( p_sys->render[i].psz_string );
539 p_sys->render[i].i_state = FBOSD_STATE_FREE;
542 #ifdef FBOSD_BLENDING
543 if( p_sys->p_blend ) CloseBlending( p_intf );
545 if( p_sys->p_text ) CloseTextRenderer( p_intf );
547 if( p_sys->p_scale ) CloseScaling( p_intf );
550 image_HandlerDelete( p_sys->p_image );
551 if( p_sys->p_overlay )
552 p_sys->p_overlay->pf_release( p_sys->p_overlay );
554 free( p_sys->p_style );
558 #ifdef FBOSD_BLENDING
559 static int OpenBlending( intf_thread_t *p_intf )
561 if( p_intf->p_sys->p_blend ) return VLC_EGENERIC;
563 p_intf->p_sys->p_blend =
564 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
565 vlc_object_attach( p_intf->p_sys->p_blend, p_intf );
566 p_intf->p_sys->p_blend->fmt_out.video.i_x_offset =
567 p_intf->p_sys->p_blend->fmt_out.video.i_y_offset = 0;
568 p_intf->p_sys->p_blend->fmt_out.video.i_aspect =
569 p_intf->p_sys->fmt_out.i_aspect;
570 p_intf->p_sys->p_blend->fmt_out.video.i_chroma =
571 p_intf->p_sys->fmt_out.i_chroma;
572 if( config_GetInt( p_intf, "freetype-yuvp" ) )
573 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
574 VLC_FOURCC('Y','U','V','P');
576 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
577 VLC_FOURCC('Y','U','V','A');
579 p_intf->p_sys->p_blend->p_module =
580 module_Need( p_intf->p_sys->p_blend, "video blending", 0, 0 );
582 if( !p_intf->p_sys->p_blend->p_module )
588 static void CloseBlending( intf_thread_t *p_intf )
590 if( p_intf->p_sys->p_blend )
592 if( p_intf->p_sys->p_blend->p_module )
593 module_Unneed( p_intf->p_sys->p_blend,
594 p_intf->p_sys->p_blend->p_module );
596 vlc_object_detach( p_intf->p_sys->p_blend );
597 vlc_object_release( p_intf->p_sys->p_blend );
602 static int OpenTextRenderer( intf_thread_t *p_intf )
604 char *psz_modulename = NULL;
606 if( p_intf->p_sys->p_text ) return VLC_EGENERIC;
608 p_intf->p_sys->p_text =
609 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
610 vlc_object_attach( p_intf->p_sys->p_text, p_intf );
612 p_intf->p_sys->p_text->fmt_out.video.i_width =
613 p_intf->p_sys->p_text->fmt_out.video.i_visible_width =
614 p_intf->p_sys->i_width;
615 p_intf->p_sys->p_text->fmt_out.video.i_height =
616 p_intf->p_sys->p_text->fmt_out.video.i_visible_height =
617 p_intf->p_sys->i_height;
619 psz_modulename = var_CreateGetString( p_intf, "text-renderer" );
620 if( psz_modulename && *psz_modulename )
622 p_intf->p_sys->p_text->p_module =
623 module_Need( p_intf->p_sys->p_text, "text renderer",
624 psz_modulename, true );
626 if( !p_intf->p_sys->p_text->p_module )
628 p_intf->p_sys->p_text->p_module =
629 module_Need( p_intf->p_sys->p_text, "text renderer", 0, 0 );
631 free( psz_modulename );
633 if( !p_intf->p_sys->p_text->p_module )
639 static void CloseTextRenderer( intf_thread_t *p_intf )
641 if( p_intf->p_sys->p_text )
643 if( p_intf->p_sys->p_text->p_module )
644 module_Unneed( p_intf->p_sys->p_text,
645 p_intf->p_sys->p_text->p_module );
647 vlc_object_detach( p_intf->p_sys->p_text );
648 vlc_object_release( p_intf->p_sys->p_text );
652 static int OpenScaling( intf_thread_t *p_intf )
654 if( p_intf->p_sys->p_scale ) return VLC_EGENERIC;
656 p_intf->p_sys->p_scale =
657 vlc_object_create( p_intf, VLC_OBJECT_FILTER );
658 vlc_object_attach( p_intf->p_sys->p_scale, p_intf );
659 p_intf->p_sys->p_scale->fmt_out.video.i_chroma =
660 p_intf->p_sys->p_scale->fmt_in.video.i_chroma =
661 p_intf->p_sys->fmt_out.i_chroma;
663 /* XXX: We'll also be using it for YUVA and RGBA blending ... */
664 p_intf->p_sys->p_scale->fmt_in.video.i_width =
665 p_intf->p_sys->p_scale->fmt_in.video.i_height = 32;
666 p_intf->p_sys->p_scale->fmt_out.video.i_width =
667 p_intf->p_sys->p_scale->fmt_out.video.i_height = 16;
669 p_intf->p_sys->p_scale->p_module =
670 module_Need( p_intf->p_sys->p_scale, "video filter2", 0, 0 );
672 if( !p_intf->p_sys->p_scale->p_module )
678 static int CloseScaling( intf_thread_t *p_intf )
680 if( p_intf->p_sys->p_scale )
682 if( p_intf->p_sys->p_scale->p_module )
683 module_Unneed( p_intf->p_sys->p_scale,
684 p_intf->p_sys->p_scale->p_module );
686 vlc_object_detach( p_intf->p_sys->p_scale );
687 vlc_object_release( p_intf->p_sys->p_scale );
692 /*****************************************************************************
694 * allocate a picture buffer for use with the overlay fb.
695 *****************************************************************************/
696 static picture_t *AllocatePicture( vlc_object_t *p_this,
697 video_format_t *p_fmt )
699 picture_t *p_pic = malloc( sizeof( picture_t ) );
700 if( !p_pic ) return NULL;
702 if( !p_fmt->p_palette &&
703 ( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') ) )
705 p_fmt->p_palette = malloc( sizeof(video_palette_t) );
706 if( !p_fmt->p_palette )
712 else p_fmt->p_palette = NULL;
714 p_pic->p_data_orig = NULL;
716 vout_AllocatePicture( p_this, p_pic, p_fmt->i_chroma,
717 p_fmt->i_width, p_fmt->i_height, p_fmt->i_aspect );
719 if( !p_pic->i_planes )
722 free( p_fmt->p_palette );
728 /*****************************************************************************
730 * Deallocate a picture buffer and free all associated memory.
731 *****************************************************************************/
732 static void DeAllocatePicture( vlc_object_t *p_this, picture_t *p_pic,
733 video_format_t *p_fmt )
738 free( p_pic->p_data_orig );
739 if( p_pic->pf_release ) p_pic->pf_release( p_pic );
743 free( p_fmt->p_palette );
744 p_fmt->p_palette = NULL;
749 /*****************************************************************************
750 * SetOverlayTransparency: Set the transparency for this overlay fb,
751 * - true is make transparent
752 * - false is make non tranparent
753 *****************************************************************************/
754 static void SetOverlayTransparency( intf_thread_t *p_intf,
757 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
758 size_t i_size = p_sys->fmt_out.i_width * p_sys->fmt_out.i_height
759 * p_sys->i_bytes_per_pixel;
760 size_t i_page_size = (p_sys->i_page_size > i_size) ?
761 i_size : p_sys->i_page_size;
763 if( p_sys->p_overlay )
765 msg_Dbg( p_intf, "Make overlay %s",
766 b_transparent ? "transparent" : "opaque" );
767 memset( p_sys->p_overlay->p[0].p_pixels, 0x00, i_page_size );
769 memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, i_page_size );
773 #ifdef FBOSD_BLENDING
774 /*****************************************************************************
775 * BlendPicture: Blend two pictures together..
776 *****************************************************************************/
777 static int BlendPicture( intf_thread_t *p_intf, video_format_t *p_fmt_src,
778 video_format_t *p_fmt_dst, picture_t *p_pic_src,
779 picture_t *p_pic_dst )
781 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
782 if( p_sys->p_blend && p_sys->p_blend->p_module )
784 int i_x_offset = p_sys->i_x;
785 int i_y_offset = p_sys->i_y;
787 memcpy( &p_sys->p_blend->fmt_in.video, p_fmt_src, sizeof( video_format_t ) );
789 msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
790 p_pic_src, (char*)&p_fmt_src->i_chroma,
791 p_sys->p_blend->fmt_in.video.i_width, p_sys->p_blend->fmt_in.video.i_height,
792 p_fmt_src->i_bits_per_pixel,
794 p_pic_src->p[0].p_pixels, p_pic_src->p[1].p_pixels,
795 p_pic_src->p[2].p_pixels, p_pic_src->p[3].p_pixels );
796 msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
797 p_pic_dst, (char*)&p_fmt_dst->i_chroma,
798 p_fmt_dst->i_width, p_fmt_dst->i_height,
799 p_fmt_dst->i_bits_per_pixel,
801 p_pic_dst->p[0].p_pixels, p_pic_dst->p[1].p_pixels,
802 p_pic_dst->p[2].p_pixels, p_pic_dst->p[3].p_pixels );
804 /* Update the output picture size */
805 p_sys->p_blend->fmt_out.video.i_width =
806 p_sys->p_blend->fmt_out.video.i_visible_width =
808 p_sys->p_blend->fmt_out.video.i_height =
809 p_sys->p_blend->fmt_out.video.i_visible_height =
812 i_x_offset = __MAX( i_x_offset, 0 );
813 i_y_offset = __MAX( i_y_offset, 0 );
815 p_sys->p_blend->pf_video_blend( p_sys->p_blend, p_pic_dst,
816 p_pic_src, p_pic_dst, i_x_offset, i_y_offset,
825 /*****************************************************************************
826 * RenderPicture: Render the picture into the p_dest buffer.
827 * We don't take transparent pixels into account, so we don't have to blend
828 * the two images together.
829 *****************************************************************************/
830 static int RenderPicture( intf_thread_t *p_intf, int i_x_offset, int i_y_offset,
831 picture_t *p_src, picture_t *p_dest )
835 if( !p_dest && !p_src ) return VLC_EGENERIC;
837 for( i = 0; i < p_src->i_planes ; i++ )
839 if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
841 /* There are margins, but with the same width : perfect ! */
842 vlc_memcpy( p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
843 p_src->p[i].i_pitch * p_src->p[i].i_visible_lines );
847 /* We need to proceed line by line */
848 uint8_t *p_in = p_src->p[i].p_pixels;
849 uint8_t *p_out = p_dest->p[i].p_pixels;
851 int i_x = i_x_offset * p_src->p[i].i_pixel_pitch;
852 int i_x_clip, i_y_clip;
854 /* Check boundaries, clip the image if necessary */
855 i_x_clip = ( i_x + p_src->p[i].i_visible_pitch ) - p_dest->p[i].i_visible_pitch;
856 i_x_clip = ( i_x_clip > 0 ) ? i_x_clip : 0;
858 i_y_clip = ( i_y_offset + p_src->p[i].i_visible_lines ) - p_dest->p[i].i_visible_lines;
859 i_y_clip = ( i_y_clip > 0 ) ? i_y_clip : 0;
861 msg_Dbg( p_intf, "i_pitch (%d,%d), (%d,%d)/(%d,%d)",
862 p_dest->p[i].i_visible_pitch, p_src->p[i].i_visible_pitch,
863 i_x_offset, i_y_offset, i_x, i_x_clip );
865 if( ( i_y_offset <= p_dest->p[i].i_visible_lines ) &&
866 ( i_x <= p_dest->p[i].i_visible_pitch ) )
870 p_out += ( i_y_offset * p_dest->p[i].i_pitch );
871 for( i_line = 0; i_line < ( p_src->p[i].i_visible_lines - i_y_clip ); i_line++ )
873 vlc_memcpy( p_out + i_x, p_in,
874 p_src->p[i].i_visible_pitch - i_x_clip );
875 p_in += p_src->p[i].i_pitch;
876 p_out += p_dest->p[i].i_pitch;
884 /*****************************************************************************
885 * RenderText - Render text to the desired picture format
886 *****************************************************************************/
887 static picture_t *RenderText( intf_thread_t *p_intf, const char *psz_string,
888 text_style_t *p_style, video_format_t *p_fmt )
890 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
891 subpicture_region_t *p_region;
892 picture_t *p_dest = NULL;
894 if( !psz_string ) return p_dest;
896 if( p_sys->p_text && p_sys->p_text->p_module )
898 p_region = (subpicture_region_t *) malloc( sizeof(subpicture_region_t) );
902 memset( p_region, 0, sizeof(subpicture_region_t) );
904 p_region->psz_text = strdup( psz_string );
905 p_region->p_style = p_style;
907 p_region->fmt.i_chroma = VLC_FOURCC('T','E','X','T');
908 p_region->fmt.i_aspect = 0;
909 p_region->fmt.i_width = p_region->fmt.i_visible_width = 0;
910 p_region->fmt.i_height = p_region->fmt.i_visible_height = 0;
911 p_region->fmt.i_x_offset = 0;
912 p_region->fmt.i_y_offset = 0;
914 p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
916 if( p_sys->p_text->pf_render_text )
918 video_format_t fmt_out;
920 memset( &fmt_out, 0, sizeof(video_format_t) );
922 p_sys->p_text->pf_render_text( p_sys->p_text,
923 p_region, p_region );
925 #ifndef FBOSD_BLENDING
926 fmt_out.i_chroma = p_fmt->i_chroma;
927 p_dest = ConvertImage( p_intf, &p_region->picture,
928 &p_region->fmt, &fmt_out );
930 fmt_out = p_region->fmt;
931 fmt_out.i_bits_per_pixel = 32;
932 vlc_memcpy( p_fmt, &fmt_out, sizeof(video_format_t) );
934 p_dest = AllocatePicture( VLC_OBJECT(p_intf), &fmt_out );
937 if( p_region->picture.pf_release )
938 p_region->picture.pf_release( &p_region->picture );
939 free( p_region->psz_text );
943 vout_CopyPicture( VLC_OBJECT(p_intf), p_dest, &p_region->picture );
945 if( p_region->picture.pf_release )
946 p_region->picture.pf_release( &p_region->picture );
947 free( p_region->psz_text );
951 free( p_region->psz_text );
957 /*****************************************************************************
958 * LoadImage: Load an image from file into a picture buffer.
959 *****************************************************************************/
960 static picture_t *LoadImage( intf_thread_t *p_intf, video_format_t *p_fmt,
963 picture_t *p_pic = NULL;
965 if( psz_file && p_intf->p_sys->p_image )
967 video_format_t fmt_in, fmt_out;
969 memset( &fmt_in, 0, sizeof(fmt_in) );
970 memset( &fmt_out, 0, sizeof(fmt_out) );
972 fmt_out.i_chroma = p_fmt->i_chroma;
973 p_pic = image_ReadUrl( p_intf->p_sys->p_image, psz_file,
976 msg_Dbg( p_intf, "image size %dx%d chroma %4.4s",
977 fmt_out.i_width, fmt_out.i_height,
978 (char *)&p_fmt->i_chroma );
983 #ifndef FBOSD_BLENDING
984 /*****************************************************************************
985 * Convertmage: Convert image to another fourcc
986 *****************************************************************************/
987 static picture_t *ConvertImage( intf_thread_t *p_intf, picture_t *p_pic,
988 video_format_t *p_fmt_in, video_format_t *p_fmt_out )
990 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
991 picture_t *p_old = NULL;
995 p_old = image_Convert( p_sys->p_image, p_pic, p_fmt_in, p_fmt_out );
997 msg_Dbg( p_intf, "converted image size %dx%d chroma %4.4s",
998 p_fmt_out->i_width, p_fmt_out->i_height,
999 (char *)&p_fmt_out->i_chroma );
1005 /*****************************************************************************
1006 * Init: initialize framebuffer video thread output method
1007 *****************************************************************************/
1008 static int Init( intf_thread_t *p_intf )
1010 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1012 /* Initialize the output structure: RGB with square pixels, whatever
1013 * the input format is, since it's the only format we know */
1014 switch( p_sys->var_info.bits_per_pixel )
1016 case 8: /* FIXME: set the palette */
1017 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','G','B','2'); break;
1019 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','5'); break;
1021 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','6'); break;
1023 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','2','4'); break;
1025 p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','3','2'); break;
1027 msg_Err( p_intf, "unknown screen depth %i",
1028 p_sys->var_info.bits_per_pixel );
1029 return VLC_EGENERIC;
1032 p_sys->fmt_out.i_bits_per_pixel = p_sys->var_info.bits_per_pixel;
1033 p_sys->fmt_out.i_width = p_sys->i_width;
1034 p_sys->fmt_out.i_height = p_sys->i_height;
1036 /* Assume we have square pixels */
1037 if( p_sys->i_aspect < 0 )
1039 p_sys->fmt_out.i_aspect = ( p_sys->i_width
1040 * VOUT_ASPECT_FACTOR ) / p_sys->i_height;
1042 else p_sys->fmt_out.i_aspect = p_sys->i_aspect;
1044 p_sys->fmt_out.i_sar_num = p_sys->fmt_out.i_sar_den = 1;
1046 /* Allocate overlay buffer */
1047 p_sys->p_overlay = AllocatePicture( VLC_OBJECT(p_intf),
1049 if( !p_sys->p_overlay ) return VLC_EGENERIC;
1051 SetOverlayTransparency( p_intf, true );
1053 /* We know the chroma, allocate a buffer which will be used
1054 * to write to the overlay framebuffer */
1055 p_sys->p_overlay->p->i_pixel_pitch = p_sys->i_bytes_per_pixel;
1056 p_sys->p_overlay->p->i_lines = p_sys->var_info.yres;
1057 p_sys->p_overlay->p->i_visible_lines = p_sys->var_info.yres;
1059 if( p_sys->var_info.xres_virtual )
1061 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres_virtual
1062 * p_sys->i_bytes_per_pixel;
1066 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres
1067 * p_sys->i_bytes_per_pixel;
1070 p_sys->p_overlay->p->i_visible_pitch = p_sys->var_info.xres
1071 * p_sys->i_bytes_per_pixel;
1073 p_sys->p_overlay->i_planes = 1;
1078 /*****************************************************************************
1079 * End: terminate framebuffer interface
1080 *****************************************************************************/
1081 static void End( intf_thread_t *p_intf )
1083 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1086 SetOverlayTransparency( p_intf, false );
1087 if( p_sys->p_overlay )
1090 ret = write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels, p_sys->i_page_size );
1092 msg_Err( p_intf, "unable to clear overlay" );
1095 DeAllocatePicture( VLC_OBJECT(p_intf), p_intf->p_sys->p_overlay,
1096 &p_intf->p_sys->fmt_out );
1097 p_intf->p_sys->p_overlay = NULL;
1100 /*****************************************************************************
1101 * OpenDisplay: initialize framebuffer
1102 *****************************************************************************/
1103 static int OpenDisplay( intf_thread_t *p_intf )
1105 intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys;
1106 char *psz_device; /* framebuffer device path */
1107 struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
1109 /* Open framebuffer device */
1110 if( !(psz_device = config_GetPsz( p_intf, "fbosd-dev" )) )
1112 msg_Err( p_intf, "don't know which fb osd/overlay device to open" );
1113 return VLC_EGENERIC;
1116 p_sys->i_fd = open( psz_device, O_RDWR );
1117 if( p_sys->i_fd == -1 )
1119 msg_Err( p_intf, "cannot open %s (%s)", psz_device, strerror(errno) );
1121 return VLC_EGENERIC;
1125 /* Get framebuffer device information */
1126 if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) )
1128 msg_Err( p_intf, "cannot get fb info (%s)", strerror(errno) );
1129 close( p_sys->i_fd );
1130 return VLC_EGENERIC;
1133 /* Get some info on the framebuffer itself */
1134 if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) == 0 )
1136 p_sys->i_width = p_sys->fmt_out.i_width = p_sys->var_info.xres;
1137 p_sys->i_height = p_sys->fmt_out.i_height = p_sys->var_info.yres;
1140 /* FIXME: if the image is full-size, it gets cropped on the left
1141 * because of the xres / xres_virtual slight difference */
1142 msg_Dbg( p_intf, "%ix%i (virtual %ix%i)",
1143 p_sys->var_info.xres, p_sys->var_info.yres,
1144 p_sys->var_info.xres_virtual,
1145 p_sys->var_info.yres_virtual );
1147 p_sys->fmt_out.i_width = p_sys->i_width;
1148 p_sys->fmt_out.i_height = p_sys->i_height;
1150 p_sys->p_palette = NULL;
1151 p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
1153 switch( p_sys->var_info.bits_per_pixel )
1156 p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) );
1157 if( !p_sys->p_palette )
1159 msg_Err( p_intf, "out of memory" );
1160 close( p_sys->i_fd );
1163 p_sys->fb_cmap.start = 0;
1164 p_sys->fb_cmap.len = 256;
1165 p_sys->fb_cmap.red = p_sys->p_palette;
1166 p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t );
1167 p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t );
1168 p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t );
1170 /* Save the colormap */
1171 ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap );
1173 p_sys->i_bytes_per_pixel = 1;
1178 p_sys->i_bytes_per_pixel = 2;
1182 p_sys->i_bytes_per_pixel = 3;
1186 p_sys->i_bytes_per_pixel = 4;
1190 msg_Err( p_intf, "screen depth %d is not supported",
1191 p_sys->var_info.bits_per_pixel );
1193 close( p_sys->i_fd );
1194 return VLC_EGENERIC;
1197 p_sys->i_page_size = p_sys->i_width * p_sys->i_height
1198 * p_sys->i_bytes_per_pixel;
1200 msg_Dbg( p_intf, "framebuffer type=%d, visual=%d, ypanstep=%d, "
1201 "ywrap=%d, accel=%d", fix_info.type, fix_info.visual,
1202 fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
1206 /*****************************************************************************
1207 * CloseDisplay: terminate FB interface thread
1208 *****************************************************************************/
1209 static void CloseDisplay( intf_thread_t *p_intf )
1211 intf_sys_t *p_sys = (intf_sys_t *) p_intf;
1213 /* Restore palette */
1214 if( p_sys->var_info.bits_per_pixel == 8 )
1216 ioctl( p_sys->i_fd, FBIOPUTCMAP, &p_sys->fb_cmap );
1217 free( p_sys->p_palette );
1218 p_sys->p_palette = NULL;
1222 close( p_sys->i_fd );
1225 static void Render( intf_thread_t *p_intf, struct fbosd_render_t *render )
1227 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1229 if( render->i_state != FBOSD_STATE_RENDER ) return;
1230 if( !render->psz_string ) return;
1232 if( render->i_type == FBOSD_RENDER_IMAGE )
1235 p_pic = LoadImage( p_intf, &p_sys->fmt_out, render->psz_string );
1238 RenderPicture( p_intf, render->i_x, render->i_y,
1239 p_pic, p_sys->p_overlay );
1240 p_pic->pf_release( p_pic );
1243 else if( render->i_type == FBOSD_RENDER_TEXT )
1246 #ifdef FBOSD_BLENDING
1247 video_format_t fmt_in;
1248 memset( &fmt_in, 0, sizeof(video_format_t) );
1249 p_text = RenderText( p_intf, render->psz_string, &render->text_style,
1253 BlendPicture( p_intf, &fmt_in, &p_sys->fmt_out,
1254 p_text, p_sys->p_overlay );
1255 msg_Dbg( p_intf, "releasing picture" );
1256 DeAllocatePicture( VLC_OBJECT( p_intf ), p_text, &fmt_in );
1259 p_text = RenderText( p_intf, render->psz_string, &render->text_style,
1263 RenderPicture( p_intf, render->i_x, render->i_y,
1264 p_text, p_sys->p_overlay );
1265 p_text->pf_release( p_text );
1271 static void RenderClear( intf_thread_t *p_intf, struct fbosd_render_t *render )
1273 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1275 vlc_memcpy( &render->text_style, &default_text_style,
1276 sizeof( text_style_t ) );
1277 free( render->psz_string );
1278 render->psz_string = NULL;
1280 render->i_x = p_sys->i_x;
1281 render->i_y = p_sys->i_y;
1282 render->i_pos = p_sys->i_pos;
1283 #ifdef FBOSD_BLENDING
1284 render->i_alpha = p_sys->i_alpha;
1286 render->b_absolute = p_sys->b_absolute;
1287 render->i_state = FBOSD_STATE_FREE;
1290 static bool isRendererReady( intf_thread_t *p_intf )
1292 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1295 /* Check if there are more items to render */
1296 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1298 if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED )
1304 /*****************************************************************************
1306 *****************************************************************************
1307 * This part of the interface is in a separate thread so that we can call
1308 * exec() from within it without annoying the rest of the program.
1309 *****************************************************************************/
1310 static void Run( intf_thread_t *p_intf )
1312 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1314 while( !intf_ShouldDie( p_intf ) )
1318 /* Is there somthing to render? */
1319 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1321 if( p_sys->render[i].i_state == FBOSD_STATE_RENDER )
1323 Render( p_intf, &p_sys->render[i] );
1324 RenderClear( p_intf, &p_sys->render[i] );
1328 if( p_sys->b_clear )
1330 SetOverlayTransparency( p_intf, true );
1332 var_SetString( p_intf, "fbosd-image", "" );
1333 var_SetString( p_intf, "fbosd-text", "" );
1335 p_sys->b_clear = false;
1336 p_sys->b_need_update = true;
1339 if( p_sys->b_need_update && p_sys->p_overlay &&
1340 isRendererReady( p_intf ) )
1343 ret = write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels,
1344 p_sys->i_page_size );
1346 msg_Err( p_intf, "unable to write to overlay" );
1347 lseek( p_sys->i_fd, 0, SEEK_SET );
1349 /* clear the picture */
1350 memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, p_sys->i_page_size );
1351 p_sys->b_need_update = false;
1354 if( vlc_CPU() & CPU_CAPABILITY_FPU )
1355 msleep( INTF_IDLE_SLEEP );
1363 static int OverlayCallback( vlc_object_t *p_this, char const *psz_cmd,
1364 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1366 intf_thread_t *p_intf = (intf_thread_t *) p_this;
1367 intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys;
1368 VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1370 if( !strncmp( psz_cmd, "fbosd-display", 13 ) )
1372 p_sys->b_need_update = true;
1374 else if( !strncmp( psz_cmd, "fbosd-clear", 11 ) )
1377 /* Clear the entire render list */
1378 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1380 RenderClear( p_intf, &p_sys->render[i] );
1382 p_sys->b_clear = true;
1384 else if( !strncmp( psz_cmd, "fbosd-render", 12 ) )
1387 /* Are we already busy with on slot ? */
1388 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1390 if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED )
1392 p_sys->render[i].i_state = FBOSD_STATE_RENDER;
1400 /* Are we already busy with on slot ? */
1401 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1403 if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED )
1406 /* No, then find first FREE slot */
1407 if( p_sys->render[i].i_state != FBOSD_STATE_RESERVED )
1409 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1411 if( p_sys->render[i].i_state == FBOSD_STATE_FREE )
1414 if( p_sys->render[i].i_state != FBOSD_STATE_FREE )
1416 msg_Warn( p_this, "render space depleated" );
1420 /* Found a free slot */
1421 p_sys->render[i].i_state = FBOSD_STATE_RESERVED;
1422 if( !strncmp( psz_cmd, "fbosd-image", 11 ) )
1424 free( p_sys->render[i].psz_string );
1425 p_sys->render[i].psz_string = strdup( newval.psz_string );
1426 p_sys->render[i].i_type = FBOSD_RENDER_IMAGE;
1428 else if( !strncmp( psz_cmd, "fbosd-text", 10 ) )
1430 free( p_sys->render[i].psz_string );
1431 p_sys->render[i].psz_string = strdup( newval.psz_string );
1432 p_sys->render[i].i_type = FBOSD_RENDER_TEXT;
1434 else if( !strncmp( psz_cmd, "fbosd-x", 7 ) )
1436 p_sys->render[i].b_absolute = false;
1437 p_sys->render[i].i_x = (newval.i_int < p_sys->i_width) ?
1438 newval.i_int : p_sys->i_width;
1440 else if( !strncmp( psz_cmd, "fbosd-y", 7 ) )
1442 p_sys->render[i].b_absolute = false;
1443 p_sys->render[i].i_y = (newval.i_int < p_sys->i_height) ?
1444 newval.i_int : p_sys->i_height;
1446 else if( !strncmp( psz_cmd, "fbosd-position", 14 ) )
1448 p_sys->render[i].b_absolute = true;
1449 p_sys->render[i].i_pos = newval.i_int;
1451 else if( !strncmp( psz_cmd, "fbosd-font-size", 15 ) )
1453 p_sys->render[i].text_style.i_font_size = newval.i_int;
1455 else if( !strncmp( psz_cmd, "fbosd-font-color", 16 ) )
1457 p_sys->render[i].text_style.i_font_color = newval.i_int;
1459 else if( !strncmp( psz_cmd, "fbosd-font-opacity", 18 ) )
1461 p_sys->render[i].text_style.i_font_alpha = 255 - newval.i_int;
1463 #ifdef FBOSD_BLENDING
1464 else if( !strncmp( psz_cmd, "fbosd-alpha", 11 ) )
1466 p_sys->render[i].i_alpha = newval.i_int;