static void obs_output_end_data_capture_internal(obs_output_t *output, bool signal) { int ret; if (!obs_output_valid(output, "obs_output_end_data_capture")) return; if (!active(output) || !data_active(output)) { if (signal) { signal_stop(output); output->stop_code = OBS_OUTPUT_SUCCESS; } return; } if (delay_active(output)) { os_atomic_set_bool(&output->delay_capturing, false); if (!os_atomic_load_long(&output->delay_restart_refs)) { os_atomic_set_bool(&output->delay_active, false); } else { os_event_signal(output->stopping_event); return; } } os_atomic_set_bool(&output->data_active, false); if (output->video) log_frame_info(output); if (data_capture_ending(output)) pthread_join(output->end_data_capture_thread, NULL); os_atomic_set_bool(&output->end_data_capture_thread_active, true); ret = pthread_create(&output->end_data_capture_thread, NULL, end_data_capture_thread, output); if (ret != 0) { blog(LOG_WARNING, "Failed to create end_data_capture_thread " "for output '%s'!", output->context.name); end_data_capture_thread(output); } if (signal) { signal_stop(output); output->stop_code = OBS_OUTPUT_SUCCESS; } }
static void set_visibility(struct obs_scene_item *item, bool vis) { pthread_mutex_lock(&item->actions_mutex); da_resize(item->audio_actions, 0); if (os_atomic_load_long(&item->active_refs) > 0) { if (!vis) obs_source_remove_active_child(item->parent->source, item->source); } else if (vis) { obs_source_add_active_child(item->parent->source, item->source); } os_atomic_set_long(&item->active_refs, vis ? 1 : 0); item->visible = vis; item->user_visible = vis; pthread_mutex_unlock(&item->actions_mutex); }
bool obs_output_actual_start(obs_output_t *output) { bool success = false; os_event_wait(output->stopping_event); output->stop_code = 0; if (output->context.data) success = output->info.start(output->context.data); if (success && output->video) { output->starting_frame_count = video_output_get_total_frames(output->video); output->starting_skipped_frame_count = video_output_get_skipped_frames(output->video); output->starting_drawn_count = obs->video.total_frames; output->starting_lagged_count = obs->video.lagged_frames; } if (os_atomic_load_long(&output->delay_restart_refs)) os_atomic_dec_long(&output->delay_restart_refs); return success; }
static void scene_enum_sources(void *data, obs_source_enum_proc_t enum_callback, void *param) { struct obs_scene *scene = data; struct obs_scene_item *item; struct obs_scene_item *next; full_lock(scene); item = scene->first_item; while (item) { next = item->next; obs_sceneitem_addref(item); if (os_atomic_load_long(&item->active_refs) > 0) enum_callback(scene->source, item->source, param); obs_sceneitem_release(item); item = next; } full_unlock(scene); }
static void on_audio_playback(void *param, obs_source_t *source, const struct audio_data *audio_data, bool muted) { struct audio_monitor *monitor = param; IAudioRenderClient *render = monitor->render; uint8_t *resample_data[MAX_AV_PLANES]; float vol = source->user_volume; uint32_t resample_frames; uint64_t ts_offset; bool success; BYTE *output; if (pthread_mutex_trylock(&monitor->playback_mutex) != 0) { return; } if (os_atomic_load_long(&source->activate_refs) == 0) { goto unlock; } success = audio_resampler_resample(monitor->resampler, resample_data, &resample_frames, &ts_offset, (const uint8_t *const *)audio_data->data, (uint32_t)audio_data->frames); if (!success) { goto unlock; } UINT32 pad = 0; monitor->client->lpVtbl->GetCurrentPadding(monitor->client, &pad); bool decouple_audio = source->async_unbuffered && source->async_decoupled; if (monitor->source_has_video && !decouple_audio) { uint64_t ts = audio_data->timestamp - ts_offset; if (!process_audio_delay(monitor, (float**)(&resample_data[0]), &resample_frames, ts, pad)) { goto unlock; } } HRESULT hr = render->lpVtbl->GetBuffer(render, resample_frames, &output); if (FAILED(hr)) { goto unlock; } if (!muted) { /* apply volume */ if (!close_float(vol, 1.0f, EPSILON)) { register float *cur = (float*)resample_data[0]; register float *end = cur + resample_frames * monitor->channels; while (cur < end) *(cur++) *= vol; } memcpy(output, resample_data[0], resample_frames * monitor->channels * sizeof(float)); } render->lpVtbl->ReleaseBuffer(render, resample_frames, muted ? AUDCLNT_BUFFERFLAGS_SILENT : 0); unlock: pthread_mutex_unlock(&monitor->playback_mutex); }
static void update_item_transform(struct obs_scene_item *item) { uint32_t width = obs_source_get_width(item->source); uint32_t height = obs_source_get_height(item->source); uint32_t cx = calc_cx(item, width); uint32_t cy = calc_cy(item, height); struct vec2 base_origin; struct vec2 origin; struct vec2 scale = item->scale; struct calldata params; uint8_t stack[128]; if (os_atomic_load_long(&item->defer_update) > 0) return; width = cx; height = cy; vec2_zero(&base_origin); vec2_zero(&origin); /* ----------------------- */ if (item->bounds_type != OBS_BOUNDS_NONE) { calculate_bounds_data(item, &origin, &scale, &cx, &cy); } else { cx = (uint32_t)((float)cx * scale.x); cy = (uint32_t)((float)cy * scale.y); } add_alignment(&origin, item->align, (int)cx, (int)cy); matrix4_identity(&item->draw_transform); matrix4_scale3f(&item->draw_transform, &item->draw_transform, scale.x, scale.y, 1.0f); matrix4_translate3f(&item->draw_transform, &item->draw_transform, -origin.x, -origin.y, 0.0f); matrix4_rotate_aa4f(&item->draw_transform, &item->draw_transform, 0.0f, 0.0f, 1.0f, RAD(item->rot)); matrix4_translate3f(&item->draw_transform, &item->draw_transform, item->pos.x, item->pos.y, 0.0f); item->output_scale = scale; /* ----------------------- */ if (item->bounds_type != OBS_BOUNDS_NONE) { vec2_copy(&scale, &item->bounds); } else { scale.x = (float)width * item->scale.x; scale.y = (float)height * item->scale.y; } add_alignment(&base_origin, item->align, (int)scale.x, (int)scale.y); matrix4_identity(&item->box_transform); matrix4_scale3f(&item->box_transform, &item->box_transform, scale.x, scale.y, 1.0f); matrix4_translate3f(&item->box_transform, &item->box_transform, -base_origin.x, -base_origin.y, 0.0f); matrix4_rotate_aa4f(&item->box_transform, &item->box_transform, 0.0f, 0.0f, 1.0f, RAD(item->rot)); matrix4_translate3f(&item->box_transform, &item->box_transform, item->pos.x, item->pos.y, 0.0f); /* ----------------------- */ item->last_width = width; item->last_height = height; calldata_init_fixed(¶ms, stack, sizeof(stack)); calldata_set_ptr(¶ms, "scene", item->parent); calldata_set_ptr(¶ms, "item", item); signal_handler_signal(item->parent->source->context.signals, "item_transform", ¶ms); }