Skip to content

Commit b9dd683

Browse files
committed
Merge pull request xbmc#8139 from fritsch/pa-isengard
2 parents f9e9eb1 + 64c67f9 commit b9dd683

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "AESinkPULSE.h"
2323
#include "utils/log.h"
2424
#include "Util.h"
25+
#include "utils/TimeUtils.h"
2526
#include "guilib/LocalizeStrings.h"
2627
#include "Application.h"
2728

@@ -441,11 +442,14 @@ CAESinkPULSE::CAESinkPULSE()
441442
m_MainLoop = NULL;
442443
m_BytesPerSecond = 0;
443444
m_BufferSize = 0;
445+
m_filled_bytes = 0;
446+
m_lastPackageStamp = 0;
444447
m_Channels = 0;
445448
m_Stream = NULL;
446449
m_Context = NULL;
447450
m_IsStreamPaused = false;
448451
m_volume_needs_update = false;
452+
m_periodSize = 0;
449453
pa_cvolume_init(&m_Volume);
450454
}
451455

@@ -463,9 +467,12 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
463467
m_passthrough = false;
464468
m_BytesPerSecond = 0;
465469
m_BufferSize = 0;
470+
m_filled_bytes = 0;
471+
m_lastPackageStamp = 0;
466472
m_Channels = 0;
467473
m_Stream = NULL;
468474
m_Context = NULL;
475+
m_periodSize = 0;
469476

470477
if (!SetupContext(NULL, &m_Context, &m_MainLoop))
471478
{
@@ -641,6 +648,7 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
641648
{
642649
unsigned int packetSize = a->minreq;
643650
m_BufferSize = a->tlength;
651+
m_periodSize = a->minreq;
644652

645653
format.m_frames = packetSize / frameSize;
646654
}
@@ -688,6 +696,9 @@ void CAESinkPULSE::Deinitialize()
688696
CSingleLock lock(m_sec);
689697
m_IsAllocated = false;
690698
m_passthrough = false;
699+
m_periodSize = 0;
700+
m_filled_bytes = 0;
701+
m_lastPackageStamp = 0;
691702

692703
if (m_Stream)
693704
Drain();
@@ -724,25 +735,24 @@ void CAESinkPULSE::GetDelay(AEDelayStatus& status)
724735
status.SetDelay(0);
725736
return;
726737
}
727-
int error = 0;
728-
pa_usec_t latency = (pa_usec_t) -1;
738+
729739
pa_threaded_mainloop_lock(m_MainLoop);
730-
if ((error = pa_stream_get_latency(m_Stream, &latency, NULL)) < 0)
731-
{
732-
if (error == -PA_ERR_NODATA)
733-
{
734-
WaitForOperation(pa_stream_update_timing_info(m_Stream, NULL,NULL), m_MainLoop, "Update Timing Information");
735-
if ((error = pa_stream_get_latency(m_Stream, &latency, NULL)) < 0)
736-
{
737-
CLog::Log(LOGDEBUG, "GetDelay - Failed to get Latency %d", error);
738-
}
739-
}
740-
}
741-
if (error < 0 )
742-
latency = (pa_usec_t) 0;
740+
const pa_timing_info* pti = pa_stream_get_timing_info(m_Stream);
741+
// only incorporate local sink delay + internal PA transport delay
742+
double sink_delay = (pti->configured_sink_usec / 1000000.0);
743+
double transport_delay = pti->transport_usec / 1000000.0;
744+
745+
uint64_t diff = CurrentHostCounter() - m_lastPackageStamp;
746+
unsigned int bytes_played = (unsigned int) ((double) diff * (double) m_BytesPerSecond / (double) CurrentHostFrequency() + 0.5);
747+
748+
int buffer_delay = m_filled_bytes - bytes_played;
749+
if (buffer_delay < 0)
750+
buffer_delay = 0;
743751

744752
pa_threaded_mainloop_unlock(m_MainLoop);
745-
status.SetDelay(latency / 1000000.0);
753+
754+
double delay = buffer_delay / (double) m_BytesPerSecond + sink_delay + transport_delay;
755+
status.SetDelay(delay);
746756
}
747757

748758
double CAESinkPULSE::GetCacheTotal()
@@ -765,10 +775,11 @@ unsigned int CAESinkPULSE::AddPackets(uint8_t **data, unsigned int frames, unsig
765775
unsigned int available = frames * m_format.m_frameSize;
766776
unsigned int length = 0;
767777
void *buffer = data[0]+offset*m_format.m_frameSize;
768-
// revisit me after Gotham - should use a callback for the write function
769-
while ((length = pa_stream_writable_size(m_Stream)) == 0)
778+
// care a bit for fragmentation
779+
while ((length = pa_stream_writable_size(m_Stream)) < m_periodSize)
770780
pa_threaded_mainloop_wait(m_MainLoop);
771781

782+
unsigned int free = length;
772783
length = std::min((unsigned int)length, available);
773784

774785
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
779790
CLog::Log(LOGERROR, "CPulseAudioDirectSound::AddPackets - pa_stream_write failed\n");
780791
return 0;
781792
}
793+
m_lastPackageStamp = CurrentHostCounter();
794+
m_filled_bytes = m_BufferSize - (free - length);
795+
unsigned int res = (unsigned int)(length / m_format.m_frameSize);
782796

783-
return (unsigned int)(length / m_format.m_frameSize);
797+
return res;
784798
}
785799

786800
void CAESinkPULSE::Drain()

xbmc/cores/AudioEngine/Sinks/AESinkPULSE.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class CAESinkPULSE : public IAESink
7070
pa_stream *m_Stream;
7171
pa_cvolume m_Volume;
7272
bool m_volume_needs_update;
73+
uint32_t m_periodSize;
74+
uint64_t m_lastPackageStamp;
75+
uint64_t m_filled_bytes;
7376

7477
pa_context *m_Context;
7578
pa_threaded_mainloop *m_MainLoop;

0 commit comments

Comments
 (0)