00001
00002
00003
00004
00005
00006
00007
00008 #include <algorithm>
00009 #include <vector>
00010
00011 using namespace std;
00012
00013 #include "audiooutputsettings.h"
00014 #include "mythlogging.h"
00015 #include "mythcorecontext.h"
00016
00017 extern "C" {
00018 #include "libavutil/avutil.h"
00019 }
00020 #include "eldutils.h"
00021
00022 #define LOC QString("AOS: ")
00023
00024 AudioOutputSettings::AudioOutputSettings(bool invalid) :
00025 m_passthrough(-1), m_features(FEATURE_NONE),
00026 m_invalid(invalid), m_has_eld(false), m_eld(ELD())
00027 {
00028 m_sr.assign(srs, srs +
00029 sizeof(srs) / sizeof(int));
00030 m_sf.assign(fmts, fmts +
00031 sizeof(fmts) / sizeof(AudioFormat));
00032 m_sr_it = m_sr.begin();
00033 m_sf_it = m_sf.begin();
00034 }
00035
00036 AudioOutputSettings::~AudioOutputSettings()
00037 {
00038 m_sr.clear();
00039 m_rates.clear();
00040 m_sf.clear();
00041 m_formats.clear();
00042 m_channels.clear();
00043 }
00044
00045 AudioOutputSettings& AudioOutputSettings::operator=(
00046 const AudioOutputSettings &rhs)
00047 {
00048 if (this == &rhs)
00049 return *this;
00050 m_sr = rhs.m_sr;
00051 m_rates = rhs.m_rates;
00052 m_sf = rhs.m_sf;
00053 m_formats = rhs.m_formats;
00054 m_channels = rhs.m_channels;
00055 m_passthrough = rhs.m_passthrough;
00056 m_features = rhs.m_features;
00057 m_invalid = rhs.m_invalid;
00058 m_has_eld = rhs.m_has_eld;
00059 m_eld = rhs.m_eld;
00060 m_sr_it = m_sr.begin() + (rhs.m_sr_it - rhs.m_sr.begin());
00061 m_sf_it = m_sf.begin() + (rhs.m_sf_it - rhs.m_sf.begin());
00062 return *this;
00063 }
00064
00065 int AudioOutputSettings::GetNextRate()
00066 {
00067 if (m_sr_it == m_sr.end())
00068 {
00069 m_sr_it = m_sr.begin();
00070 return 0;
00071 }
00072
00073 return *m_sr_it++;
00074 }
00075
00076 void AudioOutputSettings::AddSupportedRate(int rate)
00077 {
00078 m_rates.push_back(rate);
00079 LOG(VB_AUDIO, LOG_INFO, LOC +
00080 QString("Sample rate %1 is supported").arg(rate));
00081 }
00082
00083 bool AudioOutputSettings::IsSupportedRate(int rate)
00084 {
00085 if (m_rates.empty() && rate == 48000)
00086 return true;
00087
00088 vector<int>::iterator it;
00089
00090 for (it = m_rates.begin(); it != m_rates.end(); ++it)
00091 if (*it == rate)
00092 return true;
00093
00094 return false;
00095 }
00096
00097 int AudioOutputSettings::BestSupportedRate()
00098 {
00099 if (m_rates.empty())
00100 return 48000;
00101 return m_rates.back();
00102 }
00103
00104 int AudioOutputSettings::NearestSupportedRate(int rate)
00105 {
00106 if (m_rates.empty())
00107 return 48000;
00108
00109 vector<int>::iterator it;
00110
00111
00112 for (it = m_rates.begin(); it != m_rates.end(); ++it)
00113 {
00114 if (*it >= rate)
00115 return *it;
00116 }
00117
00118 return m_rates.back();
00119 }
00120
00121 AudioFormat AudioOutputSettings::GetNextFormat()
00122 {
00123 if (m_sf_it == m_sf.end())
00124 {
00125 m_sf_it = m_sf.begin();
00126 return FORMAT_NONE;
00127 }
00128
00129 return *m_sf_it++;
00130 }
00131
00132 void AudioOutputSettings::AddSupportedFormat(AudioFormat format)
00133 {
00134 LOG(VB_AUDIO, LOG_INFO, LOC +
00135 QString("Format %1 is supported").arg(FormatToString(format)));
00136 m_formats.push_back(format);
00137 }
00138
00139 bool AudioOutputSettings::IsSupportedFormat(AudioFormat format)
00140 {
00141 if (m_formats.empty() && format == FORMAT_S16)
00142 return true;
00143
00144 vector<AudioFormat>::iterator it;
00145
00146 for (it = m_formats.begin(); it != m_formats.end(); ++it)
00147 if (*it == format)
00148 return true;
00149
00150 return false;
00151 }
00152
00153 AudioFormat AudioOutputSettings::BestSupportedFormat()
00154 {
00155 if (m_formats.empty())
00156 return FORMAT_S16;
00157 return m_formats.back();
00158 }
00159
00160 int AudioOutputSettings::FormatToBits(AudioFormat format)
00161 {
00162 switch (format)
00163 {
00164 case FORMAT_U8: return 8;
00165 case FORMAT_S16: return 16;
00166 case FORMAT_S24LSB:
00167 case FORMAT_S24: return 24;
00168 case FORMAT_S32:
00169 case FORMAT_FLT: return 32;
00170 }
00171
00172 return -1;
00173 }
00174
00175 const char* AudioOutputSettings::FormatToString(AudioFormat format)
00176 {
00177 switch (format)
00178 {
00179 case FORMAT_U8: return "unsigned 8 bit";
00180 case FORMAT_S16: return "signed 16 bit";
00181 case FORMAT_S24: return "signed 24 bit MSB";
00182 case FORMAT_S24LSB: return "signed 24 bit LSB";
00183 case FORMAT_S32: return "signed 32 bit";
00184 case FORMAT_FLT: return "32 bit floating point";
00185 default: return "unknown";
00186 }
00187 }
00188
00189 int AudioOutputSettings::SampleSize(AudioFormat format)
00190 {
00191 switch (format)
00192 {
00193 case FORMAT_U8: return 1;
00194 case FORMAT_S16: return 2;
00195 case FORMAT_S24:
00196 case FORMAT_S24LSB:
00197 case FORMAT_S32:
00198 case FORMAT_FLT: return 4;
00199 }
00200
00201 return 0;
00202 }
00203
00204 void AudioOutputSettings::AddSupportedChannels(int channels)
00205 {
00206 m_channels.push_back(channels);
00207 LOG(VB_AUDIO, LOG_INFO, LOC + QString("%1 channel(s) are supported")
00208 .arg(channels));
00209 }
00210
00211 bool AudioOutputSettings::IsSupportedChannels(int channels)
00212 {
00213 if (m_channels.empty() && channels == 2)
00214 return true;
00215
00216 vector<int>::iterator it;
00217
00218 for (it = m_channels.begin(); it != m_channels.end(); ++it)
00219 if (*it == channels)
00220 return true;
00221
00222 return false;
00223 }
00224
00225 int AudioOutputSettings::BestSupportedChannels()
00226 {
00227 if (m_channels.empty())
00228 return 2;
00229 return m_channels.back();
00230 }
00231
00232 void AudioOutputSettings::SortSupportedChannels()
00233 {
00234 if (m_channels.empty())
00235 return;
00236 sort(m_channels.begin(), m_channels.end());
00237 }
00238
00239 void AudioOutputSettings::SetBestSupportedChannels(int channels)
00240 {
00241 if (m_channels.empty())
00242 {
00243 m_channels.push_back(channels);
00244 return;
00245 }
00246
00247 vector<int>::reverse_iterator it;
00248
00249 for (it = m_channels.rbegin();
00250 it != m_channels.rend() && *it >= channels;
00251 ++it)
00252 {
00253 m_channels.pop_back();
00254 }
00255 m_channels.push_back(channels);
00256 }
00257
00258 void AudioOutputSettings::setFeature(bool val, int arg)
00259 {
00260 if (val)
00261 m_features |= arg;
00262 else
00263 m_features &= ~arg;
00264 };
00265
00266 void AudioOutputSettings::setFeature(bool val, DigitalFeature arg)
00267 {
00268 setFeature(val, (int) arg);
00269 };
00270
00277 AudioOutputSettings* AudioOutputSettings::GetCleaned(bool newcopy)
00278 {
00279 AudioOutputSettings* aosettings;
00280
00281 if (newcopy)
00282 {
00283 aosettings = new AudioOutputSettings;
00284 *aosettings = *this;
00285 }
00286 else
00287 aosettings = this;
00288
00289 if (m_invalid)
00290 return aosettings;
00291
00292 if (BestSupportedPCMChannelsELD() > 2)
00293 {
00294 aosettings->setFeature(FEATURE_LPCM);
00295 }
00296
00297 if (IsSupportedFormat(FORMAT_S16))
00298 {
00299
00300
00301
00302
00303 if (m_passthrough >= 0 && IsSupportedChannels(8) &&
00304 IsSupportedRate(192000))
00305 aosettings->setFeature(FEATURE_TRUEHD | FEATURE_DTSHD |
00306 FEATURE_EAC3);
00307
00308 if (m_passthrough >= 0)
00309 {
00310 if (BestSupportedChannels() == 2)
00311 {
00312 LOG(VB_AUDIO, LOG_INFO, LOC + "may be AC3 or DTS capable");
00313 aosettings->AddSupportedChannels(6);
00314 }
00315 aosettings->setFeature(FEATURE_AC3 | FEATURE_DTS);
00316 }
00317 }
00318 else
00319 {
00320
00321 aosettings->setPassthrough(-1);
00322 aosettings->setFeature(false,
00323 FEATURE_AC3 | FEATURE_DTS |
00324 FEATURE_EAC3 | FEATURE_TRUEHD | FEATURE_DTSHD);
00325 }
00326
00327 return aosettings;
00328 }
00329
00336 AudioOutputSettings* AudioOutputSettings::GetUsers(bool newcopy)
00337 {
00338 AudioOutputSettings* aosettings;
00339
00340 if (newcopy)
00341 aosettings = GetCleaned(newcopy);
00342 else
00343 aosettings = this;
00344
00345 if (aosettings->m_invalid)
00346 return aosettings;
00347
00348 int cur_channels = gCoreContext->GetNumSetting("MaxChannels", 2);
00349 int max_channels = aosettings->BestSupportedChannels();
00350
00351 bool bAC3 = aosettings->canFeature(FEATURE_AC3) &&
00352 gCoreContext->GetNumSetting("AC3PassThru", false);
00353
00354 bool bDTS = aosettings->canFeature(FEATURE_DTS) &&
00355 gCoreContext->GetNumSetting("DTSPassThru", false);
00356
00357 bool bLPCM = aosettings->canFeature(FEATURE_LPCM) &&
00358 !gCoreContext->GetNumSetting("StereoPCM", false);
00359
00360 bool bEAC3 = aosettings->canFeature(FEATURE_EAC3) &&
00361 gCoreContext->GetNumSetting("EAC3PassThru", false) &&
00362 !gCoreContext->GetNumSetting("Audio48kOverride", false);
00363
00364
00365 bool bTRUEHD = aosettings->canFeature(FEATURE_TRUEHD) &&
00366 gCoreContext->GetNumSetting("TrueHDPassThru", false) &&
00367 !gCoreContext->GetNumSetting("Audio48kOverride", false) &&
00368 gCoreContext->GetNumSetting("HBRPassthru", true);
00369
00370 bool bDTSHD = aosettings->canFeature(FEATURE_DTSHD) &&
00371 gCoreContext->GetNumSetting("DTSHDPassThru", false) &&
00372 !gCoreContext->GetNumSetting("Audio48kOverride", false);
00373
00374 if (max_channels > 2 && !bLPCM)
00375 max_channels = 2;
00376 if (max_channels == 2 && (bAC3 || bDTS))
00377 max_channels = 6;
00378
00379 if (cur_channels > max_channels)
00380 cur_channels = max_channels;
00381
00382 aosettings->SetBestSupportedChannels(cur_channels);
00383 aosettings->setFeature(bAC3, FEATURE_AC3);
00384 aosettings->setFeature(bDTS, FEATURE_DTS);
00385 aosettings->setFeature(bLPCM, FEATURE_LPCM);
00386 aosettings->setFeature(bEAC3, FEATURE_EAC3);
00387 aosettings->setFeature(bTRUEHD, FEATURE_TRUEHD);
00388 aosettings->setFeature(bDTSHD, FEATURE_DTSHD);
00389
00390 return aosettings;
00391 }
00392
00393 int AudioOutputSettings::GetMaxHDRate()
00394 {
00395 if (!canFeature(FEATURE_DTSHD))
00396 return 0;
00397
00398
00399 if (!gCoreContext->GetNumSetting("HBRPassthru", true) ||
00400 !canFeature(FEATURE_LPCM))
00401 {
00402 return 192000;
00403 }
00404 return 768000;
00405 }
00406
00407 #define ARG(x) ((tmp.isEmpty() ? "" : ",") + QString(x))
00408
00409 QString AudioOutputSettings::FeaturesToString(DigitalFeature arg)
00410 {
00411 QString tmp;
00412 DigitalFeature feature[] = {
00413 FEATURE_AC3,
00414 FEATURE_DTS,
00415 FEATURE_LPCM,
00416 FEATURE_EAC3,
00417 FEATURE_TRUEHD,
00418 FEATURE_DTSHD,
00419 FEATURE_AAC,
00420 (DigitalFeature)-1
00421 };
00422 const char *feature_str[] = {
00423 "AC3",
00424 "DTS",
00425 "LPCM",
00426 "EAC3",
00427 "TRUEHD",
00428 "DTSHD",
00429 "AAC",
00430 NULL
00431 };
00432
00433 for (unsigned int i = 0; feature[i] != (DigitalFeature)-1; i++)
00434 {
00435 if (arg & feature[i])
00436 tmp += ARG(feature_str[i]);
00437 }
00438 return tmp;
00439 }
00440
00441 QString AudioOutputSettings::GetPassthroughParams(int codec, int codec_profile,
00442 int &samplerate,
00443 int &channels,
00444 bool canDTSHDMA)
00445 {
00446 QString log;
00447
00448 channels = 2;
00449
00450 switch (codec)
00451 {
00452 case CODEC_ID_AC3:
00453 log = "AC3";
00454 break;
00455 case CODEC_ID_EAC3:
00456 samplerate = samplerate * 4;
00457 log = "Dolby Digital Plus (E-AC3)";
00458 break;
00459 case CODEC_ID_DTS:
00460 switch(codec_profile)
00461 {
00462 case FF_PROFILE_DTS_ES:
00463 log = "DTS-ES";
00464 break;
00465 case FF_PROFILE_DTS_96_24:
00466 log = "DTS 96/24";
00467 break;
00468 case FF_PROFILE_DTS_HD_HRA:
00469 samplerate = 192000;
00470 log = "DTS-HD High-Res";
00471 break;
00472 case FF_PROFILE_DTS_HD_MA:
00473 samplerate = 192000;
00474 if (canDTSHDMA)
00475 {
00476 log = "DTS-HD MA";
00477 channels = 8;
00478 }
00479 else
00480 {
00481 log = "DTS-HD High-Res";
00482 }
00483 break;
00484 case FF_PROFILE_DTS:
00485 default:
00486 log = "DTS Core";
00487 break;
00488 }
00489 break;
00490 case CODEC_ID_TRUEHD:
00491 channels = 8;
00492 log = "TrueHD";
00493 switch(samplerate)
00494 {
00495 case 48000:
00496 case 96000:
00497 case 192000:
00498 samplerate = 192000;
00499 break;
00500 case 44100:
00501 case 88200:
00502 case 176400:
00503 samplerate = 176400;
00504 break;
00505 default:
00506 log = "TrueHD: Unsupported samplerate";
00507 break;
00508 }
00509 break;
00510 default:
00511 break;
00512 }
00513 return log;
00514 }
00515
00516 bool AudioOutputSettings::hasValidELD()
00517 {
00518 return m_has_eld && m_eld.isValid();
00519 };
00520
00521 bool AudioOutputSettings::hasELD()
00522 {
00523 return m_has_eld;
00524 };
00525
00526 void AudioOutputSettings::setELD(QByteArray *ba)
00527 {
00528 m_has_eld = true;
00529 m_eld = ELD(ba->constData(), ba->size());
00530 m_eld.show();
00531 }
00532
00533 int AudioOutputSettings::BestSupportedChannelsELD()
00534 {
00535 int chan = AudioOutputSettings::BestSupportedChannels();
00536 if (!hasValidELD())
00537 return chan;
00538 int eldc = m_eld.maxChannels();
00539 return eldc < chan ? eldc : chan;
00540 }
00541
00542 int AudioOutputSettings::BestSupportedPCMChannelsELD()
00543 {
00544 int chan = AudioOutputSettings::BestSupportedChannels();
00545 if (!hasValidELD())
00546 return chan;
00547 int eldc = m_eld.maxLPCMChannels();
00548 return eldc < chan ? eldc : chan;
00549 }