Exemplo n.º 1
0
static void *color_filter_create(obs_data_t *settings, obs_source_t *context)
{
	struct color_filter_data *filter =
		bzalloc(sizeof(struct color_filter_data));
	char *effect_path = obs_module_file("color_filter.effect");

	filter->context = context;

	obs_enter_graphics();

	filter->effect = gs_effect_create_from_file(effect_path, NULL);
	if (filter) {
		filter->color_param = gs_effect_get_param_by_name(
				filter->effect, "color");
		filter->contrast_param = gs_effect_get_param_by_name(
				filter->effect, "contrast");
		filter->brightness_param = gs_effect_get_param_by_name(
				filter->effect, "brightness");
		filter->gamma_param = gs_effect_get_param_by_name(
				filter->effect, "gamma");
	}

	obs_leave_graphics();

	bfree(effect_path);

	if (!filter->effect) {
		color_filter_destroy(filter);
		return NULL;
	}

	color_filter_update(filter, settings);
	return filter;
}
Exemplo n.º 2
0
static void color_grade_filter_render(void *data, gs_effect_t *effect)
{
	struct lut_filter_data *filter = data;
	obs_source_t *target = obs_filter_get_target(filter->context);
	gs_eparam_t *param;

	if (!target || !filter->target || !filter->effect) {
		obs_source_skip_video_filter(filter->context);
		return;
	}

	if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
				OBS_ALLOW_DIRECT_RENDERING))
		return;

	param = gs_effect_get_param_by_name(filter->effect, "clut");
	gs_effect_set_texture(param, filter->target);

	param = gs_effect_get_param_by_name(filter->effect, "clut_amount");
	gs_effect_set_float(param, filter->clut_amount);

	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);

	UNUSED_PARAMETER(effect);
}
Exemplo n.º 3
0
static void *sharpness_create(obs_data_t *settings, obs_source_t *context)
{
	struct sharpness_data *filter =
		bzalloc(sizeof(struct sharpness_data));
	char *effect_path = obs_module_file("sharpness.effect");

	filter->context = context;

	obs_enter_graphics();

	filter->effect = gs_effect_create_from_file(effect_path, NULL);
	if (filter) {
		filter->sharpness_param = gs_effect_get_param_by_name(
			filter->effect, "sharpness");
		filter->texture_width = gs_effect_get_param_by_name(
			filter->effect, "texture_width");
		filter->texture_height = gs_effect_get_param_by_name(
			filter->effect, "texture_height");
	}

	obs_leave_graphics();

	bfree(effect_path);

	if (!filter->effect) {
		sharpness_destroy(filter);
		return NULL;
	}

	sharpness_update(filter, settings);
	return filter;
}
Exemplo n.º 4
0
static void *crop_filter_create(obs_data_t *settings, obs_source_t *context)
{
	struct crop_filter_data *filter = bzalloc(sizeof(*filter));
	char *effect_path = obs_module_file("crop_filter.effect");

	filter->context = context;

	obs_enter_graphics();
	filter->effect = gs_effect_create_from_file(effect_path, NULL);
	obs_leave_graphics();

	bfree(effect_path);

	if (!filter->effect) {
		bfree(filter);
		return NULL;
	}

	filter->param_mul = gs_effect_get_param_by_name(filter->effect,
			"mul_val");
	filter->param_add = gs_effect_get_param_by_name(filter->effect,
			"add_val");

	obs_source_update(context, settings);
	return filter;
}
Exemplo n.º 5
0
void *fade_create(obs_data_t *settings, obs_source_t *source)
{
    struct fade_info *fade;
    char *file = obs_module_file("fade_transition.effect");
    gs_effect_t *effect;

    obs_enter_graphics();
    effect = gs_effect_create_from_file(file, NULL);
    obs_leave_graphics();
    bfree(file);

    if (!effect) {
        blog(LOG_ERROR, "Could not find fade_transition.effect");
        return NULL;
    }

    fade = bmalloc(sizeof(*fade));
    fade->source = source;
    fade->effect = effect;
    fade->a_param = gs_effect_get_param_by_name(effect, "tex_a");
    fade->b_param = gs_effect_get_param_by_name(effect, "tex_b");
    fade->fade_param = gs_effect_get_param_by_name(effect, "fade_val");

    UNUSED_PARAMETER(settings);
    return fade;
}
Exemplo n.º 6
0
static inline void render_output_texture(struct obs_core_video *video,
		int cur_texture, int prev_texture)
{
	profile_start(render_output_texture_name);

	gs_texture_t *texture = video->render_textures[prev_texture];
	gs_texture_t *target  = video->output_textures[cur_texture];
	uint32_t     width   = gs_texture_get_width(target);
	uint32_t     height  = gs_texture_get_height(target);
	struct vec2  base_i;

	vec2_set(&base_i,
		1.0f / (float)video->base_width,
		1.0f / (float)video->base_height);

	gs_effect_t    *effect  = get_scale_effect(video, width, height);
	gs_technique_t *tech;

	if (video->ovi.output_format == VIDEO_FORMAT_RGBA) {
		tech = gs_effect_get_technique(effect, "Draw");
	} else {
		tech = gs_effect_get_technique(effect, "DrawMatrix");
	}

	gs_eparam_t    *image   = gs_effect_get_param_by_name(effect, "image");
	gs_eparam_t    *matrix  = gs_effect_get_param_by_name(effect,
			"color_matrix");
	gs_eparam_t    *bres_i  = gs_effect_get_param_by_name(effect,
			"base_dimension_i");
	size_t      passes, i;

	if (!video->textures_rendered[prev_texture])
		goto end;

	gs_set_render_target(target, NULL);
	set_render_size(width, height);

	if (bres_i)
		gs_effect_set_vec2(bres_i, &base_i);

	gs_effect_set_val(matrix, video->color_matrix, sizeof(float) * 16);
	gs_effect_set_texture(image, texture);

	gs_enable_blending(false);
	passes = gs_technique_begin(tech);
	for (i = 0; i < passes; i++) {
		gs_technique_begin_pass(tech, i);
		gs_draw_sprite(texture, 0, width, height);
		gs_technique_end_pass(tech);
	}
	gs_technique_end(tech);
	gs_enable_blending(true);

	video->textures_output[cur_texture] = true;

end:
	profile_end(render_output_texture_name);
}
void deinterlace_render(obs_source_t *s)
{
	gs_effect_t *effect = s->deinterlace_effect;

	uint64_t frame2_ts;
	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_eparam_t *prev = gs_effect_get_param_by_name(effect,
			"previous_image");
	gs_eparam_t *field = gs_effect_get_param_by_name(effect, "field_order");
	gs_eparam_t *frame2 = gs_effect_get_param_by_name(effect, "frame2");
	gs_eparam_t *dimensions = gs_effect_get_param_by_name(effect,
			"dimensions");
	struct vec2 size = {(float)s->async_width, (float)s->async_height};
	bool yuv = format_is_yuv(s->async_format);
	bool limited_range = yuv && !s->async_full_range;
	const char *tech = yuv ? "DrawMatrix" : "Draw";

	gs_texture_t *cur_tex = s->async_texrender ?
		gs_texrender_get_texture(s->async_texrender) :
		s->async_texture;
	gs_texture_t *prev_tex = s->async_prev_texrender ?
		gs_texrender_get_texture(s->async_prev_texrender) :
		s->async_prev_texture;

	if (!cur_tex || !prev_tex || !s->async_width || !s->async_height)
		return;

	gs_effect_set_texture(image, cur_tex);
	gs_effect_set_texture(prev, prev_tex);
	gs_effect_set_int(field, s->deinterlace_top_first);
	gs_effect_set_vec2(dimensions, &size);

	if (yuv) {
		gs_eparam_t *color_matrix = gs_effect_get_param_by_name(
				effect, "color_matrix");
		gs_effect_set_val(color_matrix, s->async_color_matrix,
				sizeof(float) * 16);
	}
	if (limited_range) {
		const size_t size = sizeof(float) * 3;
		gs_eparam_t *color_range_min = gs_effect_get_param_by_name(
				effect, "color_range_min");
		gs_eparam_t *color_range_max = gs_effect_get_param_by_name(
				effect, "color_range_max");
		gs_effect_set_val(color_range_min, s->async_color_range_min,
				size);
		gs_effect_set_val(color_range_max, s->async_color_range_max,
				size);
	}

	frame2_ts = s->deinterlace_frame_ts + s->deinterlace_offset +
		s->deinterlace_half_duration - TWOX_TOLERANCE;

	gs_effect_set_bool(frame2, obs->video.video_time >= frame2_ts);

	while (gs_effect_loop(effect, tech))
		gs_draw_sprite(NULL, s->async_flip ? GS_FLIP_V : 0,
				s->async_width, s->async_height);
}
Exemplo n.º 8
0
void XCompcapMain::render(gs_effect_t *effect)
{
	if (!p->win)
		return;

	PLock lock(&p->lock, true);

	effect = obs_get_base_effect(OBS_EFFECT_OPAQUE);

	if (!lock.isLocked() || !p->tex)
		return;

	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_effect_set_texture(image, p->tex);

	while (gs_effect_loop(effect, "Draw")) {
		gs_draw_sprite(p->tex, 0, 0, 0);
	}

	if (p->cursor && p->gltex && p->show_cursor && !p->cursor_outside) {
		effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);

		while (gs_effect_loop(effect, "Draw")) {
			xcursor_render(p->cursor);
		}
	}
}
Exemplo n.º 9
0
static void render_nv12(struct obs_core_video *video, gs_texture_t *target,
		int cur_texture, int prev_texture, const char *tech_name,
		uint32_t width, uint32_t height)
{
	gs_texture_t *texture = video->output_textures[prev_texture];

	gs_effect_t    *effect  = video->conversion_effect;
	gs_eparam_t    *image   = gs_effect_get_param_by_name(effect, "image");
	gs_technique_t *tech    = gs_effect_get_technique(effect, tech_name);
	size_t         passes, i;

	gs_effect_set_texture(image, texture);

	gs_set_render_target(target, NULL);
	set_render_size(width, height);

	gs_enable_blending(false);
	passes = gs_technique_begin(tech);
	for (i = 0; i < passes; i++) {
		gs_technique_begin_pass(tech, i);
		gs_draw_sprite(texture, 0, width, height);
		gs_technique_end_pass(tech);
	}
	gs_technique_end(tech);
	gs_enable_blending(true);
}
Exemplo n.º 10
0
static bool ep_compile_pass_shaderparams(struct effect_parser *ep,
		struct darray *pass_params, struct darray *used_params,
		gs_shader_t *shader)
{
	size_t i;
	darray_resize(sizeof(struct pass_shaderparam), pass_params,
			used_params->num);

	for (i = 0; i < pass_params->num; i++) {
		struct dstr *param_name;
		struct pass_shaderparam *param;

		param_name = darray_item(sizeof(struct dstr), used_params, i);
		param = darray_item(sizeof(struct pass_shaderparam),
				pass_params, i);

		param->eparam = gs_effect_get_param_by_name(ep->effect,
				param_name->array);
		param->sparam = gs_shader_get_param_by_name(shader,
				param_name->array);

		if (!param->sparam) {
			blog(LOG_ERROR, "Effect shader parameter not found");
			return false;
		}
	}

	return true;
}
Exemplo n.º 11
0
void draw_uv_vbuffer(gs_vertbuffer_t *vbuf, gs_texture_t *tex,
		gs_effect_t *effect, uint32_t num_verts)
{
	gs_texture_t   *texture = tex;
	gs_technique_t *tech = gs_effect_get_technique(effect, "Draw");
	gs_eparam_t    *image = gs_effect_get_param_by_name(effect, "image");
	size_t      passes;

	if (vbuf == NULL || tex == NULL) return;

	gs_vertexbuffer_flush(vbuf);
	gs_load_vertexbuffer(vbuf);
	gs_load_indexbuffer(NULL);

	passes = gs_technique_begin(tech);

	for (size_t i = 0; i < passes; i++) {
		if (gs_technique_begin_pass(tech, i)) {
			gs_effect_set_texture(image, texture);

			gs_draw(GS_TRIS, 0, num_verts);

			gs_technique_end_pass(tech);
		}
	}

	gs_technique_end(tech);
}
Exemplo n.º 12
0
static void *chroma_key_create(obs_data_t *settings, obs_source_t *context)
{
	struct chroma_key_filter_data *filter =
		bzalloc(sizeof(struct chroma_key_filter_data));
	char *effect_path = obs_module_file("chroma_key_filter.effect");

	filter->context = context;

	obs_enter_graphics();

	filter->effect = gs_effect_create_from_file(effect_path, NULL);
	if (filter) {
		filter->color_param = gs_effect_get_param_by_name(
				filter->effect, "color");
		filter->contrast_param = gs_effect_get_param_by_name(
				filter->effect, "contrast");
		filter->brightness_param = gs_effect_get_param_by_name(
				filter->effect, "brightness");
		filter->gamma_param = gs_effect_get_param_by_name(
				filter->effect, "gamma");
		filter->chroma_param = gs_effect_get_param_by_name(
				filter->effect, "chroma_key");
		filter->key_rgb_param = gs_effect_get_param_by_name(
				filter->effect, "key_rgb");
		filter->pixel_size_param = gs_effect_get_param_by_name(
				filter->effect, "pixel_size");
		filter->similarity_param = gs_effect_get_param_by_name(
				filter->effect, "similarity");
		filter->smoothness_param = gs_effect_get_param_by_name(
				filter->effect, "smoothness");
		filter->spill_param = gs_effect_get_param_by_name(
				filter->effect, "spill");
	}

	obs_leave_graphics();

	bfree(effect_path);

	if (!filter->effect) {
		chroma_key_destroy(filter);
		return NULL;
	}

	chroma_key_update(filter, settings);
	return filter;
}
Exemplo n.º 13
0
static void render_item_texture(struct obs_scene_item *item)
{
	gs_texture_t *tex = gs_texrender_get_texture(item->item_render);
	gs_effect_t *effect = obs->video.default_effect;
	enum obs_scale_type type = item->scale_filter;
	uint32_t cx = gs_texture_get_width(tex);
	uint32_t cy = gs_texture_get_height(tex);

	if (type != OBS_SCALE_DISABLE) {
		if (type == OBS_SCALE_POINT) {
			gs_eparam_t *image = gs_effect_get_param_by_name(
					effect, "image");
			gs_effect_set_next_sampler(image,
					obs->video.point_sampler);

		} else if (!close_float(item->output_scale.x, 1.0f, EPSILON) ||
		           !close_float(item->output_scale.y, 1.0f, EPSILON)) {
			gs_eparam_t *scale_param;

			if (item->output_scale.x < 0.5f ||
			    item->output_scale.y < 0.5f) {
				effect = obs->video.bilinear_lowres_effect;
			} else if (type == OBS_SCALE_BICUBIC) {
				effect = obs->video.bicubic_effect;
			} else if (type == OBS_SCALE_LANCZOS) {
				effect = obs->video.lanczos_effect;
			}

			scale_param = gs_effect_get_param_by_name(effect,
					"base_dimension_i");
			if (scale_param) {
				struct vec2 base_res_i = {
					1.0f / (float)cx,
					1.0f / (float)cy
				};

				gs_effect_set_vec2(scale_param, &base_res_i);
			}
		}
	}

	while (gs_effect_loop(effect, "Draw"))
		obs_source_draw(tex, 0, 0, 0, 0, 0);
}
Exemplo n.º 14
0
static void image_source_render(void *data, gs_effect_t *effect)
{
    struct image_source *context = data;

    if (!context->image.texture)
        return;

    gs_effect_set_texture(gs_effect_get_param_by_name(effect, "image"),
                          context->image.texture);
    gs_draw_sprite(context->image.texture, 0,
                   context->image.cx, context->image.cy);
}
Exemplo n.º 15
0
static void render_convert_texture(struct obs_core_video *video,
		int cur_texture, int prev_texture)
{
	profile_start(render_convert_texture_name);

	gs_texture_t *texture = video->output_textures[prev_texture];
	gs_texture_t *target  = video->convert_textures[cur_texture];
	float        fwidth  = (float)video->output_width;
	float        fheight = (float)video->output_height;
	size_t       passes, i;

	gs_effect_t    *effect  = video->conversion_effect;
	gs_eparam_t    *image   = gs_effect_get_param_by_name(effect, "image");
	gs_technique_t *tech    = gs_effect_get_technique(effect,
			video->conversion_tech);

	if (!video->textures_output[prev_texture])
		goto end;

	set_eparam(effect, "u_plane_offset", (float)video->plane_offsets[1]);
	set_eparam(effect, "v_plane_offset", (float)video->plane_offsets[2]);
	set_eparam(effect, "width",  fwidth);
	set_eparam(effect, "height", fheight);
	set_eparam(effect, "width_i",  1.0f / fwidth);
	set_eparam(effect, "height_i", 1.0f / fheight);
	set_eparam(effect, "width_d2",  fwidth  * 0.5f);
	set_eparam(effect, "height_d2", fheight * 0.5f);
	set_eparam(effect, "width_d2_i",  1.0f / (fwidth  * 0.5f));
	set_eparam(effect, "height_d2_i", 1.0f / (fheight * 0.5f));
	set_eparam(effect, "input_height", (float)video->conversion_height);

	gs_effect_set_texture(image, texture);

	gs_set_render_target(target, NULL);
	set_render_size(video->output_width, video->conversion_height);

	gs_enable_blending(false);
	passes = gs_technique_begin(tech);
	for (i = 0; i < passes; i++) {
		gs_technique_begin_pass(tech, i);
		gs_draw_sprite(texture, 0, video->output_width,
				video->conversion_height);
		gs_technique_end_pass(tech);
	}
	gs_technique_end(tech);
	gs_enable_blending(true);

	video->textures_converted[cur_texture] = true;

end:
	profile_end(render_convert_texture_name);
}
Exemplo n.º 16
0
void xcursor_render(xcursor_t *data) {
	gs_effect_t *effect  = gs_get_effect();
	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_effect_set_texture(image, data->tex);

	gs_matrix_push();
	gs_matrix_translate3f(data->render_x, data->render_y, 0.0f);

	gs_enable_blending(True);
	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
	gs_draw_sprite(data->tex, 0, 0, 0);

	gs_matrix_pop();
}
Exemplo n.º 17
0
void BrowserSource::Impl::RenderCurrentTexture(gs_effect_t *effect)
{
	GetParent()->LockTexture();

	if (activeTexture != nullptr) {
		gs_reset_blend_state();
		gs_effect_set_texture(
				gs_effect_get_param_by_name(effect, "image"),
				activeTexture);
		gs_draw_sprite(activeTexture, 0, parent->GetWidth(), 
				parent->GetHeight());
	}
	
	GetParent()->UnlockTexture();
}
Exemplo n.º 18
0
void xcursor_render(xcursor_t *data) {
	/* TODO: why do i need effects ? */
	gs_effect_t effect  = gs_get_effect();
	gs_eparam_t image = gs_effect_get_param_by_name(effect, "image");

	gs_effect_set_texture(image, data->tex);

	gs_matrix_push();

	gs_matrix_translate3f(-data->pos_x, -data->pos_y, 0);

	gs_enable_blending(True);
	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
	gs_draw_sprite(data->tex, 0, 0, 0);

	gs_matrix_pop();
}
Exemplo n.º 19
0
void XCompcapMain::render(gs_effect_t *effect)
{
	PLock lock(&p->lock, true);

	if (!lock.isLocked() || !p->tex)
		return;

	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_effect_set_texture(image, p->tex);

	gs_enable_blending(false);
	gs_draw_sprite(p->tex, 0, 0, 0);

	if (p->cursor && p->gltex && p->show_cursor && !p->cursor_outside)
		xcursor_render(p->cursor);

	gs_reset_blend_state();
}
Exemplo n.º 20
0
/**
 * Render the capture data
 */
