libobs: Fix pulseaudio monitor playback stuttering

This commit is contained in:
Shaolin 2017-12-06 15:14:14 -02:00
parent ed00d7402f
commit 9de1ffe32b
3 changed files with 51 additions and 12 deletions

View file

@ -8,7 +8,7 @@ struct audio_monitor {
obs_source_t *source;
pa_stream *stream;
char *device;
pa_buffer_attr attr;
enum speaker_layout speakers;
pa_sample_format_t format;
uint_fast32_t samples_per_sec;
@ -22,8 +22,8 @@ struct audio_monitor {
audio_resampler_t *resampler;
size_t buffer_size;
size_t bytesRemaining;
size_t bytes_per_channel;
bool ignore;
pthread_mutex_t playback_mutex;
};
@ -191,6 +191,21 @@ static void pulseaudio_stream_write(pa_stream *p, size_t nbytes, void *userdata)
pulseaudio_signal(0);
}
static void pulseaudio_underflow(pa_stream *p, void *userdata)
{
UNUSED_PARAMETER(p);
PULSE_DATA(userdata);
pthread_mutex_lock(&data->playback_mutex);
if (obs_source_active(data->source))
data->attr.tlength = (data->attr.tlength * 3) / 2;
pa_stream_set_buffer_attr(data->stream, &data->attr, NULL, NULL);
pthread_mutex_unlock(&data->playback_mutex);
pulseaudio_signal(0);
}
static void pulseaudio_server_info(pa_context *c, const pa_server_info *i,
void *userdata)
{
@ -362,17 +377,17 @@ static bool audio_monitor_init(struct audio_monitor *monitor,
return false;
}
pa_buffer_attr attr;
attr.fragsize = (uint32_t) -1;
attr.maxlength = (uint32_t) -1;
attr.minreq = (uint32_t) -1;
attr.prebuf = (uint32_t) -1;
attr.tlength = pa_usec_to_bytes(25000, &spec);
monitor->attr.fragsize = (uint32_t) -1;
monitor->attr.maxlength = (uint32_t) -1;
monitor->attr.minreq = (uint32_t) -1;
monitor->attr.prebuf = (uint32_t) -1;
monitor->attr.tlength = pa_usec_to_bytes(25000, &spec);
monitor->buffer_size =
monitor->bytes_per_frame * pa_usec_to_bytes(100, &spec);
monitor->buffer_size = monitor->bytes_per_frame *
pa_usec_to_bytes(5000, &spec);
pa_stream_flags_t flags = PA_STREAM_ADJUST_LATENCY;
pa_stream_flags_t flags = PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_AUTO_TIMING_UPDATE;
if (pthread_mutex_init(&monitor->playback_mutex, NULL) != 0) {
blog(LOG_WARNING, "%s: %s", __FUNCTION__,
@ -381,7 +396,7 @@ static bool audio_monitor_init(struct audio_monitor *monitor,
}
int_fast32_t ret = pulseaudio_connect_playback(monitor->stream,
monitor->device, &attr, flags);
monitor->device, &monitor->attr, flags);
if (ret < 0) {
pulseaudio_stop_playback(monitor);
blog(LOG_ERROR, "Unable to connect to stream");
@ -402,6 +417,9 @@ static void audio_monitor_init_final(struct audio_monitor *monitor)
pulseaudio_write_callback(monitor->stream, pulseaudio_stream_write,
(void *) monitor);
pulseaudio_set_underflow_callback(monitor->stream, pulseaudio_underflow,
(void *) monitor);
}
static inline void audio_monitor_free(struct audio_monitor *monitor)

View file

@ -328,3 +328,14 @@ void pulseaudio_write_callback(pa_stream *p, pa_stream_request_cb_t cb,
pa_stream_set_write_callback(p, cb, userdata);
pulseaudio_unlock();
}
void pulseaudio_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb,
void *userdata)
{
if (pulseaudio_context_ready() < 0)
return;
pulseaudio_lock();
pa_stream_set_underflow_callback(p, cb, userdata);
pulseaudio_unlock();
}

View file

@ -173,3 +173,13 @@ int_fast32_t pulseaudio_connect_playback(pa_stream *s, const char *name,
*/
void pulseaudio_write_callback(pa_stream *p, pa_stream_request_cb_t cb,
void *userdata);
/**
* Sets a callback function for when an underflow happen
*
* @param p pa_stream to connect to. NULL for default
* @param cb pa_stream_notify_cb_t
* @param userdata pointer to userdata the callback will be called with
*/
void pulseaudio_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb,
void *userdata);