[vlc-devel] [PATCH 01/15] Enable selection of secondary SPU ES in the core
Thomas Guillem
thomas at gllm.fr
Fri May 17 10:16:43 CEST 2019
On Thu, May 16, 2019, at 15:40, Roland Bewick wrote:
> Hi,
>
> I've chosen the following implementation for vlc_player_SelectTrackList:
> 1. Deselect all selected tracks not matching the provided list.
> 2. Sequentially select the tracks that aren't already selected.
>
> When a track is selected in the QT GUI, I check the category of the track.
> - If Not SPU_ES, use vlc_player_SelectTrack as usual.
> - If SPU_ES:
> 1. find which tracks are already selected by looping through all
> tracks of the same category
> 2. If more than one track is already selected, do not proceed with
> the selection
> 3. Call vlc_player_SelectTrackList using the ids of the new track
> and the already selected tracks
>
> To ensure that multiple tracks get selected in the core (es_out.c) I've
> added a new parameter to EsOutSelect.
Fine wih me, that is what I had in mind.
For es_out implementation, I prefer to send directly the list of ES via a new control. This allow to select multiples tracks atomically (only one lock held).
>
> Please let me know if you have any comments.
> Thanks,
> Roland
>
> Diff:
>
> diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h
> index b690d570e9..ead0e7a0e0 100644
> --- a/include/vlc_es_out.h
> +++ b/include/vlc_es_out.h
> @@ -35,9 +35,10 @@
> enum es_out_query_e
> {
> /* set or change the selected ES in its category (audio/video/spu) */
> - ES_OUT_SET_ES, /* arg1= es_out_id_t* */
> - ES_OUT_UNSET_ES, /* arg1= es_out_id_t* res=can fail */
> - ES_OUT_RESTART_ES, /* arg1= es_out_id_t* */
> + ES_OUT_SET_ES, /* arg1= es_out_id_t* arg2=bool */
> + ES_OUT_SET_ES_MULTIPLE, /* arg1= int, arg2=bool */
> + ES_OUT_UNSET_ES, /* arg1= es_out_id_t* res=can fail */
> + ES_OUT_RESTART_ES, /* arg1= es_out_id_t* */
>
> /* set 'default' tag on ES (copied across from container) */
> ES_OUT_SET_ES_DEFAULT, /* arg1= es_out_id_t* */
> diff --git a/include/vlc_player.h b/include/vlc_player.h
> index 1aa5f8e687..aa641a712e 100644
> --- a/include/vlc_player.h
> +++ b/include/vlc_player.h
> @@ -1675,6 +1675,32 @@ vlc_player_GetSelectedTrack(vlc_player_t *player,
> enum es_format_category_e cat)
> VLC_API void
> vlc_player_SelectTrack(vlc_player_t *player, vlc_es_id_t *es_id);
>
> +
> +/**
> + * Select multiple tracks from a list of ES identifiers. Any currently
> + * selected track not referenced in the list will be unselected.
> + *
> + * @warning there is no guarantee all requested tracks will be selected.
> + * Only one audio track can be selected at a time. Two subtitle tracks
> + * can be selected simultaneously if the dual subtitles setting is enabled.
> + *
> + * @warning behaviour is undefined if the list is not null-terminated.
> + *
> + * @note A successful call will trigger the
> + * vlc_player_cbs.on_track_selection_changed event for each track that has
> + * its selection state changed.
> + *
> + * @param player locked player instance
> + * @param cat VIDEO_ES, AUDIO_ES or SPU_ES
> + * @param es_id_list a null-terminated list of ES identifiers
> + * (ES IDs can be retrieved from vlc_player_cbs.on_track_list_changed or
> + * vlc_player_GetTrackAt())
> + */
> +VLC_API void
> +vlc_player_SelectTrackList(vlc_player_t *player,
> + enum es_format_category_e cat,
> + vlc_es_id_t *const es_id_list[]);
> +
> /**
> * Select the next track
> *
> diff --git a/modules/gui/qt/util/input_models.cpp
> b/modules/gui/qt/util/input_models.cpp
> index e381fbb917..857cfee972 100644
> --- a/modules/gui/qt/util/input_models.cpp
> +++ b/modules/gui/qt/util/input_models.cpp
> @@ -62,7 +62,47 @@ bool TrackListModel::setData(const QModelIndex
> &index, const QVariant &value, in
> vlc_player_locker lock{ m_player };
>
> if (select)
> - vlc_player_SelectTrack(m_player, m_data[row].m_id.get());
> + {
> + vlc_es_id_t *esId = m_data[row].m_id.get();
> + const struct vlc_player_track *trackToSelect =
> vlc_player_GetTrack(m_player, esId);
> + assert(trackToSelect);
> +
> + if (trackToSelect->fmt.i_cat != SPU_ES)
> + {
> + /* For now, use existing behaviour for video/audio tracks */
> + vlc_player_SelectTrack(m_player, esId);
> + }
> + else
> + {
> + /* Try to select a maximum of two tracks. */
> + const int maxIds = 2;
> + enum es_format_category_e cat = trackToSelect->fmt.i_cat;
> + vlc_es_id_t *esIds[maxIds + 1] = { esId }; /* null
> terminated */
> +
> + size_t count = vlc_player_GetTrackCount(m_player, cat);
> + if (!count)
> + return false;
> +
> + unsigned int index = 1;
> + for (size_t i = 0; i < count; ++i)
> + {
> + const struct vlc_player_track *track =
> + vlc_player_GetTrackAt(m_player, SPU_ES, i);
> + assert(track);
> +
> + if (track->selected)
> + {
> + if (index == maxIds)
> + {
> + updateTrackSelection(trackToSelect->es_id, false);
> + return false;
> + }
> + esIds[index++] = track->es_id;
> + }
> + }
> + vlc_player_SelectTrackList(m_player, cat, esIds);
> + }
> + }
> 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 2026fb8c22..4523efce54 100644
> --- a/src/input/es_out.c
> +++ b/src/input/es_out.c
> @@ -216,7 +216,7 @@ static void EsOutDelLocked( es_out_t *,
> es_out_id_t * );
> static void EsOutDel ( es_out_t *, es_out_id_t * );
>
> static void EsOutTerminate( es_out_t * );
> -static void EsOutSelect( es_out_t *, es_out_id_t *es, bool
> b_force );
> +static void EsOutSelect( es_out_t *, es_out_id_t *es, bool
> b_force, bool b_multiple );
> static void EsOutUpdateInfo( es_out_t *, es_out_id_t *es,
> const vlc_meta_t * );
> static int EsOutSetRecord( es_out_t *, bool b_record );
>
> @@ -1114,7 +1114,7 @@ static void EsOutProgramSelect( es_out_t *out,
> es_out_pgrm_t *p_pgrm )
> EsOutUpdateInfo(out, es, NULL);
> }
>
> - EsOutSelect(out, es, false);
> + EsOutSelect(out, es, false, false);
> }
>
> /* Ensure the correct running EPG table is selected */
> @@ -1774,7 +1774,7 @@ static es_out_id_t *EsOutAddSlaveLocked( es_out_t
> *out, const es_format_t *fmt,
> EsOutSendEsEvent( out, es, VLC_INPUT_ES_ADDED );
>
> EsOutUpdateInfo( out, es, NULL );
> - EsOutSelect( out, es, false );
> + EsOutSelect( out, es, false, false );
>
> if( es->b_scrambled )
> EsOutProgramUpdateScrambled( out, es->p_pgrm );
> @@ -2043,9 +2043,11 @@ static void EsOutUnselectEs( es_out_t *out,
> es_out_id_t *es, bool b_update )
> * \param out The es_out structure
> * \param es es_out_id structure
> * \param b_force ...
> + * \param b_multiple preserve currently selected ES
> * \return nothing
> */
> -static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
> +static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force,
> + bool b_multiple )
> {
> es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
> es_out_es_props_t *p_esprops = GetPropsByCat( p_sys, es->fmt.i_cat );
> @@ -2058,7 +2060,8 @@ static void EsOutSelect( es_out_t *out,
> es_out_id_t *es, bool b_force )
>
> 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_multiple;
>
> if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
> {
> @@ -2218,7 +2221,7 @@ static void EsOutCreateCCChannels( es_out_t *out,
> vlc_fourcc_t codec, uint64_t i
>
> /* Enable if user specified on command line */
> if (p_sys->sub.i_channel == i)
> - EsOutSelect(out, *pp_es, true);
> + EsOutSelect(out, *pp_es, true, false);
> }
> }
>
> @@ -2410,7 +2413,7 @@ static void EsOutDelLocked( es_out_t *out,
> es_out_id_t *es )
> p_esprops->p_main_es = other;
> }
> else
> - EsOutSelect(out, other, false);
> + EsOutSelect(out, other, false, false);
> }
> }
>
> @@ -2532,7 +2535,7 @@ static int EsOutVaControlLocked( es_out_t *out,
> int i_query, va_list args )
> }
> foreach_es_then_es_slaves(es)
> {
> - EsOutSelect(out, es, false);
> + EsOutSelect(out, es, false, false);
> }
>
> if( i_mode == ES_OUT_MODE_END )
> @@ -2540,6 +2543,7 @@ static int EsOutVaControlLocked( es_out_t *out,
> int i_query, va_list args )
> return VLC_SUCCESS;
> }
>
> + case ES_OUT_SET_ES_MULTIPLE:
> case ES_OUT_SET_ES:
> case ES_OUT_RESTART_ES:
> {
> @@ -2573,9 +2577,11 @@ static int EsOutVaControlLocked( es_out_t *out,
> int i_query, va_list args )
> EsOutDestroyDecoder(out, es);
> EsOutCreateDecoder(out, es);
> }
> - else if( i_query == ES_OUT_SET_ES )
> + else if( i_query == ES_OUT_SET_ES ||
> + i_query == ES_OUT_SET_ES_MULTIPLE )
> {
> - EsOutSelect(out, es, true);
> + bool b_multiple = i_query ==
> ES_OUT_SET_ES_MULTIPLE;
> + EsOutSelect(out, es, true, b_multiple);
> }
> break;
> }
> diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
> index 406c6f2237..ddec6fbec3 100644
> --- a/src/input/es_out_timeshift.c
> +++ b/src/input/es_out_timeshift.c
> @@ -738,6 +738,7 @@ static int ControlLocked( es_out_t *p_out, int
> i_query, va_list args )
>
> /* Invalid queries for this es_out level */
> case ES_OUT_SET_ES_BY_ID:
> + case ES_OUT_SET_ES_MULTIPLE:
> case ES_OUT_RESTART_ES_BY_ID:
> case ES_OUT_SET_ES_DEFAULT_BY_ID:
> case ES_OUT_GET_ES_OBJECTS_BY_ID:
> diff --git a/src/input/input.c b/src/input/input.c
> index 381b85a9fd..0f9772211c 100644
> --- a/src/input/input.c
> +++ b/src/input/input.c
> @@ -1708,6 +1708,7 @@ static void ControlRelease( int i_type, const
> input_control_param_t *p_param )
> vlc_renderer_item_release( p_param->val.p_address );
> break;
> case INPUT_CONTROL_SET_ES:
> + case INPUT_CONTROL_SET_ES_MULTIPLE:
> case INPUT_CONTROL_UNSET_ES:
> case INPUT_CONTROL_RESTART_ES:
> vlc_es_id_Release( p_param->id );
> @@ -2124,12 +2125,17 @@ static bool Control( input_thread_t *p_input,
> ES_OUT_RESTART_ES_BY_ID,
> (int)param.val.i_int );
> break;
>
> - case INPUT_CONTROL_SET_ES:
> + case INPUT_CONTROL_SET_ES: case INPUT_CONTROL_SET_ES_MULTIPLE:
> + {
> + int i_query = i_type == INPUT_CONTROL_SET_ES ?
> + ES_OUT_SET_ES : ES_OUT_SET_ES_MULTIPLE;
> +
> if( es_out_Control( input_priv(p_input)->p_es_out_display,
> - ES_OUT_SET_ES, param.id ) == VLC_SUCCESS )
> + i_query, param.id ) == VLC_SUCCESS )
> demux_Control( input_priv(p_input)->master->p_demux,
> DEMUX_SET_ES,
> vlc_es_id_GetInputId( param.id ) );
> break;
> + }
> case INPUT_CONTROL_UNSET_ES:
> es_out_Control( input_priv(p_input)->p_es_out_display,
> ES_OUT_UNSET_ES, param.id );
> @@ -3425,7 +3431,7 @@ static int input_SlaveSourceAdd( input_thread_t
> *p_input,
> es_out_Control( priv->p_es_out_display, ES_OUT_SET_ES_DEFAULT_BY_ID,
> priv->i_last_es_id );
> es_out_Control( priv->p_es_out_display, ES_OUT_SET_ES_BY_ID,
> - priv->i_last_es_id, false );
> + priv->i_last_es_id, false, false );
>
> return VLC_SUCCESS;
> }
> diff --git a/src/input/input_internal.h b/src/input/input_internal.h
> index 18495881c2..1bb1ffe091 100644
> --- a/src/input/input_internal.h
> +++ b/src/input/input_internal.h
> @@ -247,6 +247,7 @@ enum input_control_e
> INPUT_CONTROL_RESTART_ES_BY_ID,
>
> INPUT_CONTROL_SET_ES,
> + INPUT_CONTROL_SET_ES_MULTIPLE, // select without deselecting other ES
> INPUT_CONTROL_UNSET_ES,
> INPUT_CONTROL_RESTART_ES,
>
> @@ -294,7 +295,8 @@ static inline void input_ControlPushEsHelper(
> input_thread_t *p_input, int i_typ
> vlc_es_id_t *id )
> {
> assert( i_type == INPUT_CONTROL_SET_ES || i_type ==
> INPUT_CONTROL_UNSET_ES ||
> - i_type == INPUT_CONTROL_RESTART_ES );
> + i_type == INPUT_CONTROL_RESTART_ES ||
> + i_type == INPUT_CONTROL_SET_ES_MULTIPLE );
> input_ControlPush( p_input, i_type, &(input_control_param_t) {
> .id = vlc_es_id_Hold( id ),
> } );
> diff --git a/src/input/player.c b/src/input/player.c
> index da02375a66..a896d5285d 100644
> --- a/src/input/player.c
> +++ b/src/input/player.c
> @@ -1312,6 +1312,67 @@ vlc_player_SelectTrack(vlc_player_t *player,
> vlc_es_id_t *id)
> vlc_player_vout_OSDTrack(player, id, true);
> }
>
> +void
> +vlc_player_SelectTrackList(vlc_player_t *player,
> + enum es_format_category_e cat,
> + vlc_es_id_t *const es_id_list[])
> +{
> + struct vlc_player_input *input = vlc_player_get_input_locked(player);
> + if (!input)
> + return;
> +
> + /* First, deselect any currently selected tracks not in es_id_list */
> + size_t count = vlc_player_GetTrackCount(player, cat);
> + if (!count)
> + return;
> +
> + for (size_t i = 0; i < count; ++i)
> + {
> + const struct vlc_player_track *track =
> + vlc_player_GetTrackAt(player, cat, i);
> + assert(track);
> + if (track->selected)
> + {
> + bool deselect = true;
> + for (size_t j = 0; ; j++)
> + {
> + vlc_es_id_t *es_id = es_id_list[j];
> + if (es_id == NULL)
> + break;
> +
> + if (es_id == track->es_id)
> + {
> + deselect = false;
> + break;
> + }
> + }
> + if (deselect)
> + vlc_player_UnselectTrack(player, track->es_id);
> + }
> + }
> +
> + /* Second, Select each track sequentially.
> + Already selected tracks will be ignored */
> +
> + for (size_t j = 0; ; j++)
> + {
> + vlc_es_id_t *es_id = es_id_list[j];
> + if (es_id == NULL)
> + break;
> +
> + const struct vlc_player_track *track =
> vlc_player_GetTrack(player, es_id);
> + assert(track);
> +
> + if (!track->selected)
> + {
> + input_ControlPushEsHelper(input->thread,
> + INPUT_CONTROL_SET_ES_MULTIPLE,
> + es_id);
> + vlc_player_vout_OSDTrack(player, es_id, true);
> + }
> + }
> +}
> +
> static void
> vlc_player_CycleTrack(vlc_player_t *player, enum es_format_category_e cat,
> bool next)
> diff --git a/src/libvlccore.sym b/src/libvlccore.sym
> index efc07fbb25..03a503e1ea 100644
> --- a/src/libvlccore.sym
> +++ b/src/libvlccore.sym
> @@ -856,6 +856,7 @@ vlc_player_SelectTeletextPage
> vlc_player_SelectTitle
> vlc_player_SelectTitleIdx
> vlc_player_SelectTrack
> +vlc_player_SelectTrackList
> vlc_player_SetAssociatedSubsFPS
> vlc_player_SetAtoBLoop
> vlc_player_SetAudioDelay
>
>
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list