Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #2320 from fritsch/ae-period-size

AE: Revisit Period Size, Period and Buffersize
  • Loading branch information...
commit 3644e9836124dc1647a8f19b0f084d87c9a89bc8 2 parents 96315a8 + f2faaa8
@davilla davilla authored
Showing with 59 additions and 39 deletions.
  1. +59 −39 xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
View
98 xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
@@ -38,7 +38,6 @@
#endif
#define ALSA_OPTIONS (SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_RESAMPLE)
-#define ALSA_PERIODS 16
#define ALSA_MAX_CHANNELS 16
static enum AEChannel ALSAChannelMap[ALSA_MAX_CHANNELS + 1] = {
@@ -328,59 +327,80 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format)
}
}
- unsigned int periods;
-
snd_pcm_uframes_t periodSize, bufferSize;
snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize);
+ snd_pcm_hw_params_get_period_size_max(hw_params, &periodSize, NULL);
+
+ /*
+ We want to make sure, that we have approx 500 to 800 ms Buffer with
+ a periodSize of approx 100 ms.
+ It is calced:
+ periodSize = sampleRate / 10
+ buffersize = periodSize * 1 frame * 8.
+ */
+ periodSize = std::min(periodSize, (snd_pcm_uframes_t) sampleRate / 10);
+ bufferSize = std::min(bufferSize, (snd_pcm_uframes_t) periodSize * 8);
+
+ /*
+ According to upstream we should set buffer size first - so make sure it is always at least
+ double of period size to not get underruns
+ */
+ periodSize = std::min(periodSize, bufferSize / 2);
- bufferSize = std::min(bufferSize, (snd_pcm_uframes_t)8192);
- periodSize = bufferSize / ALSA_PERIODS;
- periods = ALSA_PERIODS;
-
- CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize);
+ CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, bufferSize %lu", periodSize, bufferSize);
- /* work on a copy of the hw params */
snd_pcm_hw_params_t *hw_params_copy;
snd_pcm_hw_params_alloca(&hw_params_copy);
-
- /* try to set the buffer size then the period size */
- snd_pcm_hw_params_copy(hw_params_copy, hw_params);
- snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize);
- snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL);
- snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL);
- if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
+ snd_pcm_hw_params_copy(hw_params_copy, hw_params); // copy what we have and is already working
+
+ // first trying bufferSize, PeriodSize
+ // for more info see here:
+ // http://mailman.alsa-project.org/pipermail/alsa-devel/2009-September/021069.html
+ // the last three tries are done as within pulseaudio
+
+ // backup periodSize and bufferSize first. Restore them after every failed try
+ snd_pcm_uframes_t periodSizeTemp, bufferSizeTemp;
+ periodSizeTemp = periodSize;
+ bufferSizeTemp = bufferSize;
+ if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
+ || snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0
+ || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
{
- /* try to set the period size then the buffer size */
- snd_pcm_hw_params_copy(hw_params_copy, hw_params);
- snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL);
- snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize);
- snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL);
- if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
+ bufferSize = bufferSizeTemp;
+ periodSize = periodSizeTemp;
+ // retry with PeriodSize, bufferSize
+ snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
+ if (snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0
+ || snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
+ || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
{
- /* try to just set the buffer size */
- snd_pcm_hw_params_copy(hw_params_copy, hw_params);
- snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize);
- snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL);
- if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
+ // try only periodSize
+ periodSize = periodSizeTemp;
+ snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
+ if(snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0
+ || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
{
- /* try to just set the period size */
- snd_pcm_hw_params_copy(hw_params_copy, hw_params);
- snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL);
- snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL);
- if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
+ // try only BufferSize
+ bufferSize = bufferSizeTemp;
+ snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restory working copy
+ if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
+ || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
{
- CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Failed to set the parameters");
- return false;
+ // set default that Alsa would choose
+ CLog::Log(LOGWARNING, "CAESinkAlsa::IntializeHW - Using default alsa values - set failed");
+ if (snd_pcm_hw_params(m_pcm, hw_params) != 0)
+ {
+ CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Could not init a valid sink");
+ return false;
+ }
}
}
+ // reread values when alsa default was kept
+ snd_pcm_get_params(m_pcm, &bufferSize, &periodSize);
}
}
-
- snd_pcm_hw_params_get_period_size(hw_params_copy, &periodSize, NULL);
- snd_pcm_hw_params_get_buffer_size(hw_params_copy, &bufferSize);
-
- CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize);
+ CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, bufferSize %lu", periodSize, bufferSize);
/* set the format parameters */
format.m_sampleRate = sampleRate;
Please sign in to comment.
Something went wrong with that request. Please try again.