diff options
author | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2015-09-27 11:25:52 +0200 |
---|---|---|
committer | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2015-09-27 11:25:52 +0200 |
commit | b9dd683632b23031357cfd7059d9054ad8a11faa (patch) | |
tree | 0ff49657ec9a77011cd61cfc5b5c4a9df7018d89 | |
parent | f9e9eb1ef59c1135aa690bdbc95da4357a989137 (diff) | |
parent | 64c67f90e8009eadd480452ec3ec4d42b1192520 (diff) |
Merge pull request #8139 from fritsch/pa-isengard
-rw-r--r-- | xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp | 52 | ||||
-rw-r--r-- | xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h | 3 |
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; |