aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjenkins4kodi <jenkins4kodi@users.noreply.github.com>2015-09-27 11:25:52 +0200
committerjenkins4kodi <jenkins4kodi@users.noreply.github.com>2015-09-27 11:25:52 +0200
commitb9dd683632b23031357cfd7059d9054ad8a11faa (patch)
tree0ff49657ec9a77011cd61cfc5b5c4a9df7018d89
parentf9e9eb1ef59c1135aa690bdbc95da4357a989137 (diff)
parent64c67f90e8009eadd480452ec3ec4d42b1192520 (diff)
Merge pull request #8139 from fritsch/pa-isengard
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp52
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h3
2 files changed, 36 insertions, 19 deletions
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
index dcef42c77b..e11eddeb62 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
@@ -22,6 +22,7 @@
#include "AESinkPULSE.h"
#include "utils/log.h"
#include "Util.h"
+#include "utils/TimeUtils.h"
#include "guilib/LocalizeStrings.h"
#include "Application.h"
@@ -441,11 +442,14 @@ CAESinkPULSE::CAESinkPULSE()
m_MainLoop = NULL;
m_BytesPerSecond = 0;
m_BufferSize = 0;
+ m_filled_bytes = 0;
+ m_lastPackageStamp = 0;
m_Channels = 0;
m_Stream = NULL;
m_Context = NULL;
m_IsStreamPaused = false;
m_volume_needs_update = false;
+ m_periodSize = 0;
pa_cvolume_init(&m_Volume);
}
@@ -463,9 +467,12 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
m_passthrough = false;
m_BytesPerSecond = 0;
m_BufferSize = 0;
+ m_filled_bytes = 0;
+ m_lastPackageStamp = 0;
m_Channels = 0;
m_Stream = NULL;
m_Context = NULL;
+ m_periodSize = 0;
if (!SetupContext(NULL, &m_Context, &m_MainLoop))
{
@@ -641,6 +648,7 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
{
unsigned int packetSize = a->minreq;
m_BufferSize = a->tlength;
+ m_periodSize = a->minreq;
format.m_frames = packetSize / frameSize;
}
@@ -688,6 +696,9 @@ void CAESinkPULSE::Deinitialize()
CSingleLock lock(m_sec);
m_IsAllocated = false;
m_passthrough = false;
+ m_periodSize = 0;
+ m_filled_bytes = 0;
+ m_lastPackageStamp = 0;
if (m_Stream)
Drain();
@@ -724,25 +735,24 @@ void CAESinkPULSE::GetDelay(AEDelayStatus& status)
status.SetDelay(0);
return;
}
- int error = 0;
- pa_usec_t latency = (pa_usec_t) -1;
+
pa_threaded_mainloop_lock(m_MainLoop);
- if ((error = pa_stream_get_latency(m_Stream, &latency, NULL)) < 0)
- {
- if (error == -PA_ERR_NODATA)
- {
- WaitForOperation(pa_stream_update_timing_info(m_Stream, NULL,NULL), m_MainLoop, "Update Timing Information");
- if ((error = pa_stream_get_latency(m_Stream, &latency, NULL)) < 0)
- {
- CLog::Log(LOGDEBUG, "GetDelay - Failed to get Latency %d", error);
- }
- }
- }
- if (error < 0 )
- latency = (pa_usec_t) 0;
+ const pa_timing_info* pti = pa_stream_get_timing_info(m_Stream);
+ // only incorporate local sink delay + internal PA transport delay
+ double sink_delay = (pti->configured_sink_usec / 1000000.0);
+ double transport_delay = pti->transport_usec / 1000000.0;
+
+ uint64_t diff = CurrentHostCounter() - m_lastPackageStamp;
+ unsigned int bytes_played = (unsigned int) ((double) diff * (double) m_BytesPerSecond / (double) CurrentHostFrequency() + 0.5);
+
+ int buffer_delay = m_filled_bytes - bytes_played;
+ if (buffer_delay < 0)
+ buffer_delay = 0;
pa_threaded_mainloop_unlock(m_MainLoop);
- status.SetDelay(latency / 1000000.0);
+
+ double delay = buffer_delay / (double) m_BytesPerSecond + sink_delay + transport_delay;
+ status.SetDelay(delay);
}
double CAESinkPULSE::GetCacheTotal()
@@ -765,10 +775,11 @@ unsigned int CAESinkPULSE::AddPackets(uint8_t **data, unsigned int frames, unsig
unsigned int available = frames * m_format.m_frameSize;
unsigned int length = 0;
void *buffer = data[0]+offset*m_format.m_frameSize;
- // revisit me after Gotham - should use a callback for the write function
- while ((length = pa_stream_writable_size(m_Stream)) == 0)
+ // care a bit for fragmentation
+ while ((length = pa_stream_writable_size(m_Stream)) < m_periodSize)
pa_threaded_mainloop_wait(m_MainLoop);
+ unsigned int free = length;
length = std::min((unsigned int)length, available);
int error = pa_stream_write(m_Stream, buffer, length, NULL, 0, PA_SEEK_RELATIVE);
@@ -779,8 +790,11 @@ unsigned int CAESinkPULSE::AddPackets(uint8_t **data, unsigned int frames, unsig
CLog::Log(LOGERROR, "CPulseAudioDirectSound::AddPackets - pa_stream_write failed\n");
return 0;
}
+ m_lastPackageStamp = CurrentHostCounter();
+ m_filled_bytes = m_BufferSize - (free - length);
+ unsigned int res = (unsigned int)(length / m_format.m_frameSize);
- return (unsigned int)(length / m_format.m_frameSize);
+ return res;
}
void CAESinkPULSE::Drain()
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h
index 64cceb6f8e..c04bc18291 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h
@@ -70,6 +70,9 @@ private:
pa_stream *m_Stream;
pa_cvolume m_Volume;
bool m_volume_needs_update;
+ uint32_t m_periodSize;
+ uint64_t m_lastPackageStamp;
+ uint64_t m_filled_bytes;
pa_context *m_Context;
pa_threaded_mainloop *m_MainLoop;