libobs: Deduplicate audio for nested scenes/groups if not transitioning

This commit is contained in:
derrod 2024-05-09 12:05:02 +02:00 committed by Lain
parent 8a38e3375b
commit 72924ac1f3

View file

@ -1476,16 +1476,28 @@ static inline void mix_audio(float *p_out, float *p_in, size_t pos,
*(out++) += *(in++);
}
static bool scene_audio_render(void *data, uint64_t *ts_out,
struct obs_source_audio_mix *audio_output,
uint32_t mixers, size_t channels,
size_t sample_rate)
static inline struct scene_source_mix *get_source_mix(struct obs_scene *scene,
struct obs_source *source)
{
for (size_t i = 0; i < scene->mix_sources.num; i++) {
struct scene_source_mix *mix = &scene->mix_sources.array[i];
if (mix->source == source)
return mix;
}
return NULL;
}
static bool scene_audio_render_internal(
struct obs_scene *scene, struct obs_scene *parent, uint64_t *ts_out,
struct obs_source_audio_mix *audio_output, uint32_t mixers,
size_t channels, size_t sample_rate, float *parent_buf)
{
uint64_t timestamp = 0;
float buf[AUDIO_OUTPUT_FRAMES];
struct obs_source_audio_mix child_audio;
struct obs_scene *scene = data;
struct obs_scene_item *item;
struct obs_scene *mix_scene = parent ? parent : scene;
audio_lock(scene);
@ -1499,6 +1511,7 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
source = item->hide_transition;
else
source = item->source;
if (!obs_source_audio_pending(source) &&
(item->visible ||
transition_active(item->hide_transition))) {
@ -1531,7 +1544,7 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
size_t pos;
bool apply_buf;
struct obs_source *source;
struct scene_source_mix *source_mix = NULL;
struct scene_source_mix *source_mix;
if (item->visible && transition_active(item->show_transition))
source = item->show_transition;
@ -1569,23 +1582,48 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
continue;
}
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;
size_t count = AUDIO_OUTPUT_FRAMES - pos;
/* Update buf so that parent mute state applies to all current
* scene items as well */
if (parent_buf &&
(!apply_buf ||
memcmp(buf, parent_buf, sizeof(float) * count) != 0)) {
for (size_t i = 0; i < count; i++) {
if (!apply_buf) {
buf[i] = parent_buf[i];
} else {
buf[i] = buf[i] < parent_buf[i]
? buf[i]
: parent_buf[i];
}
}
apply_buf = true;
}
/* If "source" is a group/scene and has no transition,
* add their items to the current list */
if (source == item->source && (obs_source_is_group(source) ||
obs_source_is_scene(source))) {
scene_audio_render_internal(source->context.data,
mix_scene, NULL, NULL, 0, 0,
sample_rate,
apply_buf ? buf : NULL);
item = item->next;
continue;
}
source_mix = get_source_mix(mix_scene, item->source);
if (!source_mix) {
source_mix = da_push_back_new(scene->mix_sources);
source_mix = da_push_back_new(mix_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;
source_mix->count = count;
if (apply_buf) {
memcpy(source_mix->buf, buf,
sizeof(float) * source_mix->count);
@ -1614,6 +1652,11 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
item = item->next;
}
if (!audio_output) {
audio_unlock(scene);
return true;
}
for (size_t i = 0; i < scene->mix_sources.num; i++) {
struct scene_source_mix *source_mix =
&scene->mix_sources.array[i];
@ -1650,6 +1693,16 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
return true;
}
static bool scene_audio_render(void *data, uint64_t *ts_out,
struct obs_source_audio_mix *audio_output,
uint32_t mixers, size_t channels,
size_t sample_rate)
{
struct obs_scene *scene = data;
return scene_audio_render_internal(scene, NULL, ts_out, audio_output,
mixers, channels, sample_rate, NULL);
}
enum gs_color_space
scene_video_get_color_space(void *data, size_t count,
const enum gs_color_space *preferred_spaces)