static inline void full_lock(struct obs_scene *scene) { video_lock(scene); audio_lock(scene); }
static bool scene_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) { uint64_t timestamp = 0; float *buf = NULL; struct obs_source_audio_mix child_audio; struct obs_scene *scene = data; struct obs_scene_item *item; audio_lock(scene); item = scene->first_item; while (item) { if (!obs_source_audio_pending(item->source)) { uint64_t source_ts = obs_source_get_audio_timestamp(item->source); if (!timestamp || source_ts < timestamp) timestamp = source_ts; } item = item->next; } 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; } item = scene->first_item; while (item) { uint64_t source_ts; size_t pos, count; bool apply_buf; apply_buf = apply_scene_item_volume(item, &buf, timestamp, sample_rate); if (obs_source_audio_pending(item->source)) { item = item->next; continue; } source_ts = obs_source_get_audio_timestamp(item->source); pos = (size_t)ns_to_audio_frames(sample_rate, source_ts - timestamp); count = AUDIO_OUTPUT_FRAMES - pos; if (!apply_buf && !item->visible) { item = item->next; continue; } obs_source_get_audio_mix(item->source, &child_audio); for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) { if ((mixers & (1 << mix)) == 0) continue; for (size_t ch = 0; ch < channels; ch++) { float *out = audio_output->output[mix].data[ch]; float *in = child_audio.output[mix].data[ch]; if (apply_buf) mix_audio_with_buf(out, in, buf, pos, count); else mix_audio(out, in, pos, count); } } item = item->next; } *ts_out = timestamp; audio_unlock(scene); free(buf); return true; }
void audio_sync_start() { audio_signal_callback(); audio_lock(); audio_wait_callback(); }