12#if __has_include(<soundtouch/SoundTouch.h>)
13#include <soundtouch/SoundTouch.h>
15#include <SoundTouch.h>
20#include <QMutexLocker>
24#include "libmythbase/mythconfig.h"
36#define DISABLE_AC3_ENCODE
39#define LOC QString("AOBase: ")
44#define WPOS (&m_audioBuffer[org_waud])
45#define RPOS (&m_audioBuffer[m_raud])
46#define ABUF (m_audioBuffer.data())
47#define STST soundtouch::SAMPLETYPE
76static const float m6db = 0.5;
77static const float m3db = 0.7071067811865476F;
78static const float mm3db = -0.7071067811865476F;
80static const float sqrt_2_3 = 0.816496580927726F;
164 { 1, 0, 0, 0, 0, 0 },
165 { 0, 1, 0, 0, 0, 0 },
166 { 0, 0, 1, 0, 0, 0 },
167 { 0, 0, 0, 1, 0, 0 },
168 { 0, 0, 0, 0, 1, 0 },
169 { 0, 0, 0, 0, 0, 1 },
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 },
180 { 0, 0, 0, 0, 1, 0 },
181 { 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 },
190 { 0, 0, 0, 0,
m3db, 0 },
191 { 0, 0, 0, 0, 0,
m3db },
192 { 0, 0, 0, 0,
m3db, 0 },
193 { 0, 0, 0, 0, 0,
m3db },
198 float *dst,
const float *src,
int frames)
200 if (channels_in < channels_out)
205 if (channels_out == 2)
207 int index = channels_in - 1;
208 for (
int n=0; n < frames; n++)
210 for (
int i=0; i < channels_out; i++)
213 for (
int j=0; j < channels_in; j++)
220 else if (channels_out == 6)
222 int index = channels_in - 6;
223 for (
int n=0; n < frames; n++)
225 for (
int i=0; i < channels_out; i++)
228 for (
int j=0; j < channels_in; j++)
243#ifdef Q_PROCESSOR_X86
245static inline bool sse2_check()
247#ifdef Q_PROCESSOR_X86_64
250 static int has_sse2 = -1;
252 return (
bool)has_sse2;
258 "and $0x4000000, %%edx \n\t"
259 "shr $26, %%edx \n\t"
264 return (
bool)has_sse2;
275#ifdef Q_PROCESSOR_X86
289 bool music,
bool upmix)
291 float g = volume / 100.0F;
292 auto *fptr = (
float *)buf;
310#ifdef Q_PROCESSOR_X86
311 if (sse2_check() &&
samples >= 16)
317 "movss %2, %%xmm0 \n\t"
318 "punpckldq %%xmm0, %%xmm0 \n\t"
319 "punpckldq %%xmm0, %%xmm0 \n\t"
321 "movups (%0), %%xmm1 \n\t"
322 "movups 16(%0), %%xmm2 \n\t"
323 "mulps %%xmm0, %%xmm1 \n\t"
324 "movups 32(%0), %%xmm3 \n\t"
325 "mulps %%xmm0, %%xmm2 \n\t"
326 "movups 48(%0), %%xmm4 \n\t"
327 "mulps %%xmm0, %%xmm3 \n\t"
328 "movups %%xmm1, (%0) \n\t"
329 "mulps %%xmm0, %%xmm4 \n\t"
330 "movups %%xmm2, 16(%0) \n\t"
331 "movups %%xmm3, 32(%0) \n\t"
332 "movups %%xmm4, 48(%0) \n\t"
338 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4"
346template <
class AudioDataType>
347static void tMuteChannel(AudioDataType *buffer,
int channels,
int ch,
int frames)
349 AudioDataType *s1 = buffer + ch;
350 AudioDataType *s2 = buffer - ch + 1;
352 for (
int i = 0; i < frames; i++)
367 void *buffer,
int bytes)
369 int frames =
bytes / ((obits >> 3) * channels);
373 else if (obits == 16)
387 default:
return "unknown";
394 m_mainDevice(settings.GetMainDevice()),
395 m_passthruDevice(settings.GetPassthruDevice()),
396 m_source(settings.m_source),
397 m_setInitialVol(settings.m_setInitialVol)
422 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Programmer Error: "
423 "~AudioOutputBase called, but KillAudio has not been called!");
528 aosettings->GetUsers();
539 AVCodecID codec,
int profile)
const
546 case AV_CODEC_ID_AC3:
549 case AV_CODEC_ID_DTS:
553 case FF_PROFILE_DTS_ES:
554 case FF_PROFILE_DTS_96_24:
557 case FF_PROFILE_DTS_HD_HRA:
558 case FF_PROFILE_DTS_HD_MA:
565 case AV_CODEC_ID_EAC3:
568 case AV_CODEC_ID_TRUEHD:
580 ret &= (samplerate == 48000) ||
584 ret &= samplerate >= 44100;
634 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Cancelling time stretch"));
641 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Changing time stretch to %1")
646 else if (willstretch)
653#if defined(Q_PROCESSOR_ARM) || defined(Q_OS_ANDROID)
731 return m_sourceChannels <= 2 && m_maxChannels > 2;
739 int &samplerate_tmp,
int &channels_tmp)
741 if (codec == AV_CODEC_ID_DTS &&
746 codec_profile = FF_PROFILE_DTS;
749 codec, codec_profile,
750 samplerate_tmp, channels_tmp,
752 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Setting " +
log +
" passthrough");
763 switch(codec_profile)
766 case FF_PROFILE_DTS_ES:
767 case FF_PROFILE_DTS_96_24:
770 case FF_PROFILE_DTS_HD_HRA:
771 case FF_PROFILE_DTS_HD_MA:
803 bool lneeds_upmix =
false;
804 bool lneeds_downmix =
false;
811 lconfigured_channels =
813 bool cando_channels =
817#ifndef DISABLE_AC3_ENCODE
820 lconfigured_channels > 2 && lconfigured_channels <= 6);
822 if (!lenc && !cando_channels)
827 switch (lconfigured_channels)
830 lconfigured_channels = 8;
834 lconfigured_channels = 6;
840 lconfigured_channels = 2;
846 lconfigured_channels = 2;
852 if (lsource_channels <= 6)
853 lconfigured_channels = std::min(lconfigured_channels, 6);
854 lconfigured_channels = std::min(lconfigured_channels,
m_maxChannels);
859#ifndef DISABLE_AC3_ENCODE
862 lconfigured_channels > 2) ||
867 (settings.
m_codec == AV_CODEC_ID_AC3 ||
868 settings.
m_codec == AV_CODEC_ID_DTS))
877 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs upmix from %1 -> %2 channels")
878 .arg(settings.
m_channels).arg(lconfigured_channels));
882 else if (settings.
m_channels > lconfigured_channels)
884 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Needs downmix from %1 -> %2 channels")
885 .arg(settings.
m_channels).arg(lconfigured_channels));
887 lneeds_downmix =
true;
891 bool general_deps =
true;
895 int samplerate_tmp = 0;
896 int channels_tmp = 0;
901 samplerate_tmp, channels_tmp);
921 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reconfigure(): No change -> exiting");
959 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Original codec was %1, %2, %3 kHz, %4 channels")
960 .arg(avcodec_get_name(
m_codec),
967 QString message {QCoreApplication::translate(
"AudioOutputBase",
968 "Aborting Audio Reconfigure. Can't handle audio with more than 8 channels.")};
970 LOG(VB_GENERAL, LOG_ERR, message);
974 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"enc(%1), passthru(%2), features (%3) "
975 "configured_channels(%4), %5 channels supported(%6) "
993 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Forcing resample to 48 kHz");
1015 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Resampling from %1 kHz to %2 kHz with quality %3")
1025 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Error creating resampler: %1")
1026 .arg(src_strerror(
error))};
1028 LOG(VB_GENERAL, LOG_ERR, message);
1041 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Resampler allocating %1").arg(newsize));
1053 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Reencoding decoded AC-3/DTS to AC-3");
1055 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Creating AC-3 Encoder with sr = %1, ch = %2")
1062 QString message {QCoreApplication::translate(
"AudioOutputBase",
"AC-3 encoder initialization failed")};
1064 LOG(VB_GENERAL, LOG_ERR, message);
1094 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio processing enabled");
1112 LOG(VB_GENERAL, LOG_INFO,
LOC +
1113 QString(
"Opening audio device '%1' ch %2(%3) sr %4 sf %5 reenc %6")
1126 QString message {QCoreApplication::translate(
"AudioOutputBase",
"Aborting reconfigure")};
1128 LOG(VB_GENERAL, LOG_INFO,
LOC + message);
1137 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Software volume enabled");
1152 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Create %1 quality upmixer done")
1169 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Ending Reconfigure()");
1200 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Killing AudioOutputDSP");
1242 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Pause %1").arg(paused));
1312 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"SetEffDsp: %1").arg(dsprate));
1398 std::chrono::milliseconds oldaudiotime =
m_audioTime;
1407 * 80 / int64_t(
m_effDsp) / obpf) : 0);
1415 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"GetAudiotime audt=%1 abtc=%2 mb=%3 sb=%4 tb=%5 "
1416 "sr=%6 obpf=%7 bpf=%8 esf=%9 edsp=%10 sbr=%11")
1420 .arg(soundcard_buffer)
1421 .arg(main_buffer+soundcard_buffer)
1438 int64_t processframes_stretched = 0;
1439 int64_t processframes_unstretched = 0;
1450 processframes_unstretched -=
m_pSoundStretch->numUnprocessedSamples();
1460 timecode + std::chrono::milliseconds(
m_effDsp ? ((frames + processframes_unstretched) * 100000 +
1470 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
1472 .arg(timecode.count())
1474 .arg(processframes_unstretched)
1475 .arg(processframes_stretched));
1476#ifdef AUDIOTSTESTING
1524 int len = frames * bpf;
1530 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Audio buffer overflow, %1 frames lost!")
1531 .arg(frames - (afree / bpf)));
1533 frames = afree / bpf;
1542 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resetting resampler: %1")
1543 .arg(src_strerror(
error)));
1569 memcpy(
WPOS, buffer, bdiff);
1575 memcpy(
WPOS, buffer + off, num);
1585 int bdFrames = bdiff / bpf;
1586 if (bdFrames <= frames)
1590 off = bdFrames *
sizeof(float);
1617 if (bdFrames < nFrames)
1619 if ((org_waud % bpf) != 0)
1621 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Upmixing: org_waud = %1 (bpf = %2)")
1626 nFrames -= bdFrames;
1643 std::chrono::milliseconds timecode)
1655 std::chrono::milliseconds timecode,
1665 LOG(VB_GENERAL, LOG_ERR,
"AddData called with audio framework not "
1695 LOG(VB_AUDIO, LOG_INFO,
1696 "Passthrough activated with audio processing. Dropping audio");
1716 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"AddData frames=%1, bytes=%2, used=%3, free=%4, "
1717 "timecode=%5 needsupmix=%6")
1718 .arg(frames).arg(len).arg(used).arg(afree).arg(timecode.count())
1740 if (sampleSize <= 0)
1743 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Sample size is <= 0, AddData returning false");
1748 len =
sizeof(
m_srcInBuf[0]) / sampleSize * len;
1756 len = lround(ceil(
static_cast<double>(len) *
m_srcData.src_ratio));
1773 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Buffer is full, AddData returning false");
1777 int frames_remaining = frames;
1778 int frames_final = 0;
1782 while(frames_remaining > 0)
1784 void *buffer = (
char *)in_buffer + offset;
1785 frames = frames_remaining;
1790 if (frames > maxframes)
1800 frames_remaining -= frames;
1808 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error occurred while downmixing");
1818 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error occurred while resampling audio: %1")
1819 .arg(src_strerror(
error)));
1841 frames_final += frames;
1844 if ((len % bpf) != 0 && bdiff < len)
1846 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: len = %1 (bpf = %2)")
1850 if ((bdiff % bpf) != 0 && bdiff < len)
1852 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"AddData: Corruption likely: bdiff = %1 (bpf = %2)")
1861 int bdFrames = bdiff / bpf;
1874 if (nFrames > frames)
1877 len = nFrames * bpf;
1879 if (nFrames > bdFrames)
1925 if (bdiff <= to_get)
1986 auto *fragment =
new(std::align_val_t(16)) uchar[
m_fragmentSize];
1991 zero_fragment_size = std::min(zero_fragment_size,
m_fragmentSize);
1999 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: audio paused");
2000 Event e(Event::kPaused);
2014 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Play Event");
2015 Event e(Event::kPlaying);
2028 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"audio waiting for buffer to fill: "
2037#ifdef AUDIOTSTESTING
2038 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Start");
2055#ifdef AUDIOTSTESTING
2057 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
LOC +
"WriteAudio Done");
2062 ::operator
delete[] (zeros, std::align_val_t(16));
2063 ::operator
delete[] (fragment, std::align_val_t(16));
2064 LOG(VB_AUDIO, LOG_INFO,
LOC +
"OutputAudioLoop: Stop Event");
2065 Event e(Event::kStopped);
2077 volatile uint *local_raud)
2080#define LRPOS (&m_audioBuffer[*local_raud])
2084 int frag_size = size;
2085 int written_size = size;
2087 if (local_raud ==
nullptr)
2090 if (!full_buffer && (size > avail_size))
2093 frag_size = avail_size;
2094 written_size = frag_size;
2097 if (!avail_size || (frag_size > avail_size))
2110 if (fromFloats && obytes !=
sizeof(
float))
2111 frag_size *=
sizeof(float) / obytes;
2115 if (bdiff <= frag_size)
2124 memcpy(buffer,
LRPOS, bdiff);
2140 memcpy(buffer + off,
LRPOS, frag_size);
2144 *local_raud += frag_size;
2154 buffer, written_size);
2157 return written_size;
2182 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"kickoffOutputAudioLoop: pid = %1").arg(getpid()));
2184 LOG(VB_AUDIO, LOG_INFO,
LOC +
"kickoffOutputAudioLoop exiting");
2190 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().
static void usleep(std::chrono::microseconds time)
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)