player: mess with track selection details again

Some time ago, properties and options were mostly unified. However, the
track selection properties/options semantics are incompatible to this
change. I'm still trying to handle the fallout.

There are two things that are in the way:
1. Track properties somehow return the runtime selection, not the option
   value (all while properties are supposed to be aliases to options
   with the same name).
2. The user's track options are not supposed to be changed without
   interaction. If a track is auto-selected, the property should return
   its ID, but the option value should remain at "auto". Only if the
   user actually writes to the property the option should change. E.g.
   playing e.g. an audio-only file and then a normal video file not play
   the video file with --vid=no just because the audio file had no video
   track.

In addition to each of them being in conflict with the property/option
unification, attempt to fix one of them breaks the other one.

Today, we're trying to fix parts of this and avoiding an unfortunate
case where you can get a conflicting option/property value, and where
trying to select a track does nothing if the track to select has the
same ID as the option value.

This breaks 2. from above in certain situations. See manpage additions.

See: #7608
This commit is contained in:
wm4 2020-04-13 15:42:52 +02:00
parent dc9135b164
commit e1e714ccc3
3 changed files with 61 additions and 12 deletions

View File

@ -63,6 +63,8 @@ Interface changes
- deprecate encoding mode (lack of maintainer)
- remove deprecated --input-file option, add --input-ipc-client, which is
vaguely a replacement of the removed option, but not the same
- change another detail for track selection options (see --aid manpage
entry)
--- mpv 0.32.0 ---
- change behavior when using legacy option syntax with options that start
with two dashes (``--`` instead of a ``-``). Now, using the recommended

View File

@ -49,6 +49,35 @@ Track Selection
``--aid=no`` or ``--audio=no`` or ``--no-audio`` disables audio playback.
(The latter variant does not work with the client API.)
.. note::
The track selection options (``--aid`` but also ``--sid`` and the
others) sometimes expose behavior that may appear strange. Also, the
behavior tends to change around with each mpv release.
The track selection properties will return the option value outside of
playback (as expected), but during playbac, the affective track
selection is returned. For example, with ``--aid=auto``, the ``aid``
property will suddenly return ``2`` after playback initialization
(assuming the file has at least 2 audio tracks, and the second is the
default).
At mpv 0.32.0 (and some releases before), if you passed a track value
for which a corresponding track didn't exist (e.g. ``--aid=2`` and there
was only 1 audio track), the ``aid`` property returned ``no``. However if
another audio track was added during playback, and you tried to set the
``aid`` property to ``2``, nothing happened, because the ``aid`` option
still had the value ``2``, and writing the same value has no effect.
With mpv 0.33.0, the behavior was changed. Now track selection options
are reset to ``auto`` at playback initialization, if the option had
tries to select a track that does not exist. The same is done if the
track exists, but fails to initialize. The consequence is that unlike
before mpv 0.33.0, the user's track selection parameters are clobbered
in certain situations.
Most likely this is not the end.
``--sid=<ID|auto|no>``
Display the subtitle stream specified by ``<ID>``. ``auto`` selects
the default, ``no`` disables subtitles.

View File

@ -448,9 +448,8 @@ static int match_lang(char **langs, char *lang)
* tid is the track ID requested by the user (-2: deselect, -1: default)
* lang is a string list, NULL is same as empty list
* Sort tracks based on the following criteria, and pick the first:
* 0a) track matches ff-index (always wins)
* 0b) track matches tid (almost always wins)
* 0c) track is not from --external-file
*0a) track matches tid (always wins)
* 0b) track is not from --external-file
* 1) track is external (no_default cancels this)
* 1b) track was passed explicitly (is not an auto-loaded subtitle)
* 2) earlier match in lang list
@ -585,6 +584,15 @@ static void check_previous_track_selection(struct MPContext *mpctx)
talloc_free(h);
}
static void mark_track_selection(struct MPContext *mpctx, int order,
enum stream_type type, int value)
{
assert(order >= 0 && order < NUM_PTRACKS);
mpctx->opts->stream_id[order][type] = value;
m_config_notify_change_opt_ptr(mpctx->mconfig,
&mpctx->opts->stream_id[order][type]);
}
void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type,
struct track *track, int flags)
{
@ -593,11 +601,8 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type
// Mark the current track selection as explicitly user-requested. (This is
// different from auto-selection or disabling a track due to errors.)
if (flags & FLAG_MARK_SELECTION) {
mpctx->opts->stream_id[order][type] = track ? track->user_tid : -2;
m_config_notify_change_opt_ptr(mpctx->mconfig,
&mpctx->opts->stream_id[order][type]);
}
if (flags & FLAG_MARK_SELECTION)
mark_track_selection(mpctx, order, type, track ? track->user_tid : -2);
// No decoder should be initialized yet.
if (!mpctx->demuxer)
@ -609,19 +614,19 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type
if (current && current->sink) {
MP_ERR(mpctx, "Can't disable input to complex filter.\n");
return;
goto error;
}
if ((type == STREAM_VIDEO && mpctx->vo_chain && !mpctx->vo_chain->track) ||
(type == STREAM_AUDIO && mpctx->ao_chain && !mpctx->ao_chain->track))
{
MP_ERR(mpctx, "Can't switch away from complex filter output.\n");
return;
goto error;
}
if (track && track->selected) {
// Track has been selected in a different order parameter.
MP_ERR(mpctx, "Track %d is already selected.\n", track->user_tid);
return;
goto error;
}
if (order == 0) {
@ -666,6 +671,10 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type
talloc_free(mpctx->track_layout_hash);
mpctx->track_layout_hash = talloc_steal(mpctx, track_layout_hash(mpctx));
return;
error:
mark_track_selection(mpctx, order, type, -1);
}
void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
@ -677,8 +686,10 @@ void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
void mp_deselect_track(struct MPContext *mpctx, struct track *track)
{
if (track && track->selected) {
for (int t = 0; t < NUM_PTRACKS; t++)
for (int t = 0; t < NUM_PTRACKS; t++) {
mp_switch_track_n(mpctx, t, track->type, NULL, 0);
mark_track_selection(mpctx, t, track->type, -1); // default
}
}
}
@ -1523,16 +1534,23 @@ static void play_current_file(struct MPContext *mpctx)
}
for (int t = 0; t < STREAM_TYPE_COUNT; t++) {
for (int i = 0; i < NUM_PTRACKS; i++) {
// One track can strictly feed at most 1 decoder
struct track *track = mpctx->current_track[i][t];
if (track) {
if (track->selected) {
MP_ERR(mpctx, "Track %d can't be selected twice.\n",
track->user_tid);
mpctx->current_track[i][t] = NULL;
mark_track_selection(mpctx, i, t, -2); // disable
} else {
track->selected = true;
}
}
// Revert selection of unselected tracks to default. This is needed
// because track properties have inconsistent behavior.
if (!track && opts->stream_id[i][t] >= 0)
mark_track_selection(mpctx, i, t, -1); // default
}
}