[client] audio: allow the audiodev to determine the start fill level

This commit is contained in:
Geoffrey McRae 2022-01-19 01:52:19 +11:00
parent 46da447429
commit 04ae9217e8
4 changed files with 36 additions and 23 deletions

View file

@ -53,6 +53,7 @@ struct PipeWire
int sampleRate;
int stride;
LG_AudioPullFn pullFn;
int startFrames;
StreamState state;
}
@ -224,16 +225,16 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
pipewire_playbackStopStream();
int bufferFrames = sampleRate / 10;
int maxLatencyFrames = bufferFrames / 2;
char maxLatency[32];
snprintf(maxLatency, sizeof(maxLatency), "%d/%d", maxLatencyFrames,
sampleRate);
pw.playback.channels = channels;
pw.playback.sampleRate = sampleRate;
pw.playback.stride = sizeof(uint16_t) * channels;
pw.playback.pullFn = pullFn;
int maxLatencyFrames = bufferFrames / 2;
char maxLatency[32];
snprintf(maxLatency, sizeof(maxLatency), "%d/%d", maxLatencyFrames,
sampleRate);
pw.playback.startFrames = maxLatencyFrames;
pw_thread_loop_lock(pw.thread);
pw.playback.stream = pw_stream_new_simple(
@ -278,10 +279,12 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
pw_thread_loop_unlock(pw.thread);
}
static void pipewire_playbackStart(void)
static bool pipewire_playbackStart(int framesBuffered)
{
if (!pw.playback.stream)
return;
return false;
bool start = false;
if (pw.playback.state != STREAM_STATE_ACTIVE &&
pw.playback.state != STREAM_STATE_RESTARTING)
@ -291,13 +294,18 @@ static void pipewire_playbackStart(void)
switch (pw.playback.state)
{
case STREAM_STATE_INACTIVE:
if (framesBuffered >= pw.playback.startFrames)
{
pw_stream_set_active(pw.playback.stream, true);
pw.playback.state = STREAM_STATE_ACTIVE;
start = true;
}
break;
case STREAM_STATE_FLUSHING:
// We were preparing to stop; just carry on as if nothing happened
pw.playback.state = STREAM_STATE_ACTIVE;
start = true;
break;
case STREAM_STATE_DRAINING:
@ -312,6 +320,8 @@ static void pipewire_playbackStart(void)
pw_thread_loop_unlock(pw.thread);
}
return start;
}
static void pipewire_playbackStop(void)

View file

@ -288,15 +288,20 @@ static void pulseaudio_setup(int channels, int sampleRate,
pa_threaded_mainloop_unlock(pa.loop);
}
static void pulseaudio_start(void)
static bool pulseaudio_start(int framesBuffered)
{
if (!pa.sink)
return;
return false;
if (framesBuffered < pa.sinkStart)
return false;
pa_threaded_mainloop_lock(pa.loop);
pa_stream_cork(pa.sink, 0, NULL, NULL);
pa.sinkCorked = false;
pa_threaded_mainloop_unlock(pa.loop);
return true;
}
static void pulseaudio_stop(void)

View file

@ -49,8 +49,9 @@ struct LG_AudioDevOps
*/
void (*setup)(int channels, int sampleRate, LG_AudioPullFn pullFn);
/* called when playback is about to start */
void (*start)(void);
/* called when there is data available to start playback
* return true if playback should start */
bool (*start)(int framesBuffered);
/* called when SPICE reports the audio stream has stopped */
void (*stop)(void);

View file

@ -167,7 +167,7 @@ void audio_playbackStart(int channels, int sampleRate, PSAudioFormat format,
playbackStopNL();
}
const int bufferFrames = sampleRate / 10;
const int bufferFrames = sampleRate;
audio.playback.buffer = ringbuffer_new(bufferFrames,
channels * sizeof(uint16_t));
@ -247,17 +247,14 @@ void audio_playbackData(uint8_t * data, size_t size)
if (!STREAM_ACTIVE(audio.playback.state))
return;
const int frames = size / audio.playback.stride;
int frames = size / audio.playback.stride;
ringbuffer_append(audio.playback.buffer, data, frames);
// don't start playback until the buffer is sifficiently full to avoid
// glitches
if (audio.playback.state == STREAM_STATE_SETUP &&
ringbuffer_getCount(audio.playback.buffer) >=
ringbuffer_getLength(audio.playback.buffer) / 4)
if (audio.playback.state == STREAM_STATE_SETUP)
{
frames = ringbuffer_getLength(audio.playback.buffer);
if (audio.audioDev->playback.start(frames))
audio.playback.state = STREAM_STATE_RUN;
audio.audioDev->playback.start();
}
}