11#pragma GCC diagnostic push
12#pragma GCC diagnostic ignored "-Wundef"
13#if __has_include(<soundtouch/SoundTouch.h>)
14#include <soundtouch/SoundTouch.h>
16#include <SoundTouch.h>
18#pragma GCC diagnostic pop
21#include "libavcodec/defs.h"
26#include <QMutexLocker>
41#define DISABLE_AC3_ENCODE
44#define LOC QString("AOBase: ")
49#define WPOS (&m_audioBuffer[org_waud])
50#define RPOS (&m_audioBuffer[m_raud])
51#define ABUF (m_audioBuffer.data())
52#define STST soundtouch::SAMPLETYPE
81static const float m6db = 0.5;
82static const float m3db = 0.7071067811865476F;
83static const float mm3db = -0.7071067811865476F;
85static const float sqrt_2_3 = 0.816496580927726F;
169 { 1, 0, 0, 0, 0, 0 },
170 { 0, 1, 0, 0, 0, 0 },
171 { 0, 0, 1, 0, 0, 0 },
172 { 0, 0, 0, 1, 0, 0 },
173 { 0, 0, 0, 0, 1, 0 },
174 { 0, 0, 0, 0, 0, 1 },
180 { 1, 0, 0, 0, 0, 0 },
181 { 0, 1, 0, 0, 0, 0 },
182 { 0, 0, 1, 0, 0, 0 },
183 { 0, 0, 0, 1, 0, 0 },
185 { 0, 0, 0, 0, 1, 0 },
186 { 0, 0, 0, 0, 0, 1 },
191 { 1, 0, 0, 0, 0, 0 },
192 { 0, 1, 0, 0, 0, 0 },
193 { 0, 0, 1, 0, 0, 0 },
194 { 0, 0, 0, 1, 0, 0 },
195 { 0, 0, 0, 0,
m3db, 0 },
196 { 0, 0, 0, 0, 0,
m3db },
197 { 0, 0, 0, 0,
m3db, 0 },
198 { 0, 0, 0, 0, 0,
m3db },
203 float *dst,
const float *src,
int frames)
205 if (channels_in < channels_out)
210 if (channels_out == 2)
212 int index = channels_in - 1;
213 for (
int n=0; n < frames; n++)
215 for (
int i=0; i < channels_out; i++)
218 for (
int j=0; j < channels_in; j++)
225 else if (channels_out == 6)
227 int index = channels_in - 6;
228 for (
int n=0; n < frames; n++)
230 for (
int i=0; i < channels_out; i++)
233 for (
int j=0; j < channels_in; j++)
248#ifdef Q_PROCESSOR_X86
250static inline bool sse2_check()
252#ifdef Q_PROCESSOR_X86_64
255 static int has_sse2 = -1;
257 return (
bool)has_sse2;
263 "and $0x4000000, %%edx \n\t"
264 "shr $26, %%edx \n\t"
269 return (
bool)has_sse2;
280#ifdef Q_PROCESSOR_X86
294 bool music,
bool upmix)
296 float g = volume / 100.0F;
297 auto *fptr = (
float *)buf;
315#ifdef Q_PROCESSOR_X86
316 if (sse2_check() &&
samples >= 16)
322 "movss %2, %%xmm0 \n\t"
323 "punpckldq %%xmm0, %%xmm0 \n\t"
324 "punpckldq %%xmm0, %%xmm0 \n\t"
326 "movups (%0), %%xmm1 \n\t"
327 "movups 16(%0), %%xmm2 \n\t"
328 "mulps %%xmm0, %%xmm1 \n\t"
329 "movups 32(%0), %%xmm3 \n\t"
330 "mulps %%xmm0, %%xmm2 \n\t"
331 "movups 48(%0), %%xmm4 \n\t"
332 "mulps %%xmm0, %%xmm3 \n\t"
333 "movups %%xmm1, (%0) \n\t"
334 "mulps %%xmm0, %%xmm4 \n\t"
335 "movups %%xmm2, 16(%0) \n\t"
336 "movups %%xmm3, 32(%0) \n\t"
337 "movups %%xmm4, 48(%0) \n\t"
343 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4"
351template <
class AudioDataType>
352static void tMuteChannel(AudioDataType *buffer,
int channels,
int ch,
int frames)
354 AudioDataType *s1 = buffer + ch;
355 AudioDataType *s2 = buffer - ch + 1;
357 for (
int i = 0; i < frames; i++)
372 void *buffer,
int bytes)
374 int frames =
bytes / ((obits >> 3) * channels);
378 else if (obits == 16)
392 default:
return "unknown";
399 m_mainDevice(settings.GetMainDevice()),
400 m_passthruDevice(settings.GetPassthruDevice()),
401 m_source(settings.m_source),
402 m_setInitialVol(settings.m_setInitialVol)
427 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Programmer Error: "
428 "~AudioOutputBase called, but KillAudio has not been called!");
533 aosettings->GetUsers();
544 AVCodecID codec,
int profile)
const
551 case AV_CODEC_ID_AC3:
554 case AV_CODEC_ID_DTS:
558 case AV_PROFILE_DTS_ES:
559 case AV_PROFILE_DTS_96_24:
562 case AV_PROFILE_DTS_HD_HRA:
563 case AV_PROFILE_DTS_HD_MA:
570 case AV_CODEC_ID_EAC3:
573 case AV_CODEC_ID_TRUEHD:
585 ret &= (samplerate == 48000) ||
589 ret &= samplerate >= 44100;
639 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Cancelling time stretch"));
647 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Changing time stretch to %1")
652 else if (willstretch)
659#if defined(Q_PROCESSOR_ARM) || defined(Q_OS_ANDROID)
738 return m_sourceChannels <= 2 && m_maxChannels > 2;
746 int &samplerate_tmp,
int &channels_tmp)
748 if (codec == AV_CODEC_ID_DTS &&
753 codec_profile = AV_PROFILE_DTS;
756 codec, codec_profile,
757 samplerate_tmp, channels_tmp,
759 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Setting " +
log +
" passthrough");
770 switch(codec_profile)
773 case AV_PROFILE_DTS_ES:
774 case AV_PROFILE_DTS_96_24:
777 case AV_PROFILE_DTS_HD_HRA:
778 case AV_PROFILE_DTS_HD_MA:
810 bool lneeds_upmix =
false;
811 bool lneeds_downmix =
false;
818 lconfigured_channels =
820 bool cando_channels =
824#ifndef DISABLE_AC3_ENCODE
827 lconfigured_channels > 2 && lconfigured_channels <= 6);
829 if (!lenc && !cando_channels)
834 switch (lconfigured_channels)
837 lconfigured_channels = 8;
841 lconfigured_channels = 6;
847 lconfigured_channels = 2;
853 lconfigured_channels = 2;
859 if (lsource_channels <= 6)
860 lconfigured_channels = std::min(lconfigured_channels, 6);
861 lconfigured_channels = std::min(lconfigured_channels,
m_maxChannels);
866#ifndef DISABLE_AC3_ENCODE
869 lconfigured_channels > 2) ||
874 (settings.
m_codec == AV_CODEC_ID_AC3 ||
875 settings.
m_codec == AV_CODEC_ID_DTS))
884 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs upmix from %1 -> %2 channels")
885 .arg(settings.
m_channels).arg(lconfigured_channels));
889 else if (settings.
m_channels > lconfigured_channels)
891 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs downmix from %1 -> %2 channels")
892 .arg(settings.
m_channels).arg(lconfigured_channels));
894 lneeds_downmix =
true;
898 bool general_deps =
true;
902 int samplerate_tmp = 0;
903 int channels_tmp = 0;
908 samplerate_tmp, channels_tmp);
928 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reconfigure(): No change -> exiting");
967 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Original codec was %1, %2, %3 kHz, %4 channels")
968 .arg(avcodec_get_name(
m_codec),
975 QString message {QCoreApplication::translate(
"AudioOutputBase",
976 "Aborting Audio Reconfigure. Can't handle audio with more than 8 channels.")};
978 LOG(VB_GENERAL, LOG_ERR, message);
982 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"enc(%1), passthru(%2), features (%3) "
983 "configured_channels(%4), %5 channels supported(%6) "
1001 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Forcing resample to 48 kHz");
1023 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Resampling from %1 kHz to %2 kHz with quality %3")
1033 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Error creating resampler: %1")
1034 .arg(src_strerror(
error))};
1036 LOG(VB_GENERAL, LOG_ERR, message);
1049 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Resampler allocating %1").arg(newsize));
1061 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reencoding decoded AC-3/DTS to AC-3");
1063 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Creating AC-3 Encoder with sr = %1, ch = %2")
1070 QString message {QCoreApplication::translate(
"AudioOutputBase",
"AC-3 encoder initialization failed")};
1072 LOG(VB_GENERAL, LOG_ERR, message);
1102 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio processing enabled");
1120 LOG(VB_GENERAL, LOG_INFO,
LOC +
1121 QString(
"Opening audio device '%1' ch %2(%3) sr %4 sf %5 reenc %6")
1134 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Aborting reconfigure")};
1136 LOG(VB_GENERAL, LOG_INFO,
LOC + message);
1145 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Software volume enabled");
1160 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Create %1 quality upmixer done")
1177 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Ending Reconfigure()");
1208 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Killing AudioOutputDSP");
1250 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Pause %1").arg(paused));
1321 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"SetEffDsp: %1").arg(dsprate));
1407 std::chrono::milliseconds oldaudiotime =
m_audioTime;
1416 * 80 / int64_t(
m_effDsp) / obpf) : 0);
1424 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"GetAudiotime audt=%1 abtc=%2 mb=%3 sb=%4 tb=%5 "
1425 "sr=%6 obpf=%7 bpf=%8 esf=%9 edsp=%10 sbr=%11")
1429 .arg(soundcard_buffer)
1430 .arg(main_buffer+soundcard_buffer)
1447 int64_t processframes_stretched = 0;
1448 int64_t processframes_unstretched = 0;
1459 processframes_unstretched -=
m_pSoundStretch->numUnprocessedSamples();
1469 timecode + std::chrono::milliseconds(
m_effDsp ? ((frames + processframes_unstretched) * 100000 +
1479 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
1481 .arg(timecode.count())
1483 .arg(processframes_unstretched)
1484 .arg(processframes_stretched));
1485#ifdef AUDIOTSTESTING
1533 int len = frames * bpf;
1539 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Audio buffer overflow, %1 frames lost!")
1540 .arg(frames - (afree / bpf)));
1542 frames = afree / bpf;
1551 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resetting resampler: %1")
1552 .arg(src_strerror(
error)));
1578 memcpy(
WPOS, buffer, bdiff);
1584 memcpy(
WPOS, buffer + off, num);
1594 int bdFrames = bdiff / bpf;
1595 if (bdFrames <= frames)
1599 off = bdFrames *
sizeof(float);
1626 if (bdFrames < nFrames)
1628 if ((org_waud % bpf) != 0)
1630 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Upmixing: org_waud = %1 (bpf = %2)")
1635 nFrames -= bdFrames;
1652 std::chrono::milliseconds timecode)
1664 std::chrono::milliseconds timecode,
1674 LOG(VB_GENERAL, LOG_ERR,
"AddData called with audio framework not "
1704 LOG(VB_AUDIO, LOG_INFO,
1705 "Passthrough activated with audio processing. Dropping audio");
1725 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"AddData frames=%1, bytes=%2, used=%3, free=%4, "
1726 "timecode=%5 needsupmix=%6")
1727 .arg(frames).arg(len).arg(used).arg(afree).arg(timecode.count())
1749 if (sampleSize <= 0)
1752 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Sample size is <= 0, AddData returning false");
1757 len =
sizeof(
m_srcInBuf[0]) / sampleSize * len;
1765 len = lround(ceil(
static_cast<double>(len) *
m_srcData.src_ratio));
1782 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Buffer is full, AddData returning false");
1786 int frames_remaining = frames;
1787 int frames_final = 0;
1791 while(frames_remaining > 0)
1793 void *buffer = (
char *)in_buffer + offset;
1794 frames = frames_remaining;
1799 if (frames > maxframes)
1809 frames_remaining -= frames;
1817 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error occurred while downmixing");
1827 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resampling audio: %1")
1828 .arg(src_strerror(
error)));
1850 frames_final += frames;
1853 if ((len % bpf) != 0 && bdiff < len)
1855 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: len = %1 (bpf = %2)")
1859 if ((bdiff % bpf) != 0 && bdiff < len)
1861 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: bdiff = %1 (bpf = %2)")
1870 int bdFrames = bdiff / bpf;
1883 if (nFrames > frames)
1886 len = nFrames * bpf;
1888 if (nFrames > bdFrames)
1934 if (bdiff <= to_get)
1995 auto *fragment =
new(std::align_val_t(16)) uchar[
m_fragmentSize];
2000 zero_fragment_size = std::min(zero_fragment_size,
m_fragmentSize);
2008 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: audio paused");
2009 Event e(Event::kPaused);
2023 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Play Event");
2024 Event e(Event::kPlaying);
2037 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"audio waiting for buffer to fill: "
2042 std::this_thread::sleep_for(10ms);
2046#ifdef AUDIOTSTESTING
2047 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Start");
2064#ifdef AUDIOTSTESTING
2066 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Done");
2071 ::operator
delete[] (zeros, std::align_val_t(16));
2072 ::operator
delete[] (fragment, std::align_val_t(16));
2073 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Stop Event");
2074 Event e(Event::kStopped);
2086 volatile uint *local_raud)
2089#define LRPOS (&m_audioBuffer[*local_raud])
2093 int frag_size = size;
2094 int written_size = size;
2096 if (local_raud ==
nullptr)
2099 if (!full_buffer && (size > avail_size))
2102 frag_size = avail_size;
2103 written_size = frag_size;
2106 if (!avail_size || (frag_size <= 0) || (frag_size > avail_size))
2119 if (fromFloats && obytes !=
sizeof(
float))
2120 frag_size *=
sizeof(float) / obytes;
2124 if (bdiff <= frag_size)
2133 memcpy(buffer,
LRPOS, bdiff);
2149 memcpy(buffer + off,
LRPOS, frag_size);
2153 *local_raud += frag_size;
2163 buffer, written_size);
2166 return written_size;
2175 std::this_thread::sleep_for(1ms);
2192 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"kickoffOutputAudioLoop: pid = %1").arg(getpid()));
2194 LOG(VB_AUDIO, LOG_INFO,
LOC +
"kickoffOutputAudioLoop exiting");
2200 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::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.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
None log(str msg, int level=LOGDEBUG)