12#pragma GCC diagnostic push
13#pragma GCC diagnostic ignored "-Wundef"
14#if __has_include(<soundtouch/SoundTouch.h>)
15#include <soundtouch/SoundTouch.h>
17#include <SoundTouch.h>
19#pragma GCC diagnostic pop
22#include "libavcodec/defs.h"
27#include <QMutexLocker>
28#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
29#include <QtProcessorDetection>
45#define DISABLE_AC3_ENCODE
48#define LOC QString("AOBase: ")
53#define WPOS (&m_audioBuffer[org_waud])
54#define RPOS (&m_audioBuffer[m_raud])
55#define ABUF (m_audioBuffer.data())
56#define STST soundtouch::SAMPLETYPE
85static const float m6db = 0.5;
86static const float m3db = 1.0F / std::numbers::sqrt2_v<float>;
87static const float mm3db = -1.0F / std::numbers::sqrt2_v<float>;
88static const float msqrt_1_3 = -std::numbers::inv_sqrt3_v<float>;
89static const float sqrt_2_3 = std::numbers::sqrt2_v<float> /
90 std::numbers::sqrt3_v<float>;
93 std::numbers::sqrt3_v<float>);
175 { 1, 0, 0, 0, 0, 0 },
176 { 0, 1, 0, 0, 0, 0 },
177 { 0, 0, 1, 0, 0, 0 },
178 { 0, 0, 0, 1, 0, 0 },
179 { 0, 0, 0, 0, 1, 0 },
180 { 0, 0, 0, 0, 0, 1 },
186 { 1, 0, 0, 0, 0, 0 },
187 { 0, 1, 0, 0, 0, 0 },
188 { 0, 0, 1, 0, 0, 0 },
189 { 0, 0, 0, 1, 0, 0 },
191 { 0, 0, 0, 0, 1, 0 },
192 { 0, 0, 0, 0, 0, 1 },
197 { 1, 0, 0, 0, 0, 0 },
198 { 0, 1, 0, 0, 0, 0 },
199 { 0, 0, 1, 0, 0, 0 },
200 { 0, 0, 0, 1, 0, 0 },
201 { 0, 0, 0, 0,
m3db, 0 },
202 { 0, 0, 0, 0, 0,
m3db },
203 { 0, 0, 0, 0,
m3db, 0 },
204 { 0, 0, 0, 0, 0,
m3db },
209 float *dst,
const float *src,
int frames)
211 if (channels_in < channels_out)
216 if (channels_out == 2)
218 int index = channels_in - 1;
219 for (
int n=0; n < frames; n++)
221 for (
int i=0; i < channels_out; i++)
224 for (
int j=0; j < channels_in; j++)
231 else if (channels_out == 6)
233 int index = channels_in - 6;
234 for (
int n=0; n < frames; n++)
236 for (
int i=0; i < channels_out; i++)
239 for (
int j=0; j < channels_in; j++)
254#ifdef Q_PROCESSOR_X86
256static inline bool sse2_check()
258#ifdef Q_PROCESSOR_X86_64
261 static int has_sse2 = -1;
263 return (
bool)has_sse2;
269 "and $0x4000000, %%edx \n\t"
270 "shr $26, %%edx \n\t"
275 return (
bool)has_sse2;
286#ifdef Q_PROCESSOR_X86
300 bool music,
bool upmix)
302 float g = volume / 100.0F;
303 auto *fptr = (
float *)buf;
321#ifdef Q_PROCESSOR_X86
322 if (sse2_check() &&
samples >= 16)
328 "movss %2, %%xmm0 \n\t"
329 "punpckldq %%xmm0, %%xmm0 \n\t"
330 "punpckldq %%xmm0, %%xmm0 \n\t"
332 "movups (%0), %%xmm1 \n\t"
333 "movups 16(%0), %%xmm2 \n\t"
334 "mulps %%xmm0, %%xmm1 \n\t"
335 "movups 32(%0), %%xmm3 \n\t"
336 "mulps %%xmm0, %%xmm2 \n\t"
337 "movups 48(%0), %%xmm4 \n\t"
338 "mulps %%xmm0, %%xmm3 \n\t"
339 "movups %%xmm1, (%0) \n\t"
340 "mulps %%xmm0, %%xmm4 \n\t"
341 "movups %%xmm2, 16(%0) \n\t"
342 "movups %%xmm3, 32(%0) \n\t"
343 "movups %%xmm4, 48(%0) \n\t"
349 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4"
357template <
class AudioDataType>
358static void tMuteChannel(AudioDataType *buffer,
int channels,
int ch,
int frames)
360 AudioDataType *s1 = buffer + ch;
361 AudioDataType *s2 = buffer - ch + 1;
363 for (
int i = 0; i < frames; i++)
378 void *buffer,
int bytes)
380 int frames =
bytes / ((obits >> 3) * channels);
384 else if (obits == 16)
398 default:
return "unknown";
405 m_mainDevice(settings.GetMainDevice()),
406 m_passthruDevice(settings.GetPassthruDevice()),
407 m_source(settings.m_source),
408 m_setInitialVol(settings.m_setInitialVol)
433 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Programmer Error: "
434 "~AudioOutputBase called, but KillAudio has not been called!");
539 aosettings->GetUsers();
550 AVCodecID codec,
int profile)
const
557 case AV_CODEC_ID_AC3:
560 case AV_CODEC_ID_DTS:
564 case AV_PROFILE_DTS_ES:
565 case AV_PROFILE_DTS_96_24:
568 case AV_PROFILE_DTS_HD_HRA:
569 case AV_PROFILE_DTS_HD_MA:
576 case AV_CODEC_ID_EAC3:
579 case AV_CODEC_ID_TRUEHD:
591 ret &= (samplerate == 48000) ||
595 ret &= samplerate >= 44100;
645 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Cancelling time stretch"));
653 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Changing time stretch to %1")
658 else if (willstretch)
665#if defined(Q_PROCESSOR_ARM) || defined(Q_OS_ANDROID)
744 return m_sourceChannels <= 2 && m_maxChannels > 2;
752 int &samplerate_tmp,
int &channels_tmp)
754 if (codec == AV_CODEC_ID_DTS &&
759 codec_profile = AV_PROFILE_DTS;
762 codec, codec_profile,
763 samplerate_tmp, channels_tmp,
765 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Setting " +
log +
" passthrough");
776 switch(codec_profile)
779 case AV_PROFILE_DTS_ES:
780 case AV_PROFILE_DTS_96_24:
783 case AV_PROFILE_DTS_HD_HRA:
784 case AV_PROFILE_DTS_HD_MA:
816 bool lneeds_upmix =
false;
817 bool lneeds_downmix =
false;
824 lconfigured_channels =
826 bool cando_channels =
830#ifndef DISABLE_AC3_ENCODE
833 lconfigured_channels > 2 && lconfigured_channels <= 6);
835 if (!lenc && !cando_channels)
840 switch (lconfigured_channels)
843 lconfigured_channels = 8;
847 lconfigured_channels = 6;
853 lconfigured_channels = 2;
859 lconfigured_channels = 2;
865 if (lsource_channels <= 6)
866 lconfigured_channels = std::min(lconfigured_channels, 6);
867 lconfigured_channels = std::min(lconfigured_channels,
m_maxChannels);
872#ifndef DISABLE_AC3_ENCODE
875 lconfigured_channels > 2) ||
880 (settings.
m_codec == AV_CODEC_ID_AC3 ||
881 settings.
m_codec == AV_CODEC_ID_DTS))
890 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs upmix from %1 -> %2 channels")
891 .arg(settings.
m_channels).arg(lconfigured_channels));
895 else if (settings.
m_channels > lconfigured_channels)
897 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs downmix from %1 -> %2 channels")
898 .arg(settings.
m_channels).arg(lconfigured_channels));
900 lneeds_downmix =
true;
904 bool general_deps =
true;
908 int samplerate_tmp = 0;
909 int channels_tmp = 0;
914 samplerate_tmp, channels_tmp);
934 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reconfigure(): No change -> exiting");
973 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Original codec was %1, %2, %3 kHz, %4 channels")
974 .arg(avcodec_get_name(
m_codec),
981 QString message {QCoreApplication::translate(
"AudioOutputBase",
982 "Aborting Audio Reconfigure. Can't handle audio with more than 8 channels.")};
984 LOG(VB_GENERAL, LOG_ERR, message);
988 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"enc(%1), passthru(%2), features (%3) "
989 "configured_channels(%4), %5 channels supported(%6) "
1007 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Forcing resample to 48 kHz");
1029 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Resampling from %1 kHz to %2 kHz with quality %3")
1039 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Error creating resampler: %1")
1040 .arg(src_strerror(
error))};
1042 LOG(VB_GENERAL, LOG_ERR, message);
1055 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Resampler allocating %1").arg(newsize));
1067 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reencoding decoded AC-3/DTS to AC-3");
1069 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Creating AC-3 Encoder with sr = %1, ch = %2")
1076 QString message {QCoreApplication::translate(
"AudioOutputBase",
"AC-3 encoder initialization failed")};
1078 LOG(VB_GENERAL, LOG_ERR, message);
1108 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio processing enabled");
1126 LOG(VB_GENERAL, LOG_INFO,
LOC +
1127 QString(
"Opening audio device '%1' ch %2(%3) sr %4 sf %5 reenc %6")
1140 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Aborting reconfigure")};
1142 LOG(VB_GENERAL, LOG_INFO,
LOC + message);
1151 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Software volume enabled");
1166 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Create %1 quality upmixer done")
1183 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Ending Reconfigure()");
1214 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Killing AudioOutputDSP");
1256 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Pause %1").arg(paused));
1327 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"SetEffDsp: %1").arg(dsprate));
1415 std::chrono::milliseconds oldaudiotime =
m_audioTime;
1424 * 80 / int64_t(
m_effDsp) / obpf) : 0);
1432 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"GetAudiotime audt=%1 abtc=%2 mb=%3 sb=%4 tb=%5 "
1433 "sr=%6 obpf=%7 bpf=%8 esf=%9 edsp=%10 sbr=%11")
1437 .arg(soundcard_buffer)
1438 .arg(main_buffer+soundcard_buffer)
1455 int64_t processframes_stretched = 0;
1456 int64_t processframes_unstretched = 0;
1467 processframes_unstretched -=
m_pSoundStretch->numUnprocessedSamples();
1477 timecode + std::chrono::milliseconds(
m_effDsp ? (((frames + processframes_unstretched) * 100000) +
1487 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
1489 .arg(timecode.count())
1491 .arg(processframes_unstretched)
1492 .arg(processframes_stretched));
1493#ifdef AUDIOTSTESTING
1541 int len = frames * bpf;
1547 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Audio buffer overflow, %1 frames lost!")
1548 .arg(frames - (afree / bpf)));
1550 frames = afree / bpf;
1559 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resetting resampler: %1")
1560 .arg(src_strerror(
error)));
1586 memcpy(
WPOS, buffer, bdiff);
1592 memcpy(
WPOS, buffer + off, num);
1602 int bdFrames = bdiff / bpf;
1603 if (bdFrames <= frames)
1607 off = bdFrames *
sizeof(float);
1634 if (bdFrames < nFrames)
1636 if ((org_waud % bpf) != 0)
1638 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Upmixing: org_waud = %1 (bpf = %2)")
1643 nFrames -= bdFrames;
1660 std::chrono::milliseconds timecode)
1672 std::chrono::milliseconds timecode,
1682 LOG(VB_GENERAL, LOG_ERR,
"AddData called with audio framework not "
1712 LOG(VB_AUDIO, LOG_INFO,
1713 "Passthrough activated with audio processing. Dropping audio");
1733 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"AddData frames=%1, bytes=%2, used=%3, free=%4, "
1734 "timecode=%5 needsupmix=%6")
1735 .arg(frames).arg(len).arg(used).arg(afree).arg(timecode.count())
1757 if (sampleSize <= 0)
1760 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Sample size is <= 0, AddData returning false");
1765 len =
sizeof(
m_srcInBuf[0]) / sampleSize * len;
1773 len = lround(ceil(
static_cast<double>(len) *
m_srcData.src_ratio));
1790 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Buffer is full, AddData returning false");
1794 int frames_remaining = frames;
1795 int frames_final = 0;
1799 while(frames_remaining > 0)
1801 void *buffer = (
char *)in_buffer + offset;
1802 frames = frames_remaining;
1807 if (frames > maxframes)
1817 frames_remaining -= frames;
1825 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error occurred while downmixing");
1835 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resampling audio: %1")
1836 .arg(src_strerror(
error)));
1858 frames_final += frames;
1861 if ((len % bpf) != 0 && bdiff < len)
1863 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: len = %1 (bpf = %2)")
1867 if ((bdiff % bpf) != 0 && bdiff < len)
1869 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: bdiff = %1 (bpf = %2)")
1878 int bdFrames = bdiff / bpf;
1891 if (nFrames > frames)
1894 len = nFrames * bpf;
1896 if (nFrames > bdFrames)
1942 if (bdiff <= to_get)
2003 auto *fragment =
new(std::align_val_t(16)) uchar[
m_fragmentSize];
2008 zero_fragment_size = std::min(zero_fragment_size,
m_fragmentSize);
2016 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: audio paused");
2017 Event e(Event::kPaused);
2031 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Play Event");
2032 Event e(Event::kPlaying);
2045 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"audio waiting for buffer to fill: "
2050 std::this_thread::sleep_for(10ms);
2054#ifdef AUDIOTSTESTING
2055 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Start");
2072#ifdef AUDIOTSTESTING
2074 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Done");
2079 ::operator
delete[] (zeros, std::align_val_t(16));
2080 ::operator
delete[] (fragment, std::align_val_t(16));
2081 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Stop Event");
2082 Event e(Event::kStopped);
2094 volatile uint *local_raud)
2097#define LRPOS (&m_audioBuffer[*local_raud])
2101 int frag_size = size;
2102 int written_size = size;
2104 if (local_raud ==
nullptr)
2107 if (!full_buffer && (size > avail_size))
2110 frag_size = avail_size;
2111 written_size = frag_size;
2114 if (!avail_size || (frag_size <= 0) || (frag_size > avail_size))
2127 if (fromFloats && obytes !=
sizeof(
float))
2128 frag_size *=
sizeof(float) / obytes;
2132 if (bdiff <= frag_size)
2141 memcpy(buffer,
LRPOS, bdiff);
2157 memcpy(buffer + off,
LRPOS, frag_size);
2161 *local_raud += frag_size;
2171 buffer, written_size);
2174 return written_size;
2183 std::this_thread::sleep_for(1ms);
2200 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"kickoffOutputAudioLoop: pid = %1").arg(getpid()));
2202 LOG(VB_AUDIO, LOG_INFO,
LOC +
"kickoffOutputAudioLoop exiting");
2208 LOG(VB_GENERAL, LOG_ERR,
LOC +
"AudioOutputBase should not be getting asked to readOutputData()");
static void tMuteChannel(AudioDataType *buffer, int channels, int ch, int frames)
static const std::array< six_speaker_set, 3 > s51_matrix
static const float msqrt_1_3bym3db
static void muteChannel(int obits, int channels, int ch, void *buffer, int bytes)
Mute individual channels through mono->stereo duplication.
std::array< float, 2 > two_speaker_ratio
static const float sqrt_2_3by3db
static const float sqrt_2_3
std::array< float, 6 > six_speaker_ratio
static int DownmixFrames(int channels_in, int channels_out, float *dst, const float *src, int frames)
static constexpr int UPMIX_CHANNEL_MASK
static constexpr bool IS_VALID_UPMIX_CHANNEL(int ch)
static const std::array< two_speaker_set, 8 > stereo_matrix
std::array< six_speaker_ratio, 8 > six_speaker_set
std::array< two_speaker_ratio, 8 > two_speaker_set
static void adjustVolume(void *buf, int len, int volume, bool music, bool upmix)
Adjust the volume of samples.
static const float msqrt_1_3
static int toFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert integer samples to floats.
static void MonoToStereo(void *dst, const void *src, int samples)
Convert a mono stream to stereo by copying and interleaving samples.
static int fromFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert float samples to integers.
void KillAudio(void)
Kill the output thread and cleanup.
virtual void StopOutputThread(void)
void Reconfigure(const AudioSettings &settings) override
(Re)Configure AudioOutputBase
bool IsUpmixing(void) override
Source is currently being upmixed.
bool ToggleUpmix(void) override
Toggle between stereo and upmixed 5.1 if the source material is stereo.
AudioOutputSource m_source
void SetStretchFactor(float factor) override
Set the timestretch factor.
std::chrono::seconds m_currentSeconds
AudioOutputSettings * GetOutputSettingsUsers(bool digital=false) override
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
soundtouch::SoundTouch * m_pSoundStretch
AudioOutputBase(const AudioSettings &settings)
int m_kAudioSRCOutputSize
virtual bool StartOutputThread(void)
void OutputAudioLoop(void)
Run in the output thread, write frames to the output device as they become available and there's spac...
void SetEffDsp(int dsprate) override
Set the effective DSP rate.
int GetSWVolume(void) override
Get the volume for software volume control.
int audiofree() const
Get the free space in the audiobuffer in bytes.
std::chrono::milliseconds m_lengthLastData
AudioFormat m_outputFormat
std::chrono::milliseconds m_audbufTimecode
timecode of audio most recently placed into buffer
int CheckFreeSpace(int &frames)
Check that there's enough space in the audiobuffer to write the provided number of frames.
bool AddFrames(void *buffer, int frames, std::chrono::milliseconds timecode) override
Add frames to the audiobuffer and perform any required processing.
int m_outputBytesPerFrame
QMutex m_audioBufLock
Writes to the audiobuffer, reconfigures and audiobuffer resets can only take place while holding this...
void SetTimecode(std::chrono::milliseconds timecode) override
Set the timecode of the samples most recently added to the audiobuffer.
bool CanUpmix(void) override
Upmixing of the current source is available if requested.
float GetStretchFactor(void) const override
Get the timetretch factor.
void InitSettings(const AudioSettings &settings)
AudioOutputSettings * m_outputSettingsRaw
AudioOutputDigitalEncoder * m_encoder
std::array< uchar, kAudioRingBufferSize > m_audioBuffer
main audio buffer
void SetStretchFactorLocked(float factor)
Set the timestretch factor.
virtual void WriteAudio(unsigned char *aubuf, int size)=0
uint m_memoryCorruptionTest2
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.
virtual AudioOutputSettings * GetOutputSettings(bool)
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...
std::chrono::milliseconds GetAudioBufferedTime(void) override
Get the difference in timecode between the samples that are about to become audible and the samples m...
virtual bool OpenDevice(void)=0
uint m_memoryCorruptionTest3
uint m_memoryCorruptionTest0
AudioOutputSettings * GetOutputSettingsCleaned(bool digital=true) override
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
static const char * quality_string(int q)
bool AddData(void *buffer, int len, std::chrono::milliseconds timecode, int frames) override
Add data to the audiobuffer and perform any required processing.
std::chrono::milliseconds m_audioTime
timecode of audio leaving the soundcard (same units as timecodes)
virtual void Status(void)
Report status via an AudioOutput::Event.
int audiolen() const
Get the number of bytes in the audiobuffer.
static const uint kAudioSRCInputSize
std::array< float, kAudioSRCInputSize > m_srcInBuf
void Reset(void) override
Reset the audiobuffer, timecode and mythmusic visualisation.
void Pause(bool paused) override
int GetAudioData(uchar *buffer, int buf_size, bool full_buffer, volatile uint *local_raud=nullptr)
Copy frames from the audiobuffer into the buffer provided.
~AudioOutputBase() override
Destructor.
int m_sourceBytesPerFrame
volatile uint m_raud
Audio circular buffer.
void Drain(void) override
Block until all available frames have been written to the device.
std::chrono::milliseconds GetAudiotime(void) override
Calculate the timecode of the samples that are about to become audible.
bool SetupPassthrough(AVCodecID codec, int codec_profile, int &samplerate_tmp, int &channels_tmp)
virtual int GetBufferedOnSoundcard(void) const =0
Return the size in bytes of frames currently in the audio buffer adjusted with the audio playback lat...
int readOutputData(unsigned char *read_buffer, size_t max_length) override
void SetSWVolume(int new_volume, bool save) override
Set the volume for software volume control.
uint m_memoryCorruptionTest1
virtual void CloseDevice(void)=0
AudioOutputSettings * m_outputSettingsDigital
void run() override
Main routine for the output thread.
SPDIFEncoder * m_spdifEnc
void GetBufferStatus(uint &fill, uint &total) override
Fill in the number of bytes in the audiobuffer and the total size of the audiobuffer.
void PauseUntilBuffered(void) override
int CopyWithUpmix(char *buffer, int frames, uint &org_waud)
Copy frames into the audiobuffer, upmixing en route if necessary.
AudioOutputSettings * m_outputSettings
int audioready() const
Get the scaled number of bytes in the audiobuffer, i.e.
AudioOutputSettings * m_outputSettingsDigitalRaw
AudioOutputSettings * OutputSettings(bool digital=true)
static const uint kAudioRingBufferSize
Audio Buffer Size – should be divisible by 32,24,16,12,10,8,6,4,2..
void SetSourceBitrate(int rate) override
Set the bitrate of the source material, reported in periodic AudioOutput::Events.
QMutex m_avsyncLock
must hold avsync_lock to read or write 'audiotime' and 'audiotime_updated'
bool has_optimized_SIMD() override
Returns true if the processor supports MythTV's optimized SIMD for AudioConvert.
AsyncLooseLock m_resetActive
bool Init(AVCodecID codec_id, int bitrate, int samplerate, int channels)
int GetFrames(void *ptr, int maxlen)
int Encode(void *input, int len, AudioFormat format)
bool IsSupportedChannels(int channels)
int BestSupportedChannels()
static int SampleSize(AudioFormat format)
AudioFormat BestSupportedFormat()
bool canFeature(DigitalFeature arg) const
return DigitalFeature mask.
int GetMaxHDRate() const
return the highest iec958 rate supported.
bool IsSupportedRate(int rate)
int NearestSupportedRate(int rate)
AudioOutputSettings * GetCleaned(bool newcopy=false)
Returns capabilities supported by the audio device amended to take into account the digital audio opt...
static const char * FormatToString(AudioFormat format)
static int FormatToBits(AudioFormat format)
static QString FeaturesToString(DigitalFeature arg)
Display in human readable form the digital features supported by the output device.
static QString GetPassthroughParams(int codec, int codec_profile, int &samplerate, int &channels, bool canDTSHDMA)
Setup samplerate and number of channels for passthrough.
bool IsSupportedFormat(AudioFormat format)
void dispatchVisual(uchar *b, unsigned long b_len, std::chrono::milliseconds timecode, int chan, int prec)
void dispatchError(const QString &e)
const int & channels() const
AudioOutputSettings * m_custom
custom contains a pointer to the audio device capabilities if defined, AudioOutput will not try to au...
uint frameLatency() const
uint receiveFrames(void *buffer, uint maxFrames)
uint numUnprocessedFrames() const
uint putFrames(void *buffer, uint numFrames, uint numChannels)
This is a wrapper around QThread that does several additional things.
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
int GetNumSetting(const QString &key, int defaultval=0)
bool GetBoolSetting(const QString &key, bool defaultval=false)
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
unsigned char * GetProcessedBuffer()
void Reset()
Reset the internal encoder buffer.
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...
bool SetMaxHDRate(int rate)
Set the maximum HD rate.
virtual MuteState GetMuteState(void) const
bool SWVolume(void) const
void SetChannels(int new_channels)
static const std::array< const uint64_t, 4 > samples
std::chrono::milliseconds millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
None log(str msg, int level=LOGDEBUG)