libobs: Implement composite sources (skip)

(Note: This commit breaks libobs compilation.  Skip if bisecting)

Adds a "composite" source type which is used for sources that composite
one or more sub-sources.  The audio_render callback is called for
composite sources to allow those types of sources to do custom
processing of the audio of its sub-sources.
This commit is contained in:
jp9000 2015-12-17 06:46:10 -08:00
parent a5c9350be5
commit ddfd89a673
4 changed files with 58 additions and 6 deletions

View file

@ -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 */

View file

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

View file

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

View file

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