[client] audio: allow the audiodev to return the periodFrames

This change allows the audiodevs to return the minimum period frames
needed to start playback instead of having to rely on a pull to obtain
these details.

Additionally we are using this information to select an initial start
latency as well as to train the desired latency in order to keep it as
low as possible.
This commit is contained in:
Geoffrey McRae
2022-01-27 17:20:28 +11:00
parent dd2d84a080
commit 41884bfcc5
4 changed files with 69 additions and 50 deletions

View File

@@ -104,6 +104,17 @@ static void pipewire_onPlaybackProcess(void * userdata)
if (pw.playback.rateMatch && pw.playback.rateMatch->size > 0)
frames = min(frames, pw.playback.rateMatch->size);
/* pipewire doesn't provide a way to access the quantum, so we start the
* stream and stop it immediately at setup to get this value */
if (pw.playback.startFrames == -1)
{
sbuf->datas[0].chunk->size = 0;
pw_stream_queue_buffer(pw.playback.stream, pbuf);
pw_stream_set_active(pw.playback.stream, false);
pw.playback.startFrames = frames;
return;
}
frames = pw.playback.pullFn(dst, frames);
if (!frames)
{
@@ -179,7 +190,7 @@ static void pipewire_playbackStopStream(void)
}
static void pipewire_playbackSetup(int channels, int sampleRate,
LG_AudioPullFn pullFn)
LG_AudioPullFn pullFn, int * periodFrames)
{
const struct spa_pod * params[1];
uint8_t buffer[1024];
@@ -209,7 +220,7 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
pw.playback.sampleRate = sampleRate;
pw.playback.stride = sizeof(float) * channels;
pw.playback.pullFn = pullFn;
pw.playback.startFrames = maxLatencyFrames;
pw.playback.startFrames = -1;
pw_thread_loop_lock(pw.thread);
pw.playback.stream = pw_stream_new_simple(
@@ -247,19 +258,22 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
PW_ID_ANY,
PW_STREAM_FLAG_AUTOCONNECT |
PW_STREAM_FLAG_MAP_BUFFERS |
PW_STREAM_FLAG_RT_PROCESS |
PW_STREAM_FLAG_INACTIVE,
PW_STREAM_FLAG_RT_PROCESS,
params, 1);
pw_thread_loop_unlock(pw.thread);
/* wait for the stream to start and set this value */
while(pw.playback.startFrames == -1)
pw_thread_loop_wait(pw.thread);
*periodFrames = pw.playback.startFrames;
}
static bool pipewire_playbackStart(int framesBuffered)
static void pipewire_playbackStart(void)
{
if (!pw.playback.stream)
return false;
bool start = false;
return;
if (pw.playback.state != STREAM_STATE_ACTIVE)
{
@@ -268,12 +282,8 @@ static bool pipewire_playbackStart(int framesBuffered)
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;
}
pw_stream_set_active(pw.playback.stream, true);
pw.playback.state = STREAM_STATE_ACTIVE;
break;
case STREAM_STATE_DRAINING:
@@ -287,8 +297,6 @@ static bool pipewire_playbackStart(int framesBuffered)
pw_thread_loop_unlock(pw.thread);
}
return start;
}
static void pipewire_playbackStop(void)