MythTV  master
audiooutputbase.cpp
Go to the documentation of this file.
1 // C++ headers
2 #include <algorithm>
3 #include <cmath>
4 #include <limits>
5 
6 // POSIX headers
7 #include <unistd.h>
8 #include <sys/time.h>
9 
10 // SoundTouch
11 #if __has_include(<soundtouch/SoundTouch.h>)
12 #include <soundtouch/SoundTouch.h>
13 #else
14 #include <SoundTouch.h>
15 #endif
16 
17 // Qt headers
18 #include <QtGlobal>
19 #include <QMutexLocker>
20 
21 // MythTV headers
22 #include "libmythbase/compat.h"
23 #include "libmythbase/mythconfig.h"
26 
27 #include "audiooutputbase.h"
29 #include "audiooutputdownmix.h"
30 #include "audiooutpututil.h"
31 #include "spdifencoder.h"
32 
33 // AC3 encode currently disabled for Android
34 #if defined(Q_OS_ANDROID)
35 #define DISABLE_AC3_ENCODE
36 #endif
37 
38 #define LOC QString("AOBase: ")
39 
40 // Replacing "m_audioBuffer + org_waud" with
41 // "&m_audioBuffer[org_waud]" should provide bounds
42 // checking with c++17 arrays.
43 #define WPOS (&m_audioBuffer[org_waud])
44 #define RPOS (&m_audioBuffer[m_raud])
45 #define ABUF (m_audioBuffer.data())
46 #define STST soundtouch::SAMPLETYPE
47 
48 // 1,2,5 and 7 channels are currently valid for upmixing if required
49 static constexpr int UPMIX_CHANNEL_MASK { (1<<1)|(1<<2)|(1<<5)|(1<<7) };
50 static constexpr bool IS_VALID_UPMIX_CHANNEL(int ch)
51 { return ((1 << ch) & UPMIX_CHANNEL_MASK) != 0; }
52 
54 {
55  switch(q)
56  {
57  case QUALITY_DISABLED: return "disabled";
58  case QUALITY_LOW: return "low";
59  case QUALITY_MEDIUM: return "medium";
60  case QUALITY_HIGH: return "high";
61  default: return "unknown";
62  }
63 }
64 
66  MThread("AudioOutputBase"),
67  // protected
68  m_mainDevice(settings.GetMainDevice()),
69  m_passthruDevice(settings.GetPassthruDevice()),
70  m_source(settings.m_source),
71  m_setInitialVol(settings.m_setInitialVol)
72 {
73  m_srcIn = m_srcInBuf.data();
74 
75  if (m_mainDevice.startsWith("AudioTrack:"))
76  m_usesSpdif = false;
77  // Handle override of SRC quality settings
78  if (gCoreContext->GetBoolSetting("SRCQualityOverride", false))
79  {
81  // Extra test to keep backward compatibility with earlier SRC setting
84 
85  VBAUDIO(QString("SRC quality = %1").arg(quality_string(m_srcQuality)));
86  }
87 }
88 
95 {
96  if (!m_killAudio)
97  VBERROR("Programmer Error: "
98  "~AudioOutputBase called, but KillAudio has not been called!");
99 
100  // We got this from a subclass, delete it
101  delete m_outputSettings;
102  delete m_outputSettingsRaw;
104  {
107  }
108 
109  if (m_kAudioSRCOutputSize > 0)
110  delete[] m_srcOut;
111 
112 #ifndef NDEBUG
113  assert(m_memoryCorruptionTest0 == 0xdeadbeef);
114  assert(m_memoryCorruptionTest1 == 0xdeadbeef);
115  assert(m_memoryCorruptionTest2 == 0xdeadbeef);
116  assert(m_memoryCorruptionTest3 == 0xdeadbeef);
117 #else
118  Q_UNUSED(m_memoryCorruptionTest0);
119  Q_UNUSED(m_memoryCorruptionTest1);
120  Q_UNUSED(m_memoryCorruptionTest2);
121  Q_UNUSED(m_memoryCorruptionTest3);
122 #endif
123 }
124 
126 {
127  if (settings.m_custom)
128  {
129  // got a custom audio report already, use it
130  // this was likely provided by the AudioTest utility
132  *m_outputSettings = *settings.m_custom;
136  return;
137  }
138 
139  // Ask the subclass what we can send to the device
142 
146 
148  gCoreContext->GetBoolSetting("AudioDefaultUpmix", false) :
149  false;
150  if (settings.m_upmixer == 1) // music, upmixer off
151  m_upmixDefault = false;
152  else if (settings.m_upmixer == 2) // music, upmixer on
153  m_upmixDefault = true;
154 }
155 
162 {
163  // If we've already checked the port, use the cache
164  // version instead
165  if (!m_discreteDigital || !digital)
166  {
167  digital = false;
169  return m_outputSettingsRaw;
170  }
173 
174  AudioOutputSettings* aosettings = GetOutputSettings(digital);
175  if (aosettings)
176  aosettings->GetCleaned();
177  else
178  aosettings = new AudioOutputSettings(true);
179 
180  if (digital)
181  return (m_outputSettingsDigitalRaw = aosettings);
182  return (m_outputSettingsRaw = aosettings);
183 }
184 
191 {
192  if (!m_discreteDigital || !digital)
193  {
194  digital = false;
195  if (m_outputSettings)
196  return m_outputSettings;
197  }
198  else if (m_outputSettingsDigital)
200 
201  auto* aosettings = new AudioOutputSettings;
202 
203  *aosettings = *GetOutputSettingsCleaned(digital);
204  aosettings->GetUsers();
205 
206  if (digital)
207  return (m_outputSettingsDigital = aosettings);
208  return (m_outputSettings = aosettings);
209 }
210 
214 bool AudioOutputBase::CanPassthrough(int samplerate, int channels,
215  AVCodecID codec, int profile) const
216 {
218  bool ret = !(m_internalVol && SWVolume());
219 
220  switch(codec)
221  {
222  case AV_CODEC_ID_AC3:
223  arg = FEATURE_AC3;
224  break;
225  case AV_CODEC_ID_DTS:
226  switch(profile)
227  {
228  case FF_PROFILE_DTS:
229  case FF_PROFILE_DTS_ES:
230  case FF_PROFILE_DTS_96_24:
231  arg = FEATURE_DTS;
232  break;
233  case FF_PROFILE_DTS_HD_HRA:
234  case FF_PROFILE_DTS_HD_MA:
235  arg = FEATURE_DTSHD;
236  break;
237  default:
238  break;
239  }
240  break;
241  case AV_CODEC_ID_EAC3:
242  arg = FEATURE_EAC3;
243  break;
244  case AV_CODEC_ID_TRUEHD:
245  arg = FEATURE_TRUEHD;
246  break;
247  default:
248  arg = FEATURE_NONE;
249  break;
250  }
251  // we can't passthrough any other codecs than those defined above
252  ret &= m_outputSettingsDigital->canFeature(arg);
254  ret &= m_outputSettingsDigital->IsSupportedRate(samplerate);
255  // if we must resample to 48kHz ; we can't passthrough
256  ret &= (samplerate == 48000) ||
257  !gCoreContext->GetBoolSetting("Audio48kOverride", false);
258  // Don't know any cards that support spdif clocked at < 44100
259  // Some US cable transmissions have 2ch 32k AC-3 streams
260  ret &= samplerate >= 44100;
261  if (!ret)
262  return false;
263  // Will passthrough if surround audio was defined. Amplifier will
264  // do the downmix if required
265  bool willupmix = m_maxChannels >= 6 && (channels <= 2 && m_upmixDefault);
266  ret &= !willupmix;
267  // unless audio is configured for stereo. We can passthrough otherwise
268  ret |= m_maxChannels == 2;
269 
270  return ret;
271 }
272 
277 {
278  if (rate > 0)
279  m_sourceBitRate = rate;
280 }
281 
287 void AudioOutputBase::SetStretchFactorLocked(float lstretchfactor)
288 {
289  if (m_stretchFactor == lstretchfactor && m_pSoundStretch)
290  return;
291 
292  m_stretchFactor = lstretchfactor;
293 
294  int channels = m_needsUpmix || m_needsDownmix ?
296  if (channels < 1 || channels > 8 || !m_configureSucceeded)
297  return;
298 
299  bool willstretch = m_stretchFactor < 0.99F || m_stretchFactor > 1.01F;
300  m_effStretchFactor = lroundf(100000.0F * lstretchfactor);
301 
302  if (m_pSoundStretch)
303  {
304  if (!willstretch && m_forcedProcessing)
305  {
306  m_forcedProcessing = false;
307  m_processing = false;
308  delete m_pSoundStretch;
309  m_pSoundStretch = nullptr;
310  VBGENERAL(QString("Cancelling time stretch"));
312  m_waud = m_raud = 0;
313  m_resetActive.Ref();
314  }
315  else
316  {
317  VBGENERAL(QString("Changing time stretch to %1")
318  .arg(m_stretchFactor));
319  m_pSoundStretch->setTempo(m_stretchFactor);
320  }
321  }
322  else if (willstretch)
323  {
324  VBGENERAL(QString("Using time stretch %1").arg(m_stretchFactor));
325  m_pSoundStretch = new soundtouch::SoundTouch();
326  m_pSoundStretch->setSampleRate(m_sampleRate);
327  m_pSoundStretch->setChannels(channels);
328  m_pSoundStretch->setTempo(m_stretchFactor);
329 #if defined(Q_PROCESSOR_ARM) || defined(Q_OS_ANDROID)
330  // use less demanding settings for Raspberry pi
331  m_pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 82);
332  m_pSoundStretch->setSetting(SETTING_USE_AA_FILTER, 0);
333  m_pSoundStretch->setSetting(SETTING_USE_QUICKSEEK, 1);
334 #else
335  m_pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35);
336 #endif
337  /* If we weren't already processing we need to turn on float conversion
338  adjust sample and frame sizes accordingly and dump the contents of
339  the audiobuffer */
340  if (!m_processing)
341  {
342  m_processing = true;
343  m_forcedProcessing = true;
348  m_framesBuffered = 0;
349  m_waud = m_raud = 0;
350  m_resetActive.Ref();
352  m_pauseAudio = true;
353  m_actuallyPaused = false;
354  m_unpauseWhenReady = true;
355  }
356  }
357 }
358 
362 void AudioOutputBase::SetStretchFactor(float lstretchfactor)
363 {
364  QMutexLocker lock(&m_audioBufLock);
365  SetStretchFactorLocked(lstretchfactor);
366 }
367 
372 {
373  return m_stretchFactor;
374 }
375 
380 {
381  return m_needsUpmix && m_upmixer;
382 }
383 
388 {
389  // Can only upmix from mono/stereo to 6 ch
390  if (m_maxChannels == 2 || m_sourceChannels > 2)
391  return false;
392 
394 
397  m_upmixDefault ? false : m_passthru);
398  Reconfigure(settings);
399  return IsUpmixing();
400 }
401 
406 {
407  return m_sourceChannels <= 2 && m_maxChannels > 2;
408 }
409 
410 /*
411  * Setup samplerate and number of channels for passthrough
412  * Create SPDIF encoder and true if successful
413  */
414 bool AudioOutputBase::SetupPassthrough(AVCodecID codec, int codec_profile,
415  int &samplerate_tmp, int &channels_tmp)
416 {
417  if (codec == AV_CODEC_ID_DTS &&
419  {
420  // We do not support DTS-HD bitstream so force extraction of the
421  // DTS core track instead
422  codec_profile = FF_PROFILE_DTS;
423  }
425  codec, codec_profile,
426  samplerate_tmp, channels_tmp,
428  VBAUDIO("Setting " + log + " passthrough");
429 
430  delete m_spdifEnc;
431 
432  // No spdif encoder needed for certain devices
433  if (m_usesSpdif)
434  m_spdifEnc = new SPDIFEncoder("spdif", codec);
435  else
436  m_spdifEnc = nullptr;
437  if (m_spdifEnc && m_spdifEnc->Succeeded() && codec == AV_CODEC_ID_DTS)
438  {
439  switch(codec_profile)
440  {
441  case FF_PROFILE_DTS:
442  case FF_PROFILE_DTS_ES:
443  case FF_PROFILE_DTS_96_24:
445  break;
446  case FF_PROFILE_DTS_HD_HRA:
447  case FF_PROFILE_DTS_HD_MA:
448  m_spdifEnc->SetMaxHDRate(samplerate_tmp * channels_tmp / 2);
449  break;
450  }
451  }
452 
453  if (m_spdifEnc && !m_spdifEnc->Succeeded())
454  {
455  delete m_spdifEnc;
456  m_spdifEnc = nullptr;
457  return false;
458  }
459  return true;
460 }
461 
463 {
464  if (digital)
466  return m_outputSettings;
467 }
468 
474 void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
475 {
476  AudioSettings settings = orig_settings;
477  int lsource_channels = settings.m_channels;
478  int lconfigured_channels = m_configuredChannels;
479  bool lneeds_upmix = false;
480  bool lneeds_downmix = false;
481  bool lreenc = false;
482  bool lenc = false;
483 
484  if (!settings.m_usePassthru)
485  {
486  // Do we upmix stereo or mono?
487  lconfigured_channels =
488  (m_upmixDefault && lsource_channels <= 2) ? 6 : lsource_channels;
489  bool cando_channels =
490  m_outputSettings->IsSupportedChannels(lconfigured_channels);
491 
492  // check if the number of channels could be transmitted via AC3 encoding
493 #ifndef DISABLE_AC3_ENCODE
496  lconfigured_channels > 2 && lconfigured_channels <= 6);
497 #endif
498  if (!lenc && !cando_channels)
499  {
500  // if hardware doesn't support source audio configuration
501  // we will upmix/downmix to what we can
502  // (can safely assume hardware supports stereo)
503  switch (lconfigured_channels)
504  {
505  case 7:
506  lconfigured_channels = 8;
507  break;
508  case 8:
509  case 5:
510  lconfigured_channels = 6;
511  break;
512  case 6:
513  case 4:
514  case 3:
515  case 2: //Will never happen
516  lconfigured_channels = 2;
517  break;
518  case 1:
519  lconfigured_channels = m_upmixDefault ? 6 : 2;
520  break;
521  default:
522  lconfigured_channels = 2;
523  break;
524  }
525  }
526  // Make sure we never attempt to output more than what we can
527  // the upmixer can only upmix to 6 channels when source < 6
528  if (lsource_channels <= 6)
529  lconfigured_channels = std::min(lconfigured_channels, 6);
530  lconfigured_channels = std::min(lconfigured_channels, m_maxChannels);
531  /* Encode to AC-3 if we're allowed to passthru but aren't currently
532  and we have more than 2 channels but multichannel PCM is not
533  supported or if the device just doesn't support the number of
534  channels */
535 #ifndef DISABLE_AC3_ENCODE
538  lconfigured_channels > 2) ||
539  !m_outputSettings->IsSupportedChannels(lconfigured_channels));
540  /* Might we reencode a bitstream that's been decoded for timestretch?
541  If the device doesn't support the number of channels - see below */
543  (settings.m_codec == AV_CODEC_ID_AC3 ||
544  settings.m_codec == AV_CODEC_ID_DTS))
545  {
546  lreenc = true;
547  }
548 #endif
549  // Enough channels? Upmix if not, but only from mono/stereo/5.0 to 5.1
550  if (IS_VALID_UPMIX_CHANNEL(settings.m_channels) &&
551  settings.m_channels < lconfigured_channels)
552  {
553  VBAUDIO(QString("Needs upmix from %1 -> %2 channels")
554  .arg(settings.m_channels).arg(lconfigured_channels));
555  settings.m_channels = lconfigured_channels;
556  lneeds_upmix = true;
557  }
558  else if (settings.m_channels > lconfigured_channels)
559  {
560  VBAUDIO(QString("Needs downmix from %1 -> %2 channels")
561  .arg(settings.m_channels).arg(lconfigured_channels));
562  settings.m_channels = lconfigured_channels;
563  lneeds_downmix = true;
564  }
565  }
566 
567  ClearError();
568 
569  bool general_deps = true;
570 
571  /* Set samplerate_tmp and channels_tmp to appropriate values
572  if passing through */
573  int samplerate_tmp = 0;
574  int channels_tmp = 0;
575  if (settings.m_usePassthru)
576  {
577  samplerate_tmp = settings.m_sampleRate;
578  SetupPassthrough(settings.m_codec, settings.m_codecProfile,
579  samplerate_tmp, channels_tmp);
580  general_deps = m_sampleRate == samplerate_tmp && m_channels == channels_tmp;
581  general_deps &= m_format == m_outputFormat && m_format == FORMAT_S16;
582  }
583  else
584  {
585  general_deps =
586  settings.m_format == m_format && lsource_channels == m_sourceChannels;
587  }
588 
589  // Check if anything has changed
590  general_deps &=
591  settings.m_sampleRate == m_sourceSampleRate &&
592  settings.m_usePassthru == m_passthru &&
593  lconfigured_channels == m_configuredChannels &&
594  lneeds_upmix == m_needsUpmix && lreenc == m_reEnc &&
595  lneeds_downmix == m_needsDownmix;
596 
597  if (general_deps && m_configureSucceeded)
598  {
599  VBAUDIO("Reconfigure(): No change -> exiting");
600  // if passthrough, source channels may have changed
601  m_sourceChannels = lsource_channels;
602  return;
603  }
604 
605  KillAudio();
606 
607  QMutexLocker lock(&m_audioBufLock);
608  QMutexLocker lockav(&m_avsyncLock);
609 
610  m_waud = m_raud = 0;
613 
614  m_channels = settings.m_channels;
615  m_sourceChannels = lsource_channels;
616  m_reEnc = lreenc;
617  m_codec = settings.m_codec;
618  m_passthru = settings.m_usePassthru;
619  m_configuredChannels = lconfigured_channels;
620  m_needsUpmix = lneeds_upmix;
621  m_needsDownmix = lneeds_downmix;
622  m_format = m_outputFormat = settings.m_format;
624  m_enc = lenc;
625 
626  m_killAudio = m_pauseAudio = false;
627  m_wasPaused = true;
628 
629  // Don't try to do anything if audio hasn't been
630  // initialized yet (e.g. rubbish was provided)
631  if (m_sourceChannels <= 0 || m_format <= 0 || m_sampleRate <= 0)
632  {
633  SilentError(QString("Aborting Audio Reconfigure. ") +
634  QString("Invalid audio parameters ch %1 fmt %2 @ %3Hz")
635  .arg(m_sourceChannels).arg(m_format).arg(m_sampleRate));
636  return;
637  }
638 
639  VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels")
640  .arg(avcodec_get_name(m_codec),
642  .arg(m_sampleRate/1000)
643  .arg(m_sourceChannels));
644 
645  if (m_needsDownmix && m_sourceChannels > 8)
646  {
647  Error(QObject::tr("Aborting Audio Reconfigure. "
648  "Can't handle audio with more than 8 channels."));
649  return;
650  }
651 
652  VBAUDIO(QString("enc(%1), passthru(%2), features (%3) "
653  "configured_channels(%4), %5 channels supported(%6) "
654  "max_channels(%7)")
655  .arg(m_enc)
656  .arg(m_passthru)
659  .arg(m_channels)
660  .arg(OutputSettings(m_enc || m_passthru)->IsSupportedChannels(m_channels))
661  .arg(m_maxChannels));
662 
663  int dest_rate = 0;
664 
665  // Force resampling if we are encoding to AC3 and sr > 48k
666  // or if 48k override was checked in settings
667  if ((m_sampleRate != 48000 &&
668  gCoreContext->GetBoolSetting("Audio48kOverride", false)) ||
669  (m_enc && (m_sampleRate > 48000)))
670  {
671  VBAUDIO("Forcing resample to 48 kHz");
672  if (m_srcQuality < 0)
674  m_needResampler = true;
675  dest_rate = 48000;
676  }
677  // this will always be false for passthrough audio as
678  // CanPassthrough() already tested these conditions
679  else if ((m_needResampler =
680  !OutputSettings(m_enc || m_passthru)->IsSupportedRate(m_sampleRate)))
681  {
683  }
684 
686  {
687  m_sampleRate = dest_rate;
688 
689  VBGENERAL(QString("Resampling from %1 kHz to %2 kHz with quality %3")
690  .arg(settings.m_sampleRate/1000).arg(m_sampleRate/1000)
692 
694 
695  int error = 0;
696  m_srcCtx = src_new(2-m_srcQuality, chans, &error);
697  if (error)
698  {
699  Error(QObject::tr("Error creating resampler: %1")
700  .arg(src_strerror(error)));
701  m_srcCtx = nullptr;
702  return;
703  }
704 
705  m_srcData.src_ratio = (double)m_sampleRate / settings.m_sampleRate;
706  m_srcData.data_in = m_srcIn;
707  int newsize = (int)(kAudioSRCInputSize * m_srcData.src_ratio + 15)
708  & ~0xf;
709 
710  if (m_kAudioSRCOutputSize < newsize)
711  {
712  m_kAudioSRCOutputSize = newsize;
713  VBAUDIO(QString("Resampler allocating %1").arg(newsize));
714  delete[] m_srcOut;
715  m_srcOut = new float[m_kAudioSRCOutputSize];
716  }
717  m_srcData.data_out = m_srcOut;
718  m_srcData.output_frames = m_kAudioSRCOutputSize / chans;
719  m_srcData.end_of_input = 0;
720  }
721 
722  if (m_enc)
723  {
724  if (m_reEnc)
725  VBAUDIO("Reencoding decoded AC-3/DTS to AC-3");
726 
727  VBAUDIO(QString("Creating AC-3 Encoder with sr = %1, ch = %2")
729 
731  if (!m_encoder->Init(AV_CODEC_ID_AC3, 448000, m_sampleRate,
733  {
734  Error(QObject::tr("AC-3 encoder initialization failed"));
735  delete m_encoder;
736  m_encoder = nullptr;
737  m_enc = false;
738  // upmixing will fail if we needed the encoder
739  m_needsUpmix = false;
740  }
741  }
742 
743  if (m_passthru)
744  {
745  //AC3, DTS, DTS-HD MA and TrueHD all use 16 bits samples
746  m_channels = channels_tmp;
747  m_sampleRate = samplerate_tmp;
751  }
752  else
753  {
756  }
757 
758  // Turn on float conversion?
760  m_stretchFactor != 1.0F || (m_internalVol && SWVolume()) ||
761  (m_enc && m_outputFormat != FORMAT_S16) ||
762  !OutputSettings(m_enc || m_passthru)->IsSupportedFormat(m_outputFormat))
763  {
764  VBAUDIO("Audio processing enabled");
765  m_processing = true;
766  if (m_enc)
767  m_outputFormat = FORMAT_S16; // Output s16le for AC-3 encoder
768  else
770  }
771 
773  sizeof(float) : AudioOutputSettings::SampleSize(m_format);
775 
776  if (m_enc)
777  m_channels = 2; // But only post-encoder
778 
781 
782  VBGENERAL(
783  QString("Opening audio device '%1' ch %2(%3) sr %4 sf %5 reenc %6")
786 
788  m_framesBuffered = 0;
789  m_currentSeconds = -1s;
790  m_sourceBitRate = -1;
791  m_effDsp = m_sampleRate * 100;
792 
793  // Actually do the device specific open call
794  if (!OpenDevice())
795  {
796  if (GetError().isEmpty())
797  Error(QObject::tr("Aborting reconfigure"));
798  else
799  VBGENERAL("Aborting reconfigure");
800  m_configureSucceeded = false;
801  return;
802  }
803 
804  VBAUDIO(QString("Audio fragment size: %1").arg(m_fragmentSize));
805 
806  // Only used for software volume
808  {
809  VBAUDIO("Software volume enabled");
810  m_volumeControl = gCoreContext->GetSetting("MixerControl", "PCM");
811  m_volumeControl += "MixerVolume";
813  }
814 
818 
820  {
824  VBAUDIO(QString("Create %1 quality upmixer done")
826  }
827 
828  VBAUDIO(QString("Audio Stretch Factor: %1").arg(m_stretchFactor));
830 
831  // Setup visualisations, zero the visualisations buffers
832  prepareVisuals();
833 
834  if (m_unpauseWhenReady)
836 
837  m_configureSucceeded = true;
838 
840 
841  VBAUDIO("Ending Reconfigure()");
842 }
843 
845 {
847  return true;
848 
849  start();
850  m_audioThreadExists = true;
851 
852  return true;
853 }
854 
855 
857 {
859  {
860  wait();
861  m_audioThreadExists = false;
862  }
863 }
864 
869 {
870  m_killAudioLock.lock();
871 
872  VBAUDIO("Killing AudioOutputDSP");
873  m_killAudio = true;
875  QMutexLocker lock(&m_audioBufLock);
876 
877  if (m_pSoundStretch)
878  {
879  delete m_pSoundStretch;
880  m_pSoundStretch = nullptr;
882  m_stretchFactor = 1.0F;
883  }
884 
885  if (m_encoder)
886  {
887  delete m_encoder;
888  m_encoder = nullptr;
889  }
890 
891  if (m_upmixer)
892  {
893  delete m_upmixer;
894  m_upmixer = nullptr;
895  }
896 
897  if (m_srcCtx)
898  {
899  src_delete(m_srcCtx);
900  m_srcCtx = nullptr;
901  }
902 
903  m_needsUpmix = m_needResampler = m_enc = false;
904 
905  CloseDevice();
906 
907  m_killAudioLock.unlock();
908 }
909 
910 void AudioOutputBase::Pause(bool paused)
911 {
912  if (!paused && m_unpauseWhenReady)
913  return;
914  VBAUDIO(QString("Pause %1").arg(paused));
915  if (m_pauseAudio != paused)
917  m_pauseAudio = paused;
918  m_unpauseWhenReady = false;
919  m_actuallyPaused = false;
920 }
921 
923 {
924  Reset();
925  Pause(true);
926  m_unpauseWhenReady = true;
927 }
928 
933 {
934  QMutexLocker lock(&m_audioBufLock);
935  QMutexLocker lockav(&m_avsyncLock);
936 
938  m_framesBuffered = 0;
939  if (m_encoder)
940  {
941  m_waud = m_raud = 0; // empty ring buffer
942  m_audioBuffer.fill(0);
943  }
944  else
945  {
946  m_waud = m_raud; // empty ring buffer
947  }
948  m_resetActive.Ref();
949  m_currentSeconds = -1s;
951  m_unpauseWhenReady = false;
952  // clear any state that could remember previous audio in any active filters
953  if (m_needsUpmix && m_upmixer)
954  m_upmixer->flush();
955  if (m_pSoundStretch)
956  m_pSoundStretch->clear();
957  if (m_encoder)
958  m_encoder->clear();
959 
960  // Setup visualisations, zero the visualisations buffers
961  prepareVisuals();
962 }
963 
970 void AudioOutputBase::SetTimecode(std::chrono::milliseconds timecode)
971 {
972  m_audbufTimecode = m_audioTime = timecode;
973  m_framesBuffered = (timecode.count() * m_sourceSampleRate) / 1000;
974 }
975 
982 void AudioOutputBase::SetEffDsp(int dsprate)
983 {
984  VBAUDIO(QString("SetEffDsp: %1").arg(dsprate));
985  m_effDsp = dsprate;
986 }
987 
991 inline int AudioOutputBase::audiolen() const
992 {
993  if (m_waud >= m_raud)
994  return m_waud - m_raud;
995  return kAudioRingBufferSize - (m_raud - m_waud);
996 }
997 
1002 {
1003  return kAudioRingBufferSize - audiolen() - 1;
1004  /* There is one wasted byte in the buffer. The case where m_waud = m_raud is
1005  interpreted as an empty buffer, so the fullest the buffer can ever
1006  be is kAudioRingBufferSize - 1. */
1007 }
1008 
1017 {
1019  return audiolen();
1021 }
1022 
1026 std::chrono::milliseconds AudioOutputBase::GetAudiotime(void)
1027 {
1028  if (m_audbufTimecode == 0ms || !m_configureSucceeded)
1029  return 0ms;
1030 
1031  // output bits per 10 frames
1032  int64_t obpf = 0;
1033 
1034  if (m_passthru && !usesSpdif())
1035  obpf = m_sourceBitRate * 10 / m_sourceSampleRate;
1036  else if (m_enc && !usesSpdif())
1037  {
1038  // re-encode bitrate is hardcoded at 448000
1039  obpf = 448000 * 10 / m_sourceSampleRate;
1040  }
1041  else
1042  obpf = static_cast<int64_t>(m_outputBytesPerFrame) * 80;
1043 
1044  /* We want to calculate 'm_audioTime', which is the timestamp of the audio
1045  Which is leaving the sound card at this instant.
1046 
1047  We use these variables:
1048 
1049  'm_effDsp' is 100 * frames/sec
1050 
1051  'm_audbufTimecode' is the timecode in milliseconds of the
1052  audio that has just been written into the buffer.
1053 
1054  'm_effStretchFactor' is stretch factor * 100,000
1055 
1056  'totalbuffer' is the total # of bytes in our audio buffer, and the
1057  sound card's buffer. */
1058 
1059 
1060  QMutexLocker lockav(&m_avsyncLock);
1061 
1062  int64_t soundcard_buffer = GetBufferedOnSoundcard(); // bytes
1063 
1064  /* audioready tells us how many bytes are in audiobuffer
1065  scaled appropriately if output format != internal format */
1066  int64_t main_buffer = audioready();
1067 
1068  std::chrono::milliseconds oldaudiotime = m_audioTime;
1069 
1070  /* timecode is the stretch adjusted version
1071  of major post-stretched buffer contents
1072  processing latencies are catered for in AddData/SetAudiotime
1073  to eliminate race */
1074 
1075  m_audioTime = m_audbufTimecode - std::chrono::milliseconds(m_effDsp && obpf ?
1076  ((main_buffer + soundcard_buffer) * int64_t(m_effStretchFactor)
1077  * 80 / int64_t(m_effDsp) / obpf) : 0);
1078 
1079  /* audiotime should never go backwards, but we might get a negative
1080  value if GetBufferedOnSoundcard() isn't updated by the driver very
1081  quickly (e.g. ALSA) */
1082  if (m_audioTime < oldaudiotime)
1083  m_audioTime = oldaudiotime;
1084 
1085  VBAUDIOTS(QString("GetAudiotime audt=%1 abtc=%2 mb=%3 sb=%4 tb=%5 "
1086  "sr=%6 obpf=%7 bpf=%8 esf=%9 edsp=%10 sbr=%11")
1087  .arg(m_audioTime.count()) // 1
1088  .arg(m_audbufTimecode.count()) // 2
1089  .arg(main_buffer) // 3
1090  .arg(soundcard_buffer) // 4
1091  .arg(main_buffer+soundcard_buffer) // 5
1092  .arg(m_sampleRate).arg(obpf) // 6, 7
1093  .arg(m_bytesPerFrame) // 8
1094  .arg(m_effStretchFactor) // 9
1095  .arg(m_effDsp).arg(m_sourceBitRate) // 10, 11
1096  );
1097 
1098  return m_audioTime;
1099 }
1100 
1106 void AudioOutputBase::SetAudiotime(int frames, std::chrono::milliseconds timecode)
1107 {
1108  int64_t processframes_stretched = 0;
1109  int64_t processframes_unstretched = 0;
1110  std::chrono::milliseconds old_audbuf_timecode = m_audbufTimecode;
1111 
1112  if (!m_configureSucceeded)
1113  return;
1114 
1115  if (m_needsUpmix && m_upmixer)
1116  processframes_unstretched -= m_upmixer->frameLatency();
1117 
1118  if (m_pSoundStretch)
1119  {
1120  processframes_unstretched -= m_pSoundStretch->numUnprocessedSamples();
1121  processframes_stretched -= m_pSoundStretch->numSamples();
1122  }
1123 
1124  if (m_encoder)
1125  {
1126  processframes_stretched -= m_encoder->Buffered();
1127  }
1128 
1130  timecode + std::chrono::milliseconds(m_effDsp ? ((frames + processframes_unstretched) * 100000 +
1131  (processframes_stretched * m_effStretchFactor)
1132  ) / m_effDsp : 0);
1133 
1134  // check for timecode wrap and reset audiotime if detected
1135  // timecode will always be monotonic asc if not seeked and reset
1136  // happens if seek or pause happens
1137  if (m_audbufTimecode < old_audbuf_timecode)
1138  m_audioTime = 0ms;
1139 
1140  VBAUDIOTS(QString("SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
1141  .arg(m_audbufTimecode.count())
1142  .arg(timecode.count())
1143  .arg(frames)
1144  .arg(processframes_unstretched)
1145  .arg(processframes_stretched));
1146 #ifdef AUDIOTSTESTING
1147  GetAudiotime();
1148 #endif
1149 }
1150 
1156 std::chrono::milliseconds AudioOutputBase::GetAudioBufferedTime(void)
1157 {
1158  std::chrono::milliseconds ret = m_audbufTimecode - GetAudiotime();
1159  // Pulse can give us values that make this -ve
1160  if (ret < 0ms)
1161  return 0ms;
1162  return ret;
1163 }
1164 
1168 void AudioOutputBase::SetSWVolume(int new_volume, bool save)
1169 {
1170  m_volume = new_volume;
1171  if (save && m_volumeControl != nullptr)
1173 }
1174 
1179 {
1180  return m_volume;
1181 }
1182 
1192 {
1193  int bpf = m_bytesPerFrame;
1194  int len = frames * bpf;
1195  int afree = audiofree();
1196 
1197  if (len <= afree)
1198  return len;
1199 
1200  VBERROR(QString("Audio buffer overflow, %1 frames lost!")
1201  .arg(frames - (afree / bpf)));
1202 
1203  frames = afree / bpf;
1204  len = frames * bpf;
1205 
1206  if (!m_srcCtx)
1207  return len;
1208 
1209  int error = src_reset(m_srcCtx);
1210  if (error)
1211  {
1212  VBERROR(QString("Error occurred while resetting resampler: %1")
1213  .arg(src_strerror(error)));
1214  m_srcCtx = nullptr;
1215  }
1216 
1217  return len;
1218 }
1219 
1226 int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, uint &org_waud)
1227 {
1228  int len = CheckFreeSpace(frames);
1229  int bdiff = kAudioRingBufferSize - org_waud;
1230  int bpf = m_bytesPerFrame;
1231  ptrdiff_t off = 0;
1232 
1233  if (!m_needsUpmix)
1234  {
1235  int num = len;
1236 
1237  if (bdiff <= num)
1238  {
1239  memcpy(WPOS, buffer, bdiff);
1240  num -= bdiff;
1241  off = bdiff;
1242  org_waud = 0;
1243  }
1244  if (num > 0)
1245  memcpy(WPOS, buffer + off, num);
1246  org_waud = (org_waud + num) % kAudioRingBufferSize;
1247  return len;
1248  }
1249 
1250  // Convert mono to stereo as most devices can't accept mono
1251  if (!m_upmixer)
1252  {
1253  // we're always in the case
1254  // m_configuredChannels == 2 && m_sourceChannels == 1
1255  int bdFrames = bdiff / bpf;
1256  if (bdFrames <= frames)
1257  {
1258  AudioOutputUtil::MonoToStereo(WPOS, buffer, bdFrames);
1259  frames -= bdFrames;
1260  off = bdFrames * sizeof(float); // 1 channel of floats
1261  org_waud = 0;
1262  }
1263  if (frames > 0)
1264  AudioOutputUtil::MonoToStereo(WPOS, buffer + off, frames);
1265 
1266  org_waud = (org_waud + frames * bpf) % kAudioRingBufferSize;
1267  return len;
1268  }
1269 
1270  // Upmix to 6ch via FreeSurround
1271  // Calculate frame size of input
1272  off = m_processing ? sizeof(float) : AudioOutputSettings::SampleSize(m_format);
1273  off *= m_sourceChannels;
1274 
1275  int i = 0;
1276  len = 0;
1277  while (i < frames)
1278  {
1279  i += m_upmixer->putFrames(buffer + i * off, frames - i, m_sourceChannels);
1280  int nFrames = m_upmixer->numFrames();
1281  if (!nFrames)
1282  continue;
1283 
1284  len += CheckFreeSpace(nFrames);
1285 
1286  int bdFrames = (kAudioRingBufferSize - org_waud) / bpf;
1287  if (bdFrames < nFrames)
1288  {
1289  if ((org_waud % bpf) != 0)
1290  {
1291  VBERROR(QString("Upmixing: org_waud = %1 (bpf = %2)")
1292  .arg(org_waud)
1293  .arg(bpf));
1294  }
1295  m_upmixer->receiveFrames((float *)(WPOS), bdFrames);
1296  nFrames -= bdFrames;
1297  org_waud = 0;
1298  }
1299  if (nFrames > 0)
1300  m_upmixer->receiveFrames((float *)(WPOS), nFrames);
1301 
1302  org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
1303  }
1304  return len;
1305 }
1306 
1312 bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
1313  std::chrono::milliseconds timecode)
1314 {
1315  return AddData(in_buffer, in_frames * m_sourceBytesPerFrame, timecode,
1316  in_frames);
1317 }
1318 
1324 bool AudioOutputBase::AddData(void *in_buffer, int in_len,
1325  std::chrono::milliseconds timecode,
1326  int /*in_frames*/)
1327 {
1328  int frames = in_len / m_sourceBytesPerFrame;
1329  int bpf = m_bytesPerFrame;
1330  int len = in_len;
1331  bool music = false;
1332 
1333  if (!m_configureSucceeded)
1334  {
1335  LOG(VB_GENERAL, LOG_ERR, "AddData called with audio framework not "
1336  "initialised");
1337  m_lengthLastData = 0ms;
1338  return false;
1339  }
1340 
1341  /* See if we're waiting for new samples to be buffered before we unpause
1342  post channel change, seek, etc. Wait for 4 fragments to be buffered */
1344  {
1345  m_unpauseWhenReady = false;
1346  Pause(false);
1347  }
1348 
1349  // Don't write new samples if we're resetting the buffer or reconfiguring
1350  QMutexLocker lock(&m_audioBufLock);
1351 
1352  uint org_waud = m_waud;
1353  int afree = audiofree();
1354  int used = kAudioRingBufferSize - afree;
1355 
1356  if (m_passthru && m_spdifEnc)
1357  {
1358  if (m_processing)
1359  {
1360  /*
1361  * We shouldn't encounter this case, but it can occur when
1362  * timestretch just got activated. So we will just drop the
1363  * data
1364  */
1365  LOG(VB_AUDIO, LOG_INFO,
1366  "Passthrough activated with audio processing. Dropping audio");
1367  return false;
1368  }
1369  // mux into an IEC958 packet
1370  m_spdifEnc->WriteFrame((unsigned char *)in_buffer, len);
1371  len = m_spdifEnc->GetProcessedSize();
1372  if (len > 0)
1373  {
1374  in_buffer = m_spdifEnc->GetProcessedBuffer();
1375  m_spdifEnc->Reset();
1376  frames = len / m_sourceBytesPerFrame;
1377  }
1378  else
1379  frames = 0;
1380  }
1382  ((double)(len * 1000) / (m_sourceSampleRate * m_sourceBytesPerFrame));
1383 
1384  VBAUDIOTS(QString("AddData frames=%1, bytes=%2, used=%3, free=%4, "
1385  "timecode=%5 needsupmix=%6")
1386  .arg(frames).arg(len).arg(used).arg(afree).arg(timecode.count())
1387  .arg(m_needsUpmix));
1388 
1389  // Mythmusic doesn't give us timestamps
1390  if (timecode < 0ms)
1391  {
1392  timecode = std::chrono::milliseconds((m_framesBuffered * 1000) / m_sourceSampleRate);
1393  m_framesBuffered += frames;
1394  music = true;
1395  }
1396 
1397  if (hasVisual())
1398  {
1399  // Send original samples to any attached visualisations
1400  dispatchVisual((uchar *)in_buffer, len, timecode, m_sourceChannels,
1402  }
1403 
1404  // Calculate amount of free space required in ringbuffer
1405  if (m_processing)
1406  {
1407  int sampleSize = AudioOutputSettings::SampleSize(m_format);
1408  if (sampleSize <= 0)
1409  {
1410  // Would lead to division by zero (or unexpected results if negative)
1411  VBERROR("Sample size is <= 0, AddData returning false");
1412  return false;
1413  }
1414 
1415  // Final float conversion space requirement
1416  len = sizeof(m_srcInBuf[0]) / sampleSize * len;
1417 
1418  // Account for changes in number of channels
1419  if (m_needsDownmix)
1420  len = (len * m_configuredChannels ) / m_sourceChannels;
1421 
1422  // Check we have enough space to write the data
1423  if (m_needResampler && m_srcCtx)
1424  len = lround(ceil(static_cast<double>(len) * m_srcData.src_ratio));
1425 
1426  if (m_needsUpmix)
1427  len = (len * m_configuredChannels ) / m_sourceChannels;
1428 
1429  // Include samples in upmix buffer that may be flushed
1430  if (m_needsUpmix && m_upmixer)
1431  len += m_upmixer->numUnprocessedFrames() * bpf;
1432 
1433  // Include samples in soundstretch buffers
1434  if (m_pSoundStretch)
1435  len += (m_pSoundStretch->numUnprocessedSamples() +
1436  (int)(m_pSoundStretch->numSamples() / m_stretchFactor)) * bpf;
1437  }
1438 
1439  if (len > afree)
1440  {
1441  VBERROR("Buffer is full, AddData returning false");
1442  return false; // would overflow
1443  }
1444 
1445  int frames_remaining = frames;
1446  int frames_final = 0;
1447  int maxframes = (kAudioSRCInputSize / m_sourceChannels) & ~0xf;
1448  int offset = 0;
1449 
1450  while(frames_remaining > 0)
1451  {
1452  void *buffer = (char *)in_buffer + offset;
1453  frames = frames_remaining;
1454  len = frames * m_sourceBytesPerFrame;
1455 
1456  if (m_processing)
1457  {
1458  if (frames > maxframes)
1459  {
1460  frames = maxframes;
1461  len = frames * m_sourceBytesPerFrame;
1462  offset += len;
1463  }
1464  // Convert to floats
1465  AudioOutputUtil::toFloat(m_format, m_srcIn, buffer, len);
1466  }
1467 
1468  frames_remaining -= frames;
1469 
1470  // Perform downmix if necessary
1471  if (m_needsDownmix)
1472  {
1475  m_srcIn, m_srcIn, frames) < 0)
1476  VBERROR("Error occurred while downmixing");
1477  }
1478 
1479  // Resample if necessary
1480  if (m_needResampler && m_srcCtx)
1481  {
1482  m_srcData.input_frames = frames;
1483  int error = src_process(m_srcCtx, &m_srcData);
1484 
1485  if (error)
1486  VBERROR(QString("Error occurred while resampling audio: %1")
1487  .arg(src_strerror(error)));
1488 
1489  buffer = m_srcOut;
1490  frames = m_srcData.output_frames_gen;
1491  }
1492  else if (m_processing)
1493  buffer = m_srcIn;
1494 
1495  /* we want the timecode of the last sample added but we are given the
1496  timecode of the first - add the time in ms that the frames added
1497  represent */
1498 
1499  // Copy samples into audiobuffer, with upmix if necessary
1500  if ((len = CopyWithUpmix((char *)buffer, frames, org_waud)) <= 0)
1501  {
1502  continue;
1503  }
1504 
1505  frames = len / bpf;
1506  frames_final += frames;
1507 
1508  int bdiff = kAudioRingBufferSize - m_waud;
1509  if ((len % bpf) != 0 && bdiff < len)
1510  {
1511  VBERROR(QString("AddData: Corruption likely: len = %1 (bpf = %2)")
1512  .arg(len)
1513  .arg(bpf));
1514  }
1515  if ((bdiff % bpf) != 0 && bdiff < len)
1516  {
1517  VBERROR(QString("AddData: Corruption likely: bdiff = %1 (bpf = %2)")
1518  .arg(bdiff)
1519  .arg(bpf));
1520  }
1521 
1522  if (m_pSoundStretch)
1523  {
1524  // does not change the timecode, only the number of samples
1525  org_waud = m_waud;
1526  int bdFrames = bdiff / bpf;
1527 
1528  if (bdiff < len)
1529  {
1530  m_pSoundStretch->putSamples((STST *)(WPOS), bdFrames);
1531  m_pSoundStretch->putSamples((STST *)ABUF, (len - bdiff) / bpf);
1532  }
1533  else
1534  m_pSoundStretch->putSamples((STST *)(WPOS), frames);
1535 
1536  int nFrames = m_pSoundStretch->numSamples();
1537  if (nFrames > frames)
1538  CheckFreeSpace(nFrames);
1539 
1540  len = nFrames * bpf;
1541 
1542  if (nFrames > bdFrames)
1543  {
1544  nFrames -= m_pSoundStretch->receiveSamples((STST *)(WPOS),
1545  bdFrames);
1546  org_waud = 0;
1547  }
1548  if (nFrames > 0)
1549  nFrames = m_pSoundStretch->receiveSamples((STST *)(WPOS),
1550  nFrames);
1551 
1552  org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
1553  }
1554 
1555  if (m_internalVol && SWVolume())
1556  {
1557  org_waud = m_waud;
1558  int num = len;
1559 
1560  if (bdiff <= num)
1561  {
1563  music, m_needsUpmix && m_upmixer);
1564  num -= bdiff;
1565  org_waud = 0;
1566  }
1567  if (num > 0)
1569  music, m_needsUpmix && m_upmixer);
1570  org_waud = (org_waud + num) % kAudioRingBufferSize;
1571  }
1572 
1573  if (m_encoder)
1574  {
1575  org_waud = m_waud;
1576  int to_get = 0;
1577 
1578  if (bdiff < len)
1579  {
1581  to_get = m_encoder->Encode(ABUF, len - bdiff,
1583  }
1584  else
1585  {
1586  to_get = m_encoder->Encode(WPOS, len,
1588  }
1589 
1590  if (bdiff <= to_get)
1591  {
1592  m_encoder->GetFrames(WPOS, bdiff);
1593  to_get -= bdiff ;
1594  org_waud = 0;
1595  }
1596  if (to_get > 0)
1597  m_encoder->GetFrames(WPOS, to_get);
1598 
1599  org_waud = (org_waud + to_get) % kAudioRingBufferSize;
1600  }
1601 
1602  m_waud = org_waud;
1603  }
1604 
1605  SetAudiotime(frames_final, timecode);
1606 
1607  return true;
1608 }
1609 
1614 {
1615  std::chrono::milliseconds ct = GetAudiotime();
1616 
1617  if (ct < 0ms)
1618  ct = 0ms;
1619 
1620  if (m_sourceBitRate == -1)
1621  m_sourceBitRate = static_cast<long>(m_sourceSampleRate) * m_sourceChannels *
1623 
1624  if (duration_cast<std::chrono::seconds>(ct) != m_currentSeconds)
1625  {
1626  m_currentSeconds = duration_cast<std::chrono::seconds>(ct);
1629  dispatch(e);
1630  }
1631 }
1632 
1638 {
1639  fill = kAudioRingBufferSize - audiofree();
1640  total = kAudioRingBufferSize;
1641 }
1642 
1649 {
1650  auto *zeros = new(std::align_val_t(16)) uchar[m_fragmentSize];
1651  auto *fragment = new(std::align_val_t(16)) uchar[m_fragmentSize];
1652  memset(zeros, 0, m_fragmentSize);
1653 
1654  // to reduce startup latency, write silence in 8ms chunks
1655  int zero_fragment_size = 8 * m_sampleRate * m_outputBytesPerFrame / 1000;
1656  if (zero_fragment_size > m_fragmentSize)
1657  zero_fragment_size = m_fragmentSize;
1658 
1659  while (!m_killAudio)
1660  {
1661  if (m_pauseAudio)
1662  {
1663  if (!m_actuallyPaused)
1664  {
1665  VBAUDIO("OutputAudioLoop: audio paused");
1667  dispatch(e);
1668  m_wasPaused = true;
1669  }
1670 
1671  m_actuallyPaused = true;
1672  m_audioTime = 0ms; // mark 'audiotime' as invalid.
1673 
1674  WriteAudio(zeros, zero_fragment_size);
1675  continue;
1676  }
1677 
1678  if (m_wasPaused)
1679  {
1680  VBAUDIO("OutputAudioLoop: Play Event");
1682  dispatch(e);
1683  m_wasPaused = false;
1684  }
1685 
1686  /* do audio output */
1687  int ready = audioready();
1688 
1689  // wait for the buffer to fill with enough to play
1690  if (m_fragmentSize > ready)
1691  {
1692  if (ready > 0) // only log if we're sending some audio
1693  {
1694  VBAUDIOTS(QString("audio waiting for buffer to fill: "
1695  "have %1 want %2")
1696  .arg(ready).arg(m_fragmentSize));
1697  }
1698 
1699  usleep(10ms);
1700  continue;
1701  }
1702 
1703 #ifdef AUDIOTSTESTING
1704  VBAUDIOTS("WriteAudio Start");
1705 #endif
1706  Status();
1707 
1708  // delay setting raud until after phys buffer is filled
1709  // so GetAudiotime will be accurate without locking
1711  volatile uint next_raud = m_raud;
1712  if (GetAudioData(fragment, m_fragmentSize, true, &next_raud))
1713  {
1714  if (!m_resetActive.TestAndDeref())
1715  {
1716  WriteAudio(fragment, m_fragmentSize);
1717  if (!m_resetActive.TestAndDeref())
1718  m_raud = next_raud;
1719  }
1720  }
1721 #ifdef AUDIOTSTESTING
1722  GetAudiotime();
1723  VBAUDIOTS("WriteAudio Done");
1724 #endif
1725 
1726  }
1727 
1728  delete[] zeros;
1729  delete[] fragment;
1730  VBAUDIO("OutputAudioLoop: Stop Event");
1732  dispatch(e);
1733 }
1734 
1742 int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer,
1743  volatile uint *local_raud)
1744 {
1745 
1746 #define LRPOS (&m_audioBuffer[*local_raud])
1747  // re-check audioready() in case things changed.
1748  // for example, ClearAfterSeek() might have run
1749  int avail_size = audioready();
1750  int frag_size = size;
1751  int written_size = size;
1752 
1753  if (local_raud == nullptr)
1754  local_raud = &m_raud;
1755 
1756  if (!full_buffer && (size > avail_size))
1757  {
1758  // when full_buffer is false, return any available data
1759  frag_size = avail_size;
1760  written_size = frag_size;
1761  }
1762 
1763  if (!avail_size || (frag_size > avail_size))
1764  return 0;
1765 
1766  int bdiff = kAudioRingBufferSize - m_raud;
1767 
1769 
1770  if (obytes <= 0)
1771  return 0;
1772 
1773  bool fromFloats = m_processing && !m_enc && m_outputFormat != FORMAT_FLT;
1774 
1775  // Scale if necessary
1776  if (fromFloats && obytes != sizeof(float))
1777  frag_size *= sizeof(float) / obytes;
1778 
1779  int off = 0;
1780 
1781  if (bdiff <= frag_size)
1782  {
1783  if (fromFloats)
1784  {
1786  LRPOS, bdiff);
1787  }
1788  else
1789  {
1790  memcpy(buffer, LRPOS, bdiff);
1791  off = bdiff;
1792  }
1793 
1794  frag_size -= bdiff;
1795  *local_raud = 0;
1796  }
1797  if (frag_size > 0)
1798  {
1799  if (fromFloats)
1800  {
1802  LRPOS, frag_size);
1803  }
1804  else
1805  {
1806  memcpy(buffer + off, LRPOS, frag_size);
1807  }
1808  }
1809 
1810  *local_raud += frag_size;
1811 
1812  // Mute individual channels through mono->stereo duplication
1813  MuteState mute_state = GetMuteState();
1814  if (!m_enc && !m_passthru &&
1815  written_size && m_configuredChannels > 1 &&
1816  (mute_state == kMuteLeft || mute_state == kMuteRight))
1817  {
1819  mute_state == kMuteLeft ? 0 : 1,
1820  buffer, written_size);
1821  }
1822 
1823  return written_size;
1824 }
1825 
1830 {
1831  while (!m_pauseAudio && audioready() > m_fragmentSize)
1832  usleep(1ms);
1833  if (m_pauseAudio)
1834  {
1835  // Audio is paused and can't be drained, clear ringbuffer
1836  QMutexLocker lock(&m_audioBufLock);
1837 
1838  m_waud = m_raud = 0;
1839  }
1840 }
1841 
1846 {
1847  RunProlog();
1848  VBAUDIO(QString("kickoffOutputAudioLoop: pid = %1").arg(getpid()));
1849  OutputAudioLoop();
1850  VBAUDIO("kickoffOutputAudioLoop exiting");
1851  RunEpilog();
1852 }
1853 
1854 int AudioOutputBase::readOutputData(unsigned char* /*read_buffer*/, size_t /*max_length*/)
1855 {
1856  VBERROR("AudioOutputBase should not be getting asked to readOutputData()");
1857  return 0;
1858 }
AudioOutputBase::m_srcOut
float * m_srcOut
Definition: audiooutputbase.h:290
AudioOutput::GetError
QString GetError(void) const
Definition: audiooutput.h:148
AudioOutputBase::m_enc
bool m_enc
Definition: audiooutputbase.h:190
AudioOutputBase::m_outputSettingsRaw
AudioOutputSettings * m_outputSettingsRaw
Definition: audiooutputbase.h:225
AudioOutputBase::m_srcIn
float * m_srcIn
Definition: audiooutputbase.h:283
AudioOutputBase::Reset
void Reset(void) override
Reset the audiobuffer, timecode and mythmusic visualisation.
Definition: audiooutputbase.cpp:932
AudioOutputBase::m_pSoundStretch
soundtouch::SoundTouch * m_pSoundStretch
Definition: audiooutputbase.h:231
AudioOutputSettings::IsSupportedChannels
bool IsSupportedChannels(int channels)
Definition: audiooutputsettings.cpp:244
AudioOutputBase::m_discreteDigital
bool m_discreteDigital
Definition: audiooutputbase.h:187
AudioOutputBase::SetTimecode
void SetTimecode(std::chrono::milliseconds timecode) override
Set the timecode of the samples most recently added to the audiobuffer.
Definition: audiooutputbase.cpp:970
AudioOutputSettings::IsSupportedRate
bool IsSupportedRate(int rate)
Definition: audiooutputsettings.cpp:85
SPDIFEncoder::Succeeded
bool Succeeded() const
Definition: spdifencoder.h:24
AudioOutputBase::Pause
void Pause(bool paused) override
Definition: audiooutputbase.cpp:910
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
AudioOutputBase::m_raud
volatile uint m_raud
Audio circular buffer.
Definition: audiooutputbase.h:271
AudioOutputBase::AddData
bool AddData(void *buffer, int len, std::chrono::milliseconds timecode, int frames) override
Add data to the audiobuffer and perform any required processing.
Definition: audiooutputbase.cpp:1324
AudioOutputBase::CheckFreeSpace
int CheckFreeSpace(int &frames)
Check that there's enough space in the audiobuffer to write the provided number of frames.
Definition: audiooutputbase.cpp:1191
VBAUDIO
#define VBAUDIO(str)
Definition: audiooutputbase.h:20
FreeSurround::SurroundMode
SurroundMode
Definition: freesurround.h:29
FORMAT_S16
@ FORMAT_S16
Definition: audiooutputsettings.h:27
STST
#define STST
Definition: audiooutputbase.cpp:46
AudioOutputBase::audiolen
int audiolen() const
Get the number of bytes in the audiobuffer.
Definition: audiooutputbase.cpp:991
AudioOutputDigitalEncoder::Init
bool Init(AVCodecID codec_id, int bitrate, int samplerate, int channels)
Definition: audiooutputdigitalencoder.cpp:102
AudioOutputBase::m_resetActive
AsyncLooseLock m_resetActive
Definition: audiooutputbase.h:277
kMuteRight
@ kMuteRight
Definition: volumebase.h:9
OutputEvent
Definition: output.h:31
AudioOutputDigitalEncoder::GetFrames
int GetFrames(void *ptr, int maxlen)
Definition: audiooutputdigitalencoder.cpp:341
AudioOutputBase::m_avsyncLock
QMutex m_avsyncLock
must hold avsync_lock to read or write 'audiotime' and 'audiotime_updated'
Definition: audiooutputbase.h:261
audiooutpututil.h
ABUF
#define ABUF
Definition: audiooutputbase.cpp:45
AudioOutputBase::m_forcedProcessing
bool m_forcedProcessing
Definition: audiooutputbase.h:306
spdifencoder.h
AudioOutputBase::CanPassthrough
bool CanPassthrough(int samplerate, int channels, AVCodecID codec, int profile) const override
Test if we can output digital audio and if sample rate is supported.
Definition: audiooutputbase.cpp:214
AudioOutputBase::m_needResampler
bool m_needResampler
Definition: audiooutputbase.h:229
AudioOutput::Error
void Error(const QString &msg)
Definition: audiooutput.cpp:275
AudioOutputBase::CloseDevice
virtual void CloseDevice(void)=0
AudioOutputBase::m_configureSucceeded
bool m_configureSucceeded
Definition: audiooutputbase.h:298
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
OutputEvent::Stopped
static Type Stopped
Definition: output.h:67
AudioOutputBase::m_memoryCorruptionTest2
uint m_memoryCorruptionTest2
Definition: audiooutputbase.h:292
AudioOutputBase::SetupPassthrough
bool SetupPassthrough(AVCodecID codec, int codec_profile, int &samplerate_tmp, int &channels_tmp)
Definition: audiooutputbase.cpp:414
AudioOutputUtil::toFloat
static int toFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert integer samples to floats.
Definition: audiooutpututil.cpp:65
AudioOutputBase::audiofree
int audiofree() const
Get the free space in the audiobuffer in bytes.
Definition: audiooutputbase.cpp:1001
FEATURE_AC3
@ FEATURE_AC3
Definition: audiooutputsettings.h:36
AudioOutputBase::m_previousBpf
int m_previousBpf
Definition: audiooutputbase.h:307
SPDIFEncoder::Reset
void Reset()
Reset the internal encoder buffer.
Definition: spdifencoder.cpp:162
VolumeBase::m_internalVol
bool m_internalVol
Definition: volumebase.h:41
FreeSurround::numFrames
uint numFrames() const
Definition: freesurround.cpp:450
AudioOutputBase::KillAudio
void KillAudio(void)
Kill the output thread and cleanup.
Definition: audiooutputbase.cpp:868
AudioOutputSettings::FormatToBits
static int FormatToBits(AudioFormat format)
Definition: audiooutputsettings.cpp:150
MThread::usleep
static void usleep(std::chrono::microseconds time)
Definition: mthread.cpp:335
AudioOutputBase::readOutputData
int readOutputData(unsigned char *read_buffer, size_t max_length) override
Definition: audiooutputbase.cpp:1854
AudioOutputBase::GetAudiotime
std::chrono::milliseconds GetAudiotime(void) override
Calculate the timecode of the samples that are about to become audible.
Definition: audiooutputbase.cpp:1026
AudioOutputBase::GetStretchFactor
float GetStretchFactor(void) const override
Get the timetretch factor.
Definition: audiooutputbase.cpp:371
AudioSettings::m_codecProfile
int m_codecProfile
Definition: audiosettings.h:75
VBERROR
#define VBERROR(str)
Definition: audiooutputbase.h:23
AudioOutputSettings::SampleSize
static int SampleSize(AudioFormat format)
Definition: audiooutputsettings.cpp:180
FreeSurround
Definition: freesurround.h:26
VolumeBase::SyncVolume
void SyncVolume(void)
Definition: volumebase.cpp:209
IS_VALID_UPMIX_CHANNEL
static constexpr bool IS_VALID_UPMIX_CHANNEL(int ch)
Definition: audiooutputbase.cpp:50
AudioOutputDigitalEncoder::clear
void clear()
Definition: audiooutputdigitalencoder.cpp:354
FEATURE_TRUEHD
@ FEATURE_TRUEHD
Definition: audiooutputsettings.h:40
AudioOutputBase::IsUpmixing
bool IsUpmixing(void) override
Source is currently being upmixed.
Definition: audiooutputbase.cpp:379
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
AudioOutputBase::SetEffDsp
void SetEffDsp(int dsprate) override
Set the effective DSP rate.
Definition: audiooutputbase.cpp:982
AudioOutputBase::m_audbufTimecode
std::chrono::milliseconds m_audbufTimecode
timecode of audio most recently placed into buffer
Definition: audiooutputbase.h:276
FEATURE_EAC3
@ FEATURE_EAC3
Definition: audiooutputsettings.h:39
AudioOutputBase::quality_string
static const char * quality_string(int q)
Definition: audiooutputbase.cpp:53
freesurround.h
MythObservable::dispatch
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
Definition: mythobservable.cpp:73
AudioOutputBase::m_sampleRate
int m_sampleRate
Definition: audiooutputbase.h:180
OutputListeners::error
void error(const QString &e)
Definition: output.cpp:29
AudioOutputBase::m_volume
int m_volume
Definition: audiooutputbase.h:242
AudioOutputBase::m_sourceChannels
int m_sourceChannels
Definition: audiooutputbase.h:235
FreeSurround::putFrames
uint putFrames(void *buffer, uint numFrames, uint numChannels)
Definition: freesurround.cpp:147
AudioOutputBase::m_killAudio
bool m_killAudio
Definition: audiooutputbase.h:197
OutputListeners::hasVisual
bool hasVisual(void)
Definition: output.h:108
AudioOutputBase::SetAudiotime
void SetAudiotime(int frames, std::chrono::milliseconds timecode)
Set the timecode of the top of the ringbuffer Exclude all other processing elements as they dont vary...
Definition: audiooutputbase.cpp:1106
FreeSurround::numUnprocessedFrames
uint numUnprocessedFrames() const
Definition: freesurround.cpp:445
AudioOutputBase::GetBufferedOnSoundcard
virtual int GetBufferedOnSoundcard(void) const =0
Return the size in bytes of frames currently in the audio buffer adjusted with the audio playback lat...
AudioOutputBase::m_kAudioSRCOutputSize
int m_kAudioSRCOutputSize
Definition: audiooutputbase.h:291
MuteState
MuteState
Definition: volumebase.h:6
AudioOutputSettings::GetCleaned
AudioOutputSettings * GetCleaned(bool newcopy=false)
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
Definition: audiooutputsettings.cpp:304
AudioSettings::m_sampleRate
int m_sampleRate
Definition: audiosettings.h:76
AudioSettings
Definition: audiosettings.h:28
AudioOutputBase::m_lengthLastData
std::chrono::milliseconds m_lengthLastData
Definition: audiooutputbase.h:299
AudioOutputBase::m_mainDevice
QString m_mainDevice
Definition: audiooutputbase.h:185
AudioOutputUtil::MonoToStereo
static void MonoToStereo(void *dst, const void *src, int samples)
Convert a mono stream to stereo by copying and interleaving samples.
Definition: audiooutpututil.cpp:85
audiooutputdigitalencoder.h
AsyncLooseLock::Ref
void Ref()
Definition: audiooutputbase.h:41
AudioOutputBase::Drain
void Drain(void) override
Block until all available frames have been written to the device.
Definition: audiooutputbase.cpp:1829
AudioOutputBase::m_stretchFactor
float m_stretchFactor
Definition: audiooutputbase.h:193
AudioOutputBase::m_unpauseWhenReady
bool m_unpauseWhenReady
Definition: audiooutputbase.h:202
AudioOutputBase::m_srcInBuf
std::array< float, kAudioSRCInputSize > m_srcInBuf
Definition: audiooutputbase.h:288
AudioOutputDigitalEncoder
Definition: audiooutputdigitalencoder.h:14
AudioOutputBase::m_upmixer
FreeSurround * m_upmixer
Definition: audiooutputbase.h:233
OutputEvent::Playing
static Type Playing
Definition: output.h:63
AudioOutputBase::m_killAudioLock
QMutex m_killAudioLock
Definition: audiooutputbase.h:279
mythlogging.h
AudioOutputBase::m_srcQuality
int m_srcQuality
Definition: audiooutputbase.h:215
LRPOS
#define LRPOS
AudioOutputBase::m_volumeControl
QString m_volumeControl
Definition: audiooutputbase.h:243
AudioOutputBase::m_audioThreadExists
bool m_audioThreadExists
Definition: audiooutputbase.h:249
hardwareprofile.scan.profile
profile
Definition: scan.py:99
AudioOutputSettings::GetMaxHDRate
int GetMaxHDRate() const
return the highest iec958 rate supported.
Definition: audiooutputsettings.cpp:416
AudioOutputBase::m_format
AudioFormat m_format
Definition: audiooutputbase.h:178
AudioOutputBase::AudioOutputBase
AudioOutputBase(const AudioSettings &settings)
Definition: audiooutputbase.cpp:65
AudioOutputBase::m_waud
volatile uint m_waud
Definition: audiooutputbase.h:272
FEATURE_NONE
@ FEATURE_NONE
Definition: audiooutputsettings.h:35
AudioOutputDigitalEncoder::Buffered
int Buffered(void) const
Definition: audiooutputdigitalencoder.h:24
AudioOutputBase::m_sourceSampleRate
int m_sourceSampleRate
Definition: audiooutputbase.h:217
AudioOutputBase::QUALITY_LOW
@ QUALITY_LOW
Definition: audiooutputbase.h:211
AudioOutputSettings::BestSupportedChannels
int BestSupportedChannels()
Definition: audiooutputsettings.cpp:254
FEATURE_DTS
@ FEATURE_DTS
Definition: audiooutputsettings.h:37
AudioOutputBase::GetOutputSettingsCleaned
AudioOutputSettings * GetOutputSettingsCleaned(bool digital=true) override
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
Definition: audiooutputbase.cpp:161
compat.h
SPDIFEncoder::SetMaxHDRate
bool SetMaxHDRate(int rate)
Set the maximum HD rate.
Definition: spdifencoder.cpp:173
AudioOutputBase::m_needsUpmix
bool m_needsUpmix
Definition: audiooutputbase.h:238
AudioOutputBase::m_effStretchFactor
int m_effStretchFactor
Definition: audiooutputbase.h:194
AudioOutputBase::StopOutputThread
virtual void StopOutputThread(void)
Definition: audiooutputbase.cpp:856
FORMAT_FLT
@ FORMAT_FLT
Definition: audiooutputsettings.h:31
VBGENERAL
#define VBGENERAL(str)
Definition: audiooutputbase.h:22
AudioOutputBase::Reconfigure
void Reconfigure(const AudioSettings &settings) override
(Re)Configure AudioOutputBase
Definition: audiooutputbase.cpp:474
AudioOutputBase::GetOutputSettings
virtual AudioOutputSettings * GetOutputSettings(bool)
Definition: audiooutputbase.h:142
AudioOutputBase::~AudioOutputBase
~AudioOutputBase() override
Destructor.
Definition: audiooutputbase.cpp:94
AudioOutputBase::m_memoryCorruptionTest1
uint m_memoryCorruptionTest1
Definition: audiooutputbase.h:289
FEATURE_LPCM
@ FEATURE_LPCM
Definition: audiooutputsettings.h:38
AudioOutputBase::m_oldStretchFactor
float m_oldStretchFactor
Definition: audiooutputbase.h:241
AudioOutputBase::GetAudioData
int GetAudioData(uchar *buffer, int buf_size, bool full_buffer, volatile uint *local_raud=nullptr)
Copy frames from the audiobuffer into the buffer provided.
Definition: audiooutputbase.cpp:1742
VolumeBase::GetMuteState
virtual MuteState GetMuteState(void) const
Definition: volumebase.cpp:150
FreeSurround::frameLatency
uint frameLatency() const
Definition: freesurround.cpp:455
AudioOutputBase::m_maxChannels
int m_maxChannels
Definition: audiooutputbase.h:207
AudioOutputBase::m_currentSeconds
std::chrono::seconds m_currentSeconds
Definition: audiooutputbase.h:281
AudioSettings::m_upmixer
int m_upmixer
Definition: audiosettings.h:80
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
AudioOutputDigitalEncoder::Encode
int Encode(void *input, int len, AudioFormat format)
Definition: audiooutputdigitalencoder.cpp:166
AudioOutputBase::m_outputSettingsDigitalRaw
AudioOutputSettings * m_outputSettingsDigitalRaw
Definition: audiooutputbase.h:227
AudioSettings::m_custom
AudioOutputSettings * m_custom
custom contains a pointer to the audio device capabilities if defined, AudioOutput will not try to au...
Definition: audiosettings.h:92
AudioOutputBase::m_pauseAudio
bool m_pauseAudio
Definition: audiooutputbase.h:199
SPDIFEncoder::GetProcessedSize
int GetProcessedSize()
Definition: spdifencoder.cpp:145
AudioOutputBase::QUALITY_MEDIUM
@ QUALITY_MEDIUM
Definition: audiooutputbase.h:212
kMuteLeft
@ kMuteLeft
Definition: volumebase.h:8
AudioOutputSettings::canFeature
bool canFeature(DigitalFeature arg) const
return DigitalFeature mask.
Definition: audiooutputsettings.h:88
AudioOutputBase::kAudioRingBufferSize
static const uint kAudioRingBufferSize
Audio Buffer Size – should be divisible by 32,24,16,12,10,8,6,4,2..
Definition: audiooutputbase.h:126
FreeSurround::flush
void flush()
Definition: freesurround.cpp:418
AudioOutputBase::run
void run() override
Main routine for the output thread.
Definition: audiooutputbase.cpp:1845
AudioOutputBase::m_sourceBytesPerFrame
int m_sourceBytesPerFrame
Definition: audiooutputbase.h:236
uint
unsigned int uint
Definition: compat.h:81
SPDIFEncoder::WriteFrame
void WriteFrame(unsigned char *data, int size)
Encode data through created muxer unsigned char data: pointer to data to encode int size: size of dat...
Definition: spdifencoder.cpp:99
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:54
VolumeBase::SWVolume
bool SWVolume(void) const
Definition: volumebase.cpp:106
AudioOutputBase::m_upmixDefault
bool m_upmixDefault
Definition: audiooutputbase.h:237
AudioOutputBase::m_passthru
bool m_passthru
Definition: audiooutputbase.h:189
AudioOutputBase::OutputAudioLoop
void OutputAudioLoop(void)
Run in the output thread, write frames to the output device as they become available and there's spac...
Definition: audiooutputbase.cpp:1648
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:910
AudioOutputBase::m_outputFormat
AudioFormat m_outputFormat
Definition: audiooutputbase.h:179
AudioOutputBase::m_encoder
AudioOutputDigitalEncoder * m_encoder
Definition: audiooutputbase.h:232
AudioOutputBase::m_reEnc
bool m_reEnc
Definition: audiooutputbase.h:191
AudioOutputBase::GetSWVolume
int GetSWVolume(void) override
Get the volume for software volume control.
Definition: audiooutputbase.cpp:1178
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:904
AudioOutputBase::audioready
int audioready() const
Get the scaled number of bytes in the audiobuffer, i.e.
Definition: audiooutputbase.cpp:1016
AudioOutputBase::m_channels
int m_channels
Definition: audiooutputbase.h:174
AudioOutputBase::CopyWithUpmix
int CopyWithUpmix(char *buffer, int frames, uint &org_waud)
Copy frames into the audiobuffer, upmixing en route if necessary.
Definition: audiooutputbase.cpp:1226
AudioOutputBase::m_configuredChannels
int m_configuredChannels
Definition: audiooutputbase.h:206
AudioOutputBase::m_setInitialVol
bool m_setInitialVol
Definition: audiooutputbase.h:203
OutputEvent::Paused
static Type Paused
Definition: output.h:66
audiooutputdownmix.h
AudioOutputBase::m_spdifEnc
SPDIFEncoder * m_spdifEnc
Definition: audiooutputbase.h:303
AudioOutputBase::m_codec
AVCodecID m_codec
Definition: audiooutputbase.h:175
AudioOutputBase::SetSWVolume
void SetSWVolume(int new_volume, bool save) override
Set the volume for software volume control.
Definition: audiooutputbase.cpp:1168
AudioOutputBase::CanUpmix
bool CanUpmix(void) override
Upmixing of the current source is available if requested.
Definition: audiooutputbase.cpp:405
AudioSettings::m_usePassthru
bool m_usePassthru
Definition: audiosettings.h:78
AudioOutputBase::Status
virtual void Status(void)
Report status via an OutputEvent.
Definition: audiooutputbase.cpp:1613
assert
#define assert(x)
Definition: audiooutputalsa.cpp:16
AudioOutputBase::WriteAudio
virtual void WriteAudio(unsigned char *aubuf, int size)=0
AudioOutputBase::m_outputBytesPerFrame
int m_outputBytesPerFrame
Definition: audiooutputbase.h:177
audiooutputbase.h
AudioOutputBase::m_sourceBitRate
long m_sourceBitRate
Definition: audiooutputbase.h:216
AudioOutputDownmix::DownmixFrames
static int DownmixFrames(int channels_in, int channels_out, float *dst, const float *src, int frames)
Definition: audiooutputdownmix.cpp:169
AudioOutput::SilentError
void SilentError(const QString &msg)
Definition: audiooutput.cpp:281
AUDIOOUTPUT_VIDEO
@ AUDIOOUTPUT_VIDEO
Definition: audiosettings.h:23
AudioSettings::m_format
AudioFormat m_format
Definition: audiosettings.h:72
AudioOutputBase::m_actuallyPaused
bool m_actuallyPaused
Definition: audiooutputbase.h:200
AudioOutputBase::m_memoryCorruptionTest0
uint m_memoryCorruptionTest0
Definition: audiooutputbase.h:287
AudioOutputSettings::IsSupportedFormat
bool IsSupportedFormat(AudioFormat format)
Definition: audiooutputsettings.cpp:134
AudioOutputSettings::GetPassthroughParams
static QString GetPassthroughParams(int codec, int codec_profile, int &samplerate, int &channels, bool canDTSHDMA)
Setup samplerate and number of channels for passthrough.
Definition: audiooutputsettings.cpp:457
AudioOutputBase::m_wasPaused
bool m_wasPaused
Definition: audiooutputbase.h:201
AudioOutputBase::m_surroundMode
int m_surroundMode
Definition: audiooutputbase.h:240
AudioOutputUtil::AdjustVolume
static void AdjustVolume(void *buffer, int len, int volume, bool music, bool upmix)
Adjust the volume of samples.
Definition: audiooutpututil.cpp:96
AudioOutputBase::m_processing
bool m_processing
Definition: audiooutputbase.h:245
AsyncLooseLock::Clear
void Clear()
Definition: audiooutputbase.h:40
AudioOutputSettings
Definition: audiooutputsettings.h:48
AudioOutputBase::usesSpdif
bool usesSpdif() const
Definition: audiooutputbase.h:170
WPOS
#define WPOS
Definition: audiooutputbase.cpp:43
OutputListeners::dispatchVisual
void dispatchVisual(uchar *b, unsigned long b_len, std::chrono::milliseconds timecode, int chan, int prec)
Definition: output.cpp:49
AudioOutputBase::AddFrames
bool AddFrames(void *buffer, int frames, std::chrono::milliseconds timecode) override
Add frames to the audiobuffer and perform any required processing.
Definition: audiooutputbase.cpp:1312
AudioOutputSettings::NearestSupportedRate
int NearestSupportedRate(int rate)
Definition: audiooutputsettings.cpp:101
AudioOutputBase::QUALITY_DISABLED
@ QUALITY_DISABLED
Definition: audiooutputbase.h:210
AudioOutputBase::SetStretchFactor
void SetStretchFactor(float factor) override
Set the timestretch factor.
Definition: audiooutputbase.cpp:362
AudioOutputBase::m_bytesPerFrame
int m_bytesPerFrame
Definition: audiooutputbase.h:176
DigitalFeature
DigitalFeature
Definition: audiooutputsettings.h:34
AudioOutputBase::m_effDsp
int m_effDsp
Definition: audiooutputbase.h:181
SPDIFEncoder::GetProcessedBuffer
unsigned char * GetProcessedBuffer()
Definition: spdifencoder.cpp:152
AudioOutputBase::InitSettings
void InitSettings(const AudioSettings &settings)
Definition: audiooutputbase.cpp:125
AudioOutputBase::QUALITY_HIGH
@ QUALITY_HIGH
Definition: audiooutputbase.h:213
AudioOutputBase::OpenDevice
virtual bool OpenDevice(void)=0
common.utilities.log
def log(debug, txt)
Definition: utilities.py:5
AudioOutputBase::PauseUntilBuffered
void PauseUntilBuffered(void) override
Definition: audiooutputbase.cpp:922
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
AudioOutputBase::StartOutputThread
virtual bool StartOutputThread(void)
Definition: audiooutputbase.cpp:844
AudioOutput::ClearError
void ClearError(void)
Definition: audiooutput.cpp:292
AudioOutputBase::m_audioBuffer
std::array< uchar, kAudioRingBufferSize > m_audioBuffer
main audio buffer
Definition: audiooutputbase.h:296
AudioOutputBase::m_audioBufLock
QMutex m_audioBufLock
Writes to the audiobuffer, reconfigures and audiobuffer resets can only take place while holding this...
Definition: audiooutputbase.h:255
AudioOutputSettings::FeaturesToString
static QString FeaturesToString(DigitalFeature arg)
Display in human readable form the digital features supported by the output device.
Definition: audiooutputsettings.cpp:445
AudioOutputBase::m_source
AudioOutputSource m_source
Definition: audiooutputbase.h:195
AudioOutputBase::GetOutputSettingsUsers
AudioOutputSettings * GetOutputSettingsUsers(bool digital=false) override
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
Definition: audiooutputbase.cpp:190
VolumeBase::SetChannels
void SetChannels(int new_channels)
Definition: volumebase.cpp:218
VolumeBase::UpdateVolume
void UpdateVolume(void)
Definition: volumebase.cpp:178
AudioOutputSettings::FormatToString
static const char * FormatToString(AudioFormat format)
Definition: audiooutputsettings.cpp:165
AudioOutputBase::SetStretchFactorLocked
void SetStretchFactorLocked(float factor)
Set the timestretch factor.
Definition: audiooutputbase.cpp:287
UPMIX_CHANNEL_MASK
static constexpr int UPMIX_CHANNEL_MASK
Definition: audiooutputbase.cpp:49
AudioOutputBase::m_fragmentSize
int m_fragmentSize
Definition: audiooutputbase.h:182
AudioSettings::m_codec
AVCodecID m_codec
Definition: audiosettings.h:74
AudioOutputSettings::BestSupportedFormat
AudioFormat BestSupportedFormat()
Definition: audiooutputsettings.cpp:143
AudioOutputUtil::fromFloat
static int fromFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert float samples to integers.
Definition: audiooutpututil.cpp:76
SPDIFEncoder
Definition: spdifencoder.h:14
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:879
AudioOutputBase::m_outputSettings
AudioOutputSettings * m_outputSettings
Definition: audiooutputbase.h:226
AudioOutputBase::GetBufferStatus
void GetBufferStatus(uint &fill, uint &total) override
Fill in the number of bytes in the audiobuffer and the total size of the audiobuffer.
Definition: audiooutputbase.cpp:1637
AudioOutputBase::m_framesBuffered
int64_t m_framesBuffered
Definition: audiooutputbase.h:247
AudioOutputBase::GetAudioBufferedTime
std::chrono::milliseconds GetAudioBufferedTime(void) override
Get the difference in timecode between the samples that are about to become audible and the samples m...
Definition: audiooutputbase.cpp:1156
FEATURE_DTSHD
@ FEATURE_DTSHD
Definition: audiooutputsettings.h:41
FreeSurround::receiveFrames
uint receiveFrames(void *buffer, uint maxFrames)
Definition: freesurround.cpp:312
AudioOutputUtil::MuteChannel
static void MuteChannel(int obits, int channels, int ch, void *buffer, int bytes)
Mute individual channels through mono->stereo duplication.
Definition: audiooutpututil.cpp:174
AudioOutputBase::m_audioTime
std::chrono::milliseconds m_audioTime
timecode of audio leaving the soundcard (same units as timecodes)
Definition: audiooutputbase.h:266
AudioOutputBase::m_srcCtx
SRC_STATE * m_srcCtx
Definition: audiooutputbase.h:230
OutputListeners::prepareVisuals
void prepareVisuals()
Definition: output.cpp:63
AudioOutputBase::m_usesSpdif
bool m_usesSpdif
Definition: audiooutputbase.h:302
AudioOutputBase::kAudioSRCInputSize
static const uint kAudioSRCInputSize
Definition: audiooutputbase.h:122
AudioOutputBase::m_memoryCorruptionTest3
uint m_memoryCorruptionTest3
Definition: audiooutputbase.h:297
AudioOutputBase::ToggleUpmix
bool ToggleUpmix(void) override
Toggle between stereo and upmixed 5.1 if the source material is stereo.
Definition: audiooutputbase.cpp:387
AudioOutputBase::m_srcData
SRC_DATA m_srcData
Definition: audiooutputbase.h:286
AudioOutputBase::SetSourceBitrate
void SetSourceBitrate(int rate) override
Set the bitrate of the source material, reported in periodic OutputEvents.
Definition: audiooutputbase.cpp:276
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:896
millisecondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:91
AudioOutputBase::m_outputSettingsDigital
AudioOutputSettings * m_outputSettingsDigital
Definition: audiooutputbase.h:228
AudioSettings::m_channels
int m_channels
Definition: audiosettings.h:73
VBAUDIOTS
#define VBAUDIOTS(str)
Definition: audiooutputbase.h:21
AudioOutputBase::m_needsDownmix
bool m_needsDownmix
Definition: audiooutputbase.h:239
AsyncLooseLock::TestAndDeref
bool TestAndDeref()
Definition: audiooutputbase.h:42
AudioOutputBase::OutputSettings
AudioOutputSettings * OutputSettings(bool digital=true)
Definition: audiooutputbase.cpp:462