Пример #1
0
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;
	}
}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
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);
}
Пример #5
0
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);
}
Пример #6
0
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(&params, stack, sizeof(stack));
	calldata_set_ptr(&params, "scene", item->parent);
	calldata_set_ptr(&params, "item", item);
	signal_handler_signal(item->parent->source->context.signals,
			"item_transform", &params);
}