Skip to content

Commit

Permalink
Backport [27306-27307],[27317-27318],[27323],[27331-27333]. Improve d…
Browse files Browse the repository at this point in the history
…igital passthrough auto-settings mainly a problem with some HDMI audio cards. Fix 5.1 upmixing of AC3 stereo content. Simplify LPCM configurations moving it to advanced settings, now it should under most circumstances be not necessary to bother with it.

This bump the API version which will require to recompile all plugins (make clean all)

git-svn-id: http://svn.mythtv.org/svn/branches/release-0-24-fixes@27334 7dbf422c-18fa-0310-86e9-fd20926502f2
  • Loading branch information
jyavenard committed Nov 24, 2010
1 parent d36d385 commit ba0e1ac
Show file tree
Hide file tree
Showing 15 changed files with 139 additions and 117 deletions.
2 changes: 1 addition & 1 deletion mythtv/libs/libmyth/audiooutput.h
Expand Up @@ -65,7 +65,7 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
{ return new AudioOutputSettings; }
virtual AudioOutputSettings* GetOutputSettingsUsers(void)
{ return new AudioOutputSettings; }
virtual bool CanPassthrough(int samplerate) const = 0;
virtual bool CanPassthrough(int samplerate, int channels) const = 0;

// dsprate is in 100 * samples/second
virtual void SetEffDsp(int dsprate) = 0;
Expand Down
116 changes: 80 additions & 36 deletions mythtv/libs/libmyth/audiooutputalsa.cpp
Expand Up @@ -33,28 +33,60 @@ using namespace std;
AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
AudioOutputBase(settings),
pcm_handle(NULL),
numbadioctls(0),
pbufsize(-1),
m_card(-1),
m_device(-1),
m_subdevice(-1)
m_subdevice(-1),
m_autopassthrough(false)
{
m_mixer.handle = NULL;
m_mixer.elem = NULL;

// Set everything up
if (passthru_device == "auto")
{
m_autopassthrough = true;
passthru_device = main_device;
if (!passthru_device.contains(":"))
passthru_device += ":AES0=0x6,AES1=0x82,AES2=0x0,AES3=0x2";

/* to set the non-audio bit, use AES0=6 */
int len = passthru_device.length();
int args = passthru_device.indexOf(":");

if (args < 0)
{
/* no existing parameters: add it behind device name */
passthru_device += ":AES0=6";
}
else
{
passthru_device = passthru_device.insert(
passthru_device.indexOf(":") + 1,
"AES0=0x6,AES1=0x82,AES2=0x0,AES3=0x2,");
do
++args;
while (args < passthru_device.length() &&
passthru_device[args].isSpace());
if (args == passthru_device.length())
{
/* ":" but no parameters */
passthru_device += "AES0=6";
}
else if (passthru_device[args] != '{')
{
/* a simple list of parameters: add it at the end of the list */
passthru_device += ",AES0=6";
}
else
{
/* parameters in config syntax: add it inside the { } block */
do
--len;
while (len > 0 && passthru_device[len].isSpace());
if (passthru_device[len] == '}')
passthru_device = passthru_device.insert(len, " AES0=6");
}
}
}
else if (passthru_device.toLower() == "default")
passthru_device = main_device;

InitSettings(settings);
if (settings.init)
Reconfigure(settings);
Expand All @@ -67,6 +99,37 @@ AudioOutputALSA::~AudioOutputALSA()
KillAudio();
}

int AudioOutputALSA::TryOpenDevice(int open_mode, int try_ac3)
{
QString real_device;
QByteArray dev_ba;
int err = -1;

if (try_ac3)
{
dev_ba = passthru_device.toAscii();
err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, open_mode);
m_lastdevice = passthru_device;
if (!m_autopassthrough)
return err;
if (err < 0)
{
VBAUDIO(QString("Auto setting passthrough failed (%1), defaulting "
"to main device").arg(snd_strerror(err)));
}
}
if (!try_ac3 || err < 0)
{
// passthru open failed, retry default device
dev_ba = main_device.toAscii();
err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, open_mode);
m_lastdevice = main_device;
}
return err;
}

int AudioOutputALSA::GetPCMInfo(int &card, int &device, int &subdevice)
{
// Check for saved values
Expand Down Expand Up @@ -204,20 +267,17 @@ AudioOutputSettings* AudioOutputALSA::GetOutputSettings()
int rate;
int err;

QString real_device = (passthru || enc) ? passthru_device : main_device;

AudioOutputSettings *settings = new AudioOutputSettings();

if (pcm_handle)
{
snd_pcm_close(pcm_handle);
pcm_handle = NULL;
}
QByteArray dev_ba = real_device.toAscii();
if((err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, OPEN_FLAGS)) < 0)

