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
86afb29f
Commit
86afb29f
authored
Jun 06, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Converted logo "video filter" to "video filter2".
I also cleaned it up.
parent
b955e000
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
497 additions
and
584 deletions
+497
-584
modules/video_filter/logo.c
modules/video_filter/logo.c
+493
-584
modules/video_filter/wrapper.c
modules/video_filter/wrapper.c
+4
-0
No files found.
modules/video_filter/logo.c
View file @
86afb29f
...
...
@@ -29,41 +29,19 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout.h>
#include <assert.h>
#include "vlc_filter.h"
#include "filter_common.h"
#include
"vlc_image.h"
#include
"vlc_osd.h"
#include
<vlc_image.h>
#include
<vlc_osd.h>
#ifdef LoadImage
# undef LoadImage
#endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
Create
(
vlc_object_t
*
);
static
void
Destroy
(
vlc_object_t
*
);
static
int
Init
(
vout_thread_t
*
);
static
void
End
(
vout_thread_t
*
);
static
void
Render
(
vout_thread_t
*
,
picture_t
*
);
static
int
MouseEvent
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
static
int
Control
(
vout_thread_t
*
,
int
,
va_list
);
static
int
CreateFilter
(
vlc_object_t
*
);
static
void
DestroyFilter
(
vlc_object_t
*
);
static
int
LogoCallback
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
...
...
@@ -99,13 +77,18 @@ static const char *const 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
OpenSub
(
vlc_object_t
*
);
static
int
OpenVideo
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
()
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_SUBPIC
)
set_capability
(
"sub filter"
,
0
)
set_callbacks
(
CreateFilter
,
DestroyFilter
)
set_callbacks
(
OpenSub
,
Close
)
set_description
(
N_
(
"Logo sub filter"
)
)
set_shortname
(
N_
(
"Logo overlay"
)
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_SUBPIC
)
add_shortcut
(
"logo"
)
add_file
(
CFG_PREFIX
"file"
,
NULL
,
NULL
,
FILE_TEXT
,
FILE_LONGTEXT
,
false
)
...
...
@@ -121,20 +104,21 @@ vlc_module_begin ()
/* video output filter submodule */
add_submodule
()
set_capability
(
"video filter"
,
0
)
set_callbacks
(
Create
,
Destroy
)
set_capability
(
"video filter
2
"
,
0
)
set_callbacks
(
OpenVideo
,
Close
)
set_description
(
N_
(
"Logo video filter"
)
)
add_shortcut
(
"logo"
)
vlc_module_end
()
static
const
char
*
const
ppsz_filter_options
[]
=
{
"file"
,
"x"
,
"y"
,
"delay"
,
"repeat"
,
"transparency"
,
"position"
,
NULL
};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/**
* Structure to hold the set of individual logo image names, times,
* transparencies
*
***************************************************************************
/
*/
typedef
struct
{
char
*
psz_file
;
/* candidate for deletion -- not needed */
...
...
@@ -144,9 +128,9 @@ typedef struct
}
logo_t
;
/**
***************************************************************************
* Logo list structure.
Common to both the vout and sub picture filter
*
***************************************************************************
/
/**
* Logo list structure.
*/
typedef
struct
{
logo_t
*
p_logo
;
/* the parsing's result */
...
...
@@ -162,408 +146,417 @@ typedef struct
char
*
psz_filename
;
/* --logo-file string ( is it really useful
* to store it ? ) */
vlc_mutex_t
lock
;
}
logo_list_t
;
/**
***************************************************************************
*
LoadImage: loads the logo image into memory
*
****************************************************************************
/
st
atic
picture_t
*
LoadImage
(
vlc_object_t
*
p_this
,
char
*
psz_filename
)
/**
*
Private logo data holder
*/
st
ruct
filter_sys_t
{
picture_t
*
p_pic
;
image_handler_t
*
p_image
;
video_format_t
fmt_in
;
video_format_t
fmt_out
;
filter_t
*
p_blend
;
memset
(
&
fmt_in
,
0
,
sizeof
(
video_format_t
)
);
memset
(
&
fmt_out
,
0
,
sizeof
(
video_format_t
)
);
vlc_mutex_t
lock
;
fmt_out
.
i_chroma
=
VLC_CODEC_YUVA
;
p_image
=
image_HandlerCreate
(
p_this
);
p_pic
=
image_ReadUrl
(
p_image
,
psz_filename
,
&
fmt_in
,
&
fmt_out
);
image_HandlerDelete
(
p_image
);
logo_list_t
list
;
return
p_pic
;
}
int
i_pos
;
int
i_pos_x
;
int
i_pos_y
;
bool
b_absolute
;
/*****************************************************************************
* LoadLogoList: loads the logo images into memory
*****************************************************************************
* Read the logo-file input switch, obtaining a list of images and associated
* durations and transparencies. Store the image(s), and times. An image
* without a stated time or transparency will use the logo-delay and
* logo-transparency values.
*****************************************************************************/
#define LoadLogoList( a, b ) __LoadLogoList( VLC_OBJECT( a ), b )
static
void
__LoadLogoList
(
vlc_object_t
*
p_this
,
logo_list_t
*
p_logo_list
)
{
char
*
psz_list
;
/* the list: <logo>[,[<delay>[,[<alpha>]]]][;...] */
unsigned
int
i
;
logo_t
*
p_logo
;
/* the parsing's result */
/* On the fly control variable */
bool
b_spu_update
;
p_logo_list
->
i_counter
=
0
;
p_logo_list
->
i_next_pic
=
0
;
/* */
bool
b_mouse_grab
;
};
psz_list
=
strdup
(
p_logo_list
->
psz_filename
);
static
const
char
*
const
ppsz_filter_options
[]
=
{
"file"
,
"x"
,
"y"
,
"delay"
,
"repeat"
,
"transparency"
,
"position"
,
NULL
};
/* Count the number logos == number of ';' + 1 */
p_logo_list
->
i_count
=
1
;
for
(
i
=
0
;
i
<
strlen
(
psz_list
);
i
++
)
{
if
(
psz_list
[
i
]
==
';'
)
p_logo_list
->
i_count
++
;
}
static
const
char
*
const
ppsz_filter_callbacks
[]
=
{
"logo-file"
,
"logo-x"
,
"logo-y"
,
"logo-position"
,
"logo-transparency"
,
"logo-repeat"
,
NULL
};
p_logo_list
->
p_logo
=
p_logo
=
(
logo_t
*
)
malloc
(
p_logo_list
->
i_count
*
sizeof
(
logo_t
)
);
static
int
OpenCommon
(
vlc_object_t
*
,
bool
b_sub
);
/* Fill the data */
for
(
i
=
0
;
i
<
p_logo_list
->
i_count
;
i
++
)
{
char
*
p_c
;
char
*
p_c2
;
p_c
=
strchr
(
psz_list
,
';'
);
p_c2
=
strchr
(
psz_list
,
','
);
static
subpicture_t
*
FilterSub
(
filter_t
*
,
mtime_t
);
static
picture_t
*
FilterVideo
(
filter_t
*
,
picture_t
*
);
p_logo
[
i
].
i_alpha
=
-
1
;
/* use default settings */
p_logo
[
i
].
i_delay
=
-
1
;
/* use default settings */
static
int
Mouse
(
filter_t
*
,
vlc_mouse_t
*
,
const
vlc_mouse_t
*
,
const
vlc_mouse_t
*
);
if
(
p_c2
&&
(
p_c2
<
p_c
||
!
p_c
)
)
{
/* <logo>,<delay>[,<alpha>] type */
if
(
p_c2
[
1
]
!=
','
&&
p_c2
[
1
]
!=
';'
&&
p_c2
[
1
]
!=
'\0'
)
p_logo
[
i
].
i_delay
=
atoi
(
p_c2
+
1
);
*
p_c2
=
'\0'
;
if
(
(
p_c2
=
strchr
(
p_c2
+
1
,
','
)
)
&&
(
p_c2
<
p_c
||
!
p_c
)
&&
p_c2
[
1
]
!=
';'
&&
p_c2
[
1
]
!=
'\0'
)
p_logo
[
i
].
i_alpha
=
atoi
(
p_c2
+
1
);
}
else
{
/* <logo> type */
if
(
p_c
)
*
p_c
=
'\0'
;
}
static
int
LogoCallback
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
p_logo
[
i
].
psz_file
=
strdup
(
psz_list
);
p_logo
[
i
].
p_pic
=
LoadImage
(
p_this
,
p_logo
[
i
].
psz_file
);
static
void
LogoListLoad
(
vlc_object_t
*
,
logo_list_t
*
);
static
void
LogoListUnload
(
logo_list_t
*
);
static
logo_t
*
LogoListNext
(
logo_list_t
*
p_list
,
mtime_t
i_date
);
static
logo_t
*
LogoListCurrent
(
logo_list_t
*
p_list
);
if
(
!
p_logo
[
i
].
p_pic
)
{
msg_Warn
(
p_this
,
"error while loading logo %s, will be skipped"
,
p_logo
[
i
].
psz_file
);
}
/**
* Open the sub filter
*/
static
int
OpenSub
(
vlc_object_t
*
p_this
)
{
return
OpenCommon
(
p_this
,
true
);
}
if
(
p_c
)
psz_list
=
p_c
+
1
;
}
/**
* Open the video filter
*/
static
int
OpenVideo
(
vlc_object_t
*
p_this
)
{
return
OpenCommon
(
p_this
,
false
);
}
for
(
i
=
0
;
i
<
p_logo_list
->
i_count
;
i
++
)
/**
* Common open function
*/
static
int
OpenCommon
(
vlc_object_t
*
p_this
,
bool
b_sub
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
;
/* */
if
(
!
b_sub
&&
!
es_format_IsSimilar
(
&
p_filter
->
fmt_in
,
&
p_filter
->
fmt_out
)
)
{
msg_Dbg
(
p_this
,
"logo file name %s, delay %d, alpha %d"
,
p_logo
[
i
].
psz_file
,
p_logo
[
i
].
i_delay
,
p_logo
[
i
].
i_alpha
)
;
msg_Err
(
p_filter
,
"Input and output format does not match"
);
return
VLC_EGENERIC
;
}
/* initialize so that on the first update it will wrap back to 0 */
p_logo_list
->
i_counter
=
p_logo_list
->
i_count
;
}
/*****************************************************************************
* FreeLogoList
*****************************************************************************/
static
void
FreeLogoList
(
logo_list_t
*
p_logo_list
)
{
unsigned
int
i
;
FREENULL
(
p_logo_list
->
psz_filename
)
;
for
(
i
=
0
;
i
<
p_logo_list
->
i_count
;
i
++
)
/* */
p_filter
->
p_sys
=
p_sys
=
malloc
(
sizeof
(
*
p_sys
)
);
if
(
!
p_sys
)
return
VLC_ENOMEM
;
/* */
p_sys
->
p_blend
=
NULL
;
if
(
!
b_sub
)
{
logo_t
*
p_logo
=
&
p_logo_list
->
p_logo
[
i
];
FREENULL
(
p_logo
->
psz_file
);
if
(
p_logo
->
p_pic
)
p_sys
->
p_blend
=
filter_NewBlend
(
VLC_OBJECT
(
p_filter
),
p_filter
->
fmt_in
.
i_codec
);
if
(
!
p_sys
->
p_blend
)
{
picture_Release
(
p_logo
->
p_pic
);
p_logo
->
p_pic
=
NULL
;
free
(
p_sys
);
return
VLC_EGENERIC
;
}
}
}
/*****************************************************************************
* vout_sys_t: logo video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the Invert specific properties of an output thread.
*****************************************************************************/
struct
vout_sys_t
{
logo_list_t
*
p_logo_list
;
vout_thread_t
*
p_vout
;
filter_t
*
p_blend
;
int
i_width
,
i_height
;
int
pos
,
posx
,
posy
;
};
/* */
config_ChainParse
(
p_filter
,
CFG_PREFIX
,
ppsz_filter_options
,
p_filter
->
p_cfg
);
/*****************************************************************************
* Create: allocates logo video thread output method
*****************************************************************************/
static
int
Create
(
vlc_object_t
*
p_this
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_this
;
vout_sys_t
*
p_sys
;
logo_list_t
*
p_logo_list
;
/* */
logo_list_t
*
p_list
=
&
p_sys
->
list
;
/* Allocate structure */
p_sys
=
p_vout
->
p_sys
=
malloc
(
sizeof
(
vout_sys_t
)
);
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
p_logo_list
=
p_sys
->
p_logo_list
=
malloc
(
sizeof
(
logo_list_t
)
);
if
(
p_logo_list
==
NULL
)
p_list
->
psz_filename
=
var_CreateGetStringCommand
(
p_filter
,
"logo-file"
);
if
(
!
p_list
->
psz_filename
||
*
p_list
->
psz_filename
==
'\0'
)
{
msg_Err
(
p_this
,
"logo file not specified"
);
if
(
p_sys
->
p_blend
)
filter_DeleteBlend
(
p_sys
->
p_blend
);
free
(
p_list
->
psz_filename
);
free
(
p_sys
);
return
VLC_E
NOMEM
;
return
VLC_E
GENERIC
;
}
p_list
->
i_alpha
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-transparency"
);
p_list
->
i_alpha
=
__MAX
(
__MIN
(
p_list
->
i_alpha
,
255
),
0
);
p_list
->
i_delay
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-delay"
);
p_list
->
i_repeat
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-repeat"
);
p_sys
->
i_pos
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-position"
);
p_sys
->
i_pos_x
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-x"
);
p_sys
->
i_pos_y
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-y"
);
/* Ignore aligment if a position is given for video filter */
if
(
!
b_sub
&&
p_sys
->
i_pos_x
>=
0
&&
p_sys
->
i_pos_y
>=
0
)
p_sys
->
i_pos
=
0
;
vlc_mutex_init
(
&
p_sys
->
lock
);
LogoListLoad
(
p_this
,
p_list
);
p_sys
->
b_spu_update
=
true
;
p_sys
->
b_mouse_grab
=
false
;
config_ChainParse
(
p_vout
,
CFG_PREFIX
,
ppsz_filter_options
,
p_vout
->
p_cfg
);
for
(
int
i
=
0
;
ppsz_filter_callbacks
[
i
];
i
++
)
var_AddCallback
(
p_filter
,
ppsz_filter_callbacks
[
i
],
LogoCallback
,
p_sys
);
p_logo_list
->
psz_filename
=
var_CreateGetStringCommand
(
p_vout
,
"logo-file"
);
if
(
!
p_logo_list
->
psz_filename
||
!*
p_logo_list
->
psz_filename
)
/* Misc init */
if
(
b_sub
)
{
msg_Err
(
p_vout
,
"logo file not specified"
);
free
(
p_logo_list
->
psz_filename
);
free
(
p_sys
);
return
VLC_EGENERIC
;
p_filter
->
pf_sub_filter
=
FilterSub
;
}
else
{
p_filter
->
pf_video_filter
=
FilterVideo
;
p_filter
->
pf_mouse
=
Mouse
;
}
p_vout
->
pf_init
=
Init
;
p_vout
->
pf_end
=
End
;
p_vout
->
pf_manage
=
NULL
;
p_vout
->
pf_render
=
Render
;
p_vout
->
pf_display
=
NULL
;
p_vout
->
pf_control
=
Control
;
p_sys
->
pos
=
var_CreateGetIntegerCommand
(
p_vout
,
"logo-position"
);
p_sys
->
posx
=
var_CreateGetIntegerCommand
(
p_vout
,
"logo-x"
);
p_sys
->
posy
=
var_CreateGetIntegerCommand
(
p_vout
,
"logo-y"
);
p_logo_list
->
i_delay
=
var_CreateGetIntegerCommand
(
p_vout
,
"logo-delay"
);
p_logo_list
->
i_delay
=
__MAX
(
__MIN
(
p_logo_list
->
i_delay
,
60000
),
0
);
p_logo_list
->
i_repeat
=
var_CreateGetIntegerCommand
(
p_vout
,
"logo-repeat"
);
p_logo_list
->
i_alpha
=
var_CreateGetIntegerCommand
(
p_vout
,
"logo-transparency"
);
p_logo_list
->
i_alpha
=
__MAX
(
__MIN
(
p_logo_list
->
i_alpha
,
255
),
0
);
LoadLogoList
(
p_vout
,
p_logo_list
);
return
VLC_SUCCESS
;
}
/**
***************************************************************************
*
Init: initialize logo video thread output method
*
****************************************************************************
/
static
int
Init
(
vout_thread_t
*
p_vout
)
/**
*
Common close function
*/
static
void
Close
(
vlc_object_t
*
p_this
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
picture_t
*
p_pic
;
video_format_t
fmt
;
logo_list_t
*
p_logo_list
=
p_sys
->
p_logo_list
;
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
I_OUTPUTPICTURES
=
0
;
memset
(
&
fmt
,
0
,
sizeof
(
video_format_t
)
);
for
(
int
i
=
0
;
ppsz_filter_callbacks
[
i
];
i
++
)
var_DelCallback
(
p_filter
,
ppsz_filter_callbacks
[
i
],
LogoCallback
,
p_sys
);
/* adjust index to the next logo */
p_logo_list
->
i_counter
=
(
p_logo_list
->
i_counter
+
1
)
%
p_logo_list
->
i_count
;
p_pic
=
p_logo_list
->
p_logo
[
p_logo_list
->
i_counter
].
p_pic
;
p_sys
->
i_width
=
p_pic
?
p_pic
->
p
[
Y_PLANE
].
i_visible_pitch
:
0
;
p_sys
->
i_height
=
p_pic
?
p_pic
->
p
[
Y_PLANE
].
i_visible_lines
:
0
;
/* Initialize the output structure */
p_vout
->
output
.
i_chroma
=
p_vout
->
render
.
i_chroma
;
p_vout
->
output
.
i_width
=
p_vout
->
render
.
i_width
;
p_vout
->
output
.
i_height
=
p_vout
->
render
.
i_height
;
p_vout
->
output
.
i_aspect
=
p_vout
->
render
.
i_aspect
;
p_vout
->
fmt_out
=
p_vout
->
fmt_in
;
fmt
=
p_vout
->
fmt_out
;
/* Load the video blending filter */
p_sys
->
p_blend
=
filter_NewBlend
(
VLC_OBJECT
(
p_vout
),
p_vout
->
output
.
i_chroma
);
if
(
!
p_sys
->
p_blend
)
return
VLC_EGENERIC
;
if
(
p_sys
->
p_blend
)
filter_DeleteBlend
(
p_sys
->
p_blend
);
video_format_t
fmt_blend
;
video_format_Setup
(
&
fmt_blend
,
VLC_CODEC_YUVA
,
p_sys
->
i_width
,
p_sys
->
i_height
,
0
);
vlc_mutex_destroy
(
&
p_sys
->
lock
);
LogoListUnload
(
&
p_sys
->
list
);
free
(
p_sys
);
}
if
(
filter_ConfigureBlend
(
p_sys
->
p_blend
,
p_vout
->
output
.
i_width
,
p_vout
->
output
.
i_height
,
&
fmt_blend
)
)
{
msg_Err
(
p_vout
,
"can't configure blending filter, aborting"
);
filter_DeleteBlend
(
p_sys
->
p_blend
);
return
VLC_EGENERIC
;
}
/**
* Sub filter
*/
static
subpicture_t
*
FilterSub
(
filter_t
*
p_filter
,
mtime_t
date
)
{
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
logo_list_t
*
p_list
=
&
p_sys
->
list
;
if
(
p_sys
->
posx
<
0
||
p_sys
->
posy
<
0
)
{
p_sys
->
posx
=
0
;
p_sys
->
posy
=
0
;
subpicture_t
*
p_spu
;
subpicture_region_t
*
p_region
;
video_format_t
fmt
;
picture_t
*
p_pic
;
logo_t
*
p_logo
;
if
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_BOTTOM
)
{
p_sys
->
posy
=
p_vout
->
render
.
i_height
-
p_sys
->
i_height
;
}
else
if
(
!
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_TOP
)
)
{
p_sys
->
posy
=
p_vout
->
render
.
i_height
/
2
-
p_sys
->
i_height
/
2
;
}
vlc_mutex_lock
(
&
p_sys
->
lock
);
/* Basic test: b_spu_update occurs on a dynamic change,
& i_next_pic is the general timer, when to
look at updating the logo image */
if
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_RIGHT
)
{
p_sys
->
posx
=
p_vout
->
render
.
i_width
-
p_sys
->
i_width
;
}
else
if
(
!
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_LEFT
)
)
{
p_sys
->
posx
=
p_vout
->
render
.
i_width
/
2
-
p_sys
->
i_width
/
2
;
}
}
else
if
(
(
!
p_sys
->
b_spu_update
&&
p_list
->
i_next_pic
>
date
)
||
!
p_list
->
i_repeat
)
{
p_sys
->
pos
=
0
;
vlc_mutex_unlock
(
&
p_sys
->
lock
);
return
NULL
;
}
/* Try to open the real video output */
msg_Dbg
(
p_vout
,
"spawning the real video output"
);
/* adjust index to the next logo */
p_logo
=
LogoListNext
(
p_list
,
date
);
p_sys
->
b_spu_update
=
false
;
p_pic
=
p_logo
->
p_pic
;
p_sys
->
p_vout
=
vout_Create
(
p_vout
,
&
fmt
);
/* Allocate the subpicture internal data. */
p_spu
=
filter_NewSubpicture
(
p_filter
);
if
(
!
p_spu
)
goto
exit
;
/* Everything failed */
if
(
p_sys
->
p_vout
==
NULL
)
p_spu
->
b_absolute
=
p_sys
->
b_absolute
;
p_spu
->
i_start
=
date
;
p_spu
->
i_stop
=
0
;
p_spu
->
b_ephemer
=
true
;
/* Send an empty subpicture to clear the display when needed */
if
(
p_list
->
i_repeat
!=
-
1
&&
p_list
->
i_counter
==
0
)
{
msg_Err
(
p_vout
,
"can't open vout, aborting"
);
return
VLC_EGENERIC
;
p_list
->
i_repeat
--
;
if
(
p_list
->
i_repeat
==
0
)
goto
exit
;
}
if
(
!
p_pic
||
!
p_logo
->
i_alpha
||
(
p_logo
->
i_alpha
==
-
1
&&
!
p_list
->
i_alpha
)
)
goto
exit
;
/* Create new SPU region */
memset
(
&
fmt
,
0
,
sizeof
(
video_format_t
)
);
fmt
.
i_chroma
=
VLC_CODEC_YUVA
;
fmt
.
i_aspect
=
VOUT_ASPECT_FACTOR
;
fmt
.
i_sar_num
=
fmt
.
i_sar_den
=
1
;
fmt
.
i_width
=
fmt
.
i_visible_width
=
p_pic
->
p
[
Y_PLANE
].
i_visible_pitch
;
fmt
.
i_height
=
fmt
.
i_visible_height
=
p_pic
->
p
[
Y_PLANE
].
i_visible_lines
;
fmt
.
i_x_offset
=
fmt
.
i_y_offset
=
0
;
p_region
=
subpicture_region_New
(
&
fmt
);
if
(
!
p_region
)
{
msg_Err
(
p_filter
,
"cannot allocate SPU region"
);
p_filter
->
pf_sub_buffer_del
(
p_filter
,
p_spu
);
p_spu
=
NULL
;
goto
exit
;
}
vout_filter_AllocateDirectBuffers
(
p_vout
,
VOUT_MAX_PICTURES
);
/* */
picture_Copy
(
p_region
->
p_picture
,
p_pic
);
vout_filter_AddChild
(
p_vout
,
p_sys
->
p_vout
,
MouseEvent
);
/* where to locate the logo: */
if
(
p_sys
->
i_pos
<
0
)
{
/* set to an absolute xy */
p_region
->
i_align
=
OSD_ALIGN_RIGHT
|
OSD_ALIGN_TOP
;
p_spu
->
b_absolute
=
true
;
}
else
{
/* set to one of the 9 relative locations */
p_region
->
i_align
=
p_sys
->
i_pos
;
p_spu
->
b_absolute
=
false
;
}
return
VLC_SUCCESS
;
}
p_region
->
i_x
=
p_sys
->
i_pos_x
;
p_region
->
i_y
=
p_sys
->
i_pos_y
;
/*****************************************************************************
* End: terminate logo video thread output method
*****************************************************************************/
static
void
End
(
vout_thread_t
*
p_vout
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
p_spu
->
p_region
=
p_region
;
vout_filter_DelChild
(
p_vout
,
p_sys
->
p_vout
,
MouseEvent
);
vout_CloseAndRelease
(
p_sys
->
p_vout
);
p_spu
->
i_alpha
=
(
p_logo
->
i_alpha
!=
-
1
?
p_logo
->
i_alpha
:
p_list
->
i_alpha
);
vout_filter_ReleaseDirectBuffers
(
p_vout
);
exit:
vlc_mutex_unlock
(
&
p_sys
->
lock
);
filter_DeleteBlend
(
p_sys
->
p_blend
)
;
return
p_spu
;
}
/**
***************************************************************************
*
Destroy: destroy logo video thread output method
*
****************************************************************************
/
static
void
Destroy
(
vlc_object_t
*
p_this
)
/**
*
Video filter
*/
static
picture_t
*
FilterVideo
(
filter_t
*
p_filter
,
picture_t
*
p_src
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_thi
s
;
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sy
s
;
logo_list_t
*
p_list
=
&
p_sys
->
list
;
picture_t
*
p_dst
=
filter_NewPicture
(
p_filter
);
if
(
!
p_dst
)
goto
exit
;
FreeLogoList
(
p_sys
->
p_logo_list
);
free
(
p_sys
->
p_logo_list
);
picture_Copy
(
p_dst
,
p_src
);
free
(
p_sys
);
}
/* */
vlc_mutex_lock
(
&
p_sys
->
lock
);
/*****************************************************************************
* Render: render the logo onto the video
*****************************************************************************/
static
void
Render
(
vout_thread_t
*
p_vout
,
picture_t
*
p_inpic
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
picture_t
*
p_outpic
;
picture_t
*
p_pic
;
logo_list_t
*
p_logo_list
;
logo_t
*
p_logo
;
p_logo_list
=
p_sys
->
p_logo_list
;
logo_t
*
p_logo
;
if
(
p_list
->
i_next_pic
<
p_src
->
date
)
p_logo
=
LogoListNext
(
p_list
,
p_src
->
date
);
else
p_logo
=
LogoListCurrent
(
p_list
);
if
(
p_logo_list
->
i_next_pic
<
p_inpic
->
date
)
/* */
const
picture_t
*
p_pic
=
p_logo
->
p_pic
;
if
(
p_pic
)
{
/* It's time to use a new logo */
p_logo_list
->
i_counter
=
(
p_logo_list
->
i_counter
+
1
)
%
p_logo_list
->
i_count
;
p_logo
=
&
p_logo_list
->
p_logo
[
p_sys
->
p_logo_list
->
i_counter
];
p_pic
=
p_logo
->
p_pic
;
p_logo_list
->
i_next_pic
=
p_inpic
->
date
+
(
p_logo
->
i_delay
!=
-
1
?
p_logo
->
i_delay
:
p_logo_list
->
i_delay
)
*
1000
;
if
(
p_pic
)
{
const
video_format_t
*
p_fmt
=
&
p_pic
->
format
;
const
int
i_dst_w
=
p_filter
->
fmt_out
.
video
.
i_visible_width
;
const
int
i_dst_h
=
p_filter
->
fmt_out
.
video
.
i_visible_height
;
p_sys
->
i_width
=
p_sys
->
p_blend
->
fmt_in
.
video
.
i_width
=
p_sys
->
p_blend
->
fmt_in
.
video
.
i_visible_width
=
p_pic
->
p
[
Y_PLANE
].
i_visible_pitch
;
p_sys
->
i_height
=
p_sys
->
p_blend
->
fmt_in
.
video
.
i_height
=
p_sys
->
p_blend
->
fmt_in
.
video
.
i_visible_height
=
p_pic
->
p
[
Y_PLANE
].
i_visible_lines
;
if
(
p_sys
->
i_pos
)
{
if
(
p_sys
->
i_pos
&
SUBPICTURE_ALIGN_BOTTOM
)
{
p_sys
->
i_pos_y
=
i_dst_h
-
p_fmt
->
i_visible_height
;
}
else
if
(
!
(
p_sys
->
i_pos
&
SUBPICTURE_ALIGN_TOP
)
)
{
p_sys
->
i_pos_y
=
(
i_dst_h
-
p_fmt
->
i_visible_height
)
/
2
;
}
else
{
p_sys
->
i_pos_y
=
0
;
}
if
(
p_sys
->
pos
)
if
(
p_sys
->
i_pos
&
SUBPICTURE_ALIGN_RIGHT
)
{
p_sys
->
i_pos_x
=
i_dst_w
-
p_fmt
->
i_visible_width
;
}
else
if
(
!
(
p_sys
->
i_pos
&
SUBPICTURE_ALIGN_LEFT
)
)
{
if
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_BOTTOM
)
{
p_sys
->
posy
=
p_vout
->
render
.
i_height
-
p_sys
->
i_height
;
}
else
if
(
!
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_TOP
)
)
{
p_sys
->
posy
=
p_vout
->
render
.
i_height
/
2
-
p_sys
->
i_height
/
2
;
}
if
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_RIGHT
)
{
p_sys
->
posx
=
p_vout
->
render
.
i_width
-
p_sys
->
i_width
;
}
else
if
(
!
(
p_sys
->
pos
&
SUBPICTURE_ALIGN_LEFT
)
)
{
p_sys
->
posx
=
p_vout
->
render
.
i_width
/
2
-
p_sys
->
i_width
/
2
;
}
p_sys
->
i_pos_x
=
(
i_dst_w
-
p_fmt
->
i_visible_width
)
/
2
;
}
else
{
p_sys
->
i_pos_x
=
0
;
}
}
/* */
const
int
i_alpha
=
p_logo
->
i_alpha
!=
-
1
?
p_logo
->
i_alpha
:
p_list
->
i_alpha
;
if
(
filter_ConfigureBlend
(
p_sys
->
p_blend
,
i_dst_w
,
i_dst_h
,
p_fmt
)
||
filter_Blend
(
p_sys
->
p_blend
,
p_dst
,
p_sys
->
i_pos_x
,
p_sys
->
i_pos_y
,
p_pic
,
i_alpha
)
)
{
msg_Err
(
p_filter
,
"failed to blend a picture"
);
}
}
else
{
p_logo
=
&
p_logo_list
->
p_logo
[
p_sys
->
p_logo_list
->
i_counter
];
p_pic
=
p_logo
->
p_pic
;
}
vlc_mutex_unlock
(
&
p_sys
->
lock
);
/* This is a new frame. Get a structure from the video_output. */
while
(
!
(
p_outpic
=
vout_CreatePicture
(
p_sys
->
p_vout
,
0
,
0
,
0
))
)
{
if
(
!
vlc_object_alive
(
p_vout
)
||
p_vout
->
b_error
)
return
;
msleep
(
VOUT_OUTMEM_SLEEP
);
}
exit:
picture_Release
(
p_src
);
return
p_dst
;
}
picture_Copy
(
p_outpic
,
p_inpic
);
static
int
Mouse
(
filter_t
*
p_filter
,
vlc_mouse_t
*
p_mouse
,
const
vlc_mouse_t
*
p_old
,
const
vlc_mouse_t
*
p_new
)
{
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
vlc_mutex_lock
(
&
p_sys
->
lock
);
logo_t
*
p_logo
=
LogoListCurrent
(
&
p_sys
->
list
);
const
picture_t
*
p_pic
=
p_logo
->
p_pic
;
if
(
p_pic
)
{
const
int
i_alpha
=
p_logo
->
i_alpha
!=
-
1
?
p_logo
->
i_alpha
:
p_logo_list
->
i_alpha
;
const
video_format_t
*
p_fmt
=
&
p_pic
->
format
;
const
int
i_logo_w
=
p_fmt
->
i_visible_width
;
const
int
i_logo_h
=
p_fmt
->
i_visible_height
;
/* Check if we are over the logo */
const
bool
b_over
=
p_new
->
i_x
>=
p_sys
->
i_pos_x
&&
p_new
->
i_x
<
p_sys
->
i_pos_x
+
i_logo_w
&&
p_new
->
i_y
>=
p_sys
->
i_pos_y
&&
p_new
->
i_y
<
p_sys
->
i_pos_y
+
i_logo_h
;
if
(
b_over
&&
vlc_mouse_HasPressed
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
)
)
p_sys
->
b_mouse_grab
=
true
;
else
if
(
vlc_mouse_HasReleased
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
)
)
p_sys
->
b_mouse_grab
=
false
;
filter_Blend
(
p_sys
->
p_blend
,
p_outpic
,
p_sys
->
posx
,
p_sys
->
posy
,
p_pic
,
i_alpha
);
msg_Err
(
p_filter
,
"Mouse: %d G: %d"
,
b_over
,
p_sys
->
b_mouse_grab
);
if
(
p_sys
->
b_mouse_grab
)
{
int
i_dx
,
i_dy
;
vlc_mouse_GetMotion
(
&
i_dx
,
&
i_dy
,
p_old
,
p_new
);
msg_Err
(
p_filter
,
"Mouse: d=%d:%d"
,
i_dx
,
i_dy
);
p_sys
->
i_pos_x
=
__MIN
(
__MAX
(
p_sys
->
i_pos_x
+
i_dx
,
0
),
p_filter
->
fmt_in
.
video
.
i_width
-
i_logo_w
);
p_sys
->
i_pos_y
=
__MIN
(
__MAX
(
p_sys
->
i_pos_y
+
i_dy
,
0
),
p_filter
->
fmt_in
.
video
.
i_height
-
i_logo_h
);
}
if
(
p_sys
->
b_mouse_grab
||
b_over
)
{
vlc_mutex_unlock
(
&
p_sys
->
lock
);
return
VLC_EGENERIC
;
}
}
vlc_mutex_unlock
(
&
p_sys
->
lock
);
vout_DisplayPicture
(
p_sys
->
p_vout
,
p_outpic
);
*
p_mouse
=
*
p_new
;
return
VLC_SUCCESS
;
}
#if 0
/*****************************************************************************
* MouseEvent: callback for mouse events
*****************************************************************************/
...
...
@@ -602,288 +595,204 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
}
/* FIXME missing lock */
if
(
i_x
<
(
int
)
p_sys
->
pos
x
||
i_y
<
(
int
)
p_sys
->
pos
y
||
i_x
>
(
int
)(
p_sys
->
pos
x
+
p_sys
->
i_width
)
||
i_y
>
(
int
)(
p_sys
->
pos
y
+
p_sys
->
i_height
)
)
if( i_x < (int)p_sys->
i_pos_
x ||
i_y < (int)p_sys->
i_pos_
y ||
i_x > (int)(p_sys->
i_pos_
x + p_sys->i_width) ||
i_y > (int)(p_sys->
i_pos_
y + p_sys->i_height) )
goto forward;
p_sys
->
posx
=
__MIN
(
__MAX
(
p_sys
->
pos
x
+
i_dx
,
0
),
p_sys->
i_pos_x = __MIN( __MAX( p_sys->i_pos_
x + i_dx, 0 ),
p_vout->output.i_width - p_sys->i_width );
p_sys
->
posy
=
__MIN
(
__MAX
(
p_sys
->
pos
y
+
i_dy
,
0
),
p_sys->
i_pos_y = __MIN( __MAX( p_sys->i_pos_
y + i_dy, 0 ),
p_vout->output.i_height - p_sys->i_height );
return VLC_SUCCESS;
forward:
return var_Set( p_vout, psz_var, newval );
}
#endif
/*****************************************************************************
* Control: control facility for the vout (forwards to child vout)
*****************************************************************************/
static
int
Control
(
vout_thread_t
*
p_vout
,
int
i_query
,
va_list
args
)
{
return
vout_vaControl
(
p_vout
->
p_sys
->
p_vout
,
i_query
,
args
);
}
/*****************************************************************************
* filter_sys_t: logo filter descriptor
*****************************************************************************/
struct
filter_sys_t
{
logo_list_t
*
p_logo_list
;
int
pos
,
posx
,
posy
;
bool
b_absolute
;
/* On the fly control variable */
bool
b_need_update
;
};
static
subpicture_t
*
Filter
(
filter_t
*
,
mtime_t
);
/*****************************************************************************
* CreateFilter: allocates logo video filter
* Callback to update params on the fly
*****************************************************************************/
static
int
CreateFilter
(
vlc_object_t
*
p_this
)
static
int
LogoCallback
(
vlc_object_t
*
p_this
,
char
const
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
;
logo_list_t
*
p_l
ogo_
list
;
VLC_UNUSED
(
oldval
)
;
filter_sys_t
*
p_sys
=
(
filter_sys_t
*
)
p_data
;
logo_list_t
*
p_l
ist
=
&
p_sys
->
list
;
/* Allocate structure */
p_sys
=
p_filter
->
p_sys
=
malloc
(
sizeof
(
filter_sys_t
)
);
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
p_logo_list
=
p_sys
->
p_logo_list
=
malloc
(
sizeof
(
logo_list_t
)
);
if
(
p_logo_list
==
NULL
)
vlc_mutex_lock
(
&
p_sys
->
lock
);
if
(
!
strcmp
(
psz_var
,
"logo-file"
)
)
{
free
(
p_sys
);
return
VLC_ENOMEM
;
LogoListUnload
(
p_list
);
p_list
->
psz_filename
=
strdup
(
newval
.
psz_string
);
LogoListLoad
(
p_this
,
p_list
);
}
config_ChainParse
(
p_filter
,
CFG_PREFIX
,
ppsz_filter_options
,
p_filter
->
p_cfg
);
/* Hook used for callback variables */
p_logo_list
->
psz_filename
=
var_CreateGetStringCommand
(
p_filter
,
"logo-file"
);
if
(
!
p_logo_list
->
psz_filename
||
!*
p_logo_list
->
psz_filename
)
else
if
(
!
strcmp
(
psz_var
,
"logo-x"
)
)
{
msg_Err
(
p_this
,
"logo file not specified"
);
free
(
p_sys
);
free
(
p_logo_list
);
return
VLC_EGENERIC
;
p_sys
->
i_pos_x
=
newval
.
i_int
;
}
p_sys
->
posx
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-x"
);
p_sys
->
posy
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-y"
);
p_sys
->
pos
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-position"
);
p_logo_list
->
i_alpha
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-transparency"
);
p_logo_list
->
i_alpha
=
__MAX
(
__MIN
(
p_logo_list
->
i_alpha
,
255
),
0
);
p_logo_list
->
i_delay
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-delay"
);
p_logo_list
->
i_repeat
=
var_CreateGetIntegerCommand
(
p_filter
,
"logo-repeat"
);
vlc_mutex_init
(
&
p_logo_list
->
lock
);
LoadLogoList
(
p_this
,
p_logo_list
);
var_AddCallback
(
p_filter
,
"logo-file"
,
LogoCallback
,
p_sys
);
var_AddCallback
(
p_filter
,
"logo-x"
,
LogoCallback
,
p_sys
);
var_AddCallback
(
p_filter
,
"logo-y"
,
LogoCallback
,
p_sys
);
var_AddCallback
(
p_filter
,
"logo-position"
,
LogoCallback
,
p_sys
);
var_AddCallback
(
p_filter
,
"logo-transparency"
,
LogoCallback
,
p_sys
);
var_AddCallback
(
p_filter
,
"logo-repeat"
,
LogoCallback
,
p_sys
);
/* Misc init */
p_filter
->
pf_sub_filter
=
Filter
;
p_sys
->
b_need_update
=
true
;
else
if
(
!
strcmp
(
psz_var
,
"logo-y"
)
)
{
p_sys
->
i_pos_y
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
"logo-position"
)
)
{
p_sys
->
i_pos
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
"logo-transparency"
)
)
{
p_list
->
i_alpha
=
__MAX
(
__MIN
(
newval
.
i_int
,
255
),
0
);
}
else
if
(
!
strcmp
(
psz_var
,
"logo-repeat"
)
)
{
p_list
->
i_repeat
=
newval
.
i_int
;
}
p_sys
->
b_spu_update
=
true
;
vlc_mutex_unlock
(
&
p_sys
->
lock
);
return
VLC_SUCCESS
;
}
/**
***************************************************************************
*
DestroyFilter: destroy logo video filter
*
****************************************************************************
/
static
void
DestroyFilter
(
vlc_object_t
*
p_this
)
/**
*
It loads the logo image into memory.
*/
static
picture_t
*
LoadImage
(
vlc_object_t
*
p_this
,
char
*
psz_filename
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
video_format_t
fmt_in
;
video_format_Init
(
&
fmt_in
,
0
)
;
/* Delete the logo variables from INPUT */
var_Destroy
(
p_filter
->
p_libvlc
,
"logo-file"
);
var_Destroy
(
p_filter
->
p_libvlc
,
"logo-x"
);
var_Destroy
(
p_filter
->
p_libvlc
,
"logo-y"
);
var_Destroy
(
p_filter
->
p_libvlc
,
"logo-delay"
);
var_Destroy
(
p_filter
->
p_libvlc
,
"logo-repeat"
);
var_Destroy
(
p_filter
->
p_libvlc
,
"logo-position"
);
var_Destroy
(
p_filter
->
p_libvlc
,
"logo-transparency"
);
vlc_mutex_destroy
(
&
p_sys
->
p_logo_list
->
lock
);
FreeLogoList
(
p_sys
->
p_logo_list
);
free
(
p_sys
->
p_logo_list
);
free
(
p_sys
);
video_format_t
fmt_out
;
video_format_Init
(
&
fmt_out
,
VLC_CODEC_YUVA
);
image_handler_t
*
p_image
=
image_HandlerCreate
(
p_this
);
if
(
!
p_image
)
return
NULL
;
picture_t
*
p_pic
=
image_ReadUrl
(
p_image
,
psz_filename
,
&
fmt_in
,
&
fmt_out
);
image_HandlerDelete
(
p_image
);
return
p_pic
;
}
/*****************************************************************************
* Filter: the whole thing
*****************************************************************************
* This function outputs subpictures at regular time intervals.
*****************************************************************************/
static
subpicture_t
*
Filter
(
filter_t
*
p_filter
,
mtime_t
date
)
/**
* It loads the logo images into memory.
*
* Read the logo-file input switch, obtaining a list of images and associated
* durations and transparencies. Store the image(s), and times. An image
* without a stated time or transparency will use the logo-delay and
* logo-transparency values.
*/
static
void
LogoListLoad
(
vlc_object_t
*
p_this
,
logo_list_t
*
p_logo_list
)
{
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
logo_list_t
*
p_logo_list
=
p_sys
->
p_logo_list
;
subpicture_t
*
p_spu
;
subpicture_region_t
*
p_region
;
video_format_t
fmt
;
picture_t
*
p_pic
;
logo_t
*
p_logo
;
char
*
psz_list
;
/* the list: <logo>[,[<delay>[,[<alpha>]]]][;...] */
unsigned
int
i
;
logo_t
*
p_logo
;
/* the parsing's result */
vlc_mutex_lock
(
&
p_logo_list
->
lock
);
/* Basic test: b_need_update occurs on a dynamic change,
& i_next_pic is the general timer, when to
look at updating the logo image */
p_logo_list
->
i_counter
=
0
;
p_logo_list
->
i_next_pic
=
0
;
if
(
(
(
!
p_sys
->
b_need_update
)
&&
(
p_logo_list
->
i_next_pic
>
date
)
)
||
!
p_logo_list
->
i_repeat
)
psz_list
=
strdup
(
p_logo_list
->
psz_filename
);
/* Count the number logos == number of ';' + 1 */
p_logo_list
->
i_count
=
1
;
for
(
i
=
0
;
i
<
strlen
(
psz_list
);
i
++
)
{
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
return
0
;
if
(
psz_list
[
i
]
==
';'
)
p_logo_list
->
i_count
++
;
}
/* adjust index to the next logo */
p_logo_list
->
i_counter
=
(
p_logo_list
->
i_counter
+
1
)
%
p_logo_list
->
i_count
;
p_logo
=
&
p_logo_list
->
p_logo
[
p_logo_list
->
i_counter
];
p_pic
=
p_logo
->
p_pic
;
p_logo_list
->
p_logo
=
p_logo
=
calloc
(
p_logo_list
->
i_count
,
sizeof
(
*
p_logo
)
);
/* Allocate the subpicture internal data. */
p_spu
=
filter_NewSubpicture
(
p_filter
);
if
(
!
p_spu
)
/* Fill the data */
for
(
i
=
0
;
i
<
p_logo_list
->
i_count
;
i
++
)
{
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
return
NULL
;
}
char
*
p_c
=
strchr
(
psz_list
,
';'
);
char
*
p_c2
=
strchr
(
psz_list
,
','
);
p_spu
->
b_absolute
=
p_sys
->
b_absolute
;
p_spu
->
i_start
=
date
;
p_spu
->
i_stop
=
0
;
p_spu
->
b_ephemer
=
true
;
p_logo
[
i
].
i_alpha
=
-
1
;
/* use default settings */
p_logo
[
i
].
i_delay
=
-
1
;
/* use default settings */
if
(
p_c2
&&
(
p_c2
<
p_c
||
!
p_c
)
)
{
/* <logo>,<delay>[,<alpha>] type */
if
(
p_c2
[
1
]
!=
','
&&
p_c2
[
1
]
!=
';'
&&
p_c2
[
1
]
!=
'\0'
)
p_logo
[
i
].
i_delay
=
atoi
(
p_c2
+
1
);
*
p_c2
=
'\0'
;
if
(
(
p_c2
=
strchr
(
p_c2
+
1
,
','
)
)
&&
(
p_c2
<
p_c
||
!
p_c
)
&&
p_c2
[
1
]
!=
';'
&&
p_c2
[
1
]
!=
'\0'
)
p_logo
[
i
].
i_alpha
=
atoi
(
p_c2
+
1
);
}
else
{
/* <logo> type */
if
(
p_c
)
*
p_c
=
'\0'
;
}
p_sys
->
b_need_update
=
false
;
p_logo_list
->
i_next_pic
=
date
+
(
p_logo
->
i_delay
!=
-
1
?
p_logo
->
i_delay
:
p_logo_list
->
i_delay
)
*
1000
;
p_logo
[
i
].
psz_file
=
strdup
(
psz_list
);
p_logo
[
i
].
p_pic
=
LoadImage
(
p_this
,
p_logo
[
i
].
psz_file
);
if
(
p_logo_list
->
i_repeat
!=
-
1
&&
p_logo_list
->
i_counter
==
0
)
{
p_logo_list
->
i_repeat
--
;
if
(
p_logo_list
->
i_repeat
==
0
)
if
(
!
p_logo
[
i
].
p_pic
)
{
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
return
p_spu
;
msg_Warn
(
p_this
,
"error while loading logo %s, will be skipped"
,
p_logo
[
i
].
psz_file
)
;
}
}
if
(
!
p_pic
||
!
p_logo
->
i_alpha
||
(
p_logo
->
i_alpha
==
-
1
&&
!
p_logo_list
->
i_alpha
)
)
{
/* Send an empty subpicture to clear the display */
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
return
p_spu
;
if
(
p_c
)
psz_list
=
&
p_c
[
1
];
}
/* Create new SPU region */
memset
(
&
fmt
,
0
,
sizeof
(
video_format_t
)
);
fmt
.
i_chroma
=
VLC_CODEC_YUVA
;
fmt
.
i_aspect
=
VOUT_ASPECT_FACTOR
;
fmt
.
i_sar_num
=
fmt
.
i_sar_den
=
1
;
fmt
.
i_width
=
fmt
.
i_visible_width
=
p_pic
->
p
[
Y_PLANE
].
i_visible_pitch
;
fmt
.
i_height
=
fmt
.
i_visible_height
=
p_pic
->
p
[
Y_PLANE
].
i_visible_lines
;
fmt
.
i_x_offset
=
fmt
.
i_y_offset
=
0
;
p_region
=
subpicture_region_New
(
&
fmt
);
if
(
!
p_region
)
for
(
i
=
0
;
i
<
p_logo_list
->
i_count
;
i
++
)
{
msg_Err
(
p_filter
,
"cannot allocate SPU region"
);
p_filter
->
pf_sub_buffer_del
(
p_filter
,
p_spu
);
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
return
NULL
;
}
/* FIXME the copy is probably not needed anymore */
picture_Copy
(
p_region
->
p_picture
,
p_pic
);
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
/* where to locate the logo: */
if
(
p_sys
->
pos
<
0
)
{
/* set to an absolute xy */
p_region
->
i_align
=
OSD_ALIGN_RIGHT
|
OSD_ALIGN_TOP
;
p_spu
->
b_absolute
=
true
;
}
else
{
/* set to one of the 9 relative locations */
p_region
->
i_align
=
p_sys
->
pos
;
p_spu
->
b_absolute
=
false
;
msg_Dbg
(
p_this
,
"logo file name %s, delay %d, alpha %d"
,
p_logo
[
i
].
psz_file
,
p_logo
[
i
].
i_delay
,
p_logo
[
i
].
i_alpha
);
}
p_region
->
i_x
=
p_sys
->
posx
;
p_region
->
i_y
=
p_sys
->
posy
;
/* initialize so that on the first update it will wrap back to 0 */
p_logo_list
->
i_counter
=
p_logo_list
->
i_count
-
1
;
}
p_spu
->
p_region
=
p_region
;
/**
* Unload a list of logo and release associated ressources.
*/
static
void
LogoListUnload
(
logo_list_t
*
p_list
)
{
free
(
p_list
->
psz_filename
);
p_spu
->
i_alpha
=
(
p_logo
->
i_alpha
!=
-
1
?
p_logo
->
i_alpha
:
p_logo_list
->
i_alpha
);
for
(
unsigned
i
=
0
;
i
<
p_list
->
i_count
;
i
++
)
{
logo_t
*
p_logo
=
&
p_list
->
p_logo
[
i
];
return
p_spu
;
free
(
p_logo
->
psz_file
);
if
(
p_logo
->
p_pic
)
{
picture_Release
(
p_logo
->
p_pic
);
p_logo
->
p_pic
=
NULL
;
}
}
}
/*****************************************************************************
* Callback to update params on the fly
*****************************************************************************/
static
int
LogoCallback
(
vlc_object_t
*
p_this
,
char
const
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
/**
* Go to the next logo and return its pointer.
*/
static
logo_t
*
LogoListNext
(
logo_list_t
*
p_list
,
mtime_t
i_date
)
{
VLC_UNUSED
(
oldval
);
filter_sys_t
*
p_sys
=
(
filter_sys_t
*
)
p_data
;
logo_list_t
*
p_logo_list
=
p_sys
->
p_logo_list
;
p_list
->
i_counter
=
(
p_list
->
i_counter
+
1
)
%
p_list
->
i_count
;
if
(
!
strcmp
(
psz_var
,
"logo-file"
)
)
{
vlc_mutex_lock
(
&
p_logo_list
->
lock
);
FreeLogoList
(
p_logo_list
);
p_logo_list
->
psz_filename
=
strdup
(
newval
.
psz_string
);
LoadLogoList
(
p_this
,
p_logo_list
);
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
}
else
if
(
!
strcmp
(
psz_var
,
"logo-x"
)
)
{
p_sys
->
posx
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
"logo-y"
)
)
{
p_sys
->
posy
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
"logo-position"
)
)
{
p_sys
->
pos
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
"logo-transparency"
)
)
{
vlc_mutex_lock
(
&
p_logo_list
->
lock
);
p_logo_list
->
i_alpha
=
__MAX
(
__MIN
(
newval
.
i_int
,
255
),
0
);
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
}
else
if
(
!
strcmp
(
psz_var
,
"logo-repeat"
)
)
{
vlc_mutex_lock
(
&
p_logo_list
->
lock
);
p_logo_list
->
i_repeat
=
newval
.
i_int
;
vlc_mutex_unlock
(
&
p_logo_list
->
lock
);
}
p_sys
->
b_need_update
=
true
;
return
VLC_SUCCESS
;
logo_t
*
p_logo
=
LogoListCurrent
(
p_list
);
p_list
->
i_next_pic
=
i_date
+
(
p_logo
->
i_delay
!=
-
1
?
p_logo
->
i_delay
:
p_list
->
i_delay
)
*
1000
;
return
p_logo
;
}
/**
* Return the current logo pointer
*/
static
logo_t
*
LogoListCurrent
(
logo_list_t
*
p_list
)
{
return
&
p_list
->
p_logo
[
p_list
->
i_counter
];
}
modules/video_filter/wrapper.c
View file @
86afb29f
...
...
@@ -48,6 +48,7 @@ static void Close( vlc_object_t * );
DECLARE_OPEN
(
magnify
)
DECLARE_OPEN
(
puzzle
)
DECLARE_OPEN
(
logo
)
#undef DECLARE_OPEN
...
...
@@ -67,6 +68,9 @@ vlc_module_begin()
add_submodule
()
DECLARE_MODULE
(
puzzle
)
add_submodule
()
DECLARE_MODULE
(
logo
)
vlc_module_end
()
#undef DECLARE_MODULE
...
...
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