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