static void xshm_video_render(void *vptr, gs_effect_t effect)
{
	XSHM_DATA(vptr);

	if (!data->xshm)
		return;

	gs_eparam_t image = gs_effect_get_param_by_name(effect, "image");
	gs_effect_set_texture(image, data->texture);

	gs_enable_blending(false);
	gs_draw_sprite(data->texture, 0, 0, 0);

	if (data->show_cursor)
		xcursor_render(data->cursor);

	gs_reset_blend_state();
}
Exemplo n.º 21
0
static void draw_texture(struct dc_capture *capture, gs_effect_t *effect)
{
	gs_texture_t   *texture = capture->texture;
	gs_technique_t *tech    = gs_effect_get_technique(effect, "Draw");
	gs_eparam_t    *image   = gs_effect_get_param_by_name(effect, "image");
	size_t      passes;

	gs_effect_set_texture(image, texture);

	passes = gs_technique_begin(tech);
	for (size_t i = 0; i < passes; i++) {
		if (gs_technique_begin_pass(tech, i)) {
			if (capture->compatibility)
				gs_draw_sprite(texture, GS_FLIP_V, 0, 0);
			else
				gs_draw_sprite(texture, 0, 0, 0);

			gs_technique_end_pass(tech);
		}
	}
	gs_technique_end(tech);
}
Exemplo n.º 22
0
/**
 * Render the capture data
 */
