libobs: Process all scene audio actions if no audio playing

When there are audio sources in a scene and they've all stopped playing
their audio (audio is pending), all scene item audio actions (volume
changes, toggling visibility) will perpetually buffer and no longer be
processed until audio plays again.

So instead of that, if all audio sources have stopped playing in the
scene, just process all pending scene item audio actions immediately to
prevent them from never being processed while waiting for a scene item
to start playing audio.
This commit is contained in:
jp9000 2016-12-22 00:25:23 -08:00
parent 521c40460e
commit e71137534c

View file

@ -741,11 +741,13 @@ static void apply_scene_item_audio_actions(struct obs_scene_item *item,
bool cur_visible = item->visible;
uint64_t frame_num = 0;
size_t deref_count = 0;
float *buf;
float *buf = NULL;
if (!*p_buf)
*p_buf = malloc(AUDIO_OUTPUT_FRAMES * sizeof(float));
buf = *p_buf;
if (p_buf) {
if (!*p_buf)
*p_buf = malloc(AUDIO_OUTPUT_FRAMES * sizeof(float));
buf = *p_buf;
}
pthread_mutex_lock(&item->actions_mutex);
@ -760,7 +762,7 @@ static void apply_scene_item_audio_actions(struct obs_scene_item *item,
new_frame_num = (timestamp - ts) * (uint64_t)sample_rate /
1000000000ULL;
if (new_frame_num >= AUDIO_OUTPUT_FRAMES)
if (ts && new_frame_num >= AUDIO_OUTPUT_FRAMES)
break;
da_erase(item->audio_actions, i--);
@ -769,7 +771,7 @@ static void apply_scene_item_audio_actions(struct obs_scene_item *item,
if (!item->visible)
deref_count++;
if (new_frame_num > frame_num) {
if (buf && new_frame_num > frame_num) {
for (; frame_num < new_frame_num; frame_num++)
buf[frame_num] = cur_visible ? 1.0f : 0.0f;
}
@ -777,8 +779,10 @@ static void apply_scene_item_audio_actions(struct obs_scene_item *item,
cur_visible = item->visible;
}
for (; frame_num < AUDIO_OUTPUT_FRAMES; frame_num++)
buf[frame_num] = cur_visible ? 1.0f : 0.0f;
if (buf) {
for (; frame_num < AUDIO_OUTPUT_FRAMES; frame_num++)
buf[frame_num] = cur_visible ? 1.0f : 0.0f;
}
pthread_mutex_unlock(&item->actions_mutex);
@ -790,7 +794,7 @@ static void apply_scene_item_audio_actions(struct obs_scene_item *item,
}
}
static inline bool apply_scene_item_volume(struct obs_scene_item *item,
static bool apply_scene_item_volume(struct obs_scene_item *item,
float **buf, uint64_t ts, size_t sample_rate)
{
bool actions_pending;
@ -808,7 +812,7 @@ static inline bool apply_scene_item_volume(struct obs_scene_item *item,
uint64_t duration = (uint64_t)AUDIO_OUTPUT_FRAMES *
1000000000ULL / (uint64_t)sample_rate;
if (action.timestamp < (ts + duration)) {
if (!ts || action.timestamp < (ts + duration)) {
apply_scene_item_audio_actions(item, buf, ts,
sample_rate);
return true;
@ -818,6 +822,12 @@ static inline bool apply_scene_item_volume(struct obs_scene_item *item,
return false;
}
static void process_all_audio_actions(struct obs_scene_item *item,
size_t sample_rate)
{
while (apply_scene_item_volume(item, NULL, 0, sample_rate));
}
static void mix_audio_with_buf(float *p_out, float *p_in, float *buf_in,
size_t pos, size_t count)
{
@ -867,6 +877,14 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
}
if (!timestamp) {
/* just process all pending audio actions if no audio playing,
* otherwise audio actions will just never be processed */
item = scene->first_item;
while (item) {
process_all_audio_actions(item, sample_rate);
item = item->next;
}
audio_unlock(scene);
return false;
}