Skip to content

Commit

Permalink
Improve timestamp calculation leading to better A/V Sync (ALSA and Pu…
Browse files Browse the repository at this point in the history
…lse only so far)

GetBufferedOnSoundCard should return the length of audio in the buffer including latency ; it was only returning the latency. Also in pulse, is some cases the end calculation could overflow leading to incorrect value. Changed it to 64 bits int
  • Loading branch information
jyavenard committed Dec 16, 2010
1 parent 3fbe948 commit 5eac843
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 14 deletions.
31 changes: 26 additions & 5 deletions mythtv/libs/libmyth/audio/audiooutputalsa.cpp
Expand Up @@ -562,22 +562,43 @@ void AudioOutputALSA::WriteAudio(uchar *aubuf, int size)

int AudioOutputALSA::GetBufferedOnSoundcard(void) const
{

if (pcm_handle == NULL)
{
VBERROR("getBufferedOnSoundcard() called with pcm_handle == NULL!");
return 0;
}

snd_pcm_sframes_t delay = 0;
snd_pcm_sframes_t delay = 0, buffered = 0;

if (snd_pcm_avail_delay(pcm_handle, &buffered, &delay) < 0)
{
return 0;
}

snd_pcm_state_t state = snd_pcm_state(pcm_handle);

if (state == SND_PCM_STATE_RUNNING || state == SND_PCM_STATE_DRAINING)
snd_pcm_delay(pcm_handle, &delay);
{
delay *= output_bytes_per_frame;
}
else
{
delay = 00;
}

if (delay <= 0)
return 0;
if (buffered < 0)
{
buffered = 0;
}

buffered *= output_bytes_per_frame;
if (buffered > soundcard_buffer_size)
{
buffered = soundcard_buffer_size;
}

return delay * output_bytes_per_frame;
return delay + buffered;
}

/*
Expand Down
7 changes: 6 additions & 1 deletion mythtv/libs/libmyth/audio/audiooutputbase.h
Expand Up @@ -111,6 +111,10 @@ class AudioOutputBase : public AudioOutput, public QThread
virtual bool OpenDevice(void) = 0;
virtual void CloseDevice(void) = 0;
virtual void WriteAudio(uchar *aubuf, int size) = 0;
/*
* Return the size in bytes of frames currently in the audio buffer adjusted
* with the audio playback latency
*/
virtual int GetBufferedOnSoundcard(void) const = 0;
// Default implementation only supports 2ch s16le at 48kHz
virtual AudioOutputSettings* GetOutputSettings(void)
Expand All @@ -122,7 +126,8 @@ class AudioOutputBase : public AudioOutput, public QThread
virtual bool StartOutputThread(void);
virtual void StopOutputThread(void);

int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer, int *local_raud = NULL);
int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer,
int *local_raud = NULL);

void OutputAudioLoop(void);

Expand Down
31 changes: 23 additions & 8 deletions mythtv/libs/libmyth/audio/audiooutputpulse.cpp
Expand Up @@ -226,10 +226,6 @@ void AudioOutputPulseAudio::WriteAudio(uchar *aubuf, int size)
QString fn_log_tag = "WriteAudio, ";
pa_stream_state_t sstate = pa_stream_get_state(pstream);

// Do not write anything to pulse server if we are in pause mode
if (IsPaused())
return;

VBAUDIOTS(fn_log_tag + QString("writing %1 bytes").arg(size));

/* NB This "if" check can be replaced with PA_STREAM_IS_GOOD() in
Expand Down Expand Up @@ -299,21 +295,40 @@ void AudioOutputPulseAudio::WriteAudio(uchar *aubuf, int size)

int AudioOutputPulseAudio::GetBufferedOnSoundcard(void) const
{
pa_usec_t latency;
pa_usec_t latency = (pa_usec_t) -1;
size_t buffered = 0;

if (!pcontext || pa_context_get_state(pcontext) != PA_CONTEXT_READY)
return 0;

if (!pstream || pa_stream_get_state(pstream) != PA_STREAM_READY)
return 0;

const pa_buffer_attr *buf_attr = pa_stream_get_buffer_attr(pstream);
size_t bfree = pa_stream_writable_size(pstream);
buffered = buf_attr->tlength - bfree;

pa_threaded_mainloop_lock(mainloop);

if(pa_stream_get_latency(pstream, &latency, NULL) < 0)
latency = 0;
while (pa_stream_get_latency(pstream, &latency, NULL) < 0)
{
if (pa_context_errno(pcontext) != PA_ERR_NODATA)
{
latency = 0;
break;
}
pa_threaded_mainloop_wait(mainloop);
}

pa_threaded_mainloop_unlock(mainloop);
return (int)latency * samplerate * output_bytes_per_frame / 1000000;

if (latency < 0)
{
latency = 0;
}

return ((uint64_t)latency * samplerate *
output_bytes_per_frame / 1000000) + buffered;
}

int AudioOutputPulseAudio::GetVolumeChannel(int channel) const
Expand Down

0 comments on commit 5eac843

Please sign in to comment.