static void xshm_video_render(void *vptr, gs_effect_t *effect)
{
	XSHM_DATA(vptr);

	effect = obs_get_opaque_effect();

	if (!data->texture)
		return;

	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
	gs_effect_set_texture(image, data->texture);

	while (gs_effect_loop(effect, "Draw")) {
		gs_draw_sprite(data->texture, 0, 0, 0);
	}

	if (data->show_cursor) {
		effect = obs_get_default_effect();

		while (gs_effect_loop(effect, "Draw")) {
			xcb_xcursor_render(data->cursor);
		}
	}
}
/*
 * This function is called (see bottom of this file for more details)
 * whenever the OBS filter interface changes. So when the user is messing
 * with a slider this function is called to update the internal settings
 * in OBS, and hence the settings being passed to the CPU/GPU.
 */
static void color_correction_filter_update(void *data, obs_data_t *settings)
{
	struct color_correction_filter_data *filter = data;

	/* Build our Gamma numbers. */
	double gamma = obs_data_get_double(settings, SETTING_GAMMA);
	gamma = (gamma < 0.0) ? (-gamma + 1.0) : (1.0 / (gamma + 1.0));
	vec3_set(&filter->gamma, (float)gamma, (float)gamma, (float)gamma);

	/* Build our contrast number. */
	filter->contrast = (float)obs_data_get_double(settings,
			SETTING_CONTRAST) + 1.0f;
	float one_minus_con = (1.0f - filter->contrast) / 2.0f;

	/* Now let's build our Contrast matrix. */
	filter->con_matrix = (struct matrix4)
	{
		filter->contrast, 0.0f, 0.0f, 0.0f,
		0.0f, filter->contrast, 0.0f, 0.0f,
		0.0f, 0.0f, filter->contrast, 0.0f,
		one_minus_con, one_minus_con, one_minus_con, 1.0f
	};

	/* Build our brightness number. */
	filter->brightness = (float)obs_data_get_double(settings,
			SETTING_BRIGHTNESS);

	/*
	 * Now let's build our Brightness matrix.
	 * Earlier (in the function color_correction_filter_create) we set
	 * this matrix to the identity matrix, so now we only need
	 * to set the 3 variables that have changed.
	 */
	filter->bright_matrix.t.x = filter->brightness;
	filter->bright_matrix.t.y = filter->brightness;
	filter->bright_matrix.t.z = filter->brightness;

	/* Build our Saturation number. */
	filter->saturation = (float)obs_data_get_double(settings,
			SETTING_SATURATION) + 1.0f;

	/* Factor in the selected color weights. */
	float one_minus_sat = (1.0f - filter->saturation) / 3.0f;
	float sat_val = one_minus_sat + filter->saturation;

	/* Now we build our Saturation matrix. */
	filter->sat_matrix = (struct matrix4)
	{
		sat_val, one_minus_sat, one_minus_sat, 0.0f,
		one_minus_sat, sat_val, one_minus_sat, 0.0f,
		one_minus_sat, one_minus_sat, sat_val, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f
	};

	/* Build our Hue number. */
	filter->hue_shift = (float)obs_data_get_double(settings,
			SETTING_HUESHIFT);

	/* Build our Transparency number. */
	filter->opacity = (float)obs_data_get_int(settings,
			SETTING_OPACITY) * 0.01f;

	/* Hue is the radian of 0 to 360 degrees. */
	float half_angle = 0.5f * (float)(filter->hue_shift / (180.0f / M_PI));

	/* Pseudo-Quaternion To Matrix. */
	float rot_quad1 = root3 * (float)sin(half_angle);
	vec3_set(&filter->rot_quaternion, rot_quad1, rot_quad1,
			rot_quad1);
	filter->rot_quaternion_w = (float)cos(half_angle);

	vec3_mul(&filter->cross, &filter->rot_quaternion,
			&filter->rot_quaternion);
	vec3_mul(&filter->square, &filter->rot_quaternion,
			&filter->rot_quaternion);
	vec3_mulf(&filter->wimag, &filter->rot_quaternion,
			filter->rot_quaternion_w);

	vec3_mulf(&filter->square, &filter->square, 2.0f);
	vec3_sub(&filter->diag, &filter->half_unit, &filter->square);
	vec3_add(&filter->a_line, &filter->cross, &filter->wimag);
	vec3_sub(&filter->b_line, &filter->cross, &filter->wimag);

	/* Now we build our Hue and Opacity matrix. */
	filter->hue_op_matrix = (struct matrix4)
	{
		filter->diag.x * 2.0f,
		filter->b_line.z * 2.0f,
		filter->a_line.y * 2.0f,
		0.0f,

		filter->a_line.z * 2.0f,
		filter->diag.y * 2.0f,
		filter->b_line.x * 2.0f,
		0.0f,

		filter->b_line.y * 2.0f,
		filter->a_line.x * 2.0f,
		filter->diag.z * 2.0f,
		0.0f,

		0.0f, 0.0f, 0.0f, filter->opacity
	};

	/* Now get the overlay color data. */
	uint32_t color = (uint32_t)obs_data_get_int(settings,
			SETTING_COLOR);
	vec4_from_rgba(&filter->color, color);

	/*
	* Now let's build our Color 'overlay' matrix.
	* Earlier (in the function color_correction_filter_create) we set
	* this matrix to the identity matrix, so now we only need
	* to set the 6 variables that have changed.
	*/
	filter->color_matrix.x.x = filter->color.x;
	filter->color_matrix.y.y = filter->color.y;
	filter->color_matrix.z.z = filter->color.z;

	filter->color_matrix.t.x = filter->color.w *
			filter->color.x;
	filter->color_matrix.t.y = filter->color.w *
			filter->color.y;
	filter->color_matrix.t.z = filter->color.w *
			filter->color.z;


	/* First we apply the Contrast & Brightness matrix. */
	matrix4_mul(&filter->final_matrix, &filter->bright_matrix,
			&filter->con_matrix);
	/* Now we apply the Saturation matrix. */
	matrix4_mul(&filter->final_matrix, &filter->final_matrix,
			&filter->sat_matrix);
	/* Next we apply the Hue+Opacity matrix. */
	matrix4_mul(&filter->final_matrix, &filter->final_matrix,
			&filter->hue_op_matrix);
	/* Lastly we apply the Color Wash matrix. */
	matrix4_mul(&filter->final_matrix, &filter->final_matrix,
			&filter->color_matrix);
}

