diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index 99f1be9fe8..32fc486e59 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -1618,61 +1618,54 @@ int demuxer_set_angle(demuxer_t *demuxer, int angle) return angle; } -int demuxer_audio_track_by_lang(demuxer_t *d, char *lang) +int demuxer_audio_track_by_lang_and_default(struct demuxer *d, char *lang) { - int i, len; - lang += strspn(lang, ","); - while ((len = strcspn(lang, ",")) > 0) { - for (i = 0; i < MAX_A_STREAMS; ++i) { - sh_audio_t *sh = d->a_streams[i]; - if (sh && sh->lang && strncmp(sh->lang, lang, len) == 0) - return sh->aid; - } - lang += len; + if (!lang) + lang = ""; + while (1) { lang += strspn(lang, ","); - } - return -1; -} - -int demuxer_sub_track_by_lang(demuxer_t *d, char *lang) -{ - int i, len; - lang += strspn(lang, ","); - while ((len = strcspn(lang, ",")) > 0) { - for (i = 0; i < MAX_S_STREAMS; ++i) { - sh_sub_t *sh = d->s_streams[i]; - if (sh && sh->lang && strncmp(sh->lang, lang, len) == 0) - return sh->sid; + int len = strcspn(lang, ","); + int id = -1; + for (int i = 0; i < MAX_A_STREAMS; i++) { + struct sh_audio *sh = d->a_streams[i]; + if (sh && (!len || sh->lang && strlen(sh->lang) == len && + !memcmp(lang, sh->lang, len))) { + if (sh->default_track) + return sh->aid; + if (id < 0) + id = sh->aid; + } } + if (id >= 0) + return id; + if (!len) + return -1; lang += len; + } +} + +int demuxer_sub_track_by_lang_and_default(struct demuxer *d, char *lang) +{ + if (!lang) + lang = ""; + while (1) { lang += strspn(lang, ","); + int len = strcspn(lang, ","); + int id = -1; + for (int i = 0; i < MAX_A_STREAMS; i++) { + struct sh_audio *sh = d->a_streams[i]; + if (sh && (!len || sh->lang && strlen(sh->lang) == len && + !memcmp(lang, sh->lang, len))) { + if (sh->default_track) + return sh->aid; + if (id < 0) + id = sh->aid; + } + } + if (!len) + return -1; + if (id >= 0) + return id; + lang += len; } - return -1; -} - -int demuxer_default_audio_track(demuxer_t *d) -{ - int i; - for (i = 0; i < MAX_A_STREAMS; ++i) { - sh_audio_t *sh = d->a_streams[i]; - if (sh && sh->default_track) - return sh->aid; - } - for (i = 0; i < MAX_A_STREAMS; ++i) { - sh_audio_t *sh = d->a_streams[i]; - if (sh) - return sh->aid; - } - return -1; -} - -int demuxer_default_sub_track(demuxer_t *d) -{ - int i; - for (i = 0; i < MAX_S_STREAMS; ++i) { - sh_sub_t *sh = d->s_streams[i]; - if (sh && sh->default_track) - return sh->sid; - } - return -1; } diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 2c200ead1e..63a34f30f6 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -466,15 +466,18 @@ int demuxer_set_angle(demuxer_t *demuxer, int angle); /// Get number of angles. int demuxer_angles_count(demuxer_t *demuxer); -// get the index of a track -// lang is a comma-separated list -int demuxer_audio_track_by_lang(demuxer_t* demuxer, char* lang); -int demuxer_sub_track_by_lang(demuxer_t* demuxer, char* lang); - -// find the default track -// for subtitles, it is the first track with default attribute -// for audio, additionally, the first track is selected if no track has default attribute set -int demuxer_default_audio_track(demuxer_t* d); -int demuxer_default_sub_track(demuxer_t* d); +/* Get the index of a track. + * lang is a comma-separated list, NULL is same as empty list + * Sort tracks based on the following criteria: + * 1) earlier match in lang list, or last no match + * 2) track is marked default (default wins) + * 3) track number (lower wins) + * For audio, select best track according to these criteria; only return -1 + * if there are no tracks at all. + * For subs, select best track according to the same criteria, but return -1 + * if all tracks are no-lang-match, not-default. + */ +int demuxer_audio_track_by_lang_and_default(struct demuxer *d, char *lang); +int demuxer_sub_track_by_lang_and_default(struct demuxer *d, char *lang); #endif /* MPLAYER_DEMUXER_H */ diff --git a/mpcommon.c b/mpcommon.c index 35f9ea015a..2fa7b6d0a8 100644 --- a/mpcommon.c +++ b/mpcommon.c @@ -318,10 +318,8 @@ void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset) int select_audio(demuxer_t* demuxer, int audio_id, char* audio_lang) { - if (audio_id == -1 && audio_lang) - audio_id = demuxer_audio_track_by_lang(demuxer, audio_lang); if (audio_id == -1) - audio_id = demuxer_default_audio_track(demuxer); + audio_id = demuxer_audio_track_by_lang_and_default(demuxer, audio_lang); if (audio_id != -1) // -1 (automatic) is the default behaviour of demuxers demuxer_switch_audio(demuxer, audio_id); if (audio_id == -2) { // some demuxers don't yet know how to switch to no sound diff --git a/mplayer.c b/mplayer.c index 3423813deb..b061680012 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1957,11 +1957,10 @@ static int select_subtitle(MPContext *mpctx) if (!found && opts->sub_id == -1) { // finally select subs by language and container hints - if (opts->sub_id == -1 && opts->sub_lang) - opts->sub_id = demuxer_sub_track_by_lang(mpctx->d_sub->demuxer, - opts->sub_lang); if (opts->sub_id == -1) - opts->sub_id = demuxer_default_sub_track(mpctx->d_sub->demuxer); + opts->sub_id = + demuxer_sub_track_by_lang_and_default(mpctx->d_sub->demuxer, + opts->sub_lang); if (opts->sub_id >= 0) { id = opts->sub_id; found = mp_property_do("sub_demux", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;