libobs: Do not use signals with audio capture/controls

(Note: This commit also modifies UI)

Instead of using signals, use designated callback lists for audio
capture and audio control helpers.  Signals aren't suitable here due to
the fact that signals aren't meant for things that happen every frame or
things that happen every time audio/video is received.  Also prevents
audio from being allocated every time these functions are called due to
the calldata structure.
This commit is contained in:
jp9000 2016-01-07 19:48:36 -08:00
parent 46bb2622c4
commit 669da7ba36
7 changed files with 176 additions and 106 deletions

View file

@ -34,9 +34,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
typedef float (*obs_fader_conversion_t)(const float val);
struct fader_cb {
obs_fader_changed_t callback;
void *param;
};
struct obs_fader {
pthread_mutex_t mutex;
signal_handler_t *signals;
obs_fader_conversion_t def_to_db;
obs_fader_conversion_t db_to_def;
obs_source_t *source;
@ -45,17 +49,27 @@ struct obs_fader {
float min_db;
float cur_db;
bool ignore_next_signal;
pthread_mutex_t callback_mutex;
DARRAY(struct fader_cb)callbacks;
};
struct meter_cb {
obs_volmeter_updated_t callback;
void *param;
};
struct obs_volmeter {
pthread_mutex_t mutex;
signal_handler_t *signals;
obs_fader_conversion_t pos_to_db;
obs_fader_conversion_t db_to_pos;
obs_source_t *source;
enum obs_fader_type type;
float cur_db;
pthread_mutex_t callback_mutex;
DARRAY(struct meter_cb)callbacks;
unsigned int channels;
unsigned int update_ms;
unsigned int update_frames;
@ -72,17 +86,6 @@ struct obs_volmeter {
float vol_max;
};
static const char *fader_signals[] = {
"void volume_changed(ptr fader, float db)",
NULL
};
static const char *volmeter_signals[] = {
"void levels_updated(ptr volmeter, float level, "
"float magnitude, float peak, bool muted)",
NULL
};
static float cubic_def_to_db(const float def)
{
if (def == 1.0f)
@ -191,39 +194,26 @@ static float log_db_to_def(const float db)
/ (LOG_OFFSET_VAL - LOG_RANGE_VAL);
}
static void signal_volume_changed(signal_handler_t *sh,
struct obs_fader *fader, const float db)
static void signal_volume_changed(struct obs_fader *fader, const float db)
{
struct calldata data;
calldata_init(&data);
calldata_set_ptr (&data, "fader", fader);
calldata_set_float(&data, "db", db);
signal_handler_signal(sh, "volume_changed", &data);
calldata_free(&data);
pthread_mutex_lock(&fader->callback_mutex);
for (size_t i = fader->callbacks.num; i > 0; i--) {
struct fader_cb cb = fader->callbacks.array[i - 1];
cb.callback(cb.param, db);
}
pthread_mutex_unlock(&fader->callback_mutex);
}
static void signal_levels_updated(signal_handler_t *sh,
struct obs_volmeter *volmeter,
static void signal_levels_updated(struct obs_volmeter *volmeter,
const float level, const float magnitude, const float peak,
bool muted)
{
struct calldata data;
calldata_init(&data);
calldata_set_ptr (&data, "volmeter", volmeter);
calldata_set_float(&data, "level", level);
calldata_set_float(&data, "magnitude", magnitude);
calldata_set_float(&data, "peak", peak);
calldata_set_bool (&data, "muted", muted);
signal_handler_signal(sh, "levels_updated", &data);
calldata_free(&data);
pthread_mutex_lock(&volmeter->callback_mutex);
for (size_t i = volmeter->callbacks.num; i > 0; i--) {
struct meter_cb cb = volmeter->callbacks.array[i - 1];
cb.callback(cb.param, level, magnitude, peak, muted);
}
pthread_mutex_unlock(&volmeter->callback_mutex);
}
static void fader_source_volume_changed(void *vptr, calldata_t *calldata)
@ -238,14 +228,13 @@ static void fader_source_volume_changed(void *vptr, calldata_t *calldata)
return;
}
signal_handler_t *sh = fader->signals;
const float mul = (float)calldata_float(calldata, "volume");
const float db = mul_to_db(mul);
fader->cur_db = db;
pthread_mutex_unlock(&fader->mutex);
signal_volume_changed(sh, fader, db);
signal_volume_changed(fader, db);
}
static void volmeter_source_volume_changed(void *vptr, calldata_t *calldata)
@ -335,7 +324,7 @@ static void volmeter_calc_ival_levels(obs_volmeter_t *volmeter)
}
static bool volmeter_process_audio_data(obs_volmeter_t *volmeter,
struct audio_data *data)
const struct audio_data *data)
{
bool updated = false;
size_t frames = 0;
@ -374,16 +363,15 @@ static bool volmeter_process_audio_data(obs_volmeter_t *volmeter,
return updated;
}
static void volmeter_source_data_received(void *vptr, calldata_t *calldata)
static void volmeter_source_data_received(void *vptr, obs_source_t *source,
const struct audio_data *data, bool muted)
{
struct obs_volmeter *volmeter = (struct obs_volmeter *) vptr;
bool updated = false;
float mul, level, mag, peak;
signal_handler_t *sh;
pthread_mutex_lock(&volmeter->mutex);
struct audio_data *data = calldata_ptr(calldata, "data");
updated = volmeter_process_audio_data(volmeter, data);
if (updated) {
@ -393,14 +381,14 @@ static void volmeter_source_data_received(void *vptr, calldata_t *calldata)
mag = volmeter->db_to_pos(mul_to_db(volmeter->vol_mag * mul));
peak = volmeter->db_to_pos(
mul_to_db(volmeter->vol_peak * mul));
sh = volmeter->signals;
}
pthread_mutex_unlock(&volmeter->mutex);
if (updated)
signal_levels_updated(sh, volmeter, level, mag, peak,
calldata_bool(calldata, "muted"));
signal_levels_updated(volmeter, level, mag, peak, muted);
UNUSED_PARAMETER(source);
}
static void volmeter_update_audio_settings(obs_volmeter_t *volmeter)
@ -420,12 +408,10 @@ obs_fader_t *obs_fader_create(enum obs_fader_type type)
return NULL;
pthread_mutex_init_value(&fader->mutex);
pthread_mutex_init_value(&fader->callback_mutex);
if (pthread_mutex_init(&fader->mutex, NULL) != 0)
goto fail;
fader->signals = signal_handler_create();
if (!fader->signals)
goto fail;
if (!signal_handler_add_array(fader->signals, fader_signals))
if (pthread_mutex_init(&fader->callback_mutex, NULL) != 0)
goto fail;
switch(type) {
@ -465,7 +451,8 @@ void obs_fader_destroy(obs_fader_t *fader)
return;
obs_fader_detach_source(fader);
signal_handler_destroy(fader->signals);
da_free(fader->callbacks);
pthread_mutex_destroy(&fader->callback_mutex);
pthread_mutex_destroy(&fader->mutex);
bfree(fader);
@ -603,9 +590,30 @@ exit:
pthread_mutex_unlock(&fader->mutex);
}
signal_handler_t *obs_fader_get_signal_handler(obs_fader_t *fader)
void obs_fader_add_callback(obs_fader_t *fader, obs_fader_changed_t callback,
void *param)
{
return (fader) ? fader->signals : NULL;
struct fader_cb cb = {callback, param};
if (!obs_ptr_valid(fader, "obs_fader_add_callback"))
return;
pthread_mutex_lock(&fader->callback_mutex);
da_push_back(fader->callbacks, &cb);
pthread_mutex_unlock(&fader->callback_mutex);
}
void obs_fader_remove_callback(obs_fader_t *fader, obs_fader_changed_t callback,
void *param)
{
struct fader_cb cb = {callback, param};
if (!obs_ptr_valid(fader, "obs_fader_remove_callback"))
return;
pthread_mutex_lock(&fader->callback_mutex);
da_erase_item(fader->callbacks, &cb);
pthread_mutex_unlock(&fader->callback_mutex);
}
obs_volmeter_t *obs_volmeter_create(enum obs_fader_type type)
@ -615,12 +623,10 @@ obs_volmeter_t *obs_volmeter_create(enum obs_fader_type type)
return NULL;
pthread_mutex_init_value(&volmeter->mutex);
pthread_mutex_init_value(&volmeter->callback_mutex);
if (pthread_mutex_init(&volmeter->mutex, NULL) != 0)
goto fail;
volmeter->signals = signal_handler_create();
if (!volmeter->signals)
goto fail;
if (!signal_handler_add_array(volmeter->signals, volmeter_signals))
if (pthread_mutex_init(&volmeter->callback_mutex, NULL) != 0)
goto fail;
/* set conversion functions */
@ -658,7 +664,8 @@ void obs_volmeter_destroy(obs_volmeter_t *volmeter)
return;
obs_volmeter_detach_source(volmeter);
signal_handler_destroy(volmeter->signals);
da_free(volmeter->callbacks);
pthread_mutex_destroy(&volmeter->callback_mutex);
pthread_mutex_destroy(&volmeter->mutex);
bfree(volmeter);
@ -678,10 +685,10 @@ bool obs_volmeter_attach_source(obs_volmeter_t *volmeter, obs_source_t *source)
sh = obs_source_get_signal_handler(source);
signal_handler_connect(sh, "volume",
volmeter_source_volume_changed, volmeter);
signal_handler_connect(sh, "audio_data",
volmeter_source_data_received, volmeter);
signal_handler_connect(sh, "destroy",
volmeter_source_destroyed, volmeter);
obs_source_add_audio_capture_callback(source,
volmeter_source_data_received, volmeter);
volmeter->source = source;
volmeter->cur_db = mul_to_db(obs_source_get_volume(source));
@ -706,10 +713,10 @@ void obs_volmeter_detach_source(obs_volmeter_t *volmeter)
sh = obs_source_get_signal_handler(volmeter->source);
signal_handler_disconnect(sh, "volume",
volmeter_source_volume_changed, volmeter);
signal_handler_disconnect(sh, "audio_data",
volmeter_source_data_received, volmeter);
signal_handler_disconnect(sh, "destroy",
volmeter_source_destroyed, volmeter);
obs_source_remove_audio_capture_callback(volmeter->source,
volmeter_source_data_received, volmeter);
volmeter->source = NULL;
@ -717,11 +724,6 @@ exit:
pthread_mutex_unlock(&volmeter->mutex);
}
signal_handler_t *obs_volmeter_get_signal_handler(obs_volmeter_t *volmeter)
{
return (volmeter) ? volmeter->signals : NULL;
}
void obs_volmeter_set_update_interval(obs_volmeter_t *volmeter,
const unsigned int ms)
{
@ -768,3 +770,29 @@ unsigned int obs_volmeter_get_peak_hold(obs_volmeter_t *volmeter)
return peakhold;
}
void obs_volmeter_add_callback(obs_volmeter_t *volmeter,
obs_volmeter_updated_t callback, void *param)
{
struct meter_cb cb = {callback, param};
if (!obs_ptr_valid(volmeter, "obs_volmeter_add_callback"))
return;
pthread_mutex_lock(&volmeter->callback_mutex);
da_push_back(volmeter->callbacks, &cb);
pthread_mutex_unlock(&volmeter->callback_mutex);
}
void obs_volmeter_remove_callback(obs_volmeter_t *volmeter,
obs_volmeter_updated_t callback, void *param)
{
struct meter_cb cb = {callback, param};
if (!obs_ptr_valid(volmeter, "obs_volmeter_remove_callback"))
return;
pthread_mutex_lock(&volmeter->callback_mutex);
da_erase_item(volmeter->callbacks, &cb);
pthread_mutex_unlock(&volmeter->callback_mutex);
}

