1
0
Эх сурвалжийг харах

libobs: Fix pulseaudio monitor playback stuttering

Shaolin 7 жил өмнө
parent
commit
9de1ffe32b

+ 30 - 12
libobs/audio-monitoring/pulse/pulseaudio-output.c

@@ -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)

+ 11 - 0
libobs/audio-monitoring/pulse/pulseaudio-wrapper.c

@@ -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();
+}

+ 10 - 0
libobs/audio-monitoring/pulse/pulseaudio-wrapper.h

@@ -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);