[vlc-devel] [PATCH 09/14] Hotkey support for secondary subtitles (Part 1)
Roland Bewick
roland.bewick at gmail.com
Sat May 11 08:32:13 CEST 2019
- Toggle control of primary/secondary subtitles
- Adjust Secondary subtitle margin
(NB: Margin is only applied the first time the subtitle is rendered.)
---
include/vlc_actions.h | 2 ++
include/vlc_spu.h | 9 +++++++
modules/control/hotkeys.c | 23 ++++++++++++++--
src/input/player.c | 7 +++--
src/libvlc-module.c | 6 +++++
src/misc/actions.c | 1 +
src/video_output/video_output.c | 4 +--
src/video_output/vout_internal.h | 4 +--
src/video_output/vout_intf.c | 22 +++++++++++++++-
src/video_output/vout_subpictures.c | 52 +++++++++++++++++++++----------------
10 files changed, 99 insertions(+), 31 deletions(-)
diff --git a/include/vlc_actions.h b/include/vlc_actions.h
index 62f0afae53..e8e2224c80 100644
--- a/include/vlc_actions.h
+++ b/include/vlc_actions.h
@@ -191,6 +191,8 @@ typedef enum vlc_action_id {
ACTIONID_SUBDELAY_UP,
/* subtitle toggle */
ACTIONID_SUBTITLE_TOGGLE,
+ /* dual subtitle control */
+ ACTIONID_SUBTITLE_CONTROL_SECONDARY,
/* subtitle sync */
ACTIONID_SUBSYNC_MARKAUDIO,
ACTIONID_SUBSYNC_MARKSUB,
diff --git a/include/vlc_spu.h b/include/vlc_spu.h
index ee6c68f784..92bce26506 100644
--- a/include/vlc_spu.h
+++ b/include/vlc_spu.h
@@ -31,6 +31,15 @@
extern "C" {
#endif
+/* How many SPU tracks can be selected at once. */
+#define SPU_MAX_CLOCKS 2
+
+/* ID of the primary SPU */
+#define SPU_ID_PRIMARY 1
+
+/* In the future we may support more than one secondary sub track */
+#define SPU_ID_SECONDARY_START 2
+
/**
* \defgroup spu Sub-picture channels
* \ingroup video_output
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index b81debb4ea..45065d1b07 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -36,6 +36,7 @@
#include <vlc_player.h>
#include <vlc_playlist.h>
#include <vlc_actions.h>
+#include <vlc_spu.h>
#include "math.h"
struct intf_sys_t
@@ -51,6 +52,9 @@ struct intf_sys_t
static void handle_action(intf_thread_t *, vlc_action_id_t);
+/* Use standard subtitle hotkeys to control a selected sub track */
+static int i_control_spu_id = SPU_ID_PRIMARY;
+
/*****************************
* interface action handling *
*****************************/
@@ -447,6 +451,17 @@ PLAYER_ACTION_HANDLER(ToggleSubtitle)
vlc_player_ToggleSubtitle(player);
}
+PLAYER_ACTION_HANDLER(ControlSubtitleSecondary)
+{
+ VLC_UNUSED(action_id);
+
+ if (++i_control_spu_id > SPU_MAX_CLOCKS)
+ i_control_spu_id = SPU_ID_PRIMARY;
+
+ vlc_player_vout_OSDMessage(player, _("%s subtitle control"),
+ i_control_spu_id > SPU_ID_PRIMARY ? "Secondary" : "Primary");
+}
+
PLAYER_ACTION_HANDLER(SyncSubtitle)
{
switch (action_id)
@@ -762,13 +777,15 @@ VOUT_ACTION_HANDLER(Deinterlace)
VOUT_ACTION_HANDLER(SubtitleDisplay)
{
+ const char* psz_sub_margin = i_control_spu_id > SPU_ID_PRIMARY ?
+ "secondary-sub-margin" : "sub-margin";
switch (action_id)
{
case ACTIONID_SUBPOS_DOWN:
- var_DecInteger(vout, "sub-margin");
+ var_DecInteger(vout, psz_sub_margin);
break;
case ACTIONID_SUBPOS_UP:
- var_IncInteger(vout, "sub-margin");
+ var_IncInteger(vout, psz_sub_margin);
break;
default:
{
@@ -858,6 +875,8 @@ static struct vlc_action const actions[] =
VLC_ACTION_PLAYER(AUDIODELAY_DOWN, SUBDELAY_UP, Delay, true)
VLC_ACTION_PLAYER(RATE_NORMAL, RATE_FASTER_FINE, Rate, true)
VLC_ACTION_PLAYER(SUBTITLE_TOGGLE, SUBTITLE_TOGGLE, ToggleSubtitle, true)
+ VLC_ACTION_PLAYER(SUBTITLE_CONTROL_SECONDARY, SUBTITLE_CONTROL_SECONDARY,
+ ControlSubtitleSecondary, true)
VLC_ACTION_PLAYER(SUBSYNC_MARKAUDIO, SUBSYNC_RESET, SyncSubtitle, true)
VLC_ACTION_PLAYER(NAV_ACTIVATE, NAV_RIGHT, Navigate, true)
VLC_ACTION_PLAYER(VIEWPOINT_FOV_IN, VIEWPOINT_ROLL_ANTICLOCK, Viewpoint, true)
diff --git a/src/input/player.c b/src/input/player.c
index 47298e9fcd..626bb4c721 100644
--- a/src/input/player.c
+++ b/src/input/player.c
@@ -1793,10 +1793,10 @@ vlc_player_input_HandleVoutEvent(struct vlc_player_input *input,
{
assert(ev->vout);
- static const char osd_vars[][sizeof("deinterlace-mode")] = {
+ static const char osd_vars[][sizeof("secondary-sub-margin")] = {
"aspect-ratio", "autoscale", "crop", "crop-bottom",
"crop-top", "crop-left", "crop-right", "deinterlace",
- "deinterlace-mode", "sub-margin", "zoom"
+ "deinterlace-mode", "sub-margin", "secondary-sub-margin", "zoom"
};
vlc_player_t *player = input->player;
@@ -3312,6 +3312,9 @@ vlc_player_VoutOSDCallback(vlc_object_t *this, const char *var,
else if (strcmp(var, "sub-margin") == 0)
vouts_osd_Message(&vout, 1, _("Subtitle position %d px"), newval.i_int);
+ else if (strcmp(var, "secondary-sub-margin") == 0)
+ vouts_osd_Message(&vout, 1, _("Secondary subtitle position %d px"), newval.i_int);
+
else if (strcmp(var, "sub-text-scale") == 0)
vouts_osd_Message(&vout, 1, _("Subtitle text scale %d%%"), newval.i_int);
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index aef485b45a..6c3d44b2cb 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -1454,6 +1454,8 @@ static const char *const mouse_wheel_texts[] = {
#define SUBTITLE_TRACK_KEY_LONGTEXT N_("Cycle through the available subtitle tracks.")
#define SUBTITLE_TOGGLE_KEY_TEXT N_("Toggle subtitles")
#define SUBTITLE_TOGGLE_KEY_LONGTEXT N_("Toggle subtitle track visibility.")
+#define SUBTITLE_CONTROL_SECONDARY_KEY_TEXT N_("Toggle secondary subtitle control")
+#define SUBTITLE_CONTROL_SECONDARY_KEY_LONGTEXT N_("Use original subtitle controls to manage secondary subtitles.")
#define PROGRAM_SID_NEXT_KEY_TEXT N_("Cycle next program Service ID")
#define PROGRAM_SID_NEXT_KEY_LONGTEXT N_("Cycle through the available next program Service IDs (SIDs).")
#define PROGRAM_SID_PREV_KEY_TEXT N_("Cycle previous program Service ID")
@@ -2351,6 +2353,7 @@ vlc_module_begin ()
# define KEY_AUDIO_TRACK "l"
# define KEY_SUBTITLE_TRACK "s"
# define KEY_SUBTITLE_TOGGLE "Shift+s"
+# define KEY_SUBTITLE_CONTROL_S "Command+Shift+v"
# define KEY_SUBTITLE_REVTRACK "Alt+s"
# define KEY_PROGRAM_SID_NEXT "x"
# define KEY_PROGRAM_SID_PREV "Shift+x"
@@ -2494,6 +2497,7 @@ vlc_module_begin ()
# define KEY_AUDIO_TRACK "b"
# define KEY_SUBTITLE_TRACK "v"
# define KEY_SUBTITLE_TOGGLE "Shift+v"
+# define KEY_SUBTITLE_CONTROL_S "Ctrl+Shift+v"
# define KEY_SUBTITLE_REVTRACK "Alt+v"
# define KEY_PROGRAM_SID_NEXT "x"
# define KEY_PROGRAM_SID_PREV "Shift+x"
@@ -2663,6 +2667,8 @@ vlc_module_begin ()
SUBTITLE_TRACK_KEY_TEXT, SUBTITLE_TRACK_KEY_LONGTEXT)
add_key("key-subtitle-toggle", KEY_SUBTITLE_TOGGLE,
SUBTITLE_TOGGLE_KEY_TEXT, SUBTITLE_TOGGLE_KEY_LONGTEXT)
+ add_key("key-subtitle-control-secondary", KEY_SUBTITLE_CONTROL_S,
+ SUBTITLE_CONTROL_SECONDARY_KEY_TEXT, SUBTITLE_CONTROL_SECONDARY_KEY_LONGTEXT)
add_key("key-program-sid-next", KEY_PROGRAM_SID_NEXT,
PROGRAM_SID_NEXT_KEY_TEXT, PROGRAM_SID_NEXT_KEY_LONGTEXT)
add_key("key-program-sid-prev", KEY_PROGRAM_SID_PREV,
diff --git a/src/misc/actions.c b/src/misc/actions.c
index e10eb94790..b6e76e75d9 100644
--- a/src/misc/actions.c
+++ b/src/misc/actions.c
@@ -347,6 +347,7 @@ static const struct name2action
{ "subsync-markaudio", ACTIONID_SUBSYNC_MARKAUDIO, },
{ "subsync-marksub", ACTIONID_SUBSYNC_MARKSUB, },
{ "subsync-reset", ACTIONID_SUBSYNC_RESET, },
+ { "subtitle-control-secondary", ACTIONID_SUBTITLE_CONTROL_SECONDARY, },
{ "subtitle-revtrack", ACTIONID_SUBTITLE_REVERSE_TRACK, },
{ "subtitle-text-scale-down", ACTIONID_SUBTITLE_TEXT_SCALE_DOWN, },
{ "subtitle-text-scale-normal", ACTIONID_SUBTITLE_TEXT_SCALE_NORMAL, },
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 1c8747e6d3..e50140f1b5 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -606,14 +606,14 @@ void vout_ControlChangeSubFilters(vout_thread_t *vout, const char *filters)
vlc_mutex_unlock(&vout->p->spu_lock);
}
-void vout_ChangeSubMargin(vout_thread_t *vout, int margin)
+void vout_ChangeSubMargin(vout_thread_t *vout, int margin, int spu_id)
{
assert(!vout->p->dummy);
if (unlikely(vout->p->spu == NULL))
return;
vlc_mutex_lock(&vout->p->spu_lock);
- spu_ChangeMargin(vout->p->spu, margin);
+ spu_ChangeMargin(vout->p->spu, margin, spu_id);
vlc_mutex_unlock(&vout->p->spu_lock);
}
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index d60cf7e19b..38e4fc6cf4 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -244,7 +244,7 @@ void vout_ChangeCropBorder(vout_thread_t *, int left, int top, int right, int bo
void vout_ControlChangeFilters(vout_thread_t *, const char *);
void vout_ControlChangeSubSources(vout_thread_t *, const char *);
void vout_ControlChangeSubFilters(vout_thread_t *, const char *);
-void vout_ChangeSubMargin(vout_thread_t *, int);
+void vout_ChangeSubMargin(vout_thread_t *, int, int);
void vout_ChangeViewpoint( vout_thread_t *, const vlc_viewpoint_t *);
/* */
@@ -269,7 +269,7 @@ void spu_clock_Add(spu_t *, vlc_clock_t *);
void spu_clock_Remove(spu_t *, vlc_clock_t *);
void spu_clock_ResetAll(spu_t *);
void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay, vlc_clock_t *clock);
-void spu_ChangeMargin(spu_t *, int);
+void spu_ChangeMargin(spu_t *, int, int);
void spu_SetHighlight(spu_t *, const vlc_spu_highlight_t*);
/**
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index 238e0c44da..f67ff2cef8 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -41,6 +41,7 @@
#include <vlc_vout_osd.h>
#include <vlc_strings.h>
#include <vlc_charset.h>
+#include <vlc_spu.h>
#include "vout_internal.h"
#include "snapshot.h"
@@ -74,6 +75,8 @@ static int SubFilterCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int SubMarginCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
+static int SecondarySubMarginCallback( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
static int ViewpointCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
@@ -265,6 +268,11 @@ void vout_CreateVars( vout_thread_t *p_vout )
var_Create( p_vout, "sub-margin",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
+ /* Add secondary-sub-margin variable (dual subtitles) */
+ var_Create( p_vout, "secondary-sub-margin",
+ VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
+ var_AddCallback( p_vout, "secondary-sub-margin", SecondarySubMarginCallback, NULL );
+
/* Mouse coordinates */
var_Create( p_vout, "mouse-button-down", VLC_VAR_INTEGER );
var_Create( p_vout, "mouse-moved", VLC_VAR_COORDS );
@@ -308,12 +316,14 @@ void vout_IntfReinit( vout_thread_t *p_vout )
var_TriggerCallback( p_vout, "sub-source" );
var_TriggerCallback( p_vout, "sub-filter" );
var_TriggerCallback( p_vout, "sub-margin" );
+ var_TriggerCallback( p_vout, "secondary-sub-margin" );
}
void vout_IntfDeinit(vlc_object_t *obj)
{
var_DelCallback(obj, "viewpoint", ViewpointCallback, NULL);
var_DelCallback(obj, "sub-margin", SubMarginCallback, NULL);
+ var_DelCallback(obj, "secondary-sub-margin", SecondarySubMarginCallback, NULL);
var_DelCallback(obj, "sub-filter", SubFilterCallback, NULL);
var_DelCallback(obj, "sub-source", SubSourceCallback, NULL);
var_DelCallback(obj, "video-filter", VideoFilterCallback, NULL);
@@ -609,7 +619,17 @@ static int SubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
- vout_ChangeSubMargin(p_vout, newval.i_int);
+ vout_ChangeSubMargin(p_vout, newval.i_int, SPU_ID_PRIMARY);
+ return VLC_SUCCESS;
+}
+
+static int SecondarySubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data)
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
+
+ vout_ChangeSubMargin(p_vout, newval.i_int, SPU_ID_SECONDARY_START);
return VLC_SUCCESS;
}
diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
index 4050e9ea09..51bb97b8a9 100644
--- a/src/video_output/vout_subpictures.c
+++ b/src/video_output/vout_subpictures.c
@@ -52,13 +52,6 @@
/* Number of simultaneous subpictures */
#define VOUT_MAX_SUBPICTURES (__MAX(VOUT_MAX_PICTURES, SPU_MAX_PREPARE_TIME/5000))
-/* ID of the primary SPU. Secondary SPU IDs will be higher. */
-#define SPU_ID_PRIMARY 1
-
-/* How many SPU clocks can be used simultaneously. Secondary
- SPUs may have different delay therefore require their own clock. */
-#define SPU_MAX_CLOCKS 2
-
/* Hold of subpicture with converted ts */
typedef struct {
subpicture_t *subpicture;
@@ -83,6 +76,15 @@ struct spu_private_t {
vlc_clock_t *clocks[SPU_MAX_CLOCKS]; /* one for each selected sub track */
vlc_tick_t delays[SPU_MAX_CLOCKS]; /* delays applied to clocks above */
+ /* Force alignment for secondary subs */
+ int secondary_sub_alignment[SPU_MAX_CLOCKS - 1];
+
+ /* Move the secondary subtites vertically.
+ * Note: Primary sub margin is applied to all sub tracks and is absolute.
+ * Secondary sub margin is not absolute to enable overlap detection.
+ */
+ atomic_int secondary_sub_margin[SPU_MAX_CLOCKS - 1];
+
spu_heap_t heap;
int channel; /**< number of subpicture channels registered */
@@ -100,9 +102,6 @@ struct spu_private_t {
atomic_int margin; /**< force position of a subpicture */
video_palette_t palette; /**< force palette of subpicture */
- int secondary_sub_alignment; /**< force alignment for secondary subs */
- int secondary_sub_margin; /**< move the secondary sub vertically */
-
/* Subpiture filters */
char *source_chain_current;
char *source_chain_update;
@@ -481,12 +480,8 @@ static void SpuAreaFitInside(spu_area_t *area, const spu_area_t *boundary)
static void SpuRegionPlace(int *x, int *y,
const subpicture_t *subpic,
const subpicture_region_t *region,
- int i_secondary_spu_align_override)
+ int i_align)
{
- int i_align = region->i_align;
- if (subpic->i_spu_id > SPU_ID_PRIMARY && i_secondary_spu_align_override >= 0)
- i_align = i_secondary_spu_align_override;
-
assert(region->i_x != INT_MAX && region->i_y != INT_MAX);
if (subpic->b_absolute) {
*x = region->i_x;
@@ -833,14 +828,23 @@ static void SpuRenderRegion(spu_t *spu,
/* Place the picture
* We compute the position in the rendered size */
+
+ int i_align = region->i_align;
+ if (subpic->i_spu_id > SPU_ID_PRIMARY)
+ {
+ int i_align_override = sys->secondary_sub_alignment[subpic->i_spu_id - SPU_ID_SECONDARY_START];
+ i_align = i_align_override >= 0 ? i_align_override : i_align;
+ }
+
SpuRegionPlace(&x_offset, &y_offset,
- subpic, region, sys->secondary_sub_alignment);
+ subpic, region, i_align);
if (subpic->i_spu_id > SPU_ID_PRIMARY && !subpic->b_absolute)
{
/* Move the secondary subtitles by the secondary margin before overlap detection.
This way, overlaps will be resolved if they still exist. */
- y_offset -= spu_invscale_h(atomic_load(&sys->secondary_sub_margin), scale_size);
+ int secondary_margin = atomic_load(&sys->secondary_sub_margin[subpic->i_spu_id - SPU_ID_SECONDARY_START]);
+ y_offset -= spu_invscale_h(secondary_margin, scale_size);
}
/* Save this position for subtitle overlap support
@@ -853,7 +857,7 @@ static void SpuRenderRegion(spu_t *spu,
/* Handle overlapping subtitles when possible */
if (subpic->b_subtitle && !subpic->b_absolute)
SpuAreaFixOverlap(dst_area, subtitle_area, subtitle_area_count,
- region->i_align);
+ i_align);
/* we copy the area: for the subtitle overlap support we want
* to only save the area without margin applied */
@@ -1446,10 +1450,10 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
sys->scale_yuvp = NULL;
atomic_init(&sys->margin, var_InheritInteger(spu, "sub-margin"));
- atomic_init(&sys->secondary_sub_margin,
+ atomic_init(&sys->secondary_sub_margin[0],
var_InheritInteger(spu, "secondary-sub-margin"));
- sys->secondary_sub_alignment = var_InheritInteger(spu,
+ sys->secondary_sub_alignment[0] = var_InheritInteger(spu,
"secondary-spu-alignment");
/* Register the default subpicture channel */
@@ -1913,11 +1917,15 @@ void spu_ChangeFilters(spu_t *spu, const char *filters)
vlc_mutex_unlock(&sys->lock);
}
-void spu_ChangeMargin(spu_t *spu, int margin)
+void spu_ChangeMargin(spu_t *spu, int margin, int spu_id)
{
spu_private_t *sys = spu->p;
- atomic_store(&sys->margin, margin);
+ if (spu_id == SPU_ID_PRIMARY)
+ atomic_store(&sys->margin, margin);
+ else
+ atomic_store(&sys->secondary_sub_margin[spu_id - SPU_ID_SECONDARY_START],
+ margin);
}
void spu_SetHighlight(spu_t *spu, const vlc_spu_highlight_t *hl)
--
2.11.0
More information about the vlc-devel
mailing list