diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index f54776a9d..f75ca5bd2 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -498,6 +498,7 @@ struct obs_source { /* audio */ bool audio_failed; + bool audio_pending; bool muted; struct obs_source *next_audio_source; struct obs_source **prev_next_audio_source; @@ -567,8 +568,6 @@ extern const struct obs_source_info *find_source(struct darray *list, extern bool obs_source_init_context(struct obs_source *source, obs_data_t *settings, const char *name, obs_data_t *hotkey_data); -extern bool obs_source_init(struct obs_source *source, - const struct obs_source_info *info); extern void obs_source_save(obs_source_t *source); extern void obs_source_load(obs_source_t *source); @@ -586,6 +585,9 @@ extern void obs_source_video_tick(obs_source_t *source, float seconds); extern float obs_source_get_target_volume(obs_source_t *source, obs_source_t *target); +extern void obs_source_audio_render(obs_source_t *source, uint32_t mixers, + size_t channels, size_t sample_rate, size_t size); + /* ------------------------------------------------------------------------- */ /* outputs */ diff --git a/libobs/obs-module.c b/libobs/obs-module.c index ddb7b4e27..5a2973f06 100644 --- a/libobs/obs-module.c +++ b/libobs/obs-module.c @@ -546,6 +546,27 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size) goto error; } + memcpy(&data, info, size); + + /* mark audio-only filters as an async filter categorically */ + if (data.type == OBS_SOURCE_TYPE_FILTER) { + if ((data.output_flags & OBS_SOURCE_VIDEO) == 0) + data.output_flags |= OBS_SOURCE_ASYNC; + } + + if ((data.output_flags & OBS_SOURCE_COMPOSITE) != 0) { + if ((data.output_flags & OBS_SOURCE_AUDIO) != 0) { + blog(LOG_WARNING, "Source '%s': Composite sources " + "cannot be audio sources", info->id); + goto error; + } + if ((data.output_flags & OBS_SOURCE_ASYNC) != 0) { + blog(LOG_WARNING, "Source '%s': Composite sources " + "cannot be async sources", info->id); + goto error; + } + } + #define CHECK_REQUIRED_VAL_(info, val, func) \ CHECK_REQUIRED_VAL(struct obs_source_info, info, val, func) CHECK_REQUIRED_VAL_(info, get_name, obs_register_source); @@ -558,6 +579,10 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size) CHECK_REQUIRED_VAL_(info, get_width, obs_register_source); CHECK_REQUIRED_VAL_(info, get_height, obs_register_source); } + + if ((info->output_flags & OBS_SOURCE_COMPOSITE) != 0) { + CHECK_REQUIRED_VAL_(info, audio_render, obs_register_source); + } #undef CHECK_REQUIRED_VAL_ if (size > sizeof(data)) { diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 3a1771f6f..eba761e08 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -132,9 +132,18 @@ static void allocate_audio_output_buffer(struct obs_source *source) } } +static inline bool is_audio_source(const struct obs_source *source) +{ + return source->info.output_flags & OBS_SOURCE_AUDIO; +} + +static inline bool is_composite_source(const struct obs_source *source) +{ + return source->info.output_flags & OBS_SOURCE_COMPOSITE; +} + /* internal initialization */ -bool obs_source_init(struct obs_source *source, - const struct obs_source_info *info) +bool obs_source_init(struct obs_source *source) { pthread_mutexattr_t attr; @@ -158,9 +167,10 @@ bool obs_source_init(struct obs_source *source, if (pthread_mutex_init(&source->async_mutex, NULL) != 0) return false; - if (info && info->output_flags & OBS_SOURCE_AUDIO) { + if (is_audio_source(source) || is_composite_source(source)) allocate_audio_output_buffer(source); + if (is_audio_source(source)) { pthread_mutex_lock(&obs->data.audio_sources_mutex); source->next_audio_source = obs->data.first_audio_source; @@ -303,7 +313,7 @@ obs_source_t *obs_source_create(enum obs_source_type type, const char *id, if (info && info->get_defaults) info->get_defaults(source->context.settings); - if (!obs_source_init(source, info)) + if (!obs_source_init(source)) goto fail; obs_source_init_audio_hotkeys(source); diff --git a/libobs/obs-source.h b/libobs/obs-source.h index bffd0543f..ae21036f8 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -103,6 +103,17 @@ enum obs_source_type { */ #define OBS_SOURCE_INTERACTION (1<<5) +/** + * Source composites sub-sources + * + * When used specifies that the source composites one or more sub-sources. + * Sources that render sub-sources must implement the audio_render callback + * in order to perform custom mixing of sub-sources. + * + * This capability flag is always set for transitions. + */ +#define OBS_SOURCE_COMPOSITE (1<<6) + /** @} */ typedef void (*obs_source_enum_proc_t)(obs_source_t *parent, @@ -388,6 +399,10 @@ struct obs_source_info { * If defined, called to free private data on shutdown */ void (*free_type_data)(void *type_data); + + bool (*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); }; EXPORT void obs_register_source_s(const struct obs_source_info *info,