/*
 * Since this is C we have to be careful when destroying/removing items from
 * OBS. Jim has added several useful functions to help keep memory leaks to
 * a minimum, and handle the destruction and construction of these filters.
 */
static void color_correction_filter_destroy(void *data)
{
	struct color_correction_filter_data *filter = data;

	if (filter->effect) {
		obs_enter_graphics();
		gs_effect_destroy(filter->effect);
		obs_leave_graphics();
	}

	bfree(data);
}

/*
 * When you apply a filter OBS creates it, and adds it to the source. OBS also
 * starts rendering it immediately. This function doesn't just 'create' the
 * filter, it also calls the render function (farther below) that contains the
 * actual rendering code.
 */
static void *color_correction_filter_create(obs_data_t *settings,
	obs_source_t *context)
{
	/*
	* Because of limitations of pre-c99 compilers, you can't create an
	* array that doesn't have a known size at compile time. The below
	* function calculates the size needed and allocates memory to
	* handle the source.
	*/
	struct color_correction_filter_data *filter =
		bzalloc(sizeof(struct color_correction_filter_data));

	/*
	 * By default the effect file is stored in the ./data directory that
	 * your filter resides in.
	 */
	char *effect_path = obs_module_file("color_correction_filter.effect");

	filter->context = context;

	/* Set/clear/assign for all necessary vectors. */
	vec3_set(&filter->half_unit, 0.5f, 0.5f, 0.5f);
	matrix4_identity(&filter->bright_matrix);
	matrix4_identity(&filter->color_matrix);

	/* Here we enter the GPU drawing/shader portion of our code. */
	obs_enter_graphics();

	/* Load the shader on the GPU. */
	filter->effect = gs_effect_create_from_file(effect_path, NULL);

	/* If the filter is active pass the parameters to the filter. */
	if (filter->effect) {
		filter->gamma_param = gs_effect_get_param_by_name(
				filter->effect, SETTING_GAMMA);
		filter->final_matrix_param = gs_effect_get_param_by_name(
				filter->effect, "color_matrix");
	}

	obs_leave_graphics();

	bfree(effect_path);

	/*
	 * If the filter has been removed/deactivated, destroy the filter
	 * and exit out so we don't crash OBS by telling it to update
	 * values that don't exist anymore.
	 */
	if (!filter->effect) {
		color_correction_filter_destroy(filter);
		return NULL;
	}

	/*
	 * It's important to call the update function here. If we don't
	 * we could end up with the user controlled sliders and values
	 * updating, but the visuals not updating to match.
	 */
	color_correction_filter_update(filter, settings);
	return filter;
}