if((err = TryOpenDevice(OPEN_FLAGS, passthru || enc)) < 0)
{
AERROR(QString("snd_pcm_open(\"%1\")").arg(real_device));
AERROR(QString("snd_pcm_open(\"%1\")").arg(m_lastdevice));
delete settings;
return NULL;
}
Expand All @@ -227,11 +287,9 @@ AudioOutputSettings* AudioOutputALSA::GetOutputSettings()
if ((err = snd_pcm_hw_params_any(pcm_handle, params)) < 0)
{
snd_pcm_close(pcm_handle);
if((err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, OPEN_FLAGS&FILTER_FLAGS
)) < 0)
if((err = TryOpenDevice(OPEN_FLAGS&FILTER_FLAGS, passthru || enc)) < 0)
{
AERROR(QString("snd_pcm_open(\"%1\")").arg(real_device));
AERROR(QString("snd_pcm_open(\"%1\")").arg(m_lastdevice));
delete settings;
return NULL;
}
Expand Down Expand Up @@ -277,6 +335,9 @@ AudioOutputSettings* AudioOutputALSA::GetOutputSettings()
QMap<QString, QString> *alsadevs = GetALSADevices("pcm");
while(1)
{
QString real_device = (((passthru || enc) && !m_autopassthrough) ?
passthru_device : main_device);

QString desc = alsadevs->value(real_device);

settings->setPassthrough(1); // yes passthrough
Expand Down Expand Up @@ -314,30 +375,13 @@ bool AudioOutputALSA::OpenDevice()
snd_pcm_format_t format;
uint buffer_time, period_time;
int err;
QString real_device;

if (pcm_handle != NULL)
CloseDevice();

numbadioctls = 0;

if (passthru || enc)
{
real_device = passthru_device;
}
else
{
real_device = main_device;
}

VERBOSE(VB_GENERAL, QString("Opening ALSA audio device '%1'.")
.arg(real_device));

QByteArray dev_ba = real_device.toAscii();
if ((err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, OPEN_FLAGS&FILTER_FLAGS)) < 0)
if ((err = TryOpenDevice(0, passthru || enc)) < 0)
{
AERROR(QString("snd_pcm_open(%1)").arg(real_device));
AERROR(QString("snd_pcm_open(\"%1\")").arg(m_lastdevice));
if (pcm_handle)
CloseDevice();
return false;
Expand Down
5 changes: 4 additions & 1 deletion mythtv/libs/libmyth/audiooutputalsa.h
Expand Up @@ -31,6 +31,7 @@ class AudioOutputALSA : public AudioOutputBase
AudioOutputSettings* GetOutputSettings(void);

private:
int TryOpenDevice(int open_mode, int try_ac3);
int GetPCMInfo(int &card, int &device, int &subdevice);
bool SetPreallocBufferSize(int size);
bool IncPreallocBufferSize(int buffer_time);
Expand All @@ -42,12 +43,14 @@ class AudioOutputALSA : public AudioOutputBase

private:
snd_pcm_t *pcm_handle;
int numbadioctls;
int pbufsize;
int m_card, m_device, m_subdevice;
QMutex killAudioLock;
snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*,
snd_pcm_uframes_t);
bool m_autopassthrough;
QString m_lastdevice;

