[vlc-devel] [PATCH 01/10] Enable secondary SPU ES and selection from the GUI

Roland Bewick roland.bewick at gmail.com
Sun May 5 12:17:05 CEST 2019


On 5/05/2019 5:01 PM, Roland Bewick wrote:
> Secondary subtitles will show directly above or below primary subtitles.
>
> Currently only QT supported (See change in input_models.cpp)
> ---
>   include/vlc_player.h                 | 13 ++++++++
>   modules/gui/qt/util/input_models.cpp |  6 ++++
>   src/input/es_out.c                   | 47 ++++++++++++++++++++++++++--
>   src/input/es_out.h                   |  5 ++-
>   src/input/input.c                    |  5 +++
>   src/input/input_internal.h           |  1 +
>   src/input/player.c                   | 11 +++++++
>   src/libvlccore.sym                   |  1 +
>   8 files changed, 86 insertions(+), 3 deletions(-)
>
> diff --git a/include/vlc_player.h b/include/vlc_player.h
> index 17e927c948..f1f43b7478 100644
> --- a/include/vlc_player.h
> +++ b/include/vlc_player.h
> @@ -2429,6 +2429,19 @@ vlc_player_SetSubtitleTextScale(vlc_player_t *player, unsigned scale);
>   VLC_API unsigned
>   vlc_player_GetSubtitleTextScale(vlc_player_t *player);
>   
> +/**
> + * Set whether to select a subtitle as secondary (Dual subtitles)
> + *
> + * @note This function allows a user to select a secondary subtitle from
> + * the GUI. Immediately after selecting a secondary subtitle track this
> + * should be returned to false.
> + *
> + * @param player locked player instance
> + * @param select true to select a secondary subtitle
> + */
> +VLC_API void
> +vlc_player_SetSelectSecondarySubtitle(vlc_player_t *player, bool select);
> +
>   /**
>    * Get the signal quality and strength of the current media
>    *
> diff --git a/modules/gui/qt/util/input_models.cpp b/modules/gui/qt/util/input_models.cpp
> index e381fbb917..b480171b5c 100644
> --- a/modules/gui/qt/util/input_models.cpp
> +++ b/modules/gui/qt/util/input_models.cpp
> @@ -62,7 +62,13 @@ bool TrackListModel::setData(const QModelIndex &index, const QVariant &value, in
>       vlc_player_locker lock{ m_player };
>   
>       if (select)
> +    {
> +        /* Only allow secondary subtitles to be manually selected
> +        by the user through the GUI. */
> +        vlc_player_SetSelectSecondarySubtitle(m_player, true);
>           vlc_player_SelectTrack(m_player, m_data[row].m_id.get());
> +        vlc_player_SetSelectSecondarySubtitle(m_player, false);
> +    }
>       else
>           vlc_player_UnselectTrack(m_player, m_data[row].m_id.get());
>       return true;
> diff --git a/src/input/es_out.c b/src/input/es_out.c
> index 3352602849..78d0d3330b 100644
> --- a/src/input/es_out.c
> +++ b/src/input/es_out.c
> @@ -208,6 +208,9 @@ typedef struct
>       /* Used only to limit debugging output */
>       int         i_prev_stream_level;
>   
> +    /* Used to temporarily allow dual subtitle selection */
> +    bool        b_select_secondary_subtitle;
> +
>       es_out_t out;
>   } es_out_sys_t;
>   
> @@ -2029,6 +2032,24 @@ static void EsOutUnselectEs( es_out_t *out, es_out_id_t *es, bool b_update )
>       EsOutSendEsEvent(out, es, VLC_INPUT_ES_UNSELECTED);
>   }
>   
> +/**
> + * Count the number of selected ES of the given category
> + * \param i_cat the ES category (e.g. SPU_ES)
> + * \return count
> + */
> +static int EsOutCountSelected( es_out_sys_t *p_sys,
> +                               enum es_format_category_e i_cat )
> +{
> +    int i_selected_count = 0;
> +    es_out_id_t *other;
> +    foreach_es_then_es_slaves(other)
> +        if( other->fmt.i_cat == i_cat && EsIsSelected( other ) )
> +        {
> +            ++i_selected_count;
> +        }
> +    return i_selected_count;
> +}
> +
>   /**
>    * Select an ES given the current mode
>    * XXX: you need to take a the lock before (stream.stream_lock)
> @@ -2049,9 +2070,24 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
>           return;
>       }
>   
> +    /* Select secondary if the user has already selected a primary sub track */
> +    bool b_select_secondary_subtitle = es->fmt.i_cat == SPU_ES &&
> +                               p_sys->b_select_secondary_subtitle &&
> +                               p_esprops->p_main_es != NULL &&
> +                               EsIsSelected(p_esprops->p_main_es);
> +
> +    if ( b_select_secondary_subtitle &&
> +         EsOutCountSelected( p_sys, es->fmt.i_cat ) > 1 )
> +    {
> +        /* Don't allow more than one secondary SPU ES selected at a time. */
> +        EsOutSendEsEvent(out, es, VLC_INPUT_ES_UNSELECTED);
> +        return;
> +    }
> +
>       bool b_auto_unselect = p_esprops && p_sys->i_mode == ES_OUT_MODE_AUTO &&
>                              p_esprops->e_policy == ES_OUT_ES_POLICY_EXCLUSIVE &&
> -                           p_esprops->p_main_es && p_esprops->p_main_es != es;
> +                           p_esprops->p_main_es && p_esprops->p_main_es != es &&
> +                           !b_select_secondary_subtitle;
>   
>       if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
>       {
> @@ -2171,7 +2207,8 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
>       }
>   
>       /* FIXME TODO handle priority here */
> -    if( p_esprops && p_sys->i_mode == ES_OUT_MODE_AUTO && EsIsSelected( es ) )
> +    if( p_esprops && p_sys->i_mode == ES_OUT_MODE_AUTO && EsIsSelected( es ) &&
> +        !b_select_secondary_subtitle )
>           p_esprops->p_main_es = es;
>   }
>   
> @@ -3181,6 +3218,12 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
>           }
>           return ret;
>       }
> +    case ES_OUT_SET_SELECT_SECONDARY_SUBTITLE:
> +    {
> +        es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
> +        p_sys->b_select_secondary_subtitle = va_arg( args, int );
> +        return VLC_SUCCESS;
> +    }
>       default:
>           msg_Err( p_sys->p_input, "unknown query 0x%x in %s", i_query,
>                    __func__  );
> diff --git a/src/input/es_out.h b/src/input/es_out.h
> index 7cbea71728..42b7d0152a 100644
> --- a/src/input/es_out.h
> +++ b/src/input/es_out.h
> @@ -89,7 +89,10 @@ enum es_out_query_private_e
>       ES_OUT_SET_VBI_PAGE,                            /* arg1=unsigned res=can fail */
>   
>       /* Set VBI/Teletext menu transparent */
> -    ES_OUT_SET_VBI_TRANSPARENCY                     /* arg1=bool res=can fail */
> +    ES_OUT_SET_VBI_TRANSPARENCY,                    /* arg1=bool res=can fail */
> +
> +    /* Set to select a secondary SPU ES instead of the primary one */
> +    ES_OUT_SET_SELECT_SECONDARY_SUBTITLE            /* arg1=bool res=cannot fail */
>   };
>   
>   static inline void es_out_SetMode( es_out_t *p_out, int i_mode )
> diff --git a/src/input/input.c b/src/input/input.c
> index 506e269ecc..0965800f90 100644
> --- a/src/input/input.c
> +++ b/src/input/input.c
> @@ -2397,6 +2397,11 @@ static bool Control( input_thread_t *p_input,
>                               param.vbi_transparency.id,
>                               param.vbi_transparency.enabled );
>               break;
> +        case INPUT_CONTROL_SET_SELECT_SECONDARY_SUBTITLE:
> +             es_out_Control( priv->p_es_out_display,
> +                             ES_OUT_SET_SELECT_SECONDARY_SUBTITLE,
> +                             param.val.b_bool );
> +             break;
>   
>           case INPUT_CONTROL_NAV_ACTIVATE:
>           case INPUT_CONTROL_NAV_UP:
> diff --git a/src/input/input_internal.h b/src/input/input_internal.h
> index 18495881c2..0cd8484ca8 100644
> --- a/src/input/input_internal.h
> +++ b/src/input/input_internal.h
> @@ -268,6 +268,7 @@ enum input_control_e
>   
>       INPUT_CONTROL_SET_VBI_PAGE,
>       INPUT_CONTROL_SET_VBI_TRANSPARENCY,
> +    INPUT_CONTROL_SET_SELECT_SECONDARY_SUBTITLE,
>   };
>   
>   /* Internal helpers */
> diff --git a/src/input/player.c b/src/input/player.c
> index da74eb4ee4..977fc95d94 100644
> --- a/src/input/player.c
> +++ b/src/input/player.c
> @@ -2886,6 +2886,17 @@ vlc_player_SetSubtitleSync(vlc_player_t *player,
>       }
>   }
>   
> +void
> +vlc_player_SetSelectSecondarySubtitle(vlc_player_t *player, bool select)
> +{
> +    struct vlc_player_input *input = vlc_player_get_input_locked(player);
> +    if (!input)
> +        return;
> +    input_ControlPushHelper(input->thread,
> +                            INPUT_CONTROL_SET_SELECT_SECONDARY_SUBTITLE,
> +                            &(vlc_value_t){ .b_bool = select });
> +}
> +
>   vlc_tick_t
>   vlc_player_GetSubtitleDelay(vlc_player_t *player)
>   {
> diff --git a/src/libvlccore.sym b/src/libvlccore.sym
> index ed5e1ee661..403375678e 100644
> --- a/src/libvlccore.sym
> +++ b/src/libvlccore.sym
> @@ -908,6 +908,7 @@ vlc_player_SetStartPaused
>   vlc_player_SetSubtitleDelay
>   vlc_player_SetSubtitleSync
>   vlc_player_SetSubtitleTextScale
> +vlc_player_SetSelectSecondarySubtitle
>   vlc_player_SetTeletextEnabled
>   vlc_player_SetTeletextTransparency
>   vlc_player_SetTrackCategoryEnabled

This set of patches is regarding the feedback I received from my initial 
patch to support dual subtitles in VLC.

I've changed how the secondary SPU ES is selected and how the alignment 
is set without having to touch individual decoders.

I've added configuration for the secondary subtitles (enable, alignment 
and margin). Dual subtitles are disabled by default.

I added a new hotkey (toggle) which allows you to use the existing 
subtitle controls to control the secondary subtitles.

I also adjusted the QT GUI synchronization to allow users to set the 
secondary subtitle delay from the GUI.

Unfortunately I don't have access to a mac, but hopefully the hotkeys 
should suffice until the mac GUI can also be updated.

If you have any questions or suggestions, please let me know.

Thanks,

Roland Bewick



More information about the vlc-devel mailing list