loadfile: simplify default track selection a bit

What was previously there is extremely complicated and really confusing.
Poorly named variables like "prefer_forced" that don't neccesarily have
anything to do with prefering forced tracks didn't help either. Try to
rewrite a few things to be saner. The idea is that after you loop
through the tracks, the special sub-specific options (like subs-fallback
and so on) should be handled and the track should be deselected if
appropriate. Another change is to remove the "prefered_forced" argument
in compare_track. This actually was both not neccessary and caused bad
behavior by always depriortizing forced tracks even when it didn't apply
(e.g. forced video tracks were never selected even though the flag
should simply be ignored for anything that's not a subtitle track).
This commit is contained in:
Dudemanguy 2023-08-25 23:12:13 -05:00
parent 53d032374d
commit fbe8f99194
1 changed files with 22 additions and 36 deletions

View File

@ -485,7 +485,7 @@ static int match_lang(char **langs, const char *lang)
*/
// Return whether t1 is preferred over t2
static bool compare_track(struct track *t1, struct track *t2, char **langs,
int prefer_forced, struct MPOpts *opts, int preferred_program)
struct MPOpts *opts, int preferred_program)
{
if (!opts->autoload_files && t1->is_external != t2->is_external)
return !t1->is_external;
@ -507,8 +507,6 @@ static bool compare_track(struct track *t1, struct track *t2, char **langs,
int l1 = match_lang(langs, t1->lang), l2 = match_lang(langs, t2->lang);
if (l1 != l2)
return l1 > l2;
if (t1->forced_track != t2->forced_track)
return prefer_forced ? t1->forced_track : !t1->forced_track;
if (t1->default_track != t2->default_track)
return t1->default_track;
if (t1->attached_picture != t2->attached_picture)
@ -614,10 +612,10 @@ struct track *select_default_track(struct MPContext *mpctx, int order,
return NULL;
char **langs = process_langs(opts->stream_lang[type]);
const char *audio_lang = get_audio_lang(mpctx);
bool audio_matches = match_lang(langs, audio_lang);
int prefer_forced = type == STREAM_SUB && !opts->subs_with_matching_audio && audio_matches;
bool select_fallback = type == STREAM_VIDEO || type == STREAM_AUDIO || (type == STREAM_SUB && opts->subs_fallback == 2);
bool fallback_forced = (type == STREAM_SUB && !prefer_forced && opts->subs_fallback_forced);
bool sub = type == STREAM_SUB;
bool fallback_forced = sub && opts->subs_fallback_forced;
bool audio_matches = false;
bool sub_fallback = false;
struct track *pick = NULL;
struct track *forced_pick = NULL;
for (int n = 0; n < mpctx->num_tracks; n++) {
@ -635,51 +633,39 @@ struct track *select_default_track(struct MPContext *mpctx, int order,
continue;
if (duplicate_track(mpctx, order, type, track))
continue;
if (!pick || compare_track(track, pick, langs, false, mpctx->opts, preferred_program))
if (!pick || compare_track(track, pick, langs, mpctx->opts, preferred_program))
pick = track;
// We only try to autoselect forced tracks if they match the audio language
if ((prefer_forced || fallback_forced) && mp_match_lang_single(audio_lang, track->lang) &&
(!forced_pick || compare_track(track, forced_pick, langs, true, mpctx->opts, preferred_program)))
// We only try to autoselect forced tracks if they match the audio language and are subs
if (fallback_forced && track->forced_track && mp_match_lang_single(audio_lang, track->lang) &&
(!forced_pick || compare_track(track, forced_pick, langs, mpctx->opts, preferred_program)))
forced_pick = track;
}
// If we're trying for a forced track, and found something that matches the audio, go with that
if (prefer_forced)
// If we found a forced track, use that.
if (forced_pick)
pick = forced_pick;
// If our best pick for a subtitle track isn't suitable, we'll fall back on forced,
// or clear it out altogether.
if (pick && !select_fallback && !(pick->is_external && !pick->no_default)
&& (!match_lang(langs, pick->lang) || (prefer_forced && !pick->forced_track))
&& (!opts->subs_fallback || !pick->default_track)) {
if (fallback_forced) {
prefer_forced = 1;
// If we found a suitable forced track (matching the audio), fallback on that.
// Otherwise, if our currently-selected track matches the audio,
// we'll try using it in forced-only mode.
// If it doesn't, none of the available tracks make sense, so we give up.
if (forced_pick)
pick = forced_pick;
else if (!match_lang(langs, pick->lang))
pick = NULL;
} else {
pick = NULL;
}
// Clear out any picks for these special cases for subtitles
if (pick) {
audio_matches = mp_match_lang_single(pick->lang, audio_lang);
sub_fallback = (pick->is_external && !pick->no_default) || opts->subs_fallback == 2 ||
(opts->subs_fallback == 1 && pick->default_track);
}
if (pick && !forced_pick && sub && !match_lang(langs, pick->lang) &&
((!opts->subs_with_matching_audio && audio_matches) || !sub_fallback))
pick = NULL;
if (pick && pick->attached_picture && !mpctx->opts->audio_display)
pick = NULL;
if (pick && !opts->autoload_files && pick->is_external)
pick = NULL;
if (pick && type == STREAM_SUB && prefer_forced && !pick->forced_track) {
if (pick && sub && !pick->forced_track) {
// If the codec is DVD or PGS, we can display it in forced-only mode.
// This isn't really meaningful for other codecs, so we'll just pick nothing.
if (pick->stream &&
(!strcmp(pick->stream->codec->codec, "dvd_subtitle") ||
!strcmp(pick->stream->codec->codec, "hdmv_pgs_subtitle")))
pick->forced_only_def = 1;
else
pick = NULL;
pick->forced_only_def = true;
}
cleanup:
talloc_free(langs);