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>
42#define DISABLE_AC3_ENCODE
45#define LOC QString("AOBase: ")
50#define WPOS (&m_audioBuffer[org_waud])
51#define RPOS (&m_audioBuffer[m_raud])
52#define ABUF (m_audioBuffer.data())
53#define STST soundtouch::SAMPLETYPE
82static const float m6db = 0.5;
83static const float m3db = 1.0F / std::numbers::sqrt2_v<float>;
84static const float mm3db = -1.0F / std::numbers::sqrt2_v<float>;
85static const float msqrt_1_3 = -std::numbers::inv_sqrt3_v<float>;
86static const float sqrt_2_3 = std::numbers::sqrt2_v<float> /
87 std::numbers::sqrt3_v<float>;
90 std::numbers::sqrt3_v<float>);
172 { 1, 0, 0, 0, 0, 0 },
173 { 0, 1, 0, 0, 0, 0 },
174 { 0, 0, 1, 0, 0, 0 },
175 { 0, 0, 0, 1, 0, 0 },
176 { 0, 0, 0, 0, 1, 0 },
177 { 0, 0, 0, 0, 0, 1 },
183 { 1, 0, 0, 0, 0, 0 },
184 { 0, 1, 0, 0, 0, 0 },
185 { 0, 0, 1, 0, 0, 0 },
186 { 0, 0, 0, 1, 0, 0 },
188 { 0, 0, 0, 0, 1, 0 },
189 { 0, 0, 0, 0, 0, 1 },
194 { 1, 0, 0, 0, 0, 0 },
195 { 0, 1, 0, 0, 0, 0 },
196 { 0, 0, 1, 0, 0, 0 },
197 { 0, 0, 0, 1, 0, 0 },
198 { 0, 0, 0, 0,
m3db, 0 },
199 { 0, 0, 0, 0, 0,
m3db },
200 { 0, 0, 0, 0,
m3db, 0 },
201 { 0, 0, 0, 0, 0,
m3db },
206 float *dst,
const float *src,
int frames)
208 if (channels_in < channels_out)
213 if (channels_out == 2)
215 int index = channels_in - 1;
216 for (
int n=0; n < frames; n++)
218 for (
int i=0; i < channels_out; i++)
221 for (
int j=0; j < channels_in; j++)
228 else if (channels_out == 6)
230 int index = channels_in - 6;
231 for (
int n=0; n < frames; n++)
233 for (
int i=0; i < channels_out; i++)
236 for (
int j=0; j < channels_in; j++)
251#ifdef Q_PROCESSOR_X86
253static inline bool sse2_check()
255#ifdef Q_PROCESSOR_X86_64
258 static int has_sse2 = -1;
260 return (
bool)has_sse2;
266 "and $0x4000000, %%edx \n\t"
267 "shr $26, %%edx \n\t"
272 return (
bool)has_sse2;
283#ifdef Q_PROCESSOR_X86
297 bool music,
bool upmix)
299 float g = volume / 100.0F;
300 auto *fptr = (
float *)buf;
318#ifdef Q_PROCESSOR_X86
319 if (sse2_check() &&
samples >= 16)
325 "movss %2, %%xmm0 \n\t"
326 "punpckldq %%xmm0, %%xmm0 \n\t"
327 "punpckldq %%xmm0, %%xmm0 \n\t"
329 "movups (%0), %%xmm1 \n\t"
330 "movups 16(%0), %%xmm2 \n\t"
331 "mulps %%xmm0, %%xmm1 \n\t"
332 "movups 32(%0), %%xmm3 \n\t"
333 "mulps %%xmm0, %%xmm2 \n\t"
334 "movups 48(%0), %%xmm4 \n\t"
335 "mulps %%xmm0, %%xmm3 \n\t"
336 "movups %%xmm1, (%0) \n\t"
337 "mulps %%xmm0, %%xmm4 \n\t"
338 "movups %%xmm2, 16(%0) \n\t"
339 "movups %%xmm3, 32(%0) \n\t"
340 "movups %%xmm4, 48(%0) \n\t"
346 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4"
354template <
class AudioDataType>
355static void tMuteChannel(AudioDataType *buffer,
int channels,
int ch,
int frames)
357 AudioDataType *s1 = buffer + ch;
358 AudioDataType *s2 = buffer - ch + 1;
360 for (
int i = 0; i < frames; i++)
375 void *buffer,
int bytes)
377 int frames =
bytes / ((obits >> 3) * channels);
381 else if (obits == 16)
395 default:
return "unknown";
402 m_mainDevice(settings.GetMainDevice()),
403 m_passthruDevice(settings.GetPassthruDevice()),
404 m_source(settings.m_source),
405 m_setInitialVol(settings.m_setInitialVol)
430 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Programmer Error: "
431 "~AudioOutputBase called, but KillAudio has not been called!");
536 aosettings->GetUsers();
547 AVCodecID codec,
int profile)
const
554 case AV_CODEC_ID_AC3:
557 case AV_CODEC_ID_DTS:
561 case AV_PROFILE_DTS_ES:
562 case AV_PROFILE_DTS_96_24:
565 case AV_PROFILE_DTS_HD_HRA:
566 case AV_PROFILE_DTS_HD_MA:
573 case AV_CODEC_ID_EAC3:
576 case AV_CODEC_ID_TRUEHD:
588 ret &= (samplerate == 48000) ||
592 ret &= samplerate >= 44100;
642 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Cancelling time stretch"));
650 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Changing time stretch to %1")
655 else if (willstretch)
662#if defined(Q_PROCESSOR_ARM) || defined(Q_OS_ANDROID)
741 return m_sourceChannels <= 2 && m_maxChannels > 2;
749 int &samplerate_tmp,
int &channels_tmp)
751 if (codec == AV_CODEC_ID_DTS &&
756 codec_profile = AV_PROFILE_DTS;
759 codec, codec_profile,
760 samplerate_tmp, channels_tmp,
762 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Setting " +
log +
" passthrough");
773 switch(codec_profile)
776 case AV_PROFILE_DTS_ES:
777 case AV_PROFILE_DTS_96_24:
780 case AV_PROFILE_DTS_HD_HRA:
781 case AV_PROFILE_DTS_HD_MA:
813 bool lneeds_upmix =
false;
814 bool lneeds_downmix =
false;
821 lconfigured_channels =
823 bool cando_channels =
827#ifndef DISABLE_AC3_ENCODE
830 lconfigured_channels > 2 && lconfigured_channels <= 6);
832 if (!lenc && !cando_channels)
837 switch (lconfigured_channels)
840 lconfigured_channels = 8;
844 lconfigured_channels = 6;
850 lconfigured_channels = 2;
856 lconfigured_channels = 2;
862 if (lsource_channels <= 6)
863 lconfigured_channels = std::min(lconfigured_channels, 6);
864 lconfigured_channels = std::min(lconfigured_channels,
m_maxChannels);
869#ifndef DISABLE_AC3_ENCODE
872 lconfigured_channels > 2) ||
877 (settings.
m_codec == AV_CODEC_ID_AC3 ||
878 settings.
m_codec == AV_CODEC_ID_DTS))
887 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs upmix from %1 -> %2 channels")
888 .arg(settings.
m_channels).arg(lconfigured_channels));
892 else if (settings.
m_channels > lconfigured_channels)
894 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs downmix from %1 -> %2 channels")
895 .arg(settings.
m_channels).arg(lconfigured_channels));
897 lneeds_downmix =
true;
901 bool general_deps =
true;
905 int samplerate_tmp = 0;
906 int channels_tmp = 0;
911 samplerate_tmp, channels_tmp);
931 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reconfigure(): No change -> exiting");
970 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Original codec was %1, %2, %3 kHz, %4 channels")
971 .arg(avcodec_get_name(
m_codec),
978 QString message {QCoreApplication::translate(
"AudioOutputBase",
979 "Aborting Audio Reconfigure. Can't handle audio with more than 8 channels.")};
981 LOG(VB_GENERAL, LOG_ERR, message);
985 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"enc(%1), passthru(%2), features (%3) "
986 "configured_channels(%4), %5 channels supported(%6) "
1004 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Forcing resample to 48 kHz");
1026 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Resampling from %1 kHz to %2 kHz with quality %3")
1036 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Error creating resampler: %1")
1037 .arg(src_strerror(
error))};
1039 LOG(VB_GENERAL, LOG_ERR, message);
1052 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Resampler allocating %1").arg(newsize));
1064 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reencoding decoded AC-3/DTS to AC-3");
1066 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Creating AC-3 Encoder with sr = %1, ch = %2")
1073 QString message {QCoreApplication::translate(
"AudioOutputBase",
"AC-3 encoder initialization failed")};
1075 LOG(VB_GENERAL, LOG_ERR, message);
1105 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio processing enabled");
1123 LOG(VB_GENERAL, LOG_INFO,
LOC +
1124 QString(
"Opening audio device '%1' ch %2(%3) sr %4 sf %5 reenc %6")
1137 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Aborting reconfigure")};
1139 LOG(VB_GENERAL, LOG_INFO,
LOC + message);
1148 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Software volume enabled");
1163 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Create %1 quality upmixer done")
1180 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Ending Reconfigure()");
1211 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Killing AudioOutputDSP");
1253 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Pause %1").arg(paused));
1324 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"SetEffDsp: %1").arg(dsprate));
1410 std::chrono::milliseconds oldaudiotime =
m_audioTime;
1419 * 80 / int64_t(
m_effDsp) / obpf) : 0);
1427 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"GetAudiotime audt=%1 abtc=%2 mb=%3 sb=%4 tb=%5 "
1428 "sr=%6 obpf=%7 bpf=%8 esf=%9 edsp=%10 sbr=%11")
1432 .arg(soundcard_buffer)
1433 .arg(main_buffer+soundcard_buffer)
1450 int64_t processframes_stretched = 0;
1451 int64_t processframes_unstretched = 0;
1462 processframes_unstretched -=
m_pSoundStretch->numUnprocessedSamples();
1472 timecode + std::chrono::milliseconds(
m_effDsp ? ((frames + processframes_unstretched) * 100000 +
1482 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
1484 .arg(timecode.count())
1486 .arg(processframes_unstretched)
1487 .arg(processframes_stretched));
1488#ifdef AUDIOTSTESTING
1536 int len = frames * bpf;
1542 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Audio buffer overflow, %1 frames lost!")
1543 .arg(frames - (afree / bpf)));
1545 frames = afree / bpf;
1554 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resetting resampler: %1")
1555 .arg(src_strerror(
error)));
1581 memcpy(
WPOS, buffer, bdiff);
1587 memcpy(
WPOS, buffer + off, num);
1597 int bdFrames = bdiff / bpf;
1598 if (bdFrames <= frames)
1602 off = bdFrames *
sizeof(float);
1629 if (bdFrames < nFrames)
1631 if ((org_waud % bpf) != 0)
1633 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Upmixing: org_waud = %1 (bpf = %2)")
1638 nFrames -= bdFrames;
1655 std::chrono::milliseconds timecode)
1667 std::chrono::milliseconds timecode,
1677 LOG(VB_GENERAL, LOG_ERR,
"AddData called with audio framework not "
1707 LOG(VB_AUDIO, LOG_INFO,
1708 "Passthrough activated with audio processing. Dropping audio");
1728 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"AddData frames=%1, bytes=%2, used=%3, free=%4, "
1729 "timecode=%5 needsupmix=%6")
1730 .arg(frames).arg(len).arg(used).arg(afree).arg(timecode.count())
1752 if (sampleSize <= 0)
1755 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Sample size is <= 0, AddData returning false");
1760 len =
sizeof(
m_srcInBuf[0]) / sampleSize * len;
1768 len = lround(ceil(
static_cast<double>(len) *
m_srcData.src_ratio));
1785 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Buffer is full, AddData returning false");
1789 int frames_remaining = frames;
1790 int frames_final = 0;
1794 while(frames_remaining > 0)
1796 void *buffer = (
char *)in_buffer + offset;
1797 frames = frames_remaining;
1802 if (frames > maxframes)
1812 frames_remaining -= frames;
1820 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error occurred while downmixing");
1830 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resampling audio: %1")
1831 .arg(src_strerror(
error)));
1853 frames_final += frames;
1856 if ((len % bpf) != 0 && bdiff < len)
1858 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: len = %1 (bpf = %2)")
1862 if ((bdiff % bpf) != 0 && bdiff < len)
1864 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: bdiff = %1 (bpf = %2)")
1873 int bdFrames = bdiff / bpf;
1886 if (nFrames > frames)
1889 len = nFrames * bpf;
1891 if (nFrames > bdFrames)
1937 if (bdiff <= to_get)
1998 auto *fragment =
new(std::align_val_t(16)) uchar[
m_fragmentSize];
2003 zero_fragment_size = std::min(zero_fragment_size,
m_fragmentSize);
2011 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: audio paused");
2012 Event e(Event::kPaused);
2026 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Play Event");
2027 Event e(Event::kPlaying);
2040 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"audio waiting for buffer to fill: "
2045 std::this_thread::sleep_for(10ms);
2049#ifdef AUDIOTSTESTING
2050 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Start");
2067#ifdef AUDIOTSTESTING
2069 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Done");
2074 ::operator
delete[] (zeros, std::align_val_t(16));
2075 ::operator
delete[] (fragment, std::align_val_t(16));
2076 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Stop Event");
2077 Event e(Event::kStopped);
2089 volatile uint *local_raud)
2092#define LRPOS (&m_audioBuffer[*local_raud])
2096 int frag_size = size;
2097 int written_size = size;
2099 if (local_raud ==
nullptr)
2102 if (!full_buffer && (size > avail_size))
2105 frag_size = avail_size;
2106 written_size = frag_size;
2109 if (!avail_size || (frag_size <= 0) || (frag_size > avail_size))
2122 if (fromFloats && obytes !=
sizeof(
float))
2123 frag_size *=
sizeof(float) / obytes;
2127 if (bdiff <= frag_size)
2136 memcpy(buffer,
LRPOS, bdiff);
2152 memcpy(buffer + off,
LRPOS, frag_size);
2156 *local_raud += frag_size;
2166 buffer, written_size);
2169 return written_size;
2178 std::this_thread::sleep_for(1ms);
2195 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"kickoffOutputAudioLoop: pid = %1").arg(getpid()));
2197 LOG(VB_AUDIO, LOG_INFO,
LOC +
"kickoffOutputAudioLoop exiting");
2203 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)