/* This is where the actual rendering of the filter takes place. */
static void color_correction_filter_render(void *data, gs_effect_t *effect)
{
	struct color_correction_filter_data *filter = data;

	if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
			OBS_ALLOW_DIRECT_RENDERING))
		return;

	/* Now pass the interface variables to the .effect file. */
	gs_effect_set_vec3(filter->gamma_param, &filter->gamma);
	gs_effect_set_matrix4(filter->final_matrix_param, &filter->final_matrix);

	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);

	UNUSED_PARAMETER(effect);
}

/*
 * This function sets the interface. the types (add_*_Slider), the type of
 * data collected (int), the internal name, user-facing name, minimum,
 * maximum and step values. While a custom interface can be built, for a
 * simple filter like this it's better to use the supplied functions.
 */
static obs_properties_t *color_correction_filter_properties(void *data)
{
	obs_properties_t *props = obs_properties_create();

	obs_properties_add_float_slider(props, SETTING_GAMMA,
			TEXT_GAMMA, -3.0f, 3.0f, 0.01f);

	obs_properties_add_float_slider(props, SETTING_CONTRAST,
			TEXT_CONTRAST, -2.0f, 2.0f, 0.01f);
	obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
			TEXT_BRIGHTNESS, -1.0f, 1.0f, 0.01f);
	obs_properties_add_float_slider(props, SETTING_SATURATION,
			TEXT_SATURATION, -1.0f, 5.0f, 0.01f);
	obs_properties_add_float_slider(props, SETTING_HUESHIFT,
			TEXT_HUESHIFT, -180.0f, 180.0f, 0.01f);
	obs_properties_add_int_slider(props, SETTING_OPACITY,
			TEXT_OPACITY, 0, 100, 1);

	obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR);

	UNUSED_PARAMETER(data);
	return props;
}