struct {
QString device;
QString control;
Expand Down
9 changes: 8 additions & 1 deletion mythtv/libs/libmyth/audiooutputbase.cpp
Expand Up @@ -200,11 +200,18 @@ AudioOutputSettings* AudioOutputBase::GetOutputSettingsUsers(void)
/**
* Test if we can output digital audio and if sample rate is supported
*/
bool AudioOutputBase::CanPassthrough(int samplerate) const
bool AudioOutputBase::CanPassthrough(int samplerate, int channels) const
{
bool ret = false;
ret = output_settings->IsSupportedFormat(FORMAT_S16);
ret &= output_settings->IsSupportedRate(samplerate);
// Don't know any cards that support spdif clocked at < 44100
// Some US cable transmissions have 2ch 32k AC-3 streams
ret &= samplerate >= 44100;
// Will downmix if we can't support the amount of channels
ret &= channels <= max_channels;
// Stereo content will always be decoded so it can later be upmixed
ret &= channels != 2;

return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmyth/audiooutputbase.h
Expand Up @@ -62,7 +62,7 @@ class AudioOutputBase : public AudioOutput, public QThread
virtual void SetStretchFactor(float factor);
virtual float GetStretchFactor(void) const;

virtual bool CanPassthrough(int samplerate) const;
virtual bool CanPassthrough(int samplerate, int channels) const;
virtual bool ToggleUpmix(void);

virtual void Reset(void);
Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmyth/audiooutputdx.cpp
Expand Up @@ -108,7 +108,7 @@ AudioOutputDX::AudioOutputDX(const AudioSettings &settings) :
{
timeBeginPeriod(1);
InitSettings(settings);
if (passthru_device == "auto")
if (passthru_device == "auto" || passthru_device.toLower() == "default")
passthru_device = main_device;
if (settings.init)
Reconfigure(settings);
Expand Down
8 changes: 3 additions & 5 deletions mythtv/libs/libmyth/audiooutputsettings.cpp
Expand Up @@ -299,16 +299,16 @@ AudioOutputSettings* AudioOutputSettings::GetUsers(bool newcopy)

int cur_channels = gCoreContext->GetNumSetting("MaxChannels", 2);
int max_channels = aosettings->BestSupportedChannels();
bool bForceDigital = gCoreContext->GetNumSetting("AdvancedAudioSettings", false) &&
bool bAdv = gCoreContext->GetNumSetting("AdvancedAudioSettings", false);
bool bForceDigital = bAdv &&
gCoreContext->GetNumSetting("PassThruDeviceOverride", false);

bool bAC3 = (aosettings->m_AC3 || bForceDigital) &&
gCoreContext->GetNumSetting("AC3PassThru", false);
bool bDTS = (aosettings->m_DTS || bForceDigital) &&
gCoreContext->GetNumSetting("DTSPassThru", false);
bool bLPCM = aosettings->m_LPCM &&
(aosettings->m_passthrough == -1 ||
gCoreContext->GetNumSetting("MultiChannelPCM", false));
(bAdv && !gCoreContext->GetNumSetting("StereoPCM", false)));

if (max_channels > 2 && !bLPCM)
max_channels = 2;
Expand All @@ -319,8 +319,6 @@ AudioOutputSettings* AudioOutputSettings::GetUsers(bool newcopy)
cur_channels = max_channels;

aosettings->SetBestSupportedChannels(cur_channels);
if (cur_channels <= 2)
bDTS = bAC3 = false;
aosettings->m_AC3 = bAC3;
aosettings->m_DTS = bDTS;
aosettings->m_LPCM = bLPCM;
Expand Down
4 changes: 2 additions & 2 deletions mythtv/libs/libmyth/audiosettings.cpp
Expand Up @@ -103,14 +103,14 @@ AudioSettings::AudioSettings(

void AudioSettings::FixPassThrough(void)
{
if (passthru_device.isEmpty() || passthru_device.toLower() == "default")
if (passthru_device.isEmpty())
passthru_device = "auto";
}

void AudioSettings::TrimDeviceType(void)
{
main_device.remove(0, 5);
if (passthru_device != "auto")
if (passthru_device != "auto" && passthru_device.toLower() != "default")
passthru_device.remove(0, 5);
}

Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmythdb/mythversion.h
Expand Up @@ -11,7 +11,7 @@
/// Update this whenever the plug-in API changes.
/// Including changes in the libmythdb, libmyth, libmythtv, libmythav* and
/// libmythui class methods used by plug-ins.
#define MYTH_BINARY_VERSION "0.24.20101028-1"
#define MYTH_BINARY_VERSION "0.24.20101124-1"

/** \brief Increment this whenever the MythTV network protocol changes.
*
Expand Down
4 changes: 2 additions & 2 deletions mythtv/libs/libmythtv/audioplayer.cpp
Expand Up @@ -321,11 +321,11 @@ uint AudioPlayer::GetMaxChannels(void)
return ret;
}

bool AudioPlayer::CanPassthrough(int samplerate)
bool AudioPlayer::CanPassthrough(int samplerate, int channels)
{
bool ret = false;
if (m_audioOutput)
ret = m_audioOutput->CanPassthrough(samplerate);
ret = m_audioOutput->CanPassthrough(samplerate, channels);
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmythtv/audioplayer.h
Expand Up @@ -39,7 +39,7 @@ class MPUBLIC AudioPlayer
float GetStretchFactor(void) { return m_stretchfactor; }
void SetStretchFactor(float factor);
bool ToggleUpmix(void);
bool CanPassthrough(int samplerate);
bool CanPassthrough(int samplerate, int channels);
bool CanAC3(void);
bool CanDTS(void);
uint GetMaxChannels(void);
Expand Down
7 changes: 1 addition & 6 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -4603,14 +4603,9 @@ bool AvFormatDecoder::DoPassThrough(const AVCodecContext *ctx)
passthru = m_audio->CanAC3();
else if (ctx->codec_id == CODEC_ID_DTS)
passthru = m_audio->CanDTS();
passthru &= m_audio->CanPassthrough(ctx->sample_rate);
// Will downmix if we can't support the amount of channels
passthru &= ctx->channels <= (int)m_audio->GetMaxChannels();
passthru &= m_audio->CanPassthrough(ctx->sample_rate, ctx->channels);
passthru &= !internal_vol;
passthru &= !transcoding && !disable_passthru;
// Don't know any cards that support spdif clocked at < 44100
// Some US cable transmissions have 2ch 32k AC-3 streams
passthru &= ctx->sample_rate >= 44100;

return passthru;
}
Expand Down

0 comments on commit ba0e1ac

Please sign in to comment.