static inline void copy_transition_state(obs_source_t *transition, struct transition_state *state) { state->s[0] = transition->transition_sources[0]; state->s[1] = transition->transition_sources[1]; obs_source_addref(state->s[0]); obs_source_addref(state->s[1]); state->transitioning_video = transition->transitioning_video; state->transitioning_audio = transition->transitioning_audio; }
void obs_transition_set(obs_source_t *transition, obs_source_t *source) { obs_source_t *s[2]; bool active[2]; if (!transition_valid(transition, "obs_transition_clear")) return; obs_source_addref(source); lock_transition(transition); for (size_t i = 0; i < 2; i++) { s[i] = transition->transition_sources[i]; active[i] = transition->transition_source_active[i]; transition->transition_sources[i] = NULL; transition->transition_source_active[i] = false; } transition->transition_source_active[0] = true; transition->transition_sources[0] = source; transition->transitioning_video = false; transition->transitioning_audio = false; unlock_transition(transition); for (size_t i = 0; i < 2; i++) { if (s[i] && active[i]) obs_source_remove_active_child(transition, s[i]); obs_source_release(s[i]); } if (source) obs_source_add_active_child(transition, source); }
void obs_source_remove(obs_source_t source) { struct obs_program_data *data = &obs->data; size_t id; pthread_mutex_lock(&data->sources_mutex); if (!source || source->removed) return; source->removed = true; obs_source_addref(source); id = da_find(data->sources, &source, 0); if (id != DARRAY_INVALID) { da_erase_item(data->sources, &source); obs_source_release(source); } pthread_mutex_unlock(&data->sources_mutex); obs_source_dosignal(source, "source-remove"); obs_source_release(source); }
void obs_view_set_source(obs_view_t *view, uint32_t channel, obs_source_t *source) { struct obs_source *prev_source; assert(channel < MAX_CHANNELS); if (!view) return; if (channel >= MAX_CHANNELS) return; pthread_mutex_lock(&view->channels_mutex); obs_source_addref(source); prev_source = view->channels[channel]; view->channels[channel] = source; pthread_mutex_unlock(&view->channels_mutex); if (source) obs_source_activate(source, AUX_VIEW); if (prev_source) { obs_source_deactivate(prev_source, AUX_VIEW); obs_source_release(prev_source); } }
inline OBSSourceRef &operator=(const OBSSourceRef &ref) { obs_source_addref(ref.source); obs_source_release(source); source = ref.source; return *this; }
inline OBSSourceRef &operator=(obs_source_t sourceIn) { obs_source_addref(sourceIn); obs_source_release(source); source = sourceIn; return *this; }
void obs_source_remove(obs_source_t source) { struct obs_core_data *data = &obs->data; size_t id; bool exists; pthread_mutex_lock(&data->sources_mutex); if (!source || source->removed) { pthread_mutex_unlock(&data->sources_mutex); return; } source->removed = true; obs_source_addref(source); id = da_find(data->user_sources, &source, 0); exists = (id != DARRAY_INVALID); if (exists) { da_erase(data->user_sources, id); obs_source_release(source); } pthread_mutex_unlock(&data->sources_mutex); if (exists) obs_source_dosignal(source, "source_remove", "remove"); obs_source_release(source); }
obs_source_t obs_get_output_source(uint32_t channel) { struct obs_source *source; assert(channel < MAX_CHANNELS); source = obs->data.channels[channel]; obs_source_addref(source); return source; }
/* * Ensures that cached frames are displayed on time. If multiple frames * were cached between renders, then releases the unnecessary frames and uses * the frame with the closest timing to ensure sync. */ struct source_frame *obs_source_getframe(obs_source_t source) { uint64_t last_frame_time = source->last_frame_timestamp; struct source_frame *frame = NULL; struct source_frame *next_frame; uint64_t sys_time, frame_time; pthread_mutex_lock(&source->video_mutex); if (!source->video_frames.num) goto unlock; next_frame = source->video_frames.array[0]; sys_time = os_gettime_ns(); frame_time = next_frame->timestamp; if (!source->last_frame_timestamp) { frame = next_frame; da_erase(source->video_frames, 0); source->last_frame_timestamp = frame_time; } else { uint64_t sys_offset, frame_offset; sys_offset = sys_time - source->last_sys_timestamp; frame_offset = frame_time - last_frame_time; source->last_frame_timestamp += sys_offset; while (frame_offset <= sys_offset) { if (frame) source_frame_destroy(frame); frame = next_frame; da_erase(source->video_frames, 0); if (!source->video_frames.num) break; next_frame = source->video_frames.array[0]; frame_time = next_frame->timestamp; frame_offset = frame_time - last_frame_time; } } source->last_sys_timestamp = sys_time; unlock: pthread_mutex_unlock(&source->video_mutex); if (frame != NULL) obs_source_addref(source); return frame; }
static void push_audio_tree(obs_source_t *parent, obs_source_t *source, void *p) { struct obs_core_audio *audio = p; if (da_find(audio->render_order, &source, 0) == DARRAY_INVALID) { obs_source_addref(source); da_push_back(audio->render_order, &source); } UNUSED_PARAMETER(parent); }
obs_source_t obs_display_getsource(obs_display_t display, uint32_t channel) { obs_source_t source; assert(channel < MAX_CHANNELS); source = display->channels[channel]; if (source) obs_source_addref(source); return source; }
static void set_source(obs_source_t *transition, enum obs_transition_target target, obs_source_t *new_child, bool (*callback)(obs_source_t *t, size_t idx, obs_source_t *c)) { size_t idx = (size_t)target; obs_source_t *old_child; bool add_success = true; bool already_active; if (new_child) obs_source_addref(new_child); lock_transition(transition); old_child = transition->transition_sources[idx]; if (new_child == old_child) { unlock_transition(transition); obs_source_release(new_child); return; } already_active = transition->transition_source_active[idx]; if (already_active) { if (new_child) add_success = obs_source_add_active_child(transition, new_child); if (old_child && add_success) obs_source_remove_active_child(transition, old_child); } if (callback && add_success) add_success = callback(transition, idx, new_child); transition->transition_sources[idx] = add_success ? new_child : NULL; unlock_transition(transition); if (add_success) { if (transition->transition_cx == 0 || transition->transition_cy == 0) { recalculate_transition_size(transition); recalculate_transition_matrices(transition); } } else { obs_source_release(new_child); } obs_source_release(old_child); }
void obs_display_setsource(obs_display_t display, uint32_t channel, obs_source_t source) { struct obs_source *prev_source; assert(channel < MAX_CHANNELS); prev_source = display->channels[channel]; display->channels[channel] = source; if (source) obs_source_addref(source); if (prev_source) obs_source_release(prev_source); }
bool obs_add_source(obs_source_t source) { struct calldata params = {0}; pthread_mutex_lock(&obs->data.sources_mutex); da_push_back(obs->data.sources, &source); obs_source_addref(source); pthread_mutex_unlock(&obs->data.sources_mutex); calldata_setptr(¶ms, "source", source); signal_handler_signal(obs->signals, "source-add", ¶ms); calldata_free(¶ms); return true; }
void obs_source_enum_sources(obs_source_t source, obs_source_enum_proc_t enum_callback, void *param) { if (!source || !source->info.enum_sources || source->enum_refs) return; obs_source_addref(source); os_atomic_inc_long(&source->enum_refs); source->info.enum_sources(source->context.data, enum_callback, param); os_atomic_dec_long(&source->enum_refs); obs_source_release(source); }
obs_source_t *obs_transition_get_source(obs_source_t *transition, enum obs_transition_target target) { size_t idx = (size_t)target; obs_source_t *ret; if (!transition_valid(transition, "obs_transition_get_source")) return NULL; lock_transition(transition); ret = transition->transition_sources[idx]; obs_source_addref(ret); unlock_transition(transition); return ret; }
obs_source_t *obs_transition_get_active_source(obs_source_t *transition) { obs_source_t *ret; if (!transition_valid(transition, "obs_transition_get_source")) return NULL; lock_transition(transition); if (transition->transitioning_audio || transition->transitioning_video) ret = transition->transition_sources[1]; else ret = transition->transition_sources[0]; obs_source_addref(ret); unlock_transition(transition); return ret; }
obs_source_t *obs_view_get_source(obs_view_t *view, uint32_t channel) { obs_source_t *source; assert(channel < MAX_CHANNELS); if (!view) return NULL; if (channel >= MAX_CHANNELS) return NULL; pthread_mutex_lock(&view->channels_mutex); source = view->channels[channel]; if (source) obs_source_addref(source); pthread_mutex_unlock(&view->channels_mutex); return source; }
static inline obs_source_t *copy_source_state(obs_source_t *tr_dest, obs_source_t *tr_source, size_t idx) { obs_source_t *old_child = tr_dest->transition_sources[idx]; obs_source_t *new_child = tr_source->transition_sources[idx]; bool active = tr_source->transition_source_active[idx]; if (old_child && tr_dest->transition_source_active[idx]) obs_source_remove_active_child(tr_dest, old_child); tr_dest->transition_sources[idx] = new_child; tr_dest->transition_source_active[idx] = active; if (active && new_child) obs_source_add_active_child(tr_dest, new_child); obs_source_addref(new_child); return old_child; }
obs_source_t obs_get_source_by_name(const char *name) { struct obs_data *data = &obs->data; struct obs_source *source = NULL; size_t i; pthread_mutex_lock(&data->sources_mutex); for (i = 0; i < data->sources.num; i++) { struct obs_source *cur_source = data->sources.array[i]; if (strcmp(cur_source->name, name) == 0) { source = cur_source; obs_source_addref(source); break; } } pthread_mutex_unlock(&data->sources_mutex); return source; }
/* * Ensures that cached frames are displayed on time. If multiple frames * were cached between renders, then releases the unnecessary frames and uses * the frame with the closest timing to ensure sync. Also ensures that timing * with audio is synchronized. */ struct source_frame *obs_source_getframe(obs_source_t source) { struct source_frame *frame = NULL; uint64_t sys_time; if (!source) return NULL; pthread_mutex_lock(&source->video_mutex); if (!source->video_frames.num) goto unlock; sys_time = os_gettime_ns(); if (!source->last_frame_ts) { frame = source->video_frames.array[0]; da_erase(source->video_frames, 0); source->last_frame_ts = frame->timestamp; } else { frame = get_closest_frame(source, sys_time); } /* reset timing to current system time */ if (frame) { source->timing_adjust = sys_time - frame->timestamp; source->timing_set = true; } source->last_sys_timestamp = sys_time; unlock: pthread_mutex_unlock(&source->video_mutex); if (frame) obs_source_addref(source); return frame; }
obs_sceneitem_t obs_scene_add(obs_scene_t scene, obs_source_t source) { struct obs_scene_item *last; struct obs_scene_item *item = bmalloc(sizeof(struct obs_scene_item)); struct calldata params = {0}; memset(item, 0, sizeof(struct obs_scene_item)); item->source = source; item->visible = true; item->parent = scene; item->ref = 1; vec2_set(&item->scale, 1.0f, 1.0f); if (source) obs_source_addref(source); pthread_mutex_lock(&scene->mutex); last = scene->first_item; if (!last) { scene->first_item = item; } else { while (last->next) last = last->next; last->next = item; item->prev = last; } pthread_mutex_unlock(&scene->mutex); calldata_setptr(¶ms, "scene", scene); calldata_setptr(¶ms, "item", item); signal_handler_signal(scene->source->signals, "add", ¶ms); calldata_free(¶ms); return item; }
void obs_set_output_source(uint32_t channel, obs_source_t source) { struct obs_source *prev_source; struct calldata params = {0}; assert(channel < MAX_CHANNELS); prev_source = obs->data.channels[channel]; calldata_setuint32(¶ms, "channel", channel); calldata_setptr(¶ms, "prev_source", prev_source); calldata_setptr(¶ms, "source", source); signal_handler_signal(obs->signals, "channel-change", ¶ms); calldata_getptr(¶ms, "source", &source); calldata_free(¶ms); obs->data.channels[channel] = source; if (source != prev_source) { if (source) obs_source_addref(source); if (prev_source) obs_source_release(prev_source); } }
void obs_set_output_source(uint32_t channel, obs_source_t *source) { assert(channel < MAX_CHANNELS); if (!obs) return; if (channel >= MAX_CHANNELS) return; struct obs_source *prev_source; struct obs_view *view = &obs->data.main_view; struct calldata params = {0}; pthread_mutex_lock(&view->channels_mutex); obs_source_addref(source); prev_source = view->channels[channel]; calldata_set_int(¶ms, "channel", channel); calldata_set_ptr(¶ms, "prev_source", prev_source); calldata_set_ptr(¶ms, "source", source); signal_handler_signal(obs->signals, "channel_change", ¶ms); calldata_get_ptr(¶ms, "source", &source); calldata_free(¶ms); view->channels[channel] = source; pthread_mutex_unlock(&view->channels_mutex); if (source) obs_source_activate(source, MAIN_VIEW); if (prev_source) { obs_source_deactivate(prev_source, MAIN_VIEW); obs_source_release(prev_source); } }
void obs_scene_addref(obs_scene_t scene) { if (scene) obs_source_addref(scene->source); }
inline OBSSourceRef(obs_source_t source) : source(source) { obs_source_addref(source); }
inline OBSSourceRef(const OBSSourceRef &ref) : source(ref.source) { obs_source_addref(source); }