aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoakim Plate <elupus@ecce.se>2014-06-01 23:25:49 +0200
committerJoakim Plate <elupus@ecce.se>2014-06-04 00:26:59 +0200
commitc91fe5efad7e0546b3c3a7abba9f93baaaa39799 (patch)
treeca78c38d1c0fe24bed69757e86021cd5c0892658
parent6f699bb9bc59f6d9679d36da88e20ff2688d6e3d (diff)
AE: Let sinks provide GetDelay function that timestamps values
This uses accurate timer ticks instead of milliseconds to reduce unneccessary millisecond jitter at later stages. For now fallbacks exist to not upgrade sinks directly
-rw-r--r--xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp18
-rw-r--r--xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h4
-rw-r--r--xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp16
-rw-r--r--xbmc/cores/AudioEngine/Interfaces/AESink.h11
-rw-r--r--xbmc/cores/AudioEngine/Utils/AEUtil.cpp6
-rw-r--r--xbmc/cores/AudioEngine/Utils/AEUtil.h14
6 files changed, 53 insertions, 16 deletions
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
index c9bbfce9da..5122de6a22 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
@@ -30,6 +30,8 @@ using namespace ActiveAE;
#include "settings/AdvancedSettings.h"
#include "windowing/WindowingFactory.h"
+#include "utils/TimeUtils.h"
+
#define MAX_CACHE_LEVEL 0.5 // total cache time of stream in seconds
#define MAX_WATER_LEVEL 0.25 // buffered time after stream stages in seconds
#define MAX_BUFFER_TIME 0.1 // max time of a buffer in seconds
@@ -37,18 +39,18 @@ using namespace ActiveAE;
void CEngineStats::Reset(unsigned int sampleRate)
{
CSingleLock lock(m_lock);
- m_sinkUpdate = XbmcThreads::SystemClockMillis();
+ m_sinkUpdate = CurrentHostCounter();
m_sinkDelay = 0;
m_sinkSampleRate = sampleRate;
m_bufferedSamples = 0;
m_suspended = false;
}
-void CEngineStats::UpdateSinkDelay(double delay, int samples)
+void CEngineStats::UpdateSinkDelay(const AEDelayStatus& status, int samples)
{
CSingleLock lock(m_lock);
- m_sinkUpdate = XbmcThreads::SystemClockMillis();
- m_sinkDelay = delay;
+ m_sinkUpdate = status.tick;
+ m_sinkDelay = status.delay;
if (samples > m_bufferedSamples)
{
CLog::Log(LOGERROR, "CEngineStats::UpdateSinkDelay - inconsistency in buffer time");
@@ -80,8 +82,8 @@ void CEngineStats::AddSamples(int samples, std::list<CActiveAEStream*> &streams)
float CEngineStats::GetDelay()
{
CSingleLock lock(m_lock);
- unsigned int now = XbmcThreads::SystemClockMillis();
- float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / 1000;
+ int64_t now = CurrentHostCounter();
+ float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / CurrentHostFrequency();
delay += (float)m_bufferedSamples / m_sinkSampleRate;
if (delay < 0)
@@ -94,8 +96,8 @@ float CEngineStats::GetDelay()
float CEngineStats::GetDelay(CActiveAEStream *stream)
{
CSingleLock lock(m_lock);
- unsigned int now = XbmcThreads::SystemClockMillis();
- float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / 1000;
+ int64_t now = CurrentHostCounter();
+ float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / CurrentHostFrequency();
delay += m_sinkLatency;
delay += (float)m_bufferedSamples / m_sinkSampleRate;
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h
index 700098b257..51f7a7581d 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h
@@ -160,7 +160,7 @@ class CEngineStats
{
public:
void Reset(unsigned int sampleRate);
- void UpdateSinkDelay(double delay, int samples);
+ void UpdateSinkDelay(const AEDelayStatus& status, int samples);
void AddSamples(int samples, std::list<CActiveAEStream*> &streams);
float GetDelay();
float GetDelay(CActiveAEStream *stream);
@@ -178,7 +178,7 @@ protected:
float m_sinkLatency;
int m_bufferedSamples;
unsigned int m_sinkSampleRate;
- unsigned int m_sinkUpdate;
+ int64_t m_sinkUpdate;
bool m_suspended;
CCriticalSection m_lock;
};
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
index c773ceda3d..a7fb64d994 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
@@ -791,7 +791,6 @@ unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
unsigned int maxFrames;
int retry = 0;
unsigned int written = 0;
- double sinkDelay = 0.0;
switch(m_swapState)
{
@@ -809,6 +808,8 @@ unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
break;
}
+ AEDelayStatus status;
+
while(frames > 0)
{
maxFrames = std::min(frames, m_sinkFormat.m_frames);
@@ -821,7 +822,8 @@ unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
{
m_extError = true;
CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed");
- m_stats->UpdateSinkDelay(0, frames);
+ status.SetDelay(0);
+ m_stats->UpdateSinkDelay(status, frames);
return 0;
}
else
@@ -831,14 +833,16 @@ unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
{
m_extError = true;
CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error");
- m_stats->UpdateSinkDelay(0, samples->pool ? maxFrames : 0);
+ status.SetDelay(0);
+ m_stats->UpdateSinkDelay(status, samples->pool ? maxFrames : 0);
return 0;
}
frames -= written;
- sinkDelay = m_sink->GetDelay();
- m_stats->UpdateSinkDelay(sinkDelay, samples->pool ? written : 0);
+
+ m_sink->GetDelay(status);
+ m_stats->UpdateSinkDelay(status, samples->pool ? written : 0);
}
- return sinkDelay*1000;
+ return status.delay;
}
void CActiveAESink::SwapInit(CSampleBuffer* samples)
diff --git a/xbmc/cores/AudioEngine/Interfaces/AESink.h b/xbmc/cores/AudioEngine/Interfaces/AESink.h
index 3711ac43b5..21ab8427da 100644
--- a/xbmc/cores/AudioEngine/Interfaces/AESink.h
+++ b/xbmc/cores/AudioEngine/Interfaces/AESink.h
@@ -23,6 +23,7 @@
#include <stdint.h>
#include "cores/AudioEngine/Interfaces/AE.h" // for typedef's used in derived classes
#include "cores/AudioEngine/Utils/AEAudioFormat.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
class IAESink
{
@@ -70,6 +71,16 @@ public:
*/
virtual unsigned int AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) = 0;
+
+ /*!
+ * @brief Return a timestamped status structure with delay and sink info
+ * @param status structure filled with sink status
+ */
+ virtual void GetDelay(AEDelayStatus& status)
+ {
+ status.SetDelay(GetDelay());
+ }
+
/*
Drain the sink
*/
diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.cpp b/xbmc/cores/AudioEngine/Utils/AEUtil.cpp
index dde374ef8b..20ce1e4d05 100644
--- a/xbmc/cores/AudioEngine/Utils/AEUtil.cpp
+++ b/xbmc/cores/AudioEngine/Utils/AEUtil.cpp
@@ -35,6 +35,12 @@ unsigned int CAEUtil::m_seed = (unsigned int)(CurrentHostCounter() / 1000.0f);
MEMALIGN(16, __m128i CAEUtil::m_sseSeed) = _mm_set_epi32(CAEUtil::m_seed, CAEUtil::m_seed+1, CAEUtil::m_seed, CAEUtil::m_seed+1);
#endif
+void AEDelayStatus::SetDelay(double d)
+{
+ delay = d;
+ tick = CurrentHostCounter();
+}
+
CAEChannelInfo CAEUtil::GuessChLayout(const unsigned int channels)
{
CLog::Log(LOGWARNING, "CAEUtil::GuessChLayout - "
diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h
index 9954ac21af..006dc03937 100644
--- a/xbmc/cores/AudioEngine/Utils/AEUtil.h
+++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h
@@ -57,6 +57,20 @@ enum AVSync
SYNC_RESAMPLE
};
+struct AEDelayStatus
+{
+ AEDelayStatus()
+ : delay(0.0)
+ , tick(0)
+ {}
+
+ void SetDelay(double d);
+
+ double delay; /*!< delay in sink currently */
+ int64_t tick; /*!< timestamp when delay was calculated */
+};
+
+
class CAEUtil
{
private: