提交 4eb5be49 编写于 作者: J jp9000

obs-filters: Fix hard cross-lock when using ducking

上级 bd30a087
......@@ -72,14 +72,15 @@ struct compressor_data {
float envelope;
float slope;
char *sidechain_name;
pthread_mutex_t sidechain_update_mutex;
uint64_t sidechain_check_time;
obs_weak_source_t *weak_sidechain;
char *sidechain_name;
pthread_mutex_t sidechain_mutex;
struct circlebuf sidechain_data[MAX_AUDIO_CHANNELS];
float *sidechain_buf[MAX_AUDIO_CHANNELS];
size_t max_sidechain_frames;
uint64_t sidechain_check_time;
};
/* -------------------------------------------------------- */
......@@ -181,55 +182,6 @@ unlock:
pthread_mutex_unlock(&cd->sidechain_mutex);
}
static inline void swap_sidechain(struct compressor_data *cd, const char *name)
{
obs_source_t *sidechain = name && *name ?
obs_get_source_by_name(name) : NULL;
obs_weak_source_t *weak_sidechain = sidechain ?
obs_source_get_weak_source(sidechain) : NULL;
obs_weak_source_t *cur_weak_sidechain = cd->weak_sidechain;
if (cur_weak_sidechain != weak_sidechain) {
if (cur_weak_sidechain) {
obs_source_t *cur_sidechain =
obs_weak_source_get_source(cd->weak_sidechain);
if (cur_sidechain) {
obs_source_remove_audio_capture_callback(
cur_sidechain,
sidechain_capture, cd);
obs_source_release(cur_sidechain);
}
cd->weak_sidechain = NULL;
obs_weak_source_release(cur_weak_sidechain);
}
if (weak_sidechain) {
obs_source_add_audio_capture_callback(sidechain,
sidechain_capture, cd);
cd->weak_sidechain = weak_sidechain;
obs_source_t *parent = obs_filter_get_parent(
cd->context);
const char *parent_name = obs_source_get_name(parent);
blog(LOG_INFO, "Source '%s' now has sidechain "
"compression from source '%s'",
parent_name, cd->sidechain_name);
}
} else if (weak_sidechain) {
obs_weak_source_release(weak_sidechain);
}
cd->max_sidechain_frames =
cd->sample_rate * DEFAULT_AUDIO_BUF_MS / MS_IN_S;
if (sidechain)
obs_source_release(sidechain);
}
static void compressor_update(void *data, obs_data_t *s)
{
struct compressor_data *cd = data;
......@@ -260,15 +212,51 @@ static void compressor_update(void *data, obs_data_t *s)
bool valid_sidechain =
*sidechain_name && strcmp(sidechain_name, "none") != 0;
obs_weak_source_t *old_weak_sidechain = NULL;
bfree(cd->sidechain_name);
cd->sidechain_name = valid_sidechain ? bstrdup(sidechain_name) : NULL;
pthread_mutex_lock(&cd->sidechain_update_mutex);
if (!valid_sidechain) {
if (cd->weak_sidechain) {
old_weak_sidechain = cd->weak_sidechain;
cd->weak_sidechain = NULL;
}
bfree(cd->sidechain_name);
cd->sidechain_name = NULL;
} else {
if (!cd->sidechain_name ||
strcmp(cd->sidechain_name, sidechain_name) != 0) {
if (cd->weak_sidechain) {
old_weak_sidechain = cd->weak_sidechain;
cd->weak_sidechain = NULL;
}
bfree(cd->sidechain_name);
cd->sidechain_name = bstrdup(sidechain_name);
cd->sidechain_check_time = os_gettime_ns() - 3000000000;
}
}
pthread_mutex_unlock(&cd->sidechain_update_mutex);
if (old_weak_sidechain) {
obs_source_t *old_sidechain =
obs_weak_source_get_source(old_weak_sidechain);
if (old_sidechain) {
obs_source_remove_audio_capture_callback(old_sidechain,
sidechain_capture, cd);
obs_source_release(old_sidechain);
}
obs_weak_source_release(old_weak_sidechain);
}
size_t sample_len = sample_rate * DEFAULT_AUDIO_BUF_MS / MS_IN_S;
if (cd->envelope_buf_len == 0)
resize_env_buffer(cd, sample_len);
swap_sidechain(cd, sidechain_name);
}
static void *compressor_create(obs_data_t *settings, obs_source_t *filter)
......@@ -282,6 +270,13 @@ static void *compressor_create(obs_data_t *settings, obs_source_t *filter)
return NULL;
}
if (pthread_mutex_init(&cd->sidechain_update_mutex, NULL) != 0) {
pthread_mutex_destroy(&cd->sidechain_mutex);
blog(LOG_ERROR, "Failed to create mutex");
bfree(cd);
return NULL;
}
compressor_update(cd, settings);
return cd;
}
......@@ -306,6 +301,7 @@ static void compressor_destroy(void *data)
bfree(cd->sidechain_buf[i]);
}
pthread_mutex_destroy(&cd->sidechain_mutex);
pthread_mutex_destroy(&cd->sidechain_update_mutex);
bfree(cd->sidechain_name);
bfree(cd->envelope_buf);
......@@ -392,27 +388,65 @@ static inline void process_compression(const struct compressor_data *cd,
}
}
static struct obs_audio_data *compressor_filter_audio(void *data,
struct obs_audio_data *audio)
static void compressor_tick(void *data, float seconds)
{
struct compressor_data *cd = data;
char *new_name = NULL;
const uint32_t num_samples = audio->frames;
float **samples = (float**)audio->data;
pthread_mutex_lock(&cd->sidechain_update_mutex);
if (cd->sidechain_name && !cd->weak_sidechain) {
uint64_t t = os_gettime_ns();
if (t - cd->sidechain_check_time > 3000000000) {
swap_sidechain(cd, cd->sidechain_name);
new_name = bstrdup(cd->sidechain_name);
cd->sidechain_check_time = t;
}
}
pthread_mutex_unlock(&cd->sidechain_update_mutex);
if (new_name) {
obs_source_t *sidechain = new_name && *new_name ?
obs_get_source_by_name(new_name) : NULL;
obs_weak_source_t *weak_sidechain = sidechain ?
obs_source_get_weak_source(sidechain) : NULL;
pthread_mutex_lock(&cd->sidechain_update_mutex);
if (cd->sidechain_name &&
strcmp(cd->sidechain_name, new_name) == 0) {
cd->weak_sidechain = weak_sidechain;
weak_sidechain = NULL;
}
if (!cd->weak_sidechain)
return audio;
pthread_mutex_unlock(&cd->sidechain_update_mutex);
if (sidechain) {
obs_source_add_audio_capture_callback(sidechain,
sidechain_capture, cd);
obs_weak_source_release(weak_sidechain);
obs_source_release(sidechain);
}
bfree(new_name);
}
}
if (cd->weak_sidechain)
static struct obs_audio_data *compressor_filter_audio(void *data,
struct obs_audio_data *audio)
{
struct compressor_data *cd = data;
const uint32_t num_samples = audio->frames;
float **samples = (float**)audio->data;
pthread_mutex_lock(&cd->sidechain_update_mutex);
obs_weak_source_t *weak_sidechain = cd->weak_sidechain;
pthread_mutex_unlock(&cd->sidechain_update_mutex);
if (weak_sidechain)
analyze_sidechain(cd, num_samples);
else
analyze_envelope(cd, samples, num_samples);
......@@ -493,6 +527,7 @@ struct obs_source_info compressor_filter = {
.destroy = compressor_destroy,
.update = compressor_update,
.filter_audio = compressor_filter_audio,
.video_tick = compressor_tick,
.get_defaults = compressor_defaults,
.get_properties = compressor_properties,
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册