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 #endif
118 }
119 
121 {
122  if (settings.m_custom)
123  {
124  // got a custom audio report already, use it
125  // this was likely provided by the AudioTest utility
127  *m_outputSettings = *settings.m_custom;
131  return;
132  }
133 
134  // Ask the subclass what we can send to the device
137 
141 
143  gCoreContext->GetBoolSetting("AudioDefaultUpmix", false) :
144  false;
145  if (settings.m_upmixer == 1) // music, upmixer off
146  m_upmixDefault = false;
147  else if (settings.m_upmixer == 2) // music, upmixer on
148  m_upmixDefault = true;
149 }
150 
157 {
158  // If we've already checked the port, use the cache
159  // version instead
160  if (!m_discreteDigital || !digital)
161  {
162  digital = false;
164  return m_outputSettingsRaw;
165  }
168 
169  AudioOutputSettings* aosettings = GetOutputSettings(digital);
170  if (aosettings)
171  aosettings->GetCleaned();
172  else
173  aosettings = new AudioOutputSettings(true);
174 
175  if (digital)
176  return (m_outputSettingsDigitalRaw = aosettings);
177  return (m_outputSettingsRaw = aosettings);
178 }
179 
186 {
187  if (!m_discreteDigital || !digital)
188  {
189  digital = false;
190  if (m_outputSettings)
191  return m_outputSettings;
192  }
193  else if (m_outputSettingsDigital)
195 
196  auto* aosettings = new AudioOutputSettings;
197 
198  *aosettings = *GetOutputSettingsCleaned(digital);
199  aosettings->GetUsers();
200 
201  if (digital)
202  return (m_outputSettingsDigital = aosettings);
203  return (m_outputSettings = aosettings);
204 }
205 
209 bool AudioOutputBase::CanPassthrough(int samplerate, int channels,
210  AVCodecID codec, int profile) const
211 {
213  bool ret = !(m_internalVol && SWVolume());
214 
215  switch(codec)
216  {
217  case AV_CODEC_ID_AC3:
218  arg = FEATURE_AC3;
219  break;
220  case AV_CODEC_ID_DTS:
221  switch(profile)
222  {
223  case FF_PROFILE_DTS:
224  case FF_PROFILE_DTS_ES:
225  case FF_PROFILE_DTS_96_24:
226  arg = FEATURE_DTS;
227  break;
228  case FF_PROFILE_DTS_HD_HRA:
229  case FF_PROFILE_DTS_HD_MA:
230  arg = FEATURE_DTSHD;
231  break;
232  default:
233  break;
234  }
235  break;
236  case AV_CODEC_ID_EAC3:
237  arg = FEATURE_EAC3;
238  break;
239  case AV_CODEC_ID_TRUEHD:
240  arg = FEATURE_TRUEHD;
241  break;
242  default:
243  arg = FEATURE_NONE;
244  break;
245  }
246  // we can't passthrough any other codecs than those defined above
247  ret &= m_outputSettingsDigital->canFeature(arg);
249  ret &= m_outputSettingsDigital->IsSupportedRate(samplerate);
250  // if we must resample to 48kHz ; we can't passthrough
251  ret &= (samplerate == 48000) ||
252  !gCoreContext->GetBoolSetting("Audio48kOverride", false);
253  // Don't know any cards that support spdif clocked at < 44100
254  // Some US cable transmissions have 2ch 32k AC-3 streams
255  ret &= samplerate >= 44100;
256  if (!ret)
257  return false;
258  // Will passthrough if surround audio was defined. Amplifier will
259  // do the downmix if required
260  bool willupmix = m_maxChannels >= 6 && (channels <= 2 && m_upmixDefault);
261  ret &= !willupmix;
262  // unless audio is configured for stereo. We can passthrough otherwise
263  ret |= m_maxChannels == 2;
264 
265  return ret;
266 }
267 
272 {
273  if (rate > 0)
274  m_sourceBitRate = rate;
275 }
276 
282 void AudioOutputBase::SetStretchFactorLocked(float lstretchfactor)
283 {
284  if (m_stretchFactor == lstretchfactor && m_pSoundStretch)
285  return;
286 
287  m_stretchFactor = lstretchfactor;
288 
289  int channels = m_needsUpmix || m_needsDownmix ?
291  if (channels < 1 || channels > 8 || !m_configureSucceeded)
292  return;
293 
294  bool willstretch = m_stretchFactor < 0.99F || m_stretchFactor > 1.01F;
295  m_effStretchFactor = lroundf(100000.0F * lstretchfactor);
296 
297  if (m_pSoundStretch)
298  {
299  if (!willstretch && m_forcedProcessing)
300  {
301  m_forcedProcessing = false;
302  m_processing = false;
303  delete m_pSoundStretch;
304  m_pSoundStretch = nullptr;
305  VBGENERAL(QString("Cancelling time stretch"));
307  m_waud = m_raud = 0;
308  m_resetActive.Ref();
309  }
310  else
311  {
312  VBGENERAL(QString("Changing time stretch to %1")
313  .arg(m_stretchFactor));
314  m_pSoundStretch->setTempo(m_stretchFactor);
315  }
316  }
317  else if (willstretch)
318  {
319  VBGENERAL(QString("Using time stretch %1").arg(m_stretchFactor));
320  m_pSoundStretch = new soundtouch::SoundTouch();
321  m_pSoundStretch->setSampleRate(m_sampleRate);
322  m_pSoundStretch->setChannels(channels);
323  m_pSoundStretch->setTempo(m_stretchFactor);
324 #if defined(Q_PROCESSOR_ARM) || defined(Q_OS_ANDROID)
325  // use less demanding settings for Raspberry pi
326  m_pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 82);
327  m_pSoundStretch->setSetting(SETTING_USE_AA_FILTER, 0);
328  m_pSoundStretch->setSetting(SETTING_USE_QUICKSEEK, 1);
329 #else
330  m_pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35);
331 #endif
332  /* If we weren't already processing we need to turn on float conversion
333  adjust sample and frame sizes accordingly and dump the contents of
334  the audiobuffer */
335  if (!m_processing)
336  {
337  m_processing = true;
338  m_forcedProcessing = true;
343  m_framesBuffered = 0;
344  m_waud = m_raud = 0;
345  m_resetActive.Ref();
347  m_pauseAudio = true;
348  m_actuallyPaused = false;
349  m_unpauseWhenReady = true;
350  }
351  }
352 }
353 
357 void AudioOutputBase::SetStretchFactor(float lstretchfactor)
358 {
359  QMutexLocker lock(&m_audioBufLock);
360  SetStretchFactorLocked(lstretchfactor);
361 }
362 
367 {
368  return m_stretchFactor;
369 }
370 
375 {
376  return m_needsUpmix && m_upmixer;
377 }
378 
383 {
384  // Can only upmix from mono/stereo to 6 ch
385  if (m_maxChannels == 2 || m_sourceChannels > 2)
386  return false;
387 
389 
392  m_upmixDefault ? false : m_passthru);
393  Reconfigure(settings);
394  return IsUpmixing();
395 }
396 
401 {
402  return m_sourceChannels <= 2 && m_maxChannels > 2;
403 }
404 
405 /*
406  * Setup samplerate and number of channels for passthrough
407  * Create SPDIF encoder and true if successful
408  */
409 bool AudioOutputBase::SetupPassthrough(AVCodecID codec, int codec_profile,
410  int &samplerate_tmp, int &channels_tmp)
411 {
412  if (codec == AV_CODEC_ID_DTS &&
414  {
415  // We do not support DTS-HD bitstream so force extraction of the
416  // DTS core track instead
417  codec_profile = FF_PROFILE_DTS;
418  }
420  codec, codec_profile,
421  samplerate_tmp, channels_tmp,
423  VBAUDIO("Setting " + log + " passthrough");
424 
425  delete m_spdifEnc;
426 
427  // No spdif encoder needed for certain devices
428  if (m_usesSpdif)
429  m_spdifEnc = new SPDIFEncoder("spdif", codec);
430  else
431  m_spdifEnc = nullptr;
432  if (m_spdifEnc && m_spdifEnc->Succeeded() && codec == AV_CODEC_ID_DTS)
433  {
434  switch(codec_profile)
435  {
436  case FF_PROFILE_DTS:
437  case FF_PROFILE_DTS_ES:
438  case FF_PROFILE_DTS_96_24:
440  break;
441  case FF_PROFILE_DTS_HD_HRA:
442  case FF_PROFILE_DTS_HD_MA:
443  m_spdifEnc->SetMaxHDRate(samplerate_tmp * channels_tmp / 2);
444  break;
445  }
446  }
447 
448  if (m_spdifEnc && !m_spdifEnc->Succeeded())
449  {
450  delete m_spdifEnc;
451  m_spdifEnc = nullptr;
452  return false;
453  }
454  return true;
455 }
456 
458 {
459  if (digital)
461  return m_outputSettings;
462 }
463 
469 void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
470 {
471  AudioSettings settings = orig_settings;
472  int lsource_channels = settings.m_channels;
473  int lconfigured_channels = m_configuredChannels;
474  bool lneeds_upmix = false;
475  bool lneeds_downmix = false;
476  bool lreenc = false;
477  bool lenc = false;
478 
479  if (!settings.m_usePassthru)
480  {
481  // Do we upmix stereo or mono?
482  lconfigured_channels =
483  (m_upmixDefault && lsource_channels <= 2) ? 6 : lsource_channels;
484  bool cando_channels =
485  m_outputSettings->IsSupportedChannels(lconfigured_channels);
486 
487  // check if the number of channels could be transmitted via AC3 encoding
488 #ifndef DISABLE_AC3_ENCODE
491  lconfigured_channels > 2 && lconfigured_channels <= 6);
492 #endif
493  if (!lenc && !cando_channels)
494  {
495  // if hardware doesn't support source audio configuration
496  // we will upmix/downmix to what we can
497  // (can safely assume hardware supports stereo)
498  switch (lconfigured_channels)
499  {
500  case 7:
501  lconfigured_channels = 8;
502  break;
503  case 8:
504  case 5:
505  lconfigured_channels = 6;
506  break;
507  case 6:
508  case 4:
509  case 3:
510  case 2: //Will never happen
511  lconfigured_channels = 2;
512  break;
513  case 1:
514  lconfigured_channels = m_upmixDefault ? 6 : 2;
515  break;
516  default:
517  lconfigured_channels = 2;
518  break;
519  }
520  }
521  // Make sure we never attempt to output more than what we can
522  // the upmixer can only upmix to 6 channels when source < 6
523  if (lsource_channels <= 6)
524  lconfigured_channels = std::min(lconfigured_channels, 6);
525  lconfigured_channels = std::min(lconfigured_channels, m_maxChannels);
526  /* Encode to AC-3 if we're allowed to passthru but aren't currently
527  and we have more than 2 channels but multichannel PCM is not
528  supported or if the device just doesn't support the number of
529  channels */
530 #ifndef DISABLE_AC3_ENCODE
533  lconfigured_channels > 2) ||
534  !m_outputSettings->IsSupportedChannels(lconfigured_channels));
535  /* Might we reencode a bitstream that's been decoded for timestretch?
536  If the device doesn't support the number of channels - see below */
538  (settings.m_codec == AV_CODEC_ID_AC3 ||
539  settings.m_codec == AV_CODEC_ID_DTS))
540  {
541  lreenc = true;
542  }
543 #endif
544  // Enough channels? Upmix if not, but only from mono/stereo/5.0 to 5.1
545  if (IS_VALID_UPMIX_CHANNEL(settings.m_channels) &&
546  settings.m_channels < lconfigured_channels)
547  {
548  VBAUDIO(QString("Needs upmix from %1 -> %2 channels")
549  .arg(settings.m_channels).arg(lconfigured_channels));
550  settings.m_channels = lconfigured_channels;
551  lneeds_upmix = true;
552  }
553  else if (settings.m_channels > lconfigured_channels)
554  {
555  VBAUDIO(QString("Needs downmix from %1 -> %2 channels")
556  .arg(settings.m_channels).arg(lconfigured_channels));
557  settings.m_channels = lconfigured_channels;
558  lneeds_downmix = true;
559  }
560  }
561 
562  ClearError();
563 
564  bool general_deps = true;
565 
566  /* Set samplerate_tmp and channels_tmp to appropriate values
567  if passing through */
568  int samplerate_tmp = 0;
569  int channels_tmp = 0;
570  if (settings.m_usePassthru)
571  {
572  samplerate_tmp = settings.m_sampleRate;
573  SetupPassthrough(settings.m_codec, settings.m_codecProfile,
574  samplerate_tmp, channels_tmp);
575  general_deps = m_sampleRate == samplerate_tmp && m_channels == channels_tmp;
576  general_deps &= m_format == m_outputFormat && m_format == FORMAT_S16;
577  }
578  else
579  {
580  general_deps =
581  settings.m_format == m_format && lsource_channels == m_sourceChannels;
582  }
583 
584  // Check if anything has changed
585  general_deps &=
586  settings.m_sampleRate == m_sourceSampleRate &&
587  settings.m_usePassthru == m_passthru &&
588  lconfigured_channels == m_configuredChannels &&
589  lneeds_upmix == m_needsUpmix && lreenc == m_reEnc &&
590  lneeds_downmix == m_needsDownmix;
591 
592  if (general_deps && m_configureSucceeded)
593  {
594  VBAUDIO("Reconfigure(): No change -> exiting");
595  // if passthrough, source channels may have changed
596  m_sourceChannels = lsource_channels;
597  return;
598  }
599 
600  KillAudio();
601 
602  QMutexLocker lock(&m_audioBufLock);
603  QMutexLocker lockav(&m_avsyncLock);
604 
605  m_waud = m_raud = 0;
608 
609  m_channels = settings.m_channels;
610  m_sourceChannels = lsource_channels;
611  m_reEnc = lreenc;
612  m_codec = settings.m_codec;
613  m_passthru = settings.m_usePassthru;
614  m_configuredChannels = lconfigured_channels;
615  m_needsUpmix = lneeds_upmix;
616  m_needsDownmix = lneeds_downmix;
617  m_format = m_outputFormat = settings.m_format;
619  m_enc = lenc;
620 
621  m_killAudio = m_pauseAudio = false;
622  m_wasPaused = true;
623 
624  // Don't try to do anything if audio hasn't been
625  // initialized yet (e.g. rubbish was provided)
626  if (m_sourceChannels <= 0 || m_format <= 0 || m_sampleRate <= 0)
627  {
628  SilentError(QString("Aborting Audio Reconfigure. ") +
629  QString("Invalid audio parameters ch %1 fmt %2 @ %3Hz")
630  .arg(m_sourceChannels).arg(m_format).arg(m_sampleRate));
631  return;
632  }
633 
634  VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels")
635  .arg(avcodec_get_name(m_codec),
637  .arg(m_sampleRate/1000)
638  .arg(m_sourceChannels));
639 
640  if (m_needsDownmix && m_sourceChannels > 8)
641  {
642  Error(QObject::tr("Aborting Audio Reconfigure. "
643  "Can't handle audio with more than 8 channels."));
644  return;
645  }
646 
647  VBAUDIO(QString("enc(%1), passthru(%2), features (%3) "
648  "configured_channels(%4), %5 channels supported(%6) "
649  "max_channels(%7)")
650  .arg(m_enc)
651  .arg(m_passthru)
654  .arg(m_channels)
655  .arg(OutputSettings(m_enc || m_passthru)->IsSupportedChannels(m_channels))
656  .arg(m_maxChannels));
657 
658  int dest_rate = 0;
659 
660  // Force resampling if we are encoding to AC3 and sr > 48k
661  // or if 48k override was checked in settings
662  if ((m_sampleRate != 48000 &&
663  gCoreContext->GetBoolSetting("Audio48kOverride", false)) ||
664  (m_enc && (m_sampleRate > 48000)))
665  {
666  VBAUDIO("Forcing resample to 48 kHz");
667  if (m_srcQuality < 0)
669  m_needResampler = true;
670  dest_rate = 48000;
671  }
672  // this will always be false for passthrough audio as
673  // CanPassthrough() already tested these conditions
674  else
675  {
678  if (m_needResampler)
679  {
681  }
682  }
683 
685  {
686  m_sampleRate = dest_rate;
687 
688  VBGENERAL(QString("Resampling from %1 kHz to %2 kHz with quality %3")
689  .arg(settings.m_sampleRate/1000).arg(m_sampleRate/1000)
691 
693 
694  int error = 0;
695  m_srcCtx = src_new(2-m_srcQuality, chans, &error);
696  if (error)
697  {
698  Error(QObject::tr("Error creating resampler: %1")
699  .arg(src_strerror(error)));
700  m_srcCtx = nullptr;
701  return;
702  }
703 
704  m_srcData.src_ratio = (double)m_sampleRate / settings.m_sampleRate;
705  m_srcData.data_in = m_srcIn;
706  int newsize = (int)(kAudioSRCInputSize * m_srcData.src_ratio + 15)
707  & ~0xf;
708 
709  if (m_kAudioSRCOutputSize < newsize)
710  {
711  m_kAudioSRCOutputSize = newsize;
712  VBAUDIO(QString("Resampler allocating %1").arg(newsize));
713  delete[] m_srcOut;
714  m_srcOut = new float[m_kAudioSRCOutputSize];
715  }
716  m_srcData.data_out = m_srcOut;
717  m_srcData.output_frames = m_kAudioSRCOutputSize / chans;
718  m_srcData.end_of_input = 0;
719  }
720 
721  if (m_enc)
722  {
723  if (m_reEnc)
724  VBAUDIO("Reencoding decoded AC-3/DTS to AC-3");
725 
726  VBAUDIO(QString("Creating AC-3 Encoder with sr = %1, ch = %2")
728 
730  if (!m_encoder->Init(AV_CODEC_ID_AC3, 448000, m_sampleRate,
732  {
733  Error(QObject::tr("AC-3 encoder initialization failed"));
734  delete m_encoder;
735  m_encoder = nullptr;
736  m_enc = false;
737  // upmixing will fail if we needed the encoder
738  m_needsUpmix = false;
739  }
740  }
741 
742  if (m_passthru)
743  {
744  //AC3, DTS, DTS-HD MA and TrueHD all use 16 bits samples
745  m_channels = channels_tmp;
746  m_sampleRate = samplerate_tmp;
750  }
751  else
752  {
755  }
756 
757  // Turn on float conversion?
759  m_stretchFactor != 1.0F || (m_internalVol && SWVolume()) ||
760  (m_enc && m_outputFormat != FORMAT_S16) ||
761  !OutputSettings(m_enc || m_passthru)->IsSupportedFormat(m_outputFormat))
762  {
763  VBAUDIO("Audio processing enabled");
764  m_processing = true;
765  if (m_enc)
766  m_outputFormat = FORMAT_S16; // Output s16le for AC-3 encoder
767  else
769  }
770 
772  sizeof(float) : AudioOutputSettings::SampleSize(m_format);
774 
775  if (m_enc)
776  m_channels = 2; // But only post-encoder
777 
780 
781  VBGENERAL(
782  QString("Opening audio device '%1' ch %2(%3) sr %4 sf %5 reenc %6")
785 
787  m_framesBuffered = 0;
788  m_currentSeconds = -1s;
789  m_sourceBitRate = -1;
790  m_effDsp = m_sampleRate * 100;
791 
792  // Actually do the device specific open call
793  if (!OpenDevice())
794  {
795  if (GetError().isEmpty())
796  Error(QObject::tr("Aborting reconfigure"));
797  else
798  VBGENERAL("Aborting reconfigure");
799  m_configureSucceeded = false;
800  return;
801  }
802 
803  VBAUDIO(QString("Audio fragment size: %1").arg(m_fragmentSize));
804 
805  // Only used for software volume
807  {
808  VBAUDIO("Software volume enabled");
809  m_volumeControl = gCoreContext->GetSetting("MixerControl", "PCM");
810  m_volumeControl += "MixerVolume";
812  }
813 
817 
819  {
823  VBAUDIO(QString("Create %1 quality upmixer done")
825  }
826 
827  VBAUDIO(QString("Audio Stretch Factor: %1").arg(m_stretchFactor));
829 
830  // Setup visualisations, zero the visualisations buffers
831  prepareVisuals();
832 
833  if (m_unpauseWhenReady)
835 
836  m_configureSucceeded = true;
837 
839 
840  VBAUDIO("Ending Reconfigure()");
841 }
842 
844 {
846  return true;
847 
848  start();
849  m_audioThreadExists = true;
850 
851  return true;
852 }
853 
854 
856 {
858  {
859  wait();
860  m_audioThreadExists = false;
861  }
862 }
863 
868 {
869  m_killAudioLock.lock();
870 
871  VBAUDIO("Killing AudioOutputDSP");
872  m_killAudio = true;
874  QMutexLocker lock(&m_audioBufLock);
875 
876  if (m_pSoundStretch)
877  {
878  delete m_pSoundStretch;
879  m_pSoundStretch = nullptr;
881  m_stretchFactor = 1.0F;
882  }
883 
884  if (m_encoder)
885  {
886  delete m_encoder;
887  m_encoder = nullptr;
888  }
889 
890  if (m_upmixer)
891  {
892  delete m_upmixer;
893  m_upmixer = nullptr;
894  }
895 
896  if (m_srcCtx)
897  {
898  src_delete(m_srcCtx);
899  m_srcCtx = nullptr;
900  }
901 
902  m_needsUpmix = m_needResampler = m_enc = false;
903 
904  CloseDevice();
905 
906  m_killAudioLock.unlock();
907 }
908 
909 void AudioOutputBase::Pause(bool paused)
910 {
911  if (!paused && m_unpauseWhenReady)
912  return;
913  VBAUDIO(QString("Pause %1").arg(paused));
914  if (m_pauseAudio != paused)
916  m_pauseAudio = paused;
917  m_unpauseWhenReady = false;
918  m_actuallyPaused = false;
919 }
920 
922 {
923  Reset();
924  Pause(true);
925  m_unpauseWhenReady = true;
926 }
927 
932 {
933  QMutexLocker lock(&m_audioBufLock);
934  QMutexLocker lockav(&m_avsyncLock);
935 
937  m_framesBuffered = 0;
938  if (m_encoder)
939  {
940  m_waud = m_raud = 0; // empty ring buffer
941  m_audioBuffer.fill(0);
942  }
943  else
944  {
945  m_waud = m_raud; // empty ring buffer
946  }
947  m_resetActive.Ref();
948  m_currentSeconds = -1s;
950  m_unpauseWhenReady = false;
951  // clear any state that could remember previous audio in any active filters
952  if (m_needsUpmix && m_upmixer)
953  m_upmixer->flush();
954  if (m_pSoundStretch)
955  m_pSoundStretch->clear();
956  if (m_encoder)
957  m_encoder->clear();
958 
959  // Setup visualisations, zero the visualisations buffers
960  prepareVisuals();
961 }
962 
969 void AudioOutputBase::SetTimecode(std::chrono::milliseconds timecode)
970 {
971  m_audbufTimecode = m_audioTime = timecode;
972  m_framesBuffered = (timecode.count() * m_sourceSampleRate) / 1000;
973 }
974 
981 void AudioOutputBase::SetEffDsp(int dsprate)
982 {
983  VBAUDIO(QString("SetEffDsp: %1").arg(dsprate));
984  m_effDsp = dsprate;
985 }
986 
990 inline int AudioOutputBase::audiolen() const
991 {
992  if (m_waud >= m_raud)
993  return m_waud - m_raud;
994  return kAudioRingBufferSize - (m_raud - m_waud);
995 }
996 
1001 {
1002  return kAudioRingBufferSize - audiolen() - 1;
1003  /* There is one wasted byte in the buffer. The case where m_waud = m_raud is
1004  interpreted as an empty buffer, so the fullest the buffer can ever
1005  be is kAudioRingBufferSize - 1. */
1006 }
1007 
1016 {
1018  return audiolen();
1020 }
1021 
1025 std::chrono::milliseconds AudioOutputBase::GetAudiotime(void)
1026 {
1027  if (m_audbufTimecode == 0ms || !m_configureSucceeded)
1028  return 0ms;
1029 
1030  // output bits per 10 frames
1031  int64_t obpf = 0;
1032 
1033  if (m_passthru && !usesSpdif())
1034  obpf = m_sourceBitRate * 10 / m_sourceSampleRate;
1035  else if (m_enc && !usesSpdif())
1036  {
1037  // re-encode bitrate is hardcoded at 448000
1038  obpf = 448000 * 10 / m_sourceSampleRate;
1039  }
1040  else
1041  obpf = static_cast<int64_t>(m_outputBytesPerFrame) * 80;
1042 
1043  /* We want to calculate 'm_audioTime', which is the timestamp of the audio
1044  Which is leaving the sound card at this instant.
1045 
1046  We use these variables:
1047 
1048  'm_effDsp' is 100 * frames/sec
1049 
1050  'm_audbufTimecode' is the timecode in milliseconds of the
1051  audio that has just been written into the buffer.
1052 
1053  'm_effStretchFactor' is stretch factor * 100,000
1054 
1055  'totalbuffer' is the total # of bytes in our audio buffer, and the
1056  sound card's buffer. */
1057 
1058 
1059  QMutexLocker lockav(&m_avsyncLock);
1060 
1061  int64_t soundcard_buffer = GetBufferedOnSoundcard(); // bytes
1062 
1063  /* audioready tells us how many bytes are in audiobuffer
1064  scaled appropriately if output format != internal format */
1065  int64_t main_buffer = audioready();
1066 
1067  std::chrono::milliseconds oldaudiotime = m_audioTime;
1068 
1069  /* timecode is the stretch adjusted version
1070  of major post-stretched buffer contents
1071  processing latencies are catered for in AddData/SetAudiotime
1072  to eliminate race */
1073 
1074  m_audioTime = m_audbufTimecode - std::chrono::milliseconds(m_effDsp && obpf ?
1075  ((main_buffer + soundcard_buffer) * int64_t(m_effStretchFactor)
1076  * 80 / int64_t(m_effDsp) / obpf) : 0);
1077 
1078  /* audiotime should never go backwards, but we might get a negative
1079  value if GetBufferedOnSoundcard() isn't updated by the driver very
1080  quickly (e.g. ALSA) */
1081  if (m_audioTime < oldaudiotime)
1082  m_audioTime = oldaudiotime;
1083 
1084  VBAUDIOTS(QString("GetAudiotime audt=%1 abtc=%2 mb=%3 sb=%4 tb=%5 "
1085  "sr=%6 obpf=%7 bpf=%8 esf=%9 edsp=%10 sbr=%11")
1086  .arg(m_audioTime.count()) // 1
1087  .arg(m_audbufTimecode.count()) // 2
1088  .arg(main_buffer) // 3
1089  .arg(soundcard_buffer) // 4
1090  .arg(main_buffer+soundcard_buffer) // 5
1091  .arg(m_sampleRate).arg(obpf) // 6, 7
1092  .arg(m_bytesPerFrame) // 8
1093  .arg(m_effStretchFactor) // 9
1094  .arg(m_effDsp).arg(m_sourceBitRate) // 10, 11
1095  );
1096 
1097  return m_audioTime;
1098 }
1099 
1105 void AudioOutputBase::SetAudiotime(int frames, std::chrono::milliseconds timecode)
1106 {
1107  int64_t processframes_stretched = 0;
1108  int64_t processframes_unstretched = 0;
1109  std::chrono::milliseconds old_audbuf_timecode = m_audbufTimecode;
1110 
1111  if (!m_configureSucceeded)
1112  return;
1113 
1114  if (m_needsUpmix && m_upmixer)
1115  processframes_unstretched -= m_upmixer->frameLatency();
1116 
1117  if (m_pSoundStretch)
1118  {
1119  processframes_unstretched -= m_pSoundStretch->numUnprocessedSamples();
1120  processframes_stretched -= m_pSoundStretch->numSamples();
1121  }
1122 
1123  if (m_encoder)
1124  {
1125  processframes_stretched -= m_encoder->Buffered();
1126  }
1127 
1129  timecode + std::chrono::milliseconds(m_effDsp ? ((frames + processframes_unstretched) * 100000 +
1130  (processframes_stretched * m_effStretchFactor)
1131  ) / m_effDsp : 0);
1132 
1133  // check for timecode wrap and reset audiotime if detected
1134  // timecode will always be monotonic asc if not seeked and reset
1135  // happens if seek or pause happens
1136  if (m_audbufTimecode < old_audbuf_timecode)
1137  m_audioTime = 0ms;
1138 
1139  VBAUDIOTS(QString("SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
1140  .arg(m_audbufTimecode.count())
1141  .arg(timecode.count())
1142  .arg(frames)
1143  .arg(processframes_unstretched)
1144  .arg(processframes_stretched));
1145 #ifdef AUDIOTSTESTING
1146  GetAudiotime();
1147 #endif
1148 }
1149 
1155 std::chrono::milliseconds AudioOutputBase::GetAudioBufferedTime(void)
1156 {
1157  std::chrono::milliseconds ret = m_audbufTimecode - GetAudiotime();
1158  // Pulse can give us values that make this -ve
1159  if (ret < 0ms)
1160  return 0ms;
1161  return ret;
1162 }
1163 
1167 void AudioOutputBase::SetSWVolume(int new_volume, bool save)
1168 {
1169  m_volume = new_volume;
1170  if (save && m_volumeControl != nullptr)
1172 }
1173 
1178 {
1179  return m_volume;
1180 }
1181 
1191 {
1192  int bpf = m_bytesPerFrame;
1193  int len = frames * bpf;
1194  int afree = audiofree();
1195 
1196  if (len <= afree)
1197  return len;
1198 
1199  VBERROR(QString("Audio buffer overflow, %1 frames lost!")
1200  .arg(frames - (afree / bpf)));
1201 
1202  frames = afree / bpf;
1203  len = frames * bpf;
1204 
1205  if (!m_srcCtx)
1206  return len;
1207 
1208  int error = src_reset(m_srcCtx);
1209  if (error)
1210  {
1211  VBERROR(QString("Error occurred while resetting resampler: %1")
1212  .arg(src_strerror(error)));
1213  m_srcCtx = nullptr;
1214  }
1215 
1216  return len;
1217 }
1218 
1225 int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, uint &org_waud)
1226 {
1227  int len = CheckFreeSpace(frames);
1228  int bdiff = kAudioRingBufferSize - org_waud;
1229  int bpf = m_bytesPerFrame;
1230  ptrdiff_t off = 0;
1231 
1232  if (!m_needsUpmix)
1233  {
1234  int num = len;
1235 
1236  if (bdiff <= num)
1237  {
1238  memcpy(WPOS, buffer, bdiff);
1239  num -= bdiff;
1240  off = bdiff;
1241  org_waud = 0;
1242  }
1243  if (num > 0)
1244  memcpy(WPOS, buffer + off, num);
1245  org_waud = (org_waud + num) % kAudioRingBufferSize;
1246  return len;
1247  }
1248 
1249  // Convert mono to stereo as most devices can't accept mono
1250  if (!m_upmixer)
1251  {
1252  // we're always in the case
1253  // m_configuredChannels == 2 && m_sourceChannels == 1
1254  int bdFrames = bdiff / bpf;
1255  if (bdFrames <= frames)
1256  {
1257  AudioOutputUtil::MonoToStereo(WPOS, buffer, bdFrames);
1258  frames -= bdFrames;
1259  off = bdFrames * sizeof(float); // 1 channel of floats
1260  org_waud = 0;
1261  }
1262  if (frames > 0)
1263  AudioOutputUtil::MonoToStereo(WPOS, buffer + off, frames);
1264 
1265  org_waud = (org_waud + frames * bpf) % kAudioRingBufferSize;
1266  return len;
1267  }
1268 
1269  // Upmix to 6ch via FreeSurround
1270  // Calculate frame size of input
1271  off = m_processing ? sizeof(float) : AudioOutputSettings::SampleSize(m_format);
1272  off *= m_sourceChannels;
1273 
1274  int i = 0;
1275  len = 0;
1276  while (i < frames)
1277  {
1278  i += m_upmixer->putFrames(buffer + i * off, frames - i, m_sourceChannels);
1279  int nFrames = m_upmixer->numFrames();
1280  if (!nFrames)
1281  continue;
1282 
1283  len += CheckFreeSpace(nFrames);
1284 
1285  int bdFrames = (kAudioRingBufferSize - org_waud) / bpf;
1286  if (bdFrames < nFrames)
1287  {
1288  if ((org_waud % bpf) != 0)
1289  {
1290  VBERROR(QString("Upmixing: org_waud = %1 (bpf = %2)")
1291  .arg(org_waud)
1292  .arg(bpf));
1293  }
1294  m_upmixer->receiveFrames((float *)(WPOS), bdFrames);
1295  nFrames -= bdFrames;
1296  org_waud = 0;
1297  }
1298  if (nFrames > 0)
1299  m_upmixer->receiveFrames((float *)(WPOS), nFrames);
1300 
1301  org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
1302  }
1303  return len;
1304 }
1305 
1311 bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
1312  std::chrono::milliseconds timecode)
1313 {
1314  return AddData(in_buffer, in_frames * m_sourceBytesPerFrame, timecode,
1315  in_frames);
1316 }
1317 
1323 bool AudioOutputBase::AddData(void *in_buffer, int in_len,
1324  std::chrono::milliseconds timecode,
1325  int /*in_frames*/)
1326 {
1327  int frames = in_len / m_sourceBytesPerFrame;
1328  int bpf = m_bytesPerFrame;
1329  int len = in_len;
1330  bool music = false;
1331 
1332  if (!m_configureSucceeded)
1333  {
1334  LOG(VB_GENERAL, LOG_ERR, "AddData called with audio framework not "
1335  "initialised");
1336  m_lengthLastData = 0ms;
1337  return false;
1338  }
1339 
1340  /* See if we're waiting for new samples to be buffered before we unpause
1341  post channel change, seek, etc. Wait for 4 fragments to be buffered */
1343  {
1344  m_unpauseWhenReady = false;
1345  Pause(false);
1346  }
1347 
1348  // Don't write new samples if we're resetting the buffer or reconfiguring
1349  QMutexLocker lock(&m_audioBufLock);
1350 
1351  uint org_waud = m_waud;
1352  int afree = audiofree();
1353  int used = kAudioRingBufferSize - afree;
1354 
1355  if (m_passthru && m_spdifEnc)
1356  {
1357  if (m_processing)
1358  {
1359  /*
1360  * We shouldn't encounter this case, but it can occur when
1361  * timestretch just got activated. So we will just drop the
1362  * data
1363  */
1364  LOG(VB_AUDIO, LOG_INFO,
1365  "Passthrough activated with audio processing. Dropping audio");
1366  return false;
1367  }
1368  // mux into an IEC958 packet
1369  m_spdifEnc->WriteFrame((unsigned char *)in_buffer, len);
1370  len = m_spdifEnc->GetProcessedSize();
1371  if (len > 0)
1372  {
1373  in_buffer = m_spdifEnc->GetProcessedBuffer();
1374  m_spdifEnc->Reset();
1375  frames = len / m_sourceBytesPerFrame;
1376  }
1377  else
1378  frames = 0;
1379  }
1381  ((double)(len * 1000) / (m_sourceSampleRate * m_sourceBytesPerFrame));
1382 
1383  VBAUDIOTS(QString("AddData frames=%1, bytes=%2, used=%3, free=%4, "
1384  "timecode=%5 needsupmix=%6")
1385  .arg(frames).arg(len).arg(used).arg(afree).arg(timecode.count())
1386  .arg(m_needsUpmix));
1387 
1388  // Mythmusic doesn't give us timestamps
1389  if (timecode < 0ms)
1390  {
1391  timecode = std::chrono::milliseconds((m_framesBuffered * 1000) / m_sourceSampleRate);
1392  m_framesBuffered += frames;
1393  music = true;
1394  }
1395 
1396  if (hasVisual())
1397  {
1398  // Send original samples to any attached visualisations
1399  dispatchVisual((uchar *)in_buffer, len, timecode, m_sourceChannels,
1401  }
1402 
1403  // Calculate amount of free space required in ringbuffer
1404  if (m_processing)
1405  {
1406  int sampleSize = AudioOutputSettings::SampleSize(m_format);
1407  if (sampleSize <= 0)
1408  {
1409  // Would lead to division by zero (or unexpected results if negative)
1410  VBERROR("Sample size is <= 0, AddData returning false");
1411  return false;
1412  }
1413 
1414  // Final float conversion space requirement
1415  len = sizeof(m_srcInBuf[0]) / sampleSize * len;
1416 
1417  // Account for changes in number of channels
1418  if (m_needsDownmix)
1419  len = (len * m_configuredChannels ) / m_sourceChannels;
1420 
1421  // Check we have enough space to write the data
1422  if (m_needResampler && m_srcCtx)
1423  len = lround(ceil(static_cast<double>(len) * m_srcData.src_ratio));
1424 
1425  if (m_needsUpmix)
1426  len = (len * m_configuredChannels ) / m_sourceChannels;
1427 
1428  // Include samples in upmix buffer that may be flushed
1429  if (m_needsUpmix && m_upmixer)
1430  len += m_upmixer->numUnprocessedFrames() * bpf;
1431 
1432  // Include samples in soundstretch buffers
1433  if (m_pSoundStretch)
1434  len += (m_pSoundStretch->numUnprocessedSamples() +
1435  (int)(m_pSoundStretch->numSamples() / m_stretchFactor)) * bpf;
1436  }
1437 
1438  if (len > afree)
1439  {
1440  VBERROR("Buffer is full, AddData returning false");
1441  return false; // would overflow
1442  }
1443 
1444  int frames_remaining = frames;
1445  int frames_final = 0;
1446  int maxframes = (kAudioSRCInputSize / m_sourceChannels) & ~0xf;
1447  int offset = 0;
1448 
1449  while(frames_remaining > 0)
1450  {
1451  void *buffer = (char *)in_buffer + offset;
1452  frames = frames_remaining;
1453  len = frames * m_sourceBytesPerFrame;
1454 
1455  if (m_processing)
1456  {
1457  if (frames > maxframes)
1458  {
1459  frames = maxframes;
1460  len = frames * m_sourceBytesPerFrame;
1461  offset += len;
1462  }
1463  // Convert to floats
1464  AudioOutputUtil::toFloat(m_format, m_srcIn, buffer, len);
1465  }
1466 
1467  frames_remaining -= frames;
1468 
1469  // Perform downmix if necessary
1470  if (m_needsDownmix)
1471  {
1474  m_srcIn, m_srcIn, frames) < 0)
1475  VBERROR("Error occurred while downmixing");
1476  }
1477 
1478  // Resample if necessary
1479  if (m_needResampler && m_srcCtx)
1480  {
1481  m_srcData.input_frames = frames;
1482  int error = src_process(m_srcCtx, &m_srcData);
1483 
1484  if (error)
1485  VBERROR(QString("Error occurred while resampling audio: %1")
1486  .arg(src_strerror(error)));
1487 
1488  buffer = m_srcOut;
1489  frames = m_srcData.output_frames_gen;
1490  }
1491  else if (m_processing)
1492  buffer = m_srcIn;
1493 
1494  /* we want the timecode of the last sample added but we are given the
1495  timecode of the first - add the time in ms that the frames added
1496  represent */
1497 
1498  // Copy samples into audiobuffer, with upmix if necessary
1499  len = CopyWithUpmix((char *)buffer, frames, org_waud);
1500  if (len <= 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:931
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:969
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:909
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:1323
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:1190
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:990
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:342
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:209
AudioOutputBase::m_needResampler
bool m_needResampler
Definition: audiooutputbase.h:229
AudioOutput::Error
void Error(const QString &msg)
Definition: audiooutput.cpp:272
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
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:409
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:1000
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:867
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:1025
AudioOutputBase::GetStretchFactor
float GetStretchFactor(void) const override
Get the timetretch factor.
Definition: audiooutputbase.cpp:366
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:355
FEATURE_TRUEHD
@ FEATURE_TRUEHD
Definition: audiooutputsettings.h:40
AudioOutputBase::IsUpmixing
bool IsUpmixing(void) override
Source is currently being upmixed.
Definition: audiooutputbase.cpp:374
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:981
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:1105
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
OutputEvent::kStopped
static const Type kStopped
Definition: output.h:67
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
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:97
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:156
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:855
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:469
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:55
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:912
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:1177
OutputEvent::kPlaying
static const Type kPlaying
Definition: output.h:63
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:906
AudioOutputBase::audioready
int audioready() const
Get the scaled number of bytes in the audiobuffer, i.e.
Definition: audiooutputbase.cpp:1015
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:1225
AudioOutputBase::m_configuredChannels
int m_configuredChannels
Definition: audiooutputbase.h:206
AudioOutputBase::m_setInitialVol
bool m_setInitialVol
Definition: audiooutputbase.h:203
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:1167
AudioOutputBase::CanUpmix
bool CanUpmix(void) override
Upmixing of the current source is available if requested.
Definition: audiooutputbase.cpp:400
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:278
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:1311
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:357
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:120
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:921
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:843
AudioOutput::ClearError
void ClearError(void)
Definition: audiooutput.cpp:289
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:185
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:282
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:881
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:1155
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:382
OutputEvent::kPaused
static const Type kPaused
Definition: output.h:66
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:271
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:898
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:457