Skip to content

Commit

Permalink
Ignore DVD commentary and AD tracks when auto-selecting the audio track.
Browse files Browse the repository at this point in the history
This should prevent us playing the commentary tracks instead of the feature audio for some DVDs.

This will be expanded to ignore audio description tracks for DVB just as soon as I figure it out.

I've not looked into doing the same for Blu-ray yet.
  • Loading branch information
stuartm committed Mar 15, 2012
1 parent 3e4ec54 commit fd36db9
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 40 deletions.
96 changes: 63 additions & 33 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -1020,7 +1020,7 @@ int AvFormatDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
dur /= 1000000;
frames = m_playbackinfo->QueryTotalFrames();
}

if (dur == 0)
{
if ((ic->duration == (int64_t)AV_NOPTS_VALUE) &&
Expand Down Expand Up @@ -2124,32 +2124,39 @@ int AvFormatDecoder::ScanStreams(bool novideo)
int channels = ic->streams[i]->codec->channels;
int lang_indx = lang_aud_cnt[lang]++;
audioStreamCount++;
AudioTrackType type = kAudioTypeNormal;

if (ic->streams[i]->codec->avcodec_dual_language)
{
tracks[kTrackTypeAudio].push_back(
StreamInfo(i, lang, lang_indx, ic->streams[i]->id, channels, false));
StreamInfo(i, lang, lang_indx, ic->streams[i]->id, channels,
false, false, false, type));
lang_indx = lang_aud_cnt[lang]++;
tracks[kTrackTypeAudio].push_back(
StreamInfo(i, lang, lang_indx, ic->streams[i]->id, channels, true));
StreamInfo(i, lang, lang_indx, ic->streams[i]->id, channels,
true, false, false, type));
}
else
{
int logical_stream_id;
if (ringBuffer && ringBuffer->IsDVD())
{
logical_stream_id =
ringBuffer->DVD()->GetAudioTrackNum(ic->streams[i]->id);
type = (AudioTrackType)(ringBuffer->DVD()->GetAudioTrackType(ic->streams[i]->id));
}
else
logical_stream_id = ic->streams[i]->id;

tracks[kTrackTypeAudio].push_back(
StreamInfo(i, lang, lang_indx, logical_stream_id, channels));
StreamInfo(i, lang, lang_indx, logical_stream_id, channels,
false, false, false, type));
}

LOG(VB_AUDIO, LOG_INFO, LOC +
QString("Audio Track #%1 is A/V stream #%2 "
"and has %3 channels in the %4 language(%5).")
.arg(tracks[kTrackTypeAudio].size()).arg(i)
QString("Audio Track #%1, with type %2 is A/V stream #%3 "
"and has %4 channels in the %5 language(%6).")
.arg(tracks[kTrackTypeAudio].size()).arg((int)type).arg(i)
.arg(enc->channels)
.arg(iso639_key_toName(lang)).arg(lang));
}
Expand Down Expand Up @@ -3699,6 +3706,19 @@ static vector<int> filter_lang(const sinfo_vec_t &tracks, int lang_key)
return ret;
}

static sinfo_vec_t filter_type(const sinfo_vec_t &tracks, AudioTrackType type)
{
sinfo_vec_t ret;

for (uint i = 0; i < tracks.size(); i++)
{
if (tracks[i].audio_type == type)
ret.push_back(tracks[i]);
}

return ret;
}

int AvFormatDecoder::filter_max_ch(const AVFormatContext *ic,
const sinfo_vec_t &tracks,
const vector<int> &fs,
Expand Down Expand Up @@ -3807,7 +3827,8 @@ int AvFormatDecoder::AutoSelectAudioTrack(void)
LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select default track");
for (uint i = 0; i < atracks.size(); i++) {
int idx = atracks[i].av_stream_index;
if (ic->streams[idx]->disposition & AV_DISPOSITION_DEFAULT) {
if (ic->streams[idx]->disposition & AV_DISPOSITION_DEFAULT)
{
selTrack = i;
break;
}
Expand Down Expand Up @@ -3835,7 +3856,7 @@ int AvFormatDecoder::AutoSelectAudioTrack(void)
if ((selTrack < 0) && wlang >= -1 && numStreams)
{
LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to reselect audio track");
// Try to reselect user selected subtitle stream.
// Try to reselect user selected audio stream.
// This should find the stream after a commercial
// break and in some cases after a channel change.
uint windx = wtrack.language_index;
Expand All @@ -3855,33 +3876,42 @@ int AvFormatDecoder::AutoSelectAudioTrack(void)
{
LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select audio track (w/lang)");

// Filter out commentary and audio description tracks
sinfo_vec_t ftracks = filter_type(atracks, kAudioTypeNormal);

if (ftracks.empty())
{
LOG(VB_AUDIO, LOG_WARNING, "No audio tracks matched the filter so trying without filter.");
ftracks = atracks;
}

// try to get the language track matching the frontend language.
QString language_key_convert = iso639_str2_to_str3(gCoreContext->GetLanguage());
uint language_key = iso639_str3_to_key(language_key_convert);
uint canonical_key = iso639_key_to_canonical_key(language_key);

vector<int> flang = filter_lang(atracks, canonical_key);
vector<int> flang = filter_lang(ftracks, canonical_key);

if (m_audio->CanDTSHD())
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS,
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS,
FF_PROFILE_DTS_HD_MA);
if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_TRUEHD);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_TRUEHD);

if (selTrack < 0 && m_audio->CanDTSHD())
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS,
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS,
FF_PROFILE_DTS_HD_HRA);
if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_EAC3);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_EAC3);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_AC3);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_AC3);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang);
selTrack = filter_max_ch(ic, ftracks, flang);

