Explorar o código

libobs: Mix audio of each source in a scene only once

derrod hai 1 ano
pai
achega
8a38e3375b
Modificáronse 2 ficheiros con 76 adicións e 10 borrados
  1. 65 10
      libobs/obs-scene.c
  2. 11 0
      libobs/obs-scene.h

+ 65 - 10
libobs/obs-scene.c

@@ -239,6 +239,7 @@ static void scene_destroy(void *data)
 
 	pthread_mutex_destroy(&scene->video_mutex);
 	pthread_mutex_destroy(&scene->audio_mutex);
+	da_free(scene->mix_sources);
 	bfree(scene);
 }
 
@@ -1527,9 +1528,11 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
 	item = scene->first_item;
 	while (item) {
 		uint64_t source_ts;
-		size_t pos, count;
+		size_t pos;
 		bool apply_buf;
 		struct obs_source *source;
+		struct scene_source_mix *source_mix = NULL;
+
 		if (item->visible && transition_active(item->show_transition))
 			source = item->show_transition;
 		else if (!item->visible &&
@@ -1560,15 +1563,64 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
 			continue;
 		}
 
-		count = AUDIO_OUTPUT_FRAMES - pos;
-
 		if (!apply_buf && !item->visible &&
 		    !transition_active(item->hide_transition)) {
 			item = item->next;
 			continue;
 		}
 
-		obs_source_get_audio_mix(source, &child_audio);
+		for (size_t i = 0; i < scene->mix_sources.num; i++) {
+			struct scene_source_mix *mix =
+				&scene->mix_sources.array[i];
+			if (mix->source == item->source) {
+				source_mix = mix;
+				break;
+			}
+		}
+
+		if (!source_mix) {
+			source_mix = da_push_back_new(scene->mix_sources);
+			source_mix->source = item->source;
+			source_mix->transition = source != item->source ? source
+									: NULL;
+			source_mix->apply_buf = apply_buf;
+			source_mix->pos = pos;
+			source_mix->count = AUDIO_OUTPUT_FRAMES - pos;
+			if (apply_buf) {
+				memcpy(source_mix->buf, buf,
+				       sizeof(float) * source_mix->count);
+			}
+		} else {
+			/* Only transition audio if there are no
+			 * non-transitioning scene items. */
+			if (source_mix->transition && source == item->source)
+				source_mix->transition = NULL;
+			/* Only apply buf to mix if all scene items for this
+			 * source require it. */
+			source_mix->apply_buf = source_mix->apply_buf &&
+						apply_buf;
+			/* Update buf so that only highest value across all
+			 * items is used. */
+			if (source_mix->apply_buf &&
+			    memcmp(source_mix->buf, buf,
+				   source_mix->count * sizeof(float)) != 0) {
+				for (size_t i = 0; i < source_mix->count; i++) {
+					if (buf[i] > source_mix->buf[i])
+						source_mix->buf[i] = buf[i];
+				}
+			}
+		}
+
+		item = item->next;
+	}
+
+	for (size_t i = 0; i < scene->mix_sources.num; i++) {
+		struct scene_source_mix *source_mix =
+			&scene->mix_sources.array[i];
+		obs_source_get_audio_mix(source_mix->transition
+						 ? source_mix->transition
+						 : source_mix->source,
+					 &child_audio);
 
 		for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
 			if ((mixers & (1 << mix)) == 0)
@@ -1578,17 +1630,20 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
 				float *out = audio_output->output[mix].data[ch];
 				float *in = child_audio.output[mix].data[ch];
 
-				if (apply_buf)
-					mix_audio_with_buf(out, in, buf, pos,
-							   count);
+				if (source_mix->apply_buf)
+					mix_audio_with_buf(out, in,
+							   source_mix->buf,
+							   source_mix->pos,
+							   source_mix->count);
 				else
-					mix_audio(out, in, pos, count);
+					mix_audio(out, in, source_mix->pos,
+						  source_mix->count);
 			}
 		}
-
-		item = item->next;
 	}
 
+	da_clear(scene->mix_sources);
+
 	*ts_out = timestamp;
 	audio_unlock(scene);
 

+ 11 - 0
libobs/obs-scene.h

@@ -93,6 +93,15 @@ struct obs_scene_item {
 	struct obs_scene_item *next;
 };
 
+struct scene_source_mix {
+	obs_source_t *source;
+	obs_source_t *transition;
+	size_t pos;
+	size_t count;
+	bool apply_buf;
+	float buf[AUDIO_OUTPUT_FRAMES];
+};
+
 struct obs_scene {
 	struct obs_source *source;
 
@@ -106,4 +115,6 @@ struct obs_scene {
 	pthread_mutex_t video_mutex;
 	pthread_mutex_t audio_mutex;
 	struct obs_scene_item *first_item;
+
+	DARRAY(struct scene_source_mix) mix_sources;
 };