From fd36db98fcd128ae8a68bbe5994f1e91bd6a7f08 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 15 Mar 2012 01:03:50 +0000 Subject: [PATCH] Ignore DVD commentary and AD tracks when auto-selecting the audio track. 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. --- mythtv/libs/libmythtv/avformatdecoder.cpp | 96 +++++++++++++++-------- mythtv/libs/libmythtv/decoderbase.h | 25 ++++-- mythtv/libs/libmythtv/dvdringbuffer.cpp | 26 ++++++ mythtv/libs/libmythtv/dvdringbuffer.h | 2 +- 4 files changed, 109 insertions(+), 40 deletions(-) diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp index 842d24861e0..9d9670b15b5 100644 --- a/mythtv/libs/libmythtv/avformatdecoder.cpp +++ b/mythtv/libs/libmythtv/avformatdecoder.cpp @@ -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) && @@ -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)); } @@ -3699,6 +3706,19 @@ static vector 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 &fs, @@ -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; } @@ -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; @@ -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 flang = filter_lang(atracks, canonical_key); + vector 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. @@ -3890,31 +3920,31 @@ int AvFormatDecoder::AutoSelectAudioTrack(void) vector::const_iterator it = languagePreference.begin(); for (; it != languagePreference.end() && selTrack < 0; ++it) { - vector flang = filter_lang(atracks, *it); + vector 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 @@ -3922,29 +3952,29 @@ int AvFormatDecoder::AutoSelectAudioTrack(void) { LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select audio track (wo/lang)"); - vector flang = filter_lang(atracks, -1); + vector 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); } } diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h index a9925d494cd..78b93902de2 100644 --- a/mythtv/libs/libmythtv/decoderbase.h +++ b/mythtv/libs/libmythtv/decoderbase.h @@ -47,6 +47,13 @@ typedef enum DecodeTypes kDecodeAV = 0x03, } DecodeType; +typedef enum AudioTrackType +{ + kAudioTypeNormal = 0, + kAudioTypeAudioDescription, + kAudioTypeCommentary +} AudioTrackType; + class StreamInfo { public: @@ -54,17 +61,22 @@ class 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; @@ -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 { diff --git a/mythtv/libs/libmythtv/dvdringbuffer.cpp b/mythtv/libs/libmythtv/dvdringbuffer.cpp index eb1d24f72be..661ff3a5d3f 100644 --- a/mythtv/libs/libmythtv/dvdringbuffer.cpp +++ b/mythtv/libs/libmythtv/dvdringbuffer.cpp @@ -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) diff --git a/mythtv/libs/libmythtv/dvdringbuffer.h b/mythtv/libs/libmythtv/dvdringbuffer.h index 23d131ca9fe..d803627aa16 100644 --- a/mythtv/libs/libmythtv/dvdringbuffer.h +++ b/mythtv/libs/libmythtv/dvdringbuffer.h @@ -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);