demux: improve -alang / -slang track choosing logic

When -alang / -slang was specified the numerically first matching
track (if any) was always chosen. This meant that specifying "-alang
eng" could change the track choice even if all tracks were in English,
because now the default flag of tracks was ignored. Change the logic
to take the default flag into account as a secondary sorting key.

The code also accepted prefix matches, so that "-slang g" would match
track language "ger". I think that was not intentional. Change it to
require exact matches.
This commit is contained in:
Uoti Urpala 2010-11-08 13:05:49 +02:00
parent fc66c94360
commit 3c2cfee488
4 changed files with 61 additions and 68 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -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

View File

@ -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;