View file

@ -154,12 +154,12 @@ EXPORT bool obs_fader_attach_source(obs_fader_t *fader, obs_source_t *source);
*/
EXPORT void obs_fader_detach_source(obs_fader_t *fader);
/**
* @brief Get signal handler for the fader
* @param fader pointer to the fader object
* @return signal handler
*/
EXPORT signal_handler_t *obs_fader_get_signal_handler(obs_fader_t *fader);
typedef void (*obs_fader_changed_t)(void *param, float db);
EXPORT void obs_fader_add_callback(obs_fader_t *fader,
obs_fader_changed_t callback, void *param);
EXPORT void obs_fader_remove_callback(obs_fader_t *fader,
obs_fader_changed_t callback, void *param);
/**
* @brief Create a volume meter
@ -251,6 +251,14 @@ EXPORT void obs_volmeter_set_peak_hold(obs_volmeter_t *volmeter,
*/
EXPORT unsigned int obs_volmeter_get_peak_hold(obs_volmeter_t *volmeter);
typedef void (*obs_volmeter_updated_t)(void *param, float level,
float magnitude, float peak, float muted);
EXPORT void obs_volmeter_add_callback(obs_volmeter_t *volmeter,
obs_volmeter_updated_t callback, void *param);
EXPORT void obs_volmeter_remove_callback(obs_volmeter_t *volmeter,
obs_volmeter_updated_t callback, void *param);
#ifdef __cplusplus
}
#endif

