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"
28#include <QMutexLocker>
29#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
30#include <QtProcessorDetection>
46#define DISABLE_AC3_ENCODE
49#define LOC QString("AOBase: ")
54#define WPOS (&m_audioBuffer[org_waud])
55#define RPOS (&m_audioBuffer[m_raud])
56#define ABUF (m_audioBuffer.data())
57#define STST soundtouch::SAMPLETYPE
86static const float m6db = 0.5;
87static const float m3db = 1.0F / std::numbers::sqrt2_v<float>;
88static const float mm3db = -1.0F / std::numbers::sqrt2_v<float>;
89static const float msqrt_1_3 = -std::numbers::inv_sqrt3_v<float>;
90static const float sqrt_2_3 = std::numbers::sqrt2_v<float> /
91 std::numbers::sqrt3_v<float>;
94 std::numbers::sqrt3_v<float>);
176 { 1, 0, 0, 0, 0, 0 },
177 { 0, 1, 0, 0, 0, 0 },
178 { 0, 0, 1, 0, 0, 0 },
179 { 0, 0, 0, 1, 0, 0 },
180 { 0, 0, 0, 0, 1, 0 },
181 { 0, 0, 0, 0, 0, 1 },
187 { 1, 0, 0, 0, 0, 0 },
188 { 0, 1, 0, 0, 0, 0 },
189 { 0, 0, 1, 0, 0, 0 },
190 { 0, 0, 0, 1, 0, 0 },
192 { 0, 0, 0, 0, 1, 0 },
193 { 0, 0, 0, 0, 0, 1 },
198 { 1, 0, 0, 0, 0, 0 },
199 { 0, 1, 0, 0, 0, 0 },
200 { 0, 0, 1, 0, 0, 0 },
201 { 0, 0, 0, 1, 0, 0 },
202 { 0, 0, 0, 0,
m3db, 0 },
203 { 0, 0, 0, 0, 0,
m3db },
204 { 0, 0, 0, 0,
m3db, 0 },
205 { 0, 0, 0, 0, 0,
m3db },
210 float *dst,
const float *src,
int frames)
212 if (channels_in < channels_out)
217 if (channels_out == 2)
219 int index = channels_in - 1;
220 for (
int n=0; n < frames; n++)
222 for (
int i=0; i < channels_out; i++)
225 for (
int j=0; j < channels_in; j++)
232 else if (channels_out == 6)
234 int index = channels_in - 6;
235 for (
int n=0; n < frames; n++)
237 for (
int i=0; i < channels_out; i++)
240 for (
int j=0; j < channels_in; j++)
255#ifdef Q_PROCESSOR_X86
257static inline bool sse2_check()
259#ifdef Q_PROCESSOR_X86_64
262 static int has_sse2 = -1;
264 return (
bool)has_sse2;
270 "and $0x4000000, %%edx \n\t"
271 "shr $26, %%edx \n\t"
276 return (
bool)has_sse2;
287#ifdef Q_PROCESSOR_X86
301 bool music,
bool upmix)
303 float g = volume / 100.0F;
304 auto *fptr = (
float *)buf;
322#ifdef Q_PROCESSOR_X86
323 if (sse2_check() &&
samples >= 16)
329 "movss %2, %%xmm0 \n\t"
330 "punpckldq %%xmm0, %%xmm0 \n\t"
331 "punpckldq %%xmm0, %%xmm0 \n\t"
333 "movups (%0), %%xmm1 \n\t"
334 "movups 16(%0), %%xmm2 \n\t"
335 "mulps %%xmm0, %%xmm1 \n\t"
336 "movups 32(%0), %%xmm3 \n\t"
337 "mulps %%xmm0, %%xmm2 \n\t"
338 "movups 48(%0), %%xmm4 \n\t"
339 "mulps %%xmm0, %%xmm3 \n\t"
340 "movups %%xmm1, (%0) \n\t"
341 "mulps %%xmm0, %%xmm4 \n\t"
342 "movups %%xmm2, 16(%0) \n\t"
343 "movups %%xmm3, 32(%0) \n\t"
344 "movups %%xmm4, 48(%0) \n\t"
350 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4"
358template <
class AudioDataType>
359static void tMuteChannel(AudioDataType *buffer,
int channels,
int ch,
int frames)
361 AudioDataType *s1 = buffer + ch;
362 AudioDataType *s2 = buffer - ch + 1;
364 for (
int i = 0; i < frames; i++)
379 void *buffer,
int bytes)
381 int frames =
bytes / ((obits >> 3) * channels);
385 else if (obits == 16)
399 default:
return "unknown";
406 m_mainDevice(settings.GetMainDevice()),
407 m_passthruDevice(settings.GetPassthruDevice()),
408 m_source(settings.m_source),
409 m_setInitialVol(settings.m_setInitialVol)
434 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Programmer Error: "
435 "~AudioOutputBase called, but KillAudio has not been called!");
540 aosettings->GetUsers();
551 AVCodecID codec,
int profile)
const
558 case AV_CODEC_ID_AC3:
561 case AV_CODEC_ID_DTS:
565 case AV_PROFILE_DTS_ES:
566 case AV_PROFILE_DTS_96_24:
569 case AV_PROFILE_DTS_HD_HRA:
570 case AV_PROFILE_DTS_HD_MA:
577 case AV_CODEC_ID_EAC3:
580 case AV_CODEC_ID_TRUEHD:
592 ret &= (samplerate == 48000) ||
596 ret &= samplerate >= 44100;
646 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Cancelling time stretch"));
654 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Changing time stretch to %1")
659 else if (willstretch)
666#if defined(Q_PROCESSOR_ARM) || defined(Q_OS_ANDROID)
745 return m_sourceChannels <= 2 && m_maxChannels > 2;
753 int &samplerate_tmp,
int &channels_tmp)
755 if (codec == AV_CODEC_ID_DTS &&
760 codec_profile = AV_PROFILE_DTS;
763 codec, codec_profile,
764 samplerate_tmp, channels_tmp,
766 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Setting " +
log +
" passthrough");
777 switch(codec_profile)
780 case AV_PROFILE_DTS_ES:
781 case AV_PROFILE_DTS_96_24:
784 case AV_PROFILE_DTS_HD_HRA:
785 case AV_PROFILE_DTS_HD_MA:
817 bool lneeds_upmix =
false;
818 bool lneeds_downmix =
false;
825 lconfigured_channels =
827 bool cando_channels =
831#ifndef DISABLE_AC3_ENCODE
834 lconfigured_channels > 2 && lconfigured_channels <= 6);
836 if (!lenc && !cando_channels)
841 switch (lconfigured_channels)
844 lconfigured_channels = 8;
848 lconfigured_channels = 6;
854 lconfigured_channels = 2;
860 lconfigured_channels = 2;
866 if (lsource_channels <= 6)
867 lconfigured_channels = std::min(lconfigured_channels, 6);
868 lconfigured_channels = std::min(lconfigured_channels,
m_maxChannels);
873#ifndef DISABLE_AC3_ENCODE
876 lconfigured_channels > 2) ||
881 (settings.
m_codec == AV_CODEC_ID_AC3 ||
882 settings.
m_codec == AV_CODEC_ID_DTS))
891 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs upmix from %1 -> %2 channels")
892 .arg(settings.
m_channels).arg(lconfigured_channels));
896 else if (settings.
m_channels > lconfigured_channels)
898 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs downmix from %1 -> %2 channels")
899 .arg(settings.
m_channels).arg(lconfigured_channels));
901 lneeds_downmix =
true;
905 bool general_deps =
true;
909 int samplerate_tmp = 0;
910 int channels_tmp = 0;
915 samplerate_tmp, channels_tmp);
935 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reconfigure(): No change -> exiting");
974 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Original codec was %1, %2, %3 kHz, %4 channels")
975 .arg(avcodec_get_name(
m_codec),
982 QString message {QCoreApplication::translate(
"AudioOutputBase",
983 "Aborting Audio Reconfigure. Can't handle audio with more than 8 channels.")};
985 LOG(VB_GENERAL, LOG_ERR, message);
989 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"enc(%1), passthru(%2), features (%3) "
990 "configured_channels(%4), %5 channels supported(%6) "
1008 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Forcing resample to 48 kHz");
1030 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Resampling from %1 kHz to %2 kHz with quality %3")
1040 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Error creating resampler: %1")
1041 .arg(src_strerror(
error))};
1043 LOG(VB_GENERAL, LOG_ERR, message);
1056 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Resampler allocating %1").arg(newsize));
1068 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reencoding decoded AC-3/DTS to AC-3");
1070 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Creating AC-3 Encoder with sr = %1, ch = %2")
1077 QString message {QCoreApplication::translate(
"AudioOutputBase",
"AC-3 encoder initialization failed")};
1079 LOG(VB_GENERAL, LOG_ERR, message);
1109 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio processing enabled");
1127 LOG(VB_GENERAL, LOG_INFO,
LOC +
1128 QString(
"Opening audio device '%1' ch %2(%3) sr %4 sf %5 reenc %6")
1141 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Aborting reconfigure")};
1143 LOG(VB_GENERAL, LOG_INFO,
LOC + message);
1152 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Software volume enabled");
1167 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Create %1 quality upmixer done")
1184 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Ending Reconfigure()");
1215 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Killing AudioOutputDSP");
1257 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Pause %1").arg(paused));
1328 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"SetEffDsp: %1").arg(dsprate));
1416 std::chrono::milliseconds oldaudiotime =
m_audioTime;
1425 * 80 / int64_t(
m_effDsp) / obpf) : 0);
1433 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"GetAudiotime audt=%1 abtc=%2 mb=%3 sb=%4 tb=%5 "
1434 "sr=%6 obpf=%7 bpf=%8 esf=%9 edsp=%10 sbr=%11")
1438 .arg(soundcard_buffer)
1439 .arg(main_buffer+soundcard_buffer)
1456 int64_t processframes_stretched = 0;
1457 int64_t processframes_unstretched = 0;
1468 processframes_unstretched -=
m_pSoundStretch->numUnprocessedSamples();
1478 timecode + std::chrono::milliseconds(
m_effDsp ? (((frames + processframes_unstretched) * 100000) +
1488 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
1490 .arg(timecode.count())
1492 .arg(processframes_unstretched)
1493 .arg(processframes_stretched));
1494#ifdef AUDIOTSTESTING
1542 int len = frames * bpf;
1548 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Audio buffer overflow, %1 frames lost!")
1549 .arg(frames - (afree / bpf)));
1551 frames = afree / bpf;
1560 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resetting resampler: %1")
1561 .arg(src_strerror(
error)));
1587 memcpy(
WPOS, buffer, bdiff);
1593 memcpy(
WPOS, buffer + off, num);
1603 int bdFrames = bdiff / bpf;
1604 if (bdFrames <= frames)
1608 off = bdFrames *
sizeof(float);
1635 if (bdFrames < nFrames)
1637 if ((org_waud % bpf) != 0)
1639 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Upmixing: org_waud = %1 (bpf = %2)")
1644 nFrames -= bdFrames;
1661 std::chrono::milliseconds timecode)
1673 std::chrono::milliseconds timecode,
1683 LOG(VB_GENERAL, LOG_ERR,
"AddData called with audio framework not "
1713 LOG(VB_AUDIO, LOG_INFO,
1714 "Passthrough activated with audio processing. Dropping audio");
1734 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"AddData frames=%1, bytes=%2, used=%3, free=%4, "
1735 "timecode=%5 needsupmix=%6")
1736 .arg(frames).arg(len).arg(used).arg(afree).arg(timecode.count())
1758 if (sampleSize <= 0)
1761 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Sample size is <= 0, AddData returning false");
1766 len =
sizeof(
m_srcInBuf[0]) / sampleSize * len;
1774 len = lround(ceil(
static_cast<double>(len) *
m_srcData.src_ratio));
1791 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Buffer is full, AddData returning false");
1795 int frames_remaining = frames;
1796 int frames_final = 0;
1800 while(frames_remaining > 0)
1802 void *buffer = (
char *)in_buffer + offset;
1803 frames = frames_remaining;
1808 if (frames > maxframes)
1818 frames_remaining -= frames;
1826 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error occurred while downmixing");
1836 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resampling audio: %1")
1837 .arg(src_strerror(
error)));
1859 frames_final += frames;
1862 if ((len % bpf) != 0 && bdiff < len)
1864 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: len = %1 (bpf = %2)")
1868 if ((bdiff % bpf) != 0 && bdiff < len)
1870 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: bdiff = %1 (bpf = %2)")
1879 int bdFrames = bdiff / bpf;
1892 if (nFrames > frames)
1895 len = nFrames * bpf;
1897 if (nFrames > bdFrames)
1943 if (bdiff <= to_get)
2004 auto *fragment =
new(std::align_val_t(16)) uchar[
m_fragmentSize];
2009 zero_fragment_size = std::min(zero_fragment_size,
m_fragmentSize);
2017 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: audio paused");
2018 Event e(Event::kPaused);
2032 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Play Event");
2033 Event e(Event::kPlaying);
2046 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"audio waiting for buffer to fill: "
2051 std::this_thread::sleep_for(10ms);
2055#ifdef AUDIOTSTESTING
2056 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Start");
2073#ifdef AUDIOTSTESTING
2075 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Done");
2080 ::operator
delete[] (zeros, std::align_val_t(16));
2081 ::operator
delete[] (fragment, std::align_val_t(16));
2082 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Stop Event");
2083 Event e(Event::kStopped);
2095 volatile uint *local_raud)
2098#define LRPOS (&m_audioBuffer[*local_raud])
2102 int frag_size = size;
2103 int written_size = size;
2105 if (local_raud ==
nullptr)
2108 if (!full_buffer && (size > avail_size))
2111 frag_size = avail_size;
2112 written_size = frag_size;
2115 if (!avail_size || (frag_size <= 0) || (frag_size > avail_size))
2128 if (fromFloats && obytes !=
sizeof(
float))
2129 frag_size *=
sizeof(float) / obytes;
2133 if (bdiff <= frag_size)
2142 memcpy(buffer,
LRPOS, bdiff);
2158 memcpy(buffer + off,
LRPOS, frag_size);
2162 *local_raud += frag_size;
2172 buffer, written_size);
2175 return written_size;
2184 std::this_thread::sleep_for(1ms);
2201 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"kickoffOutputAudioLoop: pid = %1").arg(getpid()));
2203 LOG(VB_AUDIO, LOG_INFO,
LOC +
"kickoffOutputAudioLoop exiting");
2209 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)