// try to get best track for most preferred language
// Set by the "Guide Data" language prefs in Appearance.
Expand All @@ -3890,61 +3920,61 @@ int AvFormatDecoder::AutoSelectAudioTrack(void)
vector<int>::const_iterator it = languagePreference.begin();
for (; it != languagePreference.end() && selTrack < 0; ++it)
{
vector<int> flang = filter_lang(atracks, *it);
vector<int> flang = filter_lang(ftracks, *it);

if (m_audio->CanDTSHD())
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS,
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS,
FF_PROFILE_DTS_HD_MA);
if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang,
selTrack = filter_max_ch(ic, ftracks, flang,
CODEC_ID_TRUEHD);

if (selTrack < 0 && m_audio->CanDTSHD())
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS,
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS,
FF_PROFILE_DTS_HD_HRA);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang,
selTrack = filter_max_ch(ic, ftracks, flang,
CODEC_ID_EAC3);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_AC3);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_AC3);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang);
selTrack = filter_max_ch(ic, ftracks, flang);
}
}
// try to get best track for any language
if (selTrack < 0)
{
LOG(VB_AUDIO, LOG_INFO, LOC +
"Trying to select audio track (wo/lang)");
vector<int> flang = filter_lang(atracks, -1);
vector<int> flang = filter_lang(ftracks, -1);

if (m_audio->CanDTSHD())
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS,
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS,
FF_PROFILE_DTS_HD_MA);
if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_TRUEHD);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_TRUEHD);

if (selTrack < 0 && m_audio->CanDTSHD())
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS,
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS,
FF_PROFILE_DTS_HD_HRA);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_EAC3);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_EAC3);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_DTS);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_DTS);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang, CODEC_ID_AC3);
selTrack = filter_max_ch(ic, ftracks, flang, CODEC_ID_AC3);

if (selTrack < 0)
selTrack = filter_max_ch(ic, atracks, flang);
selTrack = filter_max_ch(ic, ftracks, flang);
}
}

Expand Down
25 changes: 19 additions & 6 deletions mythtv/libs/libmythtv/decoderbase.h
Expand Up @@ -47,24 +47,36 @@ typedef enum DecodeTypes
kDecodeAV = 0x03,
} DecodeType;

typedef enum AudioTrackType
{
kAudioTypeNormal = 0,
kAudioTypeAudioDescription,
kAudioTypeCommentary
} AudioTrackType;

class StreamInfo
{
public:
StreamInfo() :
av_stream_index(-1), av_substream_index(-1),
language(-2), language_index(0),
stream_id(-1), easy_reader(false),
wide_aspect_ratio(false), orig_num_channels(2), forced(false) {}
StreamInfo(int a, int b, uint c, int d, int e, bool f = false,
bool g = false, bool h = false) :
wide_aspect_ratio(false), orig_num_channels(2), forced(false),
audio_type(kAudioTypeNormal) {}
StreamInfo(int a, int b, uint c, int d, int e, bool f = false,
bool g = false, bool h = false,
AudioTrackType i = kAudioTypeNormal) :
av_stream_index(a), av_substream_index(-1),
language(b), language_index(c), stream_id(d),
easy_reader(f), wide_aspect_ratio(g), orig_num_channels(e), forced(h) {}
easy_reader(f), wide_aspect_ratio(g), orig_num_channels(e), forced(h),
audio_type(i) {}
StreamInfo(int a, int b, uint c, int d, int e, int f,
bool g = false, bool h = false, bool i = false) :
bool g = false, bool h = false, bool i = false,
AudioTrackType j = kAudioTypeNormal) :
av_stream_index(a), av_substream_index(e),
language(b), language_index(c), stream_id(d),
easy_reader(g), wide_aspect_ratio(h), orig_num_channels(f), forced(i) {}
easy_reader(g), wide_aspect_ratio(h), orig_num_channels(f), forced(i),
audio_type(j) {}

public:
int av_stream_index;
Expand All @@ -77,6 +89,7 @@ class StreamInfo
bool wide_aspect_ratio;
int orig_num_channels;
bool forced;
AudioTrackType audio_type;

bool operator<(const StreamInfo& b) const
{
Expand Down
26 changes: 26 additions & 0 deletions mythtv/libs/libmythtv/dvdringbuffer.cpp
Expand Up @@ -1571,6 +1571,32 @@ int DVDRingBuffer::GetAudioTrackNum(uint stream_id)
return dvdnav_get_audio_logical_stream(m_dvdnav, stream_id);
}

int DVDRingBuffer::GetAudioTrackType(uint stream_id)
{
AudioTrackType ret = kAudioTypeNormal;
audio_attr_t attributes;
int logicalStreamId = dvdnav_get_audio_logical_stream(m_dvdnav, stream_id);
if (dvdnav_get_audio_attr(m_dvdnav, logicalStreamId, &attributes) >= 1)
{
switch (attributes.code_extension)
{
case 1:
ret = kAudioTypeNormal;
break;
case 2:
ret = kAudioTypeAudioDescription;
break;
case 3: case 4:
ret = kAudioTypeCommentary;
break;
case 0: default:
break;
}
}

return (int)ret;
}

/** \brief get the subtitle language from the dvd
*/
uint DVDRingBuffer::GetSubtitleLanguage(int id)
Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmythtv/dvdringbuffer.h
Expand Up @@ -96,7 +96,7 @@ class MTV_PUBLIC DVDRingBuffer : public RingBuffer

uint GetAudioLanguage(int id);
int GetAudioTrackNum(uint key);

int GetAudioTrackType(uint stream_id);

bool GetNameAndSerialNum(QString& _name, QString& _serialnum);
double GetFrameRate(void);
Expand Down

0 comments on commit fd36db9

Please sign in to comment.