Ver Fonte

libobs/audio-monitoring: Add reconnect logic

Automatically tear down if monitor is invalidated, and retry every time
an input sample is played.
jpark37 há 4 anos atrás
pai
commit
3c71399650
1 ficheiros alterados com 44 adições e 6 exclusões
  1. 44 6
      libobs/audio-monitoring/win32/wasapi-output.c

+ 44 - 6
libobs/audio-monitoring/win32/wasapi-output.c

@@ -276,6 +276,29 @@ fail:
 	return success;
 }
 
+static void audio_monitor_free_for_reconnect(struct audio_monitor *monitor)
+{
+	if (monitor->client)
+		monitor->client->lpVtbl->Stop(monitor->client);
+
+	if (monitor->render) {
+		monitor->render->lpVtbl->Release(monitor->render);
+		monitor->render = NULL;
+	}
+
+	if (monitor->client) {
+		monitor->client->lpVtbl->Stop(monitor->client);
+		monitor->client->lpVtbl->Release(monitor->client);
+		monitor->client = NULL;
+	}
+
+	audio_resampler_destroy(monitor->resampler);
+	monitor->resampler = NULL;
+
+	circlebuf_free(&monitor->delay_buffer);
+	da_free(monitor->buf);
+}
+
 static void on_audio_playback(void *param, obs_source_t *source,
 			      const struct audio_data *audio_data, bool muted)
 {
@@ -294,6 +317,10 @@ static void on_audio_playback(void *param, obs_source_t *source,
 		goto unlock;
 	}
 
+	if (!monitor->client && !audio_monitor_init_wasapi(monitor)) {
+		goto free_for_reconnect;
+	}
+
 	success = audio_resampler_resample(
 		monitor->resampler, resample_data, &resample_frames, &ts_offset,
 		(const uint8_t *const *)audio_data->data,
@@ -303,7 +330,11 @@ static void on_audio_playback(void *param, obs_source_t *source,
 	}
 
 	UINT32 pad = 0;
-	monitor->client->lpVtbl->GetCurrentPadding(monitor->client, &pad);
+	HRESULT hr = monitor->client->lpVtbl->GetCurrentPadding(monitor->client,
+								&pad);
+	if (FAILED(hr)) {
+		goto free_for_reconnect;
+	}
 
 	bool decouple_audio = source->async_unbuffered &&
 			      source->async_decoupled;
@@ -318,10 +349,9 @@ static void on_audio_playback(void *param, obs_source_t *source,
 	}
 
 	IAudioRenderClient *const render = monitor->render;
-	HRESULT hr =
-		render->lpVtbl->GetBuffer(render, resample_frames, &output);
+	hr = render->lpVtbl->GetBuffer(render, resample_frames, &output);
 	if (FAILED(hr)) {
-		goto unlock;
+		goto free_for_reconnect;
 	}
 
 	if (!muted) {
@@ -338,9 +368,17 @@ static void on_audio_playback(void *param, obs_source_t *source,
 		       resample_frames * monitor->channels * sizeof(float));
 	}
 
-	render->lpVtbl->ReleaseBuffer(render, resample_frames,
-				      muted ? AUDCLNT_BUFFERFLAGS_SILENT : 0);
+	hr = render->lpVtbl->ReleaseBuffer(render, resample_frames,
+					   muted ? AUDCLNT_BUFFERFLAGS_SILENT
+						 : 0);
+	if (FAILED(hr)) {
+		goto free_for_reconnect;
+	}
+
+	goto unlock;
 
+free_for_reconnect:
+	audio_monitor_free_for_reconnect(monitor);
 unlock:
 	ReleaseSRWLockExclusive(&monitor->playback_mutex);
 }