/*
 * As the functions' namesake, this provides the default settings for any
 * options you wish to provide a default for. Try to select defaults that
 * make sense to the end user, or that don't effect the data.
 * *NOTE* this function is completely optional, as is providing a default
 * for any particular setting.
 */
static void color_correction_filter_defaults(obs_data_t *settings)
{
	obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
	obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
	obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
	obs_data_set_default_double(settings,
			SETTING_SATURATION, 0.0);
	obs_data_set_default_double(settings, SETTING_HUESHIFT, 0.0);
	obs_data_set_default_double(settings, SETTING_OPACITY, 100.0);
	obs_data_set_default_int(settings, SETTING_COLOR, 0xFFFFFF);
}

/*
 * So how does OBS keep track of all these plug-ins/filters? How does OBS know
 * which function to call when it needs to update a setting? Or a source? Or
 * what type of source this is?
 *
 * OBS does it through the obs_source_info_struct. Notice how variables are
 * assigned the name of a function? Notice how the function name has the
 * variable name in it? While not mandatory, it helps a ton for you (and those
 * reading your code) to follow this convention.
 */
struct obs_source_info color_filter = {
	.id = "color_filter",
	.type = OBS_SOURCE_TYPE_FILTER,
	.output_flags = OBS_SOURCE_VIDEO,
	.get_name = color_correction_filter_name,
	.create = color_correction_filter_create,
	.destroy = color_correction_filter_destroy,
	.video_render = color_correction_filter_render,
	.update = color_correction_filter_update,
	.get_properties = color_correction_filter_properties,
	.get_defaults = color_correction_filter_defaults
};
Exemplo n.º 24
0
static inline void set_eparam(gs_effect_t *effect, const char *name, float val)
{
	gs_eparam_t *param = gs_effect_get_param_by_name(effect, name);
	gs_effect_set_float(param, val);
}
Exemplo n.º 25
0
OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
		QString title, ProjectorType type_)
	: OBSQTDisplay                 (widget,
	                                Qt::Window),
	  source                       (source_),
	  removedSignal                (obs_source_get_signal_handler(source),
	                                "remove", OBSSourceRemoved, this)
{
	projectorTitle = std::move(title);
	savedMonitor   = monitor;
	isWindow       = savedMonitor < 0;
	type           = type_;

	if (isWindow) {
		setWindowIcon(QIcon::fromTheme("obs",
				QIcon(":/res/images/obs.png")));

		UpdateProjectorTitle(projectorTitle);
		windowedProjectors.push_back(this);

		resize(480, 270);
	} else {
		setWindowFlags(Qt::FramelessWindowHint |
				Qt::X11BypassWindowManagerHint);

		QScreen *screen = QGuiApplication::screens()[savedMonitor];
		setGeometry(screen->geometry());

		QAction *action = new QAction(this);
		action->setShortcut(Qt::Key_Escape);
		addAction(action);
		connect(action, SIGNAL(triggered()), this,
				SLOT(EscapeTriggered()));
	}

	SetAlwaysOnTop(this, config_get_bool(GetGlobalConfig(),
			"BasicWindow", "ProjectorAlwaysOnTop"));

	setAttribute(Qt::WA_DeleteOnClose, true);

	//disable application quit when last window closed
	setAttribute(Qt::WA_QuitOnClose, false);

	installEventFilter(CreateShortcutFilter());

	auto addDrawCallback = [this] ()
	{
		bool isMultiview = type == ProjectorType::Multiview;
		obs_display_add_draw_callback(GetDisplay(),
				isMultiview ? OBSRenderMultiview : OBSRender,
				this);
		obs_display_set_background_color(GetDisplay(), 0x000000);
	};

	connect(this, &OBSQTDisplay::DisplayCreated, addDrawCallback);

	bool hideCursor = config_get_bool(GetGlobalConfig(),
			"BasicWindow", "HideProjectorCursor");
	if (hideCursor && !isWindow) {
		QPixmap empty(16, 16);
		empty.fill(Qt::transparent);
		setCursor(QCursor(empty));
	}

	if (type == ProjectorType::Multiview) {
		obs_enter_graphics();

		// All essential action should be placed inside this area
		gs_render_start(true);
		gs_vertex2f(actionSafePercentage, actionSafePercentage);
		gs_vertex2f(actionSafePercentage, 1 - actionSafePercentage);
		gs_vertex2f(1 - actionSafePercentage, 1 - actionSafePercentage);
		gs_vertex2f(1 - actionSafePercentage, actionSafePercentage);
		gs_vertex2f(actionSafePercentage, actionSafePercentage);
		actionSafeMargin = gs_render_save();

		// All graphics should be placed inside this area
		gs_render_start(true);
		gs_vertex2f(graphicsSafePercentage, graphicsSafePercentage);
		gs_vertex2f(graphicsSafePercentage, 1 - graphicsSafePercentage);
		gs_vertex2f(1 - graphicsSafePercentage,
				1 - graphicsSafePercentage);
		gs_vertex2f(1 - graphicsSafePercentage, graphicsSafePercentage);
		gs_vertex2f(graphicsSafePercentage, graphicsSafePercentage);
		graphicsSafeMargin = gs_render_save();

		// 4:3 safe area for widescreen
		gs_render_start(true);
		gs_vertex2f(fourByThreeSafePercentage, graphicsSafePercentage);
		gs_vertex2f(1 - fourByThreeSafePercentage,
				graphicsSafePercentage);
		gs_vertex2f(1 - fourByThreeSafePercentage, 1 -
				graphicsSafePercentage);
		gs_vertex2f(fourByThreeSafePercentage,
				1 - graphicsSafePercentage);
		gs_vertex2f(fourByThreeSafePercentage, graphicsSafePercentage);
		fourByThreeSafeMargin = gs_render_save();

		gs_render_start(true);
		gs_vertex2f(0.0f, 0.5f);
		gs_vertex2f(lineLength, 0.5f);
		leftLine = gs_render_save();

		gs_render_start(true);
		gs_vertex2f(0.5f, 0.0f);
		gs_vertex2f(0.5f, lineLength);
		topLine = gs_render_save();

		gs_render_start(true);
		gs_vertex2f(1.0f, 0.5f);
		gs_vertex2f(1 - lineLength, 0.5f);
		rightLine = gs_render_save();
		obs_leave_graphics();

		solid = obs_get_base_effect(OBS_EFFECT_SOLID);
		color = gs_effect_get_param_by_name(solid, "color");

		UpdateMultiview();

		multiviewProjectors.push_back(this);
	}

	App()->IncrementSleepInhibition();

	if (source)
		obs_source_inc_showing(source);

	ready = true;

	show();

	// We need it here to allow keyboard input in X11 to listen to Escape
	if (!isWindow)
		activateWindow();
}
Exemplo n.º 26
0
static void scale_filter_tick(void *data, float seconds)
{
	struct scale_filter_data *filter = data;
	enum obs_base_effect type;
	obs_source_t *target;
	bool lower_than_2x;
	double cx_f;
	double cy_f;
	int cx;
	int cy;

	if (filter->base_canvas_resolution) {
		struct obs_video_info ovi;
		obs_get_video_info(&ovi);
		filter->cx_in = ovi.base_width;
		filter->cy_in = ovi.base_height;
	}

	target = obs_filter_get_target(filter->context);
	filter->cx_out = 0;
	filter->cy_out = 0;

	filter->target_valid = !!target;
	if (!filter->target_valid)
		return;

	cx = obs_source_get_base_width(target);
	cy = obs_source_get_base_height(target);

	if (!cx || !cy) {
		filter->target_valid = false;
		return;
	}

	filter->cx_out = cx;
	filter->cy_out = cy;

	if (!filter->valid)
		return;

	/* ------------------------- */

	cx_f = (double)cx;
	cy_f = (double)cy;

	double old_aspect = cx_f / cy_f;
	double new_aspect =
		(double)filter->cx_in / (double)filter->cy_in;

	if (filter->aspect_ratio_only) {
		if (fabs(old_aspect - new_aspect) <= EPSILON) {
			filter->target_valid = false;
			return;
		} else {
			if (new_aspect > old_aspect) {
				filter->cx_out = (int)(cy_f * new_aspect);
				filter->cy_out = cy;
			} else {
				filter->cx_out = cx;
				filter->cy_out = (int)(cx_f / new_aspect);
			}
		}
	} else {
		filter->cx_out = filter->cx_in;
		filter->cy_out = filter->cy_in;
	}

	vec2_set(&filter->dimension_i,
			1.0f / (float)cx,
			1.0f / (float)cy);

	if (filter->undistort) {
		filter->undistort_factor = new_aspect / old_aspect;
	} else {
		filter->undistort_factor = 1.0;
	}

	/* ------------------------- */

	lower_than_2x = filter->cx_out < cx / 2 || filter->cy_out < cy / 2;

	if (lower_than_2x && filter->sampling != OBS_SCALE_POINT) {
		type = OBS_EFFECT_BILINEAR_LOWRES;
	} else {
		switch (filter->sampling) {
		default:
		case OBS_SCALE_POINT:
		case OBS_SCALE_BILINEAR: type = OBS_EFFECT_DEFAULT; break;
		case OBS_SCALE_BICUBIC:  type = OBS_EFFECT_BICUBIC; break;
		case OBS_SCALE_LANCZOS:  type = OBS_EFFECT_LANCZOS; break;
		}
	}

	filter->effect = obs_get_base_effect(type);
	filter->image_param = gs_effect_get_param_by_name(filter->effect,
			"image");

	if (type != OBS_EFFECT_DEFAULT) {
		filter->dimension_param = gs_effect_get_param_by_name(
				filter->effect, "base_dimension_i");
	} else {
		filter->dimension_param = NULL;
	}

	if (type == OBS_EFFECT_BICUBIC || type == OBS_EFFECT_LANCZOS) {
		filter->undistort_factor_param = gs_effect_get_param_by_name(
			filter->effect, "undistort_factor");
	}
	else {
		filter->undistort_factor_param = NULL;
	}

	UNUSED_PARAMETER(seconds);
}