mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-20 04:42:18 +02:00
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:
parent
a5c9350be5
commit
ddfd89a673
@ -498,6 +498,7 @@ struct obs_source {
|
|||||||
|
|
||||||
/* audio */
|
/* audio */
|
||||||
bool audio_failed;
|
bool audio_failed;
|
||||||
|
bool audio_pending;
|
||||||
bool muted;
|
bool muted;
|
||||||
struct obs_source *next_audio_source;
|
struct obs_source *next_audio_source;
|
||||||
struct obs_source **prev_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,
|
extern bool obs_source_init_context(struct obs_source *source,
|
||||||
obs_data_t *settings, const char *name,
|
obs_data_t *settings, const char *name,
|
||||||
obs_data_t *hotkey_data);
|
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_save(obs_source_t *source);
|
||||||
extern void obs_source_load(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,
|
extern float obs_source_get_target_volume(obs_source_t *source,
|
||||||
obs_source_t *target);
|
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 */
|
/* outputs */
|
||||||
|
@ -546,6 +546,27 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size)
|
|||||||
goto error;
|
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) \
|
#define CHECK_REQUIRED_VAL_(info, val, func) \
|
||||||
CHECK_REQUIRED_VAL(struct obs_source_info, info, val, func)
|
CHECK_REQUIRED_VAL(struct obs_source_info, info, val, func)
|
||||||
CHECK_REQUIRED_VAL_(info, get_name, obs_register_source);
|
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_width, obs_register_source);
|
||||||
CHECK_REQUIRED_VAL_(info, get_height, 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_
|
#undef CHECK_REQUIRED_VAL_
|
||||||
|
|
||||||
if (size > sizeof(data)) {
|
if (size > sizeof(data)) {
|
||||||
|
@ -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 */
|
/* internal initialization */
|
||||||
bool obs_source_init(struct obs_source *source,
|
bool obs_source_init(struct obs_source *source)
|
||||||
const struct obs_source_info *info)
|
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t attr;
|
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)
|
if (pthread_mutex_init(&source->async_mutex, NULL) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (info && info->output_flags & OBS_SOURCE_AUDIO) {
|
if (is_audio_source(source) || is_composite_source(source))
|
||||||
allocate_audio_output_buffer(source);
|
allocate_audio_output_buffer(source);
|
||||||
|
|
||||||
|
if (is_audio_source(source)) {
|
||||||
pthread_mutex_lock(&obs->data.audio_sources_mutex);
|
pthread_mutex_lock(&obs->data.audio_sources_mutex);
|
||||||
|
|
||||||
source->next_audio_source = obs->data.first_audio_source;
|
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)
|
if (info && info->get_defaults)
|
||||||
info->get_defaults(source->context.settings);
|
info->get_defaults(source->context.settings);
|
||||||
|
|
||||||
if (!obs_source_init(source, info))
|
if (!obs_source_init(source))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
obs_source_init_audio_hotkeys(source);
|
obs_source_init_audio_hotkeys(source);
|
||||||
|
@ -103,6 +103,17 @@ enum obs_source_type {
|
|||||||
*/
|
*/
|
||||||
#define OBS_SOURCE_INTERACTION (1<<5)
|
#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,
|
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
|
* If defined, called to free private data on shutdown
|
||||||
*/
|
*/
|
||||||
void (*free_type_data)(void *type_data);
|
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,
|
EXPORT void obs_register_source_s(const struct obs_source_info *info,
|
||||||
|
Loading…
Reference in New Issue
Block a user