Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
3e08d955
Commit
3e08d955
authored
Oct 26, 2007
by
Jean-Paul Saman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new gui module for use with overlay framebuffer devices.
parent
64fd3b59
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1332 additions
and
0 deletions
+1332
-0
configure.ac
configure.ac
+12
-0
modules/gui/Modules.am
modules/gui/Modules.am
+1
-0
modules/gui/fbosd.c
modules/gui/fbosd.c
+1319
-0
No files found.
configure.ac
View file @
3e08d955
...
...
@@ -5385,6 +5385,18 @@ then
fi
fi
dnl
dnl Framebuffer (overlay) plugin
dnl
AC_ARG_ENABLE(fbosd,
[ --enable-fbosd fbosd interface supprt (default disabled)])
if test "${enable_fbosd}" = "yes"
then
AC_CHECK_HEADERS(linux/fb.h, [
VLC_ADD_PLUGINS([fbosd])
])
fi
dnl
dnl Visualisation plugin
dnl
...
...
modules/gui/Modules.am
View file @
3e08d955
SOURCES_ncurses = ncurses.c
SOURCES_fbosd = fbosd.c
modules/gui/fbosd.c
0 → 100644
View file @
3e08d955
/*****************************************************************************
* fbosd.c : framebuffer osd plugin for vlc
*****************************************************************************
* Copyright (C) 2007, the VideoLAN team
* $Id: vlc-fb-overlay.patch,v 1.8 2007/10/19 14:33:23 jeanpaul.saman Exp $
*
* Authors: Jean-Paul Saman
* Copied from modules/video_output/fb.c by Samuel Hocevar <sam@zoy.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <errno.h>
#include <stdlib.h>
/* free() */
#include <string.h>
/* strerror() */
#include <fcntl.h>
/* open() */
#include <unistd.h>
/* close() */
#include <sys/ioctl.h>
#include <sys/mman.h>
/* mmap() */
#include <linux/fb.h>
#include <vlc_image.h>
#include <vlc_interface.h>
#include <vlc_input.h>
#include <vlc_vout.h>
#include <vlc_filter.h>
#include <vlc_osd.h>
#include <vlc_strings.h>
// #define FBOSD_BLENDING 1
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
Create
(
vlc_object_t
*
);
static
void
Destroy
(
vlc_object_t
*
);
static
void
Run
(
intf_thread_t
*
);
static
int
Init
(
intf_thread_t
*
);
static
void
End
(
intf_thread_t
*
);
static
int
OpenDisplay
(
intf_thread_t
*
);
static
void
CloseDisplay
(
intf_thread_t
*
);
/* Load modules needed for rendering and blending */
#ifdef FBOSD_BLENDING
static
int
OpenBlending
(
intf_thread_t
*
);
static
void
CloseBlending
(
intf_thread_t
*
);
#endif
static
int
OpenTextRenderer
(
intf_thread_t
*
);
static
void
CloseTextRenderer
(
intf_thread_t
*
);
#if 0
static int OpenScaling ( intf_thread_t * );
static int CloseScaling ( intf_thread_t * );
#endif
/* Manipulate the overlay buffer */
static
int
OverlayCallback
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
static
picture_t
*
AllocatePicture
(
vlc_object_t
*
,
video_format_t
*
);
static
void
DeAllocatePicture
(
vlc_object_t
*
,
picture_t
*
,
video_format_t
*
);
static
void
SetOverlayTransparency
(
intf_thread_t
*
,
vlc_bool_t
);
static
picture_t
*
LoadImage
(
intf_thread_t
*
,
video_format_t
*
,
char
*
);
#ifdef FBOSD_BLENDING
static
int
BlendPicture
(
intf_thread_t
*
,
video_format_t
*
,
video_format_t
*
,
picture_t
*
,
picture_t
*
);
#else
static
picture_t
*
ConvertImage
(
intf_thread_t
*
,
picture_t
*
,
video_format_t
*
,
video_format_t
*
);
#endif
static
int
RenderPicture
(
intf_thread_t
*
,
int
,
int
,
picture_t
*
,
picture_t
*
);
static
picture_t
*
RenderText
(
intf_thread_t
*
,
const
char
*
,
video_format_t
*
);
#define DEVICE_TEXT N_("Framebuffer device")
#define DEVICE_LONGTEXT N_( \
"Framebuffer device to use for rendering (usually /dev/fb0).")
#define ASPECT_RATIO_TEXT N_("Video aspect ratio")
#define ASPECT_RATIO_LONGTEXT N_( \
"Aspect ratio of the video image (4:3, 16:9). Default is square pixels." )
#define FBOSD_IMAGE_TEXT N_("Image file")
#define FBOSD_IMAGE_LONGTEXT N_( \
"Filename of image file to use on the overlay framebuffer." )
#define ALPHA_TEXT N_("Transparency of the image")
#define ALPHA_LONGTEXT N_( "Transparency value of the new image " \
"used in blending. By default it set to fully opaque (255). " \
"(from 0 for full transparency to 255 for full opacity)" )
#define FBOSD_TEXT N_("Text")
#define FBOSD_LONGTEXT N_( "Text to display on the overlay framebuffer." )
#define POSX_TEXT N_("X coordinate")
#define POSX_LONGTEXT N_("X coordinate of the rendered image")
#define POSY_TEXT N_("Y coordinate")
#define POSY_LONGTEXT N_("Y coordinate of the rendered image")
#define POS_TEXT N_("Position")
#define POS_LONGTEXT N_( \
"You can enforce the picture position on the overlay " \
"(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
"also use combinations of these values, e.g. 6=top-right).")
#define OPACITY_TEXT N_("Opacity")
#define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
"overlayed text. 0 = transparent, 255 = totally opaque. " )
#define SIZE_TEXT N_("Font size, pixels")
#define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
"font size)." )
#define COLOR_TEXT N_("Color")
#define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
"the video. This must be an hexadecimal (like HTML colors). The first two "\
"chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
" #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
#define CLEAR_TEXT N_( "Clear overlay framebuffer" )
#define CLEAR_LONGTEXT N_( "The displayed overlay images is cleared by " \
"making the overlay completely transparent. All previously rendered " \
"images and text will be cleared from the cache." )
#define RENDER_TEXT N_( "Render text or image" )
#define RENDER_LONGTEXT N_( "Render the image or text in current overlay " \
"buffer." )
#define DISPLAY_TEXT N_( "Display on overlay framebuffer" )
#define DISPLAY_LONGTEXT N_( "All rendered images and text will be " \
"displayed on the overlay framebuffer." )
static
int
pi_pos_values
[]
=
{
0
,
1
,
2
,
4
,
8
,
5
,
6
,
9
,
10
};
static
const
char
*
ppsz_pos_descriptions
[]
=
{
N_
(
"Center"
),
N_
(
"Left"
),
N_
(
"Right"
),
N_
(
"Top"
),
N_
(
"Bottom"
),
N_
(
"Top-Left"
),
N_
(
"Top-Right"
),
N_
(
"Bottom-Left"
),
N_
(
"Bottom-Right"
)
};
static
int
pi_color_values
[]
=
{
0xf0000000
,
0x00000000
,
0x00808080
,
0x00C0C0C0
,
0x00FFFFFF
,
0x00800000
,
0x00FF0000
,
0x00FF00FF
,
0x00FFFF00
,
0x00808000
,
0x00008000
,
0x00008080
,
0x0000FF00
,
0x00800080
,
0x00000080
,
0x000000FF
,
0x0000FFFF
};
static
const
char
*
ppsz_color_descriptions
[]
=
{
N_
(
"Default"
),
N_
(
"Black"
),
N_
(
"Gray"
),
N_
(
"Silver"
),
N_
(
"White"
),
N_
(
"Maroon"
),
N_
(
"Red"
),
N_
(
"Fuchsia"
),
N_
(
"Yellow"
),
N_
(
"Olive"
),
N_
(
"Green"
),
N_
(
"Teal"
),
N_
(
"Lime"
),
N_
(
"Purple"
),
N_
(
"Navy"
),
N_
(
"Blue"
),
N_
(
"Aqua"
)
};
vlc_module_begin
();
set_shortname
(
"fbosd"
);
set_category
(
CAT_INTERFACE
);
set_subcategory
(
SUBCAT_INTERFACE_MAIN
);
add_file
(
"fbosd-dev"
,
"/dev/fb1"
,
NULL
,
DEVICE_TEXT
,
DEVICE_LONGTEXT
,
VLC_FALSE
);
add_string
(
"fbosd-aspect-ratio"
,
""
,
NULL
,
ASPECT_RATIO_TEXT
,
ASPECT_RATIO_LONGTEXT
,
VLC_TRUE
);
add_string
(
"fbosd-image"
,
NULL
,
NULL
,
FBOSD_IMAGE_TEXT
,
FBOSD_IMAGE_LONGTEXT
,
VLC_TRUE
);
add_string
(
"fbosd-text"
,
NULL
,
NULL
,
FBOSD_TEXT
,
FBOSD_LONGTEXT
,
VLC_TRUE
);
#ifdef FBOSD_BLENDING
add_integer_with_range
(
"fbosd-alpha"
,
255
,
0
,
255
,
NULL
,
ALPHA_TEXT
,
ALPHA_LONGTEXT
,
VLC_TRUE
);
#endif
set_section
(
N_
(
"Position"
),
NULL
);
add_integer
(
"fbosd-x"
,
0
,
NULL
,
POSX_TEXT
,
POSX_LONGTEXT
,
VLC_FALSE
);
add_integer
(
"fbosd-y"
,
0
,
NULL
,
POSY_TEXT
,
POSY_LONGTEXT
,
VLC_FALSE
);
add_integer
(
"fbosd-position"
,
8
,
NULL
,
POS_TEXT
,
POS_LONGTEXT
,
VLC_TRUE
);
change_integer_list
(
pi_pos_values
,
ppsz_pos_descriptions
,
0
);
set_section
(
N_
(
"Font"
),
NULL
);
add_integer_with_range
(
"fbosd-font-opacity"
,
255
,
0
,
255
,
NULL
,
OPACITY_TEXT
,
OPACITY_LONGTEXT
,
VLC_FALSE
);
add_integer
(
"fbosd-font-color"
,
0x00FFFFFF
,
NULL
,
COLOR_TEXT
,
COLOR_LONGTEXT
,
VLC_FALSE
);
change_integer_list
(
pi_color_values
,
ppsz_color_descriptions
,
0
);
add_integer
(
"fbosd-font-size"
,
-
1
,
NULL
,
SIZE_TEXT
,
SIZE_LONGTEXT
,
VLC_FALSE
);
set_section
(
N_
(
"Commands"
),
NULL
);
add_bool
(
"fbosd-clear"
,
VLC_FALSE
,
NULL
,
CLEAR_TEXT
,
CLEAR_LONGTEXT
,
VLC_TRUE
);
add_bool
(
"fbosd-render"
,
VLC_FALSE
,
NULL
,
RENDER_TEXT
,
RENDER_LONGTEXT
,
VLC_TRUE
);
add_bool
(
"fbosd-display"
,
VLC_FALSE
,
NULL
,
DISPLAY_TEXT
,
DISPLAY_LONGTEXT
,
VLC_TRUE
);
set_description
(
_
(
"GNU/Linux osd/overlay framebuffer interface"
)
);
set_capability
(
"interface"
,
10
);
set_callbacks
(
Create
,
Destroy
);
vlc_module_end
();
/*****************************************************************************
* intf_sys_t: interface framebuffer method descriptor
*****************************************************************************/
struct
intf_sys_t
{
/* Framebuffer information */
int
i_fd
;
/* device handle */
struct
fb_var_screeninfo
var_info
;
/* current mode information */
vlc_bool_t
b_pan
;
/* does device supports panning ? */
struct
fb_cmap
fb_cmap
;
/* original colormap */
uint16_t
*
p_palette
;
/* original palette */
/* Overlay framebuffer format */
video_format_t
fmt_out
;
picture_t
*
p_overlay
;
size_t
i_page_size
;
/* page size */
int
i_width
;
int
i_height
;
int
i_aspect
;
int
i_bytes_per_pixel
;
/* Image and Picture rendering */
image_handler_t
*
p_image
;
#ifdef FBOSD_BLENDING
filter_t
*
p_blend
;
/* alpha blending module */
#endif
filter_t
*
p_text
;
/* text renderer module */
#if 0
filter_t *p_scale; /* scaling module */
#endif
vlc_bool_t
b_force_crop
;
/* force cropping of picture */
int
i_crop_x
,
i_crop_y
,
i_crop_width
,
i_crop_height
;
/* cropping */
/* Misc */
char
*
psz_file
;
char
*
psz_text
;
vlc_bool_t
b_image
;
vlc_bool_t
b_text
;
/* Font style */
text_style_t
*
p_style
;
/* font control */
/* Positon of image/text */
vlc_bool_t
b_absolute
;
int
i_x
;
int
i_y
;
int
i_pos
;
int
i_alpha
;
/* transparency for images */
/* commands control */
vlc_bool_t
b_need_update
;
/* update display with \overlay buffer */
vlc_bool_t
b_clear
;
/* clear overlay buffer make it tranparent */
vlc_bool_t
b_render
;
/* render an image or text in overlay buffer */
};
/*****************************************************************************
* Create: allocates FB interface thread output method
*****************************************************************************/
static
int
Create
(
vlc_object_t
*
p_this
)
{
intf_thread_t
*
p_intf
=
(
intf_thread_t
*
)
p_this
;
intf_sys_t
*
p_sys
;
char
*
psz_aspect
;
/* Allocate instance and initialize some members */
p_intf
->
p_sys
=
p_sys
=
malloc
(
sizeof
(
intf_sys_t
)
);
if
(
!
p_intf
->
p_sys
)
{
msg_Err
(
p_intf
,
"out of memory"
);
return
VLC_ENOMEM
;
};
memset
(
p_sys
,
0
,
sizeof
(
intf_sys_t
)
);
p_sys
->
p_style
=
malloc
(
sizeof
(
text_style_t
)
);
if
(
!
p_sys
->
p_style
)
{
free
(
p_intf
->
p_sys
);
msg_Err
(
p_intf
,
"out of memory"
);
return
VLC_ENOMEM
;
}
p_intf
->
p_libvlc
->
pf_memcpy
(
p_sys
->
p_style
,
&
default_text_style
,
sizeof
(
text_style_t
)
);
p_intf
->
pf_run
=
Run
;
p_sys
->
p_image
=
image_HandlerCreate
(
p_this
);
if
(
!
p_sys
->
p_image
)
{
free
(
p_intf
->
p_sys
->
p_style
);
free
(
p_intf
->
p_sys
);
msg_Err
(
p_intf
,
"out of memory"
);
return
VLC_ENOMEM
;
}
#ifdef FBOSD_BLENDING
p_sys
->
i_alpha
=
var_CreateGetIntegerCommand
(
p_intf
,
"fbosd-alpha"
);
var_AddCallback
(
p_intf
,
"fbosd-alpha"
,
OverlayCallback
,
NULL
);
#else
p_sys
->
i_alpha
=
255
;
#endif
p_sys
->
i_aspect
=
-
1
;
psz_aspect
=
var_CreateGetNonEmptyString
(
p_intf
,
"fbosd-aspect-ratio"
);
if
(
psz_aspect
)
{
char
*
psz_parser
=
strchr
(
psz_aspect
,
':'
);
if
(
psz_parser
)
{
*
psz_parser
++
=
'\0'
;
p_sys
->
i_aspect
=
(
atoi
(
psz_aspect
)
*
VOUT_ASPECT_FACTOR
)
/
atoi
(
psz_parser
);
p_sys
->
fmt_out
.
i_aspect
=
p_sys
->
i_aspect
;
}
msg_Dbg
(
p_intf
,
"using aspect ratio %d:%d"
,
atoi
(
psz_aspect
),
atoi
(
psz_parser
)
);
free
(
psz_aspect
);
psz_aspect
=
NULL
;
}
/* Use PAL by default */
p_sys
->
i_width
=
p_sys
->
fmt_out
.
i_width
=
704
;
p_sys
->
i_height
=
p_sys
->
fmt_out
.
i_height
=
576
;
p_sys
->
psz_file
=
var_CreateGetNonEmptyStringCommand
(
p_intf
,
"fbosd-image"
);
var_AddCallback
(
p_intf
,
"fbosd-image"
,
OverlayCallback
,
NULL
);
if
(
p_sys
->
psz_file
&&
*
p_sys
->
psz_file
)
p_sys
->
b_image
=
VLC_TRUE
;
p_sys
->
psz_text
=
var_CreateGetNonEmptyStringCommand
(
p_intf
,
"fbosd-text"
);
var_AddCallback
(
p_intf
,
"fbosd-text"
,
OverlayCallback
,
NULL
);
if
(
p_sys
->
psz_text
&&
*
p_sys
->
psz_text
)
p_sys
->
b_text
=
VLC_TRUE
;
p_sys
->
i_pos
=
var_CreateGetIntegerCommand
(
p_intf
,
"fbosd-position"
);
p_sys
->
i_x
=
var_CreateGetIntegerCommand
(
p_intf
,
"fbosd-x"
);
p_sys
->
i_y
=
var_CreateGetIntegerCommand
(
p_intf
,
"fbosd-y"
);
var_AddCallback
(
p_intf
,
"fbosd-position"
,
OverlayCallback
,
NULL
);
var_AddCallback
(
p_intf
,
"fbosd-x"
,
OverlayCallback
,
NULL
);
var_AddCallback
(
p_intf
,
"fbosd-y"
,
OverlayCallback
,
NULL
);
p_sys
->
p_style
->
i_font_size
=
var_CreateGetIntegerCommand
(
p_intf
,
"fbosd-font-size"
);
p_sys
->
p_style
->
i_font_color
=
var_CreateGetIntegerCommand
(
p_intf
,
"fbosd-font-color"
);
p_sys
->
p_style
->
i_font_alpha
=
255
-
var_CreateGetIntegerCommand
(
p_intf
,
"fbosd-font-opacity"
);
var_AddCallback
(
p_intf
,
"fbosd-font-color"
,
OverlayCallback
,
NULL
);
var_AddCallback
(
p_intf
,
"fbosd-font-size"
,
OverlayCallback
,
NULL
);
var_AddCallback
(
p_intf
,
"fbosd-font-opacity"
,
OverlayCallback
,
NULL
);
p_sys
->
b_clear
=
var_CreateGetBoolCommand
(
p_intf
,
"fbosd-clear"
);
p_sys
->
b_render
=
var_CreateGetBoolCommand
(
p_intf
,
"fbosd-render"
);
p_sys
->
b_need_update
=
var_CreateGetBoolCommand
(
p_intf
,
"fbosd-display"
);
var_AddCallback
(
p_intf
,
"fbosd-clear"
,
OverlayCallback
,
NULL
);
var_AddCallback
(
p_intf
,
"fbosd-render"
,
OverlayCallback
,
NULL
);
var_AddCallback
(
p_intf
,
"fbosd-display"
,
OverlayCallback
,
NULL
);
/* Check if picture position was overridden */
p_sys
->
b_absolute
=
VLC_TRUE
;
if
(
(
p_sys
->
i_x
>=
0
)
&&
(
p_sys
->
i_y
>=
0
)
)
{
p_sys
->
b_absolute
=
VLC_FALSE
;
p_sys
->
i_y
=
(
p_sys
->
i_y
<
p_sys
->
i_height
)
?
p_sys
->
i_y
:
p_sys
->
i_height
;
p_sys
->
i_x
=
(
p_sys
->
i_x
<
p_sys
->
i_width
)
?
p_sys
->
i_x
:
p_sys
->
i_width
;
}
/* Initialize framebuffer */
if
(
OpenDisplay
(
p_intf
)
)
{
Destroy
(
VLC_OBJECT
(
p_intf
)
);
return
VLC_EGENERIC
;
}
Init
(
p_intf
);
#ifdef FBOSD_BLENDING
/* Load the blending module */
if
(
OpenBlending
(
p_intf
)
)
{
msg_Err
(
p_intf
,
"Unable to load image blending module"
);
Destroy
(
VLC_OBJECT
(
p_intf
)
);
return
VLC_EGENERIC
;
}
#endif
/* Load text renderer module */
if
(
OpenTextRenderer
(
p_intf
)
)
{
msg_Err
(
p_intf
,
"Unable to load text rendering module"
);
Destroy
(
VLC_OBJECT
(
p_intf
)
);
return
VLC_EGENERIC
;
}
#if 0
/* Load scaling module */
if( OpenScaling( p_intf ) )
{
msg_Err( p_intf, "Unable to load image scaling module" );
Destroy( VLC_OBJECT(p_intf) );
return VLC_EGENERIC;
}
#endif
p_sys
->
b_render
=
VLC_TRUE
;
p_sys
->
b_need_update
=
VLC_TRUE
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Destroy: destroy FB interface thread output method
*****************************************************************************
* Terminate an output method created by Create
*****************************************************************************/
static
void
Destroy
(
vlc_object_t
*
p_this
)
{
intf_thread_t
*
p_intf
=
(
intf_thread_t
*
)
p_this
;
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
p_sys
->
b_need_update
=
VLC_FALSE
;
p_sys
->
b_render
=
VLC_FALSE
;
p_sys
->
b_clear
=
VLC_FALSE
;
#ifdef FBOSD_BLENDING
var_DelCallback
(
p_intf
,
"fbosd-alpha"
,
OverlayCallback
,
NULL
);
var_Destroy
(
p_intf
,
"fbosd-alpha"
);
#endif
var_DelCallback
(
p_intf
,
"fbosd-x"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-y"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-position"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-image"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-text"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-font-size"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-font-color"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-font-opacity"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-clear"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-render"
,
OverlayCallback
,
NULL
);
var_DelCallback
(
p_intf
,
"fbosd-display"
,
OverlayCallback
,
NULL
);
var_Destroy
(
p_intf
,
"fbosd-x"
);
var_Destroy
(
p_intf
,
"fbosd-y"
);
var_Destroy
(
p_intf
,
"fbosd-position"
);
var_Destroy
(
p_intf
,
"fbosd-image"
);
var_Destroy
(
p_intf
,
"fbosd-text"
);
var_Destroy
(
p_intf
,
"fbosd-font-size"
);
var_Destroy
(
p_intf
,
"fbosd-font-color"
);
var_Destroy
(
p_intf
,
"fbosd-font-opacity"
);
var_Destroy
(
p_intf
,
"fbosd-clear"
);
var_Destroy
(
p_intf
,
"fbosd-render"
);
var_Destroy
(
p_intf
,
"fbosd-display"
);
var_Destroy
(
p_intf
,
"fbosd-aspect-ratio"
);
CloseDisplay
(
p_intf
);
#ifdef FBOSD_BLENDING
if
(
p_sys
->
p_blend
)
CloseBlending
(
p_intf
);
#endif
if
(
p_sys
->
p_text
)
CloseTextRenderer
(
p_intf
);
#if 0
if( p_sys->p_scale ) CloseScaling( p_intf );
#endif
if
(
p_sys
->
p_image
)
image_HandlerDelete
(
p_sys
->
p_image
);
if
(
p_sys
->
p_overlay
)
p_sys
->
p_overlay
->
pf_release
(
p_sys
->
p_overlay
);
free
(
p_sys
->
psz_file
);
free
(
p_sys
->
psz_text
);
free
(
p_sys
->
p_style
);
free
(
p_sys
);
}
#ifdef FBOSD_BLENDING
static
int
OpenBlending
(
intf_thread_t
*
p_intf
)
{
if
(
p_intf
->
p_sys
->
p_blend
)
return
VLC_EGENERIC
;
p_intf
->
p_sys
->
p_blend
=
vlc_object_create
(
p_intf
,
VLC_OBJECT_FILTER
);
vlc_object_attach
(
p_intf
->
p_sys
->
p_blend
,
p_intf
);
p_intf
->
p_sys
->
p_blend
->
fmt_out
.
video
.
i_x_offset
=
p_intf
->
p_sys
->
p_blend
->
fmt_out
.
video
.
i_y_offset
=
0
;
p_intf
->
p_sys
->
p_blend
->
fmt_out
.
video
.
i_aspect
=
p_intf
->
p_sys
->
fmt_out
.
i_aspect
;
p_intf
->
p_sys
->
p_blend
->
fmt_out
.
video
.
i_chroma
=
p_intf
->
p_sys
->
fmt_out
.
i_chroma
;
if
(
config_GetInt
(
p_intf
,
"freetype-yuvp"
)
)
p_intf
->
p_sys
->
p_blend
->
fmt_in
.
video
.
i_chroma
=
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'P'
);
else
p_intf
->
p_sys
->
p_blend
->
fmt_in
.
video
.
i_chroma
=
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'A'
);
p_intf
->
p_sys
->
p_blend
->
p_module
=
module_Need
(
p_intf
->
p_sys
->
p_blend
,
"video blending"
,
0
,
0
);
if
(
!
p_intf
->
p_sys
->
p_blend
->
p_module
)
return
VLC_EGENERIC
;
return
VLC_SUCCESS
;
}
static
void
CloseBlending
(
intf_thread_t
*
p_intf
)
{
if
(
p_intf
->
p_sys
->
p_blend
)
{
if
(
p_intf
->
p_sys
->
p_blend
->
p_module
)
module_Unneed
(
p_intf
->
p_sys
->
p_blend
,
p_intf
->
p_sys
->
p_blend
->
p_module
);
vlc_object_detach
(
p_intf
->
p_sys
->
p_blend
);
vlc_object_destroy
(
p_intf
->
p_sys
->
p_blend
);
}
}
#endif
static
int
OpenTextRenderer
(
intf_thread_t
*
p_intf
)
{
char
*
psz_modulename
=
NULL
;
if
(
p_intf
->
p_sys
->
p_text
)
return
VLC_EGENERIC
;
p_intf
->
p_sys
->
p_text
=
vlc_object_create
(
p_intf
,
VLC_OBJECT_FILTER
);
vlc_object_attach
(
p_intf
->
p_sys
->
p_text
,
p_intf
);
p_intf
->
p_sys
->
p_text
->
fmt_out
.
video
.
i_width
=
p_intf
->
p_sys
->
p_text
->
fmt_out
.
video
.
i_visible_width
=
p_intf
->
p_sys
->
i_width
;
p_intf
->
p_sys
->
p_text
->
fmt_out
.
video
.
i_height
=
p_intf
->
p_sys
->
p_text
->
fmt_out
.
video
.
i_visible_height
=
p_intf
->
p_sys
->
i_height
;
psz_modulename
=
var_CreateGetString
(
p_intf
,
"text-renderer"
);
if
(
psz_modulename
&&
*
psz_modulename
)
{
p_intf
->
p_sys
->
p_text
->
p_module
=
module_Need
(
p_intf
->
p_sys
->
p_text
,
"text renderer"
,
psz_modulename
,
VLC_TRUE
);
}
if
(
!
p_intf
->
p_sys
->
p_text
->
p_module
)
{
p_intf
->
p_sys
->
p_text
->
p_module
=
module_Need
(
p_intf
->
p_sys
->
p_text
,
"text renderer"
,
0
,
0
);
}
if
(
psz_modulename
)
free
(
psz_modulename
);
if
(
!
p_intf
->
p_sys
->
p_text
->
p_module
)
return
VLC_EGENERIC
;
return
VLC_SUCCESS
;
}
static
void
CloseTextRenderer
(
intf_thread_t
*
p_intf
)
{
if
(
p_intf
->
p_sys
->
p_text
)
{
if
(
p_intf
->
p_sys
->
p_text
->
p_module
)
module_Unneed
(
p_intf
->
p_sys
->
p_text
,
p_intf
->
p_sys
->
p_text
->
p_module
);
vlc_object_detach
(
p_intf
->
p_sys
->
p_text
);
vlc_object_destroy
(
p_intf
->
p_sys
->
p_text
);
}
}
#if 0
static int OpenScaling( intf_thread_t *p_intf )
{
if( p_intf->p_sys->p_scale ) return VLC_EGENERIC;
p_intf->p_sys->p_scale =
vlc_object_create( p_intf, VLC_OBJECT_FILTER );
vlc_object_attach( p_intf->p_sys->p_scale, p_intf );
p_intf->p_sys->p_scale->fmt_out.video.i_chroma =
p_intf->p_sys->p_scale->fmt_in.video.i_chroma =
p_intf->p_sys->fmt_out.i_chroma;
/* XXX: We'll also be using it for YUVA and RGBA blending ... */
p_intf->p_sys->p_scale->fmt_in.video.i_width =
p_intf->p_sys->p_scale->fmt_in.video.i_height = 32;
p_intf->p_sys->p_scale->fmt_out.video.i_width =
p_intf->p_sys->p_scale->fmt_out.video.i_height = 16;
p_intf->p_sys->p_scale->p_module =
module_Need( p_intf->p_sys->p_scale, "video filter2", 0, 0 );
if( !p_intf->p_sys->p_scale->p_module )
return VLC_EGENERIC;
return VLC_SUCCESS;
}
static int CloseScaling( intf_thread_t *p_intf )
{
if( p_intf->p_sys->p_scale )
{
if( p_intf->p_sys->p_scale->p_module )
module_Unneed( p_intf->p_sys->p_scale,
p_intf->p_sys->p_scale->p_module );
vlc_object_detach( p_intf->p_sys->p_scale );
vlc_object_destroy( p_intf->p_sys->p_scale );
}
}
#endif
/*****************************************************************************
* AllocatePicture:
* allocate a picture buffer for use with the overlay fb.
*****************************************************************************/
static
picture_t
*
AllocatePicture
(
vlc_object_t
*
p_this
,
video_format_t
*
p_fmt
)
{
picture_t
*
p_pic
=
malloc
(
sizeof
(
picture_t
)
);
if
(
!
p_pic
)
return
NULL
;
if
(
!
p_fmt
->
p_palette
&&
(
p_fmt
->
i_chroma
==
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'P'
)
)
)
{
p_fmt
->
p_palette
=
malloc
(
sizeof
(
video_palette_t
)
);
if
(
!
p_fmt
->
p_palette
)
{
free
(
p_pic
);
return
NULL
;
}
}
else
p_fmt
->
p_palette
=
NULL
;
p_pic
->
p_data_orig
=
NULL
;
vout_AllocatePicture
(
p_this
,
p_pic
,
p_fmt
->
i_chroma
,
p_fmt
->
i_width
,
p_fmt
->
i_height
,
p_fmt
->
i_aspect
);
if
(
!
p_pic
->
i_planes
)
{
free
(
p_pic
);
free
(
p_fmt
->
p_palette
);
return
NULL
;
}
return
p_pic
;
}
/*****************************************************************************
* DeAllocatePicture:
* Deallocate a picture buffer and free all associated memory.
*****************************************************************************/
static
void
DeAllocatePicture
(
vlc_object_t
*
p_this
,
picture_t
*
p_pic
,
video_format_t
*
p_fmt
)
{
if
(
p_pic
&&
p_pic
->
p_data_orig
)
free
(
p_pic
->
p_data_orig
);
if
(
p_pic
&&
p_pic
->
pf_release
)
p_pic
->
pf_release
(
p_pic
);
if
(
p_fmt
&&
p_fmt
->
p_palette
)
{
free
(
p_fmt
->
p_palette
);
p_fmt
->
p_palette
=
NULL
;
}
p_pic
=
NULL
;
}
/*****************************************************************************
* SetOverlayTransparency: Set the transparency for this overlay fb,
* - VLC_TRUE is make transparent
* - VLC_FALSE is make non tranparent
*****************************************************************************/
static
void
SetOverlayTransparency
(
intf_thread_t
*
p_intf
,
vlc_bool_t
b_transparent
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
size_t
i_size
=
p_sys
->
fmt_out
.
i_width
*
p_sys
->
fmt_out
.
i_height
*
p_sys
->
i_bytes_per_pixel
;
size_t
i_page_size
=
(
p_sys
->
i_page_size
>
i_size
)
?
i_size
:
p_sys
->
i_page_size
;
if
(
p_sys
->
p_overlay
)
{
msg_Dbg
(
p_intf
,
"Make overlay %s"
,
b_transparent
?
"transparent"
:
"opaque"
);
memset
(
p_sys
->
p_overlay
->
p
[
0
].
p_pixels
,
0x00
,
i_page_size
);
if
(
b_transparent
)
memset
(
p_sys
->
p_overlay
->
p
[
0
].
p_pixels
,
0xFF
,
i_page_size
);
}
}
#ifdef FBOSD_BLENDING
/*****************************************************************************
* BlendPicture: Blend two pictures together..
*****************************************************************************/
static
int
BlendPicture
(
intf_thread_t
*
p_intf
,
video_format_t
*
p_fmt_src
,
video_format_t
*
p_fmt_dst
,
picture_t
*
p_pic_src
,
picture_t
*
p_pic_dst
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
if
(
p_sys
->
p_blend
&&
p_sys
->
p_blend
->
p_module
)
{
int
i_x_offset
=
p_sys
->
i_x
;
int
i_y_offset
=
p_sys
->
i_y
;
memcpy
(
&
p_sys
->
p_blend
->
fmt_in
.
video
,
p_fmt_src
,
sizeof
(
video_format_t
)
);
#if 0
msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
p_pic_src, (char*)&p_fmt_src->i_chroma,
p_sys->p_blend->fmt_in.video.i_width, p_sys->p_blend->fmt_in.video.i_height,
p_fmt_src->i_bits_per_pixel,
p_pic_src->i_planes,
p_pic_src->p[0].p_pixels, p_pic_src->p[1].p_pixels,
p_pic_src->p[2].p_pixels, p_pic_src->p[3].p_pixels );
msg_Dbg( p_intf, "Blending pictures %p %4.4s (%dx%d) %d bits %d planes: 0=%p 1=%p 2=%p 3=%p",
p_pic_dst, (char*)&p_fmt_dst->i_chroma,
p_fmt_dst->i_width, p_fmt_dst->i_height,
p_fmt_dst->i_bits_per_pixel,
p_pic_dst->i_planes,
p_pic_dst->p[0].p_pixels, p_pic_dst->p[1].p_pixels,
p_pic_dst->p[2].p_pixels, p_pic_dst->p[3].p_pixels );
#endif
/* Update the output picture size */
p_sys
->
p_blend
->
fmt_out
.
video
.
i_width
=
p_sys
->
p_blend
->
fmt_out
.
video
.
i_visible_width
=
p_fmt_dst
->
i_width
;
p_sys
->
p_blend
->
fmt_out
.
video
.
i_height
=
p_sys
->
p_blend
->
fmt_out
.
video
.
i_visible_height
=
p_fmt_dst
->
i_height
;
i_x_offset
=
__MAX
(
i_x_offset
,
0
);
i_y_offset
=
__MAX
(
i_y_offset
,
0
);
p_sys
->
p_blend
->
pf_video_blend
(
p_sys
->
p_blend
,
p_pic_dst
,
p_pic_src
,
p_pic_dst
,
i_x_offset
,
i_y_offset
,
p_sys
->
i_alpha
);
return
VLC_SUCCESS
;
}
return
VLC_EGENERIC
;
}
#endif
/*****************************************************************************
* RenderPicture: Render the picture into the p_dest buffer.
* We don't take transparent pixels into account, so we don't have to blend
* the two images together.
*****************************************************************************/
static
int
RenderPicture
(
intf_thread_t
*
p_intf
,
int
i_x_offset
,
int
i_y_offset
,
picture_t
*
p_src
,
picture_t
*
p_dest
)
{
int
i
;
if
(
!
p_dest
&&
!
p_src
)
return
VLC_EGENERIC
;
for
(
i
=
0
;
i
<
p_src
->
i_planes
;
i
++
)
{
if
(
p_src
->
p
[
i
].
i_pitch
==
p_dest
->
p
[
i
].
i_pitch
)
{
/* There are margins, but with the same width : perfect ! */
p_intf
->
p_libvlc
->
pf_memcpy
(
p_dest
->
p
[
i
].
p_pixels
,
p_src
->
p
[
i
].
p_pixels
,
p_src
->
p
[
i
].
i_pitch
*
p_src
->
p
[
i
].
i_visible_lines
);
}
else
{
/* We need to proceed line by line */
uint8_t
*
p_in
=
p_src
->
p
[
i
].
p_pixels
;
uint8_t
*
p_out
=
p_dest
->
p
[
i
].
p_pixels
;
int
i_x
=
i_x_offset
*
p_src
->
p
[
i
].
i_pixel_pitch
;
int
i_x_clip
,
i_y_clip
;
/* Check boundaries, clip the image if necessary */
i_x_clip
=
(
i_x
+
p_src
->
p
[
i
].
i_visible_pitch
)
-
p_dest
->
p
[
i
].
i_visible_pitch
;
i_x_clip
=
(
i_x_clip
>
0
)
?
i_x_clip
:
0
;
i_y_clip
=
(
i_y_offset
+
p_src
->
p
[
i
].
i_visible_lines
)
-
p_dest
->
p
[
i
].
i_visible_lines
;
i_y_clip
=
(
i_y_clip
>
0
)
?
i_y_clip
:
0
;
#if 0
msg_Dbg( p_intf, "i_pitch (%d,%d), (%d,%d)/(%d,%d)",
p_dest->p[i].i_visible_pitch, p_src->p[i].i_visible_pitch,
i_x_offset, i_y_offset, i_x, i_x_clip );
#endif
if
(
(
i_y_offset
<=
p_dest
->
p
[
i
].
i_visible_lines
)
&&
(
i_x
<=
p_dest
->
p
[
i
].
i_visible_pitch
)
)
{
int
i_line
;
p_out
+=
(
i_y_offset
*
p_dest
->
p
[
i
].
i_pitch
);
for
(
i_line
=
0
;
i_line
<
(
p_src
->
p
[
i
].
i_visible_lines
-
i_y_clip
);
i_line
++
)
{
p_intf
->
p_libvlc
->
pf_memcpy
(
p_out
+
i_x
,
p_in
,
p_src
->
p
[
i
].
i_visible_pitch
-
i_x_clip
);
p_in
+=
p_src
->
p
[
i
].
i_pitch
;
p_out
+=
p_dest
->
p
[
i
].
i_pitch
;
}
}
}
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* RenderText - Render text to the desired picture format
*****************************************************************************/
static
picture_t
*
RenderText
(
intf_thread_t
*
p_intf
,
const
char
*
psz_text
,
video_format_t
*
p_fmt
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
subpicture_region_t
*
p_region
;
picture_t
*
p_dest
=
NULL
;
if
(
!
psz_text
)
return
p_dest
;
if
(
p_sys
->
p_text
&&
p_sys
->
p_text
->
p_module
)
{
p_region
=
(
subpicture_region_t
*
)
malloc
(
sizeof
(
subpicture_region_t
)
);
if
(
!
p_region
)
return
p_dest
;
memset
(
p_region
,
0
,
sizeof
(
subpicture_region_t
)
);
p_region
->
psz_text
=
strdup
(
p_sys
->
psz_text
);
p_region
->
p_style
=
p_sys
->
p_style
;
p_region
->
fmt
.
i_chroma
=
VLC_FOURCC
(
'T'
,
'E'
,
'X'
,
'T'
);
p_region
->
fmt
.
i_aspect
=
0
;
p_region
->
fmt
.
i_width
=
p_region
->
fmt
.
i_visible_width
=
0
;
p_region
->
fmt
.
i_height
=
p_region
->
fmt
.
i_visible_height
=
0
;
p_region
->
fmt
.
i_x_offset
=
0
;
p_region
->
fmt
.
i_y_offset
=
0
;
p_region
->
i_align
=
OSD_ALIGN_LEFT
|
OSD_ALIGN_TOP
;
if
(
p_sys
->
p_text
->
pf_render_text
)
{
video_format_t
fmt_out
;
memset
(
&
fmt_out
,
0
,
sizeof
(
video_format_t
)
);
p_sys
->
p_text
->
pf_render_text
(
p_sys
->
p_text
,
p_region
,
p_region
);
#ifndef FBOSD_BLENDING
fmt_out
.
i_chroma
=
p_fmt
->
i_chroma
;
p_dest
=
ConvertImage
(
p_intf
,
&
p_region
->
picture
,
&
p_region
->
fmt
,
&
fmt_out
);
#else
fmt_out
=
p_region
->
fmt
;
fmt_out
.
i_bits_per_pixel
=
32
;
memcpy
(
p_fmt
,
&
fmt_out
,
sizeof
(
video_format_t
)
);
p_dest
=
AllocatePicture
(
VLC_OBJECT
(
p_intf
),
&
fmt_out
);
if
(
!
p_dest
)
{
if
(
p_region
->
picture
.
pf_release
)
p_region
->
picture
.
pf_release
(
&
p_region
->
picture
);
free
(
p_region
->
psz_text
);
free
(
p_region
);
return
NULL
;
}
vout_CopyPicture
(
VLC_OBJECT
(
p_intf
),
p_dest
,
&
p_region
->
picture
);
#endif
if
(
p_region
->
picture
.
pf_release
)
p_region
->
picture
.
pf_release
(
&
p_region
->
picture
);
free
(
p_region
->
psz_text
);
free
(
p_region
);
return
p_dest
;
}
free
(
p_region
->
psz_text
);
free
(
p_region
);
}
return
p_dest
;
}
/*****************************************************************************
* LoadImage: Load an image from file into a picture buffer.
*****************************************************************************/
static
picture_t
*
LoadImage
(
intf_thread_t
*
p_intf
,
video_format_t
*
p_fmt
,
char
*
psz_file
)
{
picture_t
*
p_pic
=
NULL
;
if
(
psz_file
&&
p_intf
->
p_sys
->
p_image
)
{
video_format_t
fmt_in
,
fmt_out
;
memset
(
&
fmt_in
,
0
,
sizeof
(
fmt_in
)
);
memset
(
&
fmt_out
,
0
,
sizeof
(
fmt_out
)
);
fmt_out
.
i_chroma
=
p_fmt
->
i_chroma
;
p_pic
=
image_ReadUrl
(
p_intf
->
p_sys
->
p_image
,
psz_file
,
&
fmt_in
,
&
fmt_out
);
msg_Dbg
(
p_intf
,
"image size %dx%d chroma %4.4s"
,
fmt_out
.
i_width
,
fmt_out
.
i_height
,
(
char
*
)
&
p_fmt
->
i_chroma
);
}
return
p_pic
;
}
#ifndef FBOSD_BLENDING
/*****************************************************************************
* Convertmage: Convert image to another fourcc
*****************************************************************************/
static
picture_t
*
ConvertImage
(
intf_thread_t
*
p_intf
,
picture_t
*
p_pic
,
video_format_t
*
p_fmt_in
,
video_format_t
*
p_fmt_out
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
picture_t
*
p_old
=
NULL
;
if
(
p_sys
->
p_image
)
{
p_old
=
image_Convert
(
p_sys
->
p_image
,
p_pic
,
p_fmt_in
,
p_fmt_out
);
msg_Dbg
(
p_intf
,
"converted image size %dx%d chroma %4.4s"
,
p_fmt_out
->
i_width
,
p_fmt_out
->
i_height
,
(
char
*
)
&
p_fmt_out
->
i_chroma
);
}
return
p_old
;
}
#endif
/*****************************************************************************
* Init: initialize framebuffer video thread output method
*****************************************************************************/
static
int
Init
(
intf_thread_t
*
p_intf
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
/* Initialize the output structure: RGB with square pixels, whatever
* the input format is, since it's the only format we know */
switch
(
p_sys
->
var_info
.
bits_per_pixel
)
{
case
8
:
/* FIXME: set the palette */
p_sys
->
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'G'
,
'B'
,
'2'
);
break
;
case
15
:
p_sys
->
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'5'
);
break
;
case
16
:
p_sys
->
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'6'
);
break
;
case
24
:
p_sys
->
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'2'
,
'4'
);
break
;
case
32
:
p_sys
->
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'3'
,
'2'
);
break
;
default:
msg_Err
(
p_intf
,
"unknown screen depth %i"
,
p_sys
->
var_info
.
bits_per_pixel
);
return
VLC_EGENERIC
;
}
p_sys
->
fmt_out
.
i_bits_per_pixel
=
p_sys
->
var_info
.
bits_per_pixel
;
p_sys
->
fmt_out
.
i_width
=
p_sys
->
i_width
;
p_sys
->
fmt_out
.
i_height
=
p_sys
->
i_height
;
/* Assume we have square pixels */
if
(
p_sys
->
i_aspect
<
0
)
{
p_sys
->
fmt_out
.
i_aspect
=
(
p_sys
->
i_width
*
VOUT_ASPECT_FACTOR
)
/
p_sys
->
i_height
;
}
else
p_sys
->
fmt_out
.
i_aspect
=
p_sys
->
i_aspect
;
p_sys
->
fmt_out
.
i_sar_num
=
p_sys
->
fmt_out
.
i_sar_den
=
1
;
/* Allocate overlay buffer */
p_sys
->
p_overlay
=
AllocatePicture
(
VLC_OBJECT
(
p_intf
),
&
p_sys
->
fmt_out
);
if
(
!
p_sys
->
p_overlay
)
return
VLC_EGENERIC
;
SetOverlayTransparency
(
p_intf
,
VLC_TRUE
);
/* We know the chroma, allocate a buffer which will be used
* to write to the overlay framebuffer */
p_sys
->
p_overlay
->
p
->
i_pixel_pitch
=
p_sys
->
i_bytes_per_pixel
;
p_sys
->
p_overlay
->
p
->
i_lines
=
p_sys
->
var_info
.
yres
;
p_sys
->
p_overlay
->
p
->
i_visible_lines
=
p_sys
->
var_info
.
yres
;
if
(
p_sys
->
var_info
.
xres_virtual
)
{
p_sys
->
p_overlay
->
p
->
i_pitch
=
p_sys
->
var_info
.
xres_virtual
*
p_sys
->
i_bytes_per_pixel
;
}
else
{
p_sys
->
p_overlay
->
p
->
i_pitch
=
p_sys
->
var_info
.
xres
*
p_sys
->
i_bytes_per_pixel
;
}
p_sys
->
p_overlay
->
p
->
i_visible_pitch
=
p_sys
->
var_info
.
xres
*
p_sys
->
i_bytes_per_pixel
;
p_sys
->
p_overlay
->
i_planes
=
1
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
* End: terminate framebuffer interface
*****************************************************************************/
static
void
End
(
intf_thread_t
*
p_intf
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
/* CleanUp */
SetOverlayTransparency
(
p_intf
,
VLC_FALSE
);
if
(
p_sys
->
p_overlay
)
{
write
(
p_sys
->
i_fd
,
p_sys
->
p_overlay
->
p
[
0
].
p_pixels
,
p_sys
->
i_page_size
);
}
DeAllocatePicture
(
VLC_OBJECT
(
p_intf
),
p_intf
->
p_sys
->
p_overlay
,
&
p_intf
->
p_sys
->
fmt_out
);
p_intf
->
p_sys
->
p_overlay
=
NULL
;
}
/*****************************************************************************
* OpenDisplay: initialize framebuffer
*****************************************************************************/
static
int
OpenDisplay
(
intf_thread_t
*
p_intf
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
char
*
psz_device
;
/* framebuffer device path */
struct
fb_fix_screeninfo
fix_info
;
/* framebuffer fix information */
/* Open framebuffer device */
if
(
!
(
psz_device
=
config_GetPsz
(
p_intf
,
"fbosd-dev"
))
)
{
msg_Err
(
p_intf
,
"don't know which fb osd/overlay device to open"
);
return
VLC_EGENERIC
;
}
p_sys
->
i_fd
=
open
(
psz_device
,
O_RDWR
);
if
(
p_sys
->
i_fd
==
-
1
)
{
msg_Err
(
p_intf
,
"cannot open %s (%s)"
,
psz_device
,
strerror
(
errno
)
);
free
(
psz_device
);
return
VLC_EGENERIC
;
}
free
(
psz_device
);
/* Get framebuffer device information */
if
(
ioctl
(
p_sys
->
i_fd
,
FBIOGET_VSCREENINFO
,
&
p_sys
->
var_info
)
)
{
msg_Err
(
p_intf
,
"cannot get fb info (%s)"
,
strerror
(
errno
)
);
close
(
p_sys
->
i_fd
);
return
VLC_EGENERIC
;
}
/* Get some info on the framebuffer itself */
if
(
ioctl
(
p_sys
->
i_fd
,
FBIOGET_FSCREENINFO
,
&
fix_info
)
==
0
)
{
p_sys
->
i_width
=
p_sys
->
fmt_out
.
i_width
=
p_sys
->
var_info
.
xres
;
p_sys
->
i_height
=
p_sys
->
fmt_out
.
i_height
=
p_sys
->
var_info
.
yres
;
}
/* FIXME: if the image is full-size, it gets cropped on the left
* because of the xres / xres_virtual slight difference */
msg_Dbg
(
p_intf
,
"%ix%i (virtual %ix%i)"
,
p_sys
->
var_info
.
xres
,
p_sys
->
var_info
.
yres
,
p_sys
->
var_info
.
xres_virtual
,
p_sys
->
var_info
.
yres_virtual
);
p_sys
->
fmt_out
.
i_width
=
p_sys
->
i_width
;
p_sys
->
fmt_out
.
i_height
=
p_sys
->
i_height
;
p_sys
->
p_palette
=
NULL
;
p_sys
->
b_pan
=
(
fix_info
.
ypanstep
||
fix_info
.
ywrapstep
);
switch
(
p_sys
->
var_info
.
bits_per_pixel
)
{
case
8
:
p_sys
->
p_palette
=
malloc
(
8
*
256
*
sizeof
(
uint16_t
)
);
if
(
!
p_sys
->
p_palette
)
{
msg_Err
(
p_intf
,
"out of memory"
);
close
(
p_sys
->
i_fd
);
return
VLC_ENOMEM
;
}
p_sys
->
fb_cmap
.
start
=
0
;
p_sys
->
fb_cmap
.
len
=
256
;
p_sys
->
fb_cmap
.
red
=
p_sys
->
p_palette
;
p_sys
->
fb_cmap
.
green
=
p_sys
->
p_palette
+
256
*
sizeof
(
uint16_t
);
p_sys
->
fb_cmap
.
blue
=
p_sys
->
p_palette
+
2
*
256
*
sizeof
(
uint16_t
);
p_sys
->
fb_cmap
.
transp
=
p_sys
->
p_palette
+
3
*
256
*
sizeof
(
uint16_t
);
/* Save the colormap */
ioctl
(
p_sys
->
i_fd
,
FBIOGETCMAP
,
&
p_sys
->
fb_cmap
);
p_sys
->
i_bytes_per_pixel
=
1
;
break
;
case
15
:
case
16
:
p_sys
->
i_bytes_per_pixel
=
2
;
break
;
case
24
:
p_sys
->
i_bytes_per_pixel
=
3
;
break
;
case
32
:
p_sys
->
i_bytes_per_pixel
=
4
;
break
;
default:
msg_Err
(
p_intf
,
"screen depth %d is not supported"
,
p_sys
->
var_info
.
bits_per_pixel
);
close
(
p_sys
->
i_fd
);
return
VLC_EGENERIC
;
}
p_sys
->
i_page_size
=
p_sys
->
i_width
*
p_sys
->
i_height
*
p_sys
->
i_bytes_per_pixel
;
msg_Dbg
(
p_intf
,
"framebuffer type=%d, visual=%d, ypanstep=%d, "
"ywrap=%d, accel=%d"
,
fix_info
.
type
,
fix_info
.
visual
,
fix_info
.
ypanstep
,
fix_info
.
ywrapstep
,
fix_info
.
accel
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* CloseDisplay: terminate FB interface thread
*****************************************************************************/
static
void
CloseDisplay
(
intf_thread_t
*
p_intf
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
;
/* Restore palette */
if
(
p_sys
->
var_info
.
bits_per_pixel
==
8
)
{
ioctl
(
p_sys
->
i_fd
,
FBIOPUTCMAP
,
&
p_sys
->
fb_cmap
);
free
(
p_sys
->
p_palette
);
p_sys
->
p_palette
=
NULL
;
}
/* Close fb */
close
(
p_sys
->
i_fd
);
}
/*****************************************************************************
* Run: rc thread
*****************************************************************************
* This part of the interface is in a separate thread so that we can call
* exec() from within it without annoying the rest of the program.
*****************************************************************************/
static
void
Run
(
intf_thread_t
*
p_intf
)
{
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
while
(
!
intf_ShouldDie
(
p_intf
)
)
{
if
(
p_sys
->
b_render
)
{
if
(
p_sys
->
b_image
)
{
picture_t
*
p_pic
;
p_pic
=
LoadImage
(
p_intf
,
&
p_sys
->
fmt_out
,
p_sys
->
psz_file
);
if
(
p_pic
)
{
RenderPicture
(
p_intf
,
p_sys
->
i_x
,
p_sys
->
i_y
,
p_pic
,
p_sys
->
p_overlay
);
p_pic
->
pf_release
(
p_pic
);
}
var_SetString
(
p_intf
,
"fbosd-image"
,
""
);
p_sys
->
b_image
=
VLC_FALSE
;
}
if
(
p_sys
->
b_text
)
{
picture_t
*
p_text
;
#ifndef FBOSD_BLENDING
p_text
=
RenderText
(
p_intf
,
p_sys
->
psz_text
,
&
p_sys
->
fmt_out
);
if
(
p_text
)
{
RenderPicture
(
p_intf
,
p_sys
->
i_x
,
p_sys
->
i_y
,
p_text
,
p_sys
->
p_overlay
);
p_text
->
pf_release
(
p_text
);
}
#else
video_format_t
fmt_in
;
memset
(
&
fmt_in
,
0
,
sizeof
(
video_format_t
)
);
p_text
=
RenderText
(
p_intf
,
p_sys
->
psz_text
,
&
fmt_in
);
if
(
p_text
)
{
BlendPicture
(
p_intf
,
&
fmt_in
,
&
p_sys
->
fmt_out
,
p_text
,
p_sys
->
p_overlay
);
msg_Dbg
(
p_intf
,
"releasing picture"
);
DeAllocatePicture
(
VLC_OBJECT
(
p_intf
),
p_text
,
&
fmt_in
);
}
#endif
var_SetString
(
p_intf
,
"fbosd-text"
,
""
);
p_sys
->
b_text
=
VLC_FALSE
;
}
p_sys
->
b_render
=
VLC_FALSE
;
}
if
(
p_sys
->
b_clear
)
{
SetOverlayTransparency
(
p_intf
,
VLC_TRUE
);
var_SetString
(
p_intf
,
"fbosd-image"
,
""
);
var_SetString
(
p_intf
,
"fbosd-text"
,
""
);
p_sys
->
b_image
=
VLC_FALSE
;
p_sys
->
b_text
=
VLC_FALSE
;
p_sys
->
b_clear
=
VLC_FALSE
;
p_sys
->
b_need_update
=
VLC_TRUE
;
}
if
(
p_sys
->
b_need_update
&&
p_sys
->
p_overlay
)
{
write
(
p_sys
->
i_fd
,
p_sys
->
p_overlay
->
p
[
0
].
p_pixels
,
p_sys
->
i_page_size
);
lseek
(
p_sys
->
i_fd
,
0
,
SEEK_SET
);
p_sys
->
b_need_update
=
VLC_FALSE
;
}
if
(
vlc_CPU
()
&
CPU_CAPABILITY_FPU
)
msleep
(
INTF_IDLE_SLEEP
);
else
msleep
(
1000
);
}
End
(
p_intf
);
}
static
int
OverlayCallback
(
vlc_object_t
*
p_this
,
char
const
*
psz_cmd
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
intf_thread_t
*
p_intf
=
(
intf_thread_t
*
)
p_this
;
intf_sys_t
*
p_sys
=
(
intf_sys_t
*
)
p_intf
->
p_sys
;
if
(
!
strncmp
(
psz_cmd
,
"fbosd-image"
,
11
)
)
{
free
(
p_sys
->
psz_file
);
p_sys
->
psz_file
=
strdup
(
newval
.
psz_string
);
p_sys
->
b_image
=
VLC_TRUE
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-text"
,
10
)
)
{
free
(
p_sys
->
psz_text
);
p_sys
->
psz_text
=
strdup
(
newval
.
psz_string
);
p_sys
->
b_text
=
VLC_TRUE
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-x"
,
7
)
)
{
p_sys
->
b_absolute
=
VLC_FALSE
;
p_sys
->
i_x
=
(
newval
.
i_int
<
p_sys
->
i_width
)
?
newval
.
i_int
:
p_sys
->
i_width
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-y"
,
7
)
)
{
p_sys
->
b_absolute
=
VLC_FALSE
;
p_sys
->
i_y
=
(
newval
.
i_int
<
p_sys
->
i_height
)
?
newval
.
i_int
:
p_sys
->
i_height
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-position"
,
14
)
)
{
p_sys
->
b_absolute
=
VLC_TRUE
;
p_sys
->
i_pos
=
newval
.
i_int
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-font-size"
,
15
)
)
{
p_sys
->
p_style
->
i_font_size
=
newval
.
i_int
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-font-color"
,
16
)
)
{
p_sys
->
p_style
->
i_font_color
=
newval
.
i_int
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-font-opacity"
,
18
)
)
{
p_sys
->
p_style
->
i_font_alpha
=
255
-
newval
.
i_int
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-display"
,
13
)
)
{
p_sys
->
b_need_update
=
VLC_TRUE
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-render"
,
12
)
)
{
p_sys
->
b_render
=
VLC_TRUE
;
}
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-clear"
,
11
)
)
{
p_sys
->
b_clear
=
VLC_TRUE
;
}
#ifdef FBOSD_BLENDING
else
if
(
!
strncmp
(
psz_cmd
,
"fbosd-alpha"
,
11
)
)
{
p_sys
->
i_alpha
=
newval
.
i_int
;
}
#endif
return
VLC_SUCCESS
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment