22
22
#include " AESinkPULSE.h"
23
23
#include " utils/log.h"
24
24
#include " Util.h"
25
+ #include " utils/TimeUtils.h"
25
26
#include " guilib/LocalizeStrings.h"
26
27
#include " Application.h"
27
28
@@ -441,11 +442,14 @@ CAESinkPULSE::CAESinkPULSE()
441
442
m_MainLoop = NULL ;
442
443
m_BytesPerSecond = 0 ;
443
444
m_BufferSize = 0 ;
445
+ m_filled_bytes = 0 ;
446
+ m_lastPackageStamp = 0 ;
444
447
m_Channels = 0 ;
445
448
m_Stream = NULL ;
446
449
m_Context = NULL ;
447
450
m_IsStreamPaused = false ;
448
451
m_volume_needs_update = false ;
452
+ m_periodSize = 0 ;
449
453
pa_cvolume_init (&m_Volume);
450
454
}
451
455
@@ -463,9 +467,12 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
463
467
m_passthrough = false ;
464
468
m_BytesPerSecond = 0 ;
465
469
m_BufferSize = 0 ;
470
+ m_filled_bytes = 0 ;
471
+ m_lastPackageStamp = 0 ;
466
472
m_Channels = 0 ;
467
473
m_Stream = NULL ;
468
474
m_Context = NULL ;
475
+ m_periodSize = 0 ;
469
476
470
477
if (!SetupContext (NULL , &m_Context, &m_MainLoop))
471
478
{
@@ -641,6 +648,7 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
641
648
{
642
649
unsigned int packetSize = a->minreq ;
643
650
m_BufferSize = a->tlength ;
651
+ m_periodSize = a->minreq ;
644
652
645
653
format.m_frames = packetSize / frameSize;
646
654
}
@@ -688,6 +696,9 @@ void CAESinkPULSE::Deinitialize()
688
696
CSingleLock lock (m_sec);
689
697
m_IsAllocated = false ;
690
698
m_passthrough = false ;
699
+ m_periodSize = 0 ;
700
+ m_filled_bytes = 0 ;
701
+ m_lastPackageStamp = 0 ;
691
702
692
703
if (m_Stream)
693
704
Drain ();
@@ -724,25 +735,24 @@ void CAESinkPULSE::GetDelay(AEDelayStatus& status)
724
735
status.SetDelay (0 );
725
736
return ;
726
737
}
727
- int error = 0 ;
728
- pa_usec_t latency = (pa_usec_t ) -1 ;
738
+
729
739
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 ;
743
751
744
752
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);
746
756
}
747
757
748
758
double CAESinkPULSE::GetCacheTotal ()
@@ -765,10 +775,11 @@ unsigned int CAESinkPULSE::AddPackets(uint8_t **data, unsigned int frames, unsig
765
775
unsigned int available = frames * m_format.m_frameSize ;
766
776
unsigned int length = 0 ;
767
777
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 )
770
780
pa_threaded_mainloop_wait (m_MainLoop);
771
781
782
+ unsigned int free = length;
772
783
length = std::min ((unsigned int )length, available);
773
784
774
785
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
779
790
CLog::Log (LOGERROR, " CPulseAudioDirectSound::AddPackets - pa_stream_write failed\n " );
780
791
return 0 ;
781
792
}
793
+ m_lastPackageStamp = CurrentHostCounter ();
794
+ m_filled_bytes = m_BufferSize - (free - length);
795
+ unsigned int res = (unsigned int )(length / m_format.m_frameSize );
782
796
783
- return ( unsigned int )(length / m_format. m_frameSize ) ;
797
+ return res ;
784
798
}
785
799
786
800
void CAESinkPULSE::Drain ()
0 commit comments