MythTV  master
audiooutputsettings.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2  *
3  * Copyright (C) 2010 foobum@gmail.com and jyavenard@gmail.com
4  *
5  * Licensed under the GPL v2 or a later version at your choosing.
6  */
7 
8 #include <algorithm>
9 #include <vector>
10 
11 using namespace std;
12 
13 #include "audiooutputsettings.h"
14 #include "mythlogging.h"
15 #include "mythcorecontext.h"
16 
17 extern "C" {
18 #include "libavutil/avutil.h" // to check version of libavformat
19 }
20 #include "eldutils.h"
21 
22 #define LOC QString("AOS: ")
23 
25  m_invalid(invalid), m_eld(ELD())
26 {
27  m_sr.assign(srs, srs +
28  sizeof(srs) / sizeof(int));
29  m_sf.assign(fmts, fmts +
30  sizeof(fmts) / sizeof(AudioFormat));
31  m_sr_it = m_sr.begin();
32  m_sf_it = m_sf.begin();
33 }
34 
36 {
37  m_sr.clear();
38  m_rates.clear();
39  m_sf.clear();
40  m_formats.clear();
41  m_channels.clear();
42 }
43 
45  const AudioOutputSettings &rhs)
46 {
47  if (this == &rhs)
48  return *this;
49  m_sr = rhs.m_sr;
50  m_rates = rhs.m_rates;
51  m_sf = rhs.m_sf;
52  m_formats = rhs.m_formats;
53  m_channels = rhs.m_channels;
55  m_features = rhs.m_features;
56  m_invalid = rhs.m_invalid;
57  m_has_eld = rhs.m_has_eld;
58  m_eld = rhs.m_eld;
59  m_sr_it = m_sr.begin() + (rhs.m_sr_it - rhs.m_sr.begin());
60  m_sf_it = m_sf.begin() + (rhs.m_sf_it - rhs.m_sf.begin());
61  return *this;
62 }
63 
65 {
66  if (m_sr_it == m_sr.end())
67  {
68  m_sr_it = m_sr.begin();
69  return 0;
70  }
71 
72  return *m_sr_it++;
73 }
74 
76 {
77  m_rates.push_back(rate);
78  LOG(VB_AUDIO, LOG_INFO, LOC +
79  QString("Sample rate %1 is supported").arg(rate));
80 }
81 
83 {
84  if (m_rates.empty() && rate == 48000)
85  return true;
86 
87  vector<int>::iterator it;
88 
89  for (it = m_rates.begin(); it != m_rates.end(); ++it)
90  if (*it == rate)
91  return true;
92 
93  return false;
94 }
95 
97 {
98  if (m_rates.empty())
99  return 48000;
100  return m_rates.back();
101 }
102 
104 {
105  if (m_rates.empty())
106  return 48000;
107 
108  vector<int>::iterator it;
109 
110  // Assume rates vector is sorted
111  for (it = m_rates.begin(); it != m_rates.end(); ++it)
112  {
113  if (*it >= rate)
114  return *it;
115  }
116  // Not found, so return highest available rate
117  return m_rates.back();
118 }
119 
121 {
122  if (m_sf_it == m_sf.end())
123  {
124  m_sf_it = m_sf.begin();
125  return FORMAT_NONE;
126  }
127 
128  return *m_sf_it++;
129 }
130 
132 {
133  LOG(VB_AUDIO, LOG_INFO, LOC +
134  QString("Format %1 is supported").arg(FormatToString(format)));
135  m_formats.push_back(format);
136 }
137 
139 {
140  if (m_formats.empty() && format == FORMAT_S16)
141  return true;
142 
143  vector<AudioFormat>::iterator it;
144 
145  for (it = m_formats.begin(); it != m_formats.end(); ++it)
146  if (*it == format)
147  return true;
148 
149  return false;
150 }
151 
153 {
154  if (m_formats.empty())
155  return FORMAT_S16;
156  return m_formats.back();
157 }
158 
160 {
161  switch (format)
162  {
163  case FORMAT_U8: return 8;
164  case FORMAT_S16: return 16;
165  case FORMAT_S24LSB:
166  case FORMAT_S24: return 24;
167  case FORMAT_S32:
168  case FORMAT_FLT: return 32;
169  case FORMAT_NONE:
170  default: return -1;
171  }
172 }
173 
175 {
176  switch (format)
177  {
178  case FORMAT_U8: return "unsigned 8 bit";
179  case FORMAT_S16: return "signed 16 bit";
180  case FORMAT_S24: return "signed 24 bit MSB";
181  case FORMAT_S24LSB: return "signed 24 bit LSB";
182  case FORMAT_S32: return "signed 32 bit";
183  case FORMAT_FLT: return "32 bit floating point";
184  case FORMAT_NONE: return "none";
185  default: return "unknown";
186  }
187 }
188 
190 {
191  switch (format)
192  {
193  case FORMAT_U8: return 1;
194  case FORMAT_S16: return 2;
195  case FORMAT_S24:
196  case FORMAT_S24LSB:
197  case FORMAT_S32:
198  case FORMAT_FLT: return 4;
199  case FORMAT_NONE:
200  default: return 0;
201  }
202 }
203 
208 {
209  switch (av_get_packed_sample_fmt(format))
210  {
211  case AV_SAMPLE_FMT_U8: return FORMAT_U8;
212  case AV_SAMPLE_FMT_S16: return FORMAT_S16;
213  case AV_SAMPLE_FMT_FLT: return FORMAT_FLT;
214  case AV_SAMPLE_FMT_DBL: return FORMAT_NONE;
215  case AV_SAMPLE_FMT_S32:
216  switch (bits)
217  {
218  case 0: return FORMAT_S32;
219  case 24: return FORMAT_S24;
220  case 32: return FORMAT_S32;
221  default: return FORMAT_NONE;
222  }
223  default: return FORMAT_NONE;
224  }
225 }
226 
233 {
234  switch (format)
235  {
236  case FORMAT_U8: return AV_SAMPLE_FMT_U8;
237  case FORMAT_S16: return AV_SAMPLE_FMT_S16;
238  case FORMAT_FLT: return AV_SAMPLE_FMT_FLT;
239  case FORMAT_S32:
240  case FORMAT_S24:
241  case FORMAT_S24LSB: return AV_SAMPLE_FMT_S32;
242  default: return AV_SAMPLE_FMT_NONE;
243  }
244 }
245 
247 {
248  m_channels.push_back(channels);
249  LOG(VB_AUDIO, LOG_INFO, LOC + QString("%1 channel(s) are supported")
250  .arg(channels));
251 }
252 
254 {
255  if (m_channels.empty() && channels == 2)
256  return true;
257 
258  vector<int>::iterator it;
259 
260  for (it = m_channels.begin(); it != m_channels.end(); ++it)
261  if (*it == channels)
262  return true;
263 
264  return false;
265 }
266 
268 {
269  if (m_channels.empty())
270  return 2;
271  return m_channels.back();
272 }
273 
275 {
276  if (m_channels.empty())
277  return;
278  sort(m_channels.begin(), m_channels.end());
279 }
280 
282 {
283  if (m_channels.empty())
284  {
285  m_channels.push_back(channels);
286  return;
287  }
288 
289  vector<int>::reverse_iterator it;
290 
291  for (it = m_channels.rbegin();
292  it != m_channels.rend() && *it >= channels;
293  ++it)
294  {
295  m_channels.pop_back();
296  }
297  m_channels.push_back(channels);
298 }
299 
300 void AudioOutputSettings::setFeature(bool val, int arg)
301 {
302  if (val)
303  m_features |= arg;
304  else
305  m_features &= ~arg;
306 };
307 
309 {
310  setFeature(val, (int) arg);
311 };
312 
320 {
321  AudioOutputSettings* aosettings;
322 
323  if (newcopy)
324  {
325  aosettings = new AudioOutputSettings;
326  *aosettings = *this;
327  }
328  else
329  aosettings = this;
330 
331  if (m_invalid)
332  return aosettings;
333 
334  if (BestSupportedPCMChannelsELD() > 2)
335  {
336  aosettings->setFeature(FEATURE_LPCM);
337  }
338 
340  {
341  // E-AC3 is transferred as stereo PCM at 4 times the rates
342  // assume all amplifier supporting E-AC3 also supports 7.1 LPCM
343  // as it's mandatory under the bluray standard
344 //#if LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 52, 83, 0 )
345  if (m_passthrough >= 0 && IsSupportedChannels(8) &&
346  IsSupportedRate(192000))
347  aosettings->setFeature(FEATURE_TRUEHD | FEATURE_DTSHD |
348  FEATURE_EAC3);
349 //#endif
350  if (m_passthrough >= 0)
351  {
352  if (BestSupportedChannels() == 2)
353  {
354  LOG(VB_AUDIO, LOG_INFO, LOC + "may be AC3 or DTS capable");
355  aosettings->AddSupportedChannels(6);
356  }
357  aosettings->setFeature(FEATURE_AC3 | FEATURE_DTS);
358  }
359  }
360  else
361  {
362  // Can't do digital passthrough without 16 bits audio
363  aosettings->setPassthrough(-1);
364  aosettings->setFeature(false,
367  }
368 
369  return aosettings;
370 }
371 
379 {
380  AudioOutputSettings* aosettings;
381 
382  if (newcopy)
383  aosettings = GetCleaned(newcopy);
384  else
385  aosettings = this;
386 
387  if (aosettings->m_invalid)
388  return aosettings;
389 
390  int cur_channels = gCoreContext->GetNumSetting("MaxChannels", 2);
391  int max_channels = aosettings->BestSupportedChannels();
392 
393  bool bAC3 = aosettings->canFeature(FEATURE_AC3) &&
394  gCoreContext->GetBoolSetting("AC3PassThru", false);
395 
396  bool bDTS = aosettings->canFeature(FEATURE_DTS) &&
397  gCoreContext->GetBoolSetting("DTSPassThru", false);
398 
399  bool bLPCM = aosettings->canFeature(FEATURE_LPCM) &&
400  !gCoreContext->GetBoolSetting("StereoPCM", false);
401 
402  bool bEAC3 = aosettings->canFeature(FEATURE_EAC3) &&
403  gCoreContext->GetBoolSetting("EAC3PassThru", false) &&
404  !gCoreContext->GetBoolSetting("Audio48kOverride", false);
405 
406  // TrueHD requires HBR support.
407  bool bTRUEHD = aosettings->canFeature(FEATURE_TRUEHD) &&
408  gCoreContext->GetBoolSetting("TrueHDPassThru", false) &&
409  !gCoreContext->GetBoolSetting("Audio48kOverride", false) &&
410  gCoreContext->GetBoolSetting("HBRPassthru", true);
411 
412  bool bDTSHD = aosettings->canFeature(FEATURE_DTSHD) &&
413  gCoreContext->GetBoolSetting("DTSHDPassThru", false) &&
414  !gCoreContext->GetBoolSetting("Audio48kOverride", false);
415 
416  if (max_channels > 2 && !bLPCM)
417  max_channels = 2;
418  if (max_channels == 2 && (bAC3 || bDTS))
419  max_channels = 6;
420 
421  if (cur_channels > max_channels)
422  cur_channels = max_channels;
423 
424  aosettings->SetBestSupportedChannels(cur_channels);
425  aosettings->setFeature(bAC3, FEATURE_AC3);
426  aosettings->setFeature(bDTS, FEATURE_DTS);
427  aosettings->setFeature(bLPCM, FEATURE_LPCM);
428  aosettings->setFeature(bEAC3, FEATURE_EAC3);
429  aosettings->setFeature(bTRUEHD, FEATURE_TRUEHD);
430  aosettings->setFeature(bDTSHD, FEATURE_DTSHD);
431 
432  return aosettings;
433 }
434 
436 {
438  return 0;
439 
440  // If no HBR or no LPCM, limit bitrate to 6.144Mbit/s
441  if (!gCoreContext->GetBoolSetting("HBRPassthru", true) ||
443  {
444  return 192000; // E-AC3/DTS-HD High Res: 192k, 16 bits, 2 ch
445  }
446  return 768000; // TrueHD or DTS-HD MA: 192k, 16 bits, 8 ch
447 }
448 
449 #define ARG(x) ((tmp.isEmpty() ? "" : ",") + QString(x))
450 
452 {
453  QString tmp;
454  DigitalFeature feature[] = {
455  FEATURE_AC3,
456  FEATURE_DTS,
457  FEATURE_LPCM,
458  FEATURE_EAC3,
461  FEATURE_AAC,
462  (DigitalFeature)-1
463  };
464  const char *feature_str[] = {
465  "AC3",
466  "DTS",
467  "LPCM",
468  "EAC3",
469  "TRUEHD",
470  "DTSHD",
471  "AAC",
472  nullptr
473  };
474 
475  for (unsigned int i = 0; feature[i] != (DigitalFeature)-1; i++)
476  {
477  if (arg & feature[i])
478  tmp += ARG(feature_str[i]);
479  }
480  return tmp;
481 }
482 
483 QString AudioOutputSettings::GetPassthroughParams(int codec, int codec_profile,
484  int &samplerate,
485  int &channels,
486  bool canDTSHDMA)
487 {
488  QString log;
489 
490  channels = 2;
491 
492  switch (codec)
493  {
494  case AV_CODEC_ID_AC3:
495  log = "AC3";
496  break;
497  case AV_CODEC_ID_EAC3:
498  samplerate = samplerate * 4;
499  log = "Dolby Digital Plus (E-AC3)";
500  break;
501  case AV_CODEC_ID_DTS:
502  switch(codec_profile)
503  {
504  case FF_PROFILE_DTS_ES:
505  log = "DTS-ES";
506  break;
507  case FF_PROFILE_DTS_96_24:
508  log = "DTS 96/24";
509  break;
510  case FF_PROFILE_DTS_HD_HRA:
511  samplerate = 192000;
512  log = "DTS-HD High-Res";
513  break;
514  case FF_PROFILE_DTS_HD_MA:
515  samplerate = 192000;
516  if (canDTSHDMA)
517  {
518  log = "DTS-HD MA";
519  channels = 8;
520  }
521  else
522  {
523  log = "DTS-HD High-Res";
524  }
525  break;
526  case FF_PROFILE_DTS:
527  default:
528  log = "DTS Core";
529  break;
530  }
531  break;
532  case AV_CODEC_ID_TRUEHD:
533  channels = 8;
534  log = "TrueHD";
535  switch(samplerate)
536  {
537  case 48000:
538  case 96000:
539  case 192000:
540  samplerate = 192000;
541  break;
542  case 44100:
543  case 88200:
544  case 176400:
545  samplerate = 176400;
546  break;
547  default:
548  log = "TrueHD: Unsupported samplerate";
549  break;
550  }
551  break;
552  default:
553  break;
554  }
555  return log;
556 }
557 
559 {
560  return m_has_eld && m_eld.isValid();
561 };
562 
564 {
565  return m_has_eld;
566 };
567 
568 void AudioOutputSettings::setELD(QByteArray *ba)
569 {
570  m_has_eld = true;
571  m_eld = ELD(ba->constData(), ba->size());
572  m_eld.show();
573 }
574 
576 {
578  if (!hasValidELD())
579  return chan;
580  int eldc = m_eld.maxChannels();
581  return eldc < chan ? eldc : chan;
582 }
583 
585 {
587  if (!hasValidELD())
588  return chan;
589  int eldc = m_eld.maxLPCMChannels();
590  return eldc < chan ? eldc : chan;
591 }
int NearestSupportedRate(int rate)
static const AudioFormat fmts[]
bool IsSupportedChannels(int channels)
void setELD(QByteArray *ba)
set ELD data
Definition: eldutils.h:39
bool IsSupportedFormat(AudioFormat format)
int BestSupportedPCMChannelsELD()
Reports best supported PCM channel number, restricted to ELD.
void setPassthrough(int val)
void SetBestSupportedChannels(int channels)
Force set the greatest number of channels supported by the audio device.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
int BestSupportedChannelsELD()
Reports best supported channel number, restricted to ELD range.
static const char * FormatToString(AudioFormat format)
static int FormatToBits(AudioFormat format)
static guint32 * tmp
Definition: goom_core.c:35
static QString GetPassthroughParams(int codec, int codec_profile, int &samplerate, int &channels, bool canDTSHDMA)
Setup samplerate and number of channels for passthrough.
std::vector< AudioFormat > m_formats
static const int srs[]
std::vector< int >::iterator m_sr_it
AudioFormat BestSupportedFormat()
std::vector< AudioFormat > m_sf
AudioOutputSettings(bool invalid=false)
void setFeature(DigitalFeature arg)
set the provided digital feature possible values are:
#define LOC
static int SampleSize(AudioFormat format)
QString FeaturesToString(void)
int maxChannels()
Definition: eldutils.cpp:495
int maxLPCMChannels()
Definition: eldutils.cpp:480
def log(debug, txt)
Definition: utilities.py:5
bool canFeature(DigitalFeature arg)
return DigitalFeature mask.
bool m_has_eld
will be set to true if we were able to retrieve the device ELD (EDID like Data).
std::vector< int > m_channels
void show()
Definition: eldutils.cpp:443
AudioOutputSettings & operator=(const AudioOutputSettings &)
int GetNumSetting(const QString &key, int defaultval=0)
std::vector< int > m_sr
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
AudioOutputSettings * GetCleaned(bool newcopy=false)
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
std::vector< AudioFormat >::iterator m_sf_it
bool GetBoolSetting(const QString &key, bool defaultval=false)
void AddSupportedRate(int rate)
#define ARG(x)
bool IsSupportedRate(int rate)
int GetMaxHDRate()
return the highest iec958 rate supported.
bool isValid()
Definition: eldutils.cpp:438
std::vector< int > m_rates
AudioOutputSettings * GetUsers(bool newcopy=false)
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
DigitalFeature
void AddSupportedFormat(AudioFormat format)
bool hasELD()
get the ELD flag
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
int m_passthrough
passthrough status -1 : no 0: unknown 1: yes
void AddSupportedChannels(int channels)
static AVSampleFormat FormatToAVSampleFormat(AudioFormat format)
Return AudioFormat closest equivalent to AVSampleFormat Note that FORMAT_S24LSB and FORMAT_S24 have n...