View file

@ -485,6 +485,11 @@ struct obs_weak_source {
struct obs_source *source;
};
struct audio_cb_info {
obs_source_audio_capture_t callback;
void *param;
};
struct obs_source {
struct obs_context_data context;
struct obs_source_info info;
@ -542,6 +547,8 @@ struct obs_source {
pthread_mutex_t audio_actions_mutex;
pthread_mutex_t audio_buf_mutex;
pthread_mutex_t audio_mutex;
pthread_mutex_t audio_cb_mutex;
DARRAY(struct audio_cb_info) audio_cb_list;
struct obs_audio_data audio_data;
size_t audio_storage_size;
uint32_t audio_mixers;

View file

@ -65,7 +65,6 @@ static const char *source_signals[] = {
"void update_properties(ptr source)",
"void update_flags(ptr source, int flags)",
"void audio_sync(ptr source, int out int offset)",
"void audio_data(ptr source, ptr data, bool muted)",
"void audio_mixers(ptr source, in out int mixers)",
"void filter_add(ptr source, ptr filter)",
"void filter_remove(ptr source, ptr filter)",
@ -131,6 +130,7 @@ bool obs_source_init(struct obs_source *source)
pthread_mutex_init_value(&source->async_mutex);
pthread_mutex_init_value(&source->audio_mutex);
pthread_mutex_init_value(&source->audio_buf_mutex);
pthread_mutex_init_value(&source->audio_cb_mutex);
if (pthread_mutexattr_init(&attr) != 0)
return false;
@ -142,6 +142,8 @@ bool obs_source_init(struct obs_source *source)
return false;
if (pthread_mutex_init(&source->audio_actions_mutex, NULL) != 0)
return false;
if (pthread_mutex_init(&source->audio_cb_mutex, NULL) != 0)
return false;
if (pthread_mutex_init(&source->audio_mutex, NULL) != 0)
return false;
if (pthread_mutex_init(&source->async_mutex, NULL) != 0)
@ -415,12 +417,14 @@ void obs_source_destroy(struct obs_source *source)
obs_transition_free(source);
da_free(source->audio_actions);
da_free(source->audio_cb_list);
da_free(source->async_cache);
da_free(source->async_frames);
da_free(source->filters);
pthread_mutex_destroy(&source->filter_mutex);
pthread_mutex_destroy(&source->audio_actions_mutex);
pthread_mutex_destroy(&source->audio_buf_mutex);
pthread_mutex_destroy(&source->audio_cb_mutex);
pthread_mutex_destroy(&source->audio_mutex);
pthread_mutex_destroy(&source->async_mutex);
obs_context_data_free(&source->context);
@ -912,17 +916,14 @@ static void handle_ts_jump(obs_source_t *source, uint64_t expected,
static void source_signal_audio_data(obs_source_t *source,
struct audio_data *in, bool muted)
{
struct calldata data;
pthread_mutex_lock(&source->audio_cb_mutex);
calldata_init(&data);
for (size_t i = source->audio_cb_list.num; i > 0; i--) {
struct audio_cb_info info = source->audio_cb_list.array[i - 1];
info.callback(info.param, source, in, muted);
}
calldata_set_ptr(&data, "source", source);
calldata_set_ptr(&data, "data", in);
calldata_set_bool(&data, "muted", muted);
signal_handler_signal(source->context.signals, "audio_data", &data);
calldata_free(&data);
pthread_mutex_unlock(&source->audio_cb_mutex);
}
static inline uint64_t uint64_diff(uint64_t ts1, uint64_t ts2)
@ -3531,3 +3532,29 @@ void obs_source_get_audio_mix(const obs_source_t *source,
}
}
}
void obs_source_add_audio_capture_callback(obs_source_t *source,
obs_source_audio_capture_t callback, void *param)
{
struct audio_cb_info info = {callback, param};
if (!obs_source_valid(source, "obs_source_add_audio_capture_callback"))
return;
pthread_mutex_lock(&source->audio_cb_mutex);
da_push_back(source->audio_cb_list, &info);
pthread_mutex_unlock(&source->audio_cb_mutex);
}
void obs_source_remove_audio_capture_callback(obs_source_t *source,
obs_source_audio_capture_t callback, void *param)
{
struct audio_cb_info info = {callback, param};
if (!obs_source_valid(source, "obs_source_remove_audio_capture_callback"))
return;
pthread_mutex_lock(&source->audio_cb_mutex);
da_erase_item(source->audio_cb_list, &info);
pthread_mutex_unlock(&source->audio_cb_mutex);
}

View file

@ -844,6 +844,14 @@ EXPORT uint64_t obs_source_get_push_to_talk_delay(obs_source_t *source);
EXPORT void obs_source_set_push_to_talk_delay(obs_source_t *source,
uint64_t delay);
typedef void (*obs_source_audio_capture_t)(void *param, obs_source_t *source,
const struct audio_data *audio_data, bool muted);
EXPORT void obs_source_add_audio_capture_callback(obs_source_t *source,
obs_source_audio_capture_t callback, void *param);
EXPORT void obs_source_remove_audio_capture_callback(obs_source_t *source,
obs_source_audio_capture_t callback, void *param);
/* ------------------------------------------------------------------------- */
/* Functions used by sources */

View file

@ -16,26 +16,23 @@
using namespace std;
void VolControl::OBSVolumeChanged(void *data, calldata_t *calldata)
void VolControl::OBSVolumeChanged(void *data, float db)
{
Q_UNUSED(calldata);
Q_UNUSED(db);
VolControl *volControl = static_cast<VolControl*>(data);
QMetaObject::invokeMethod(volControl, "VolumeChanged");
}
void VolControl::OBSVolumeLevel(void *data, calldata_t *calldata)
void VolControl::OBSVolumeLevel(void *data, float level, float mag,
float peak, float muted)
{
VolControl *volControl = static_cast<VolControl*>(data);
float peak = calldata_float(calldata, "level");
float mag = calldata_float(calldata, "magnitude");
float peakHold = calldata_float(calldata, "peak");
bool muted = calldata_bool (calldata, "muted");
QMetaObject::invokeMethod(volControl, "VolumeLevel",
Q_ARG(float, mag),
Q_ARG(float, level),
Q_ARG(float, peak),
Q_ARG(float, peakHold),
Q_ARG(bool, muted));
}
@ -174,11 +171,8 @@ VolControl::VolControl(OBSSource source_, bool showConfig)
setLayout(mainLayout);
signal_handler_connect(obs_fader_get_signal_handler(obs_fader),
"volume_changed", OBSVolumeChanged, this);
signal_handler_connect(obs_volmeter_get_signal_handler(obs_volmeter),
"levels_updated", OBSVolumeLevel, this);
obs_fader_add_callback(obs_fader, OBSVolumeChanged, this);
obs_volmeter_add_callback(obs_volmeter, OBSVolumeLevel, this);
signal_handler_connect(obs_source_get_signal_handler(source),
"mute", OBSVolumeMuted, this);
@ -199,11 +193,8 @@ VolControl::VolControl(OBSSource source_, bool showConfig)
VolControl::~VolControl()
{
signal_handler_disconnect(obs_fader_get_signal_handler(obs_fader),
"volume_changed", OBSVolumeChanged, this);
signal_handler_disconnect(obs_volmeter_get_signal_handler(obs_volmeter),
"levels_updated", OBSVolumeLevel, this);
obs_fader_remove_callback(obs_fader, OBSVolumeChanged, this);
obs_volmeter_remove_callback(obs_volmeter, OBSVolumeLevel, this);
signal_handler_disconnect(obs_source_get_signal_handler(source),
"mute", OBSVolumeMuted, this);

View file

@ -56,8 +56,9 @@ private:
obs_fader_t *obs_fader;
obs_volmeter_t *obs_volmeter;
static void OBSVolumeChanged(void *param, calldata_t *calldata);
static void OBSVolumeLevel(void *data, calldata_t *calldata);
static void OBSVolumeChanged(void *param, float db);
static void OBSVolumeLevel(void *data, float level, float mag,
float peak, float muted);
static void OBSVolumeMuted(void *data, calldata_t *calldata);
void EmitConfigClicked();