浏览代码

obs-filters: Add option to undistort ultrawide -> wide

Adds an option to the aspect/scale filter to undistort the center of the
image when scaling from ultrawide to wide.

Closes jp9000/obs-studio#762
Take Vos 8 年之前
父节点
当前提交
9007de70cc
共有 2 个文件被更改,包括 66 次插入6 次删除
  1. 1 0
      plugins/obs-filters/data/locale/en-US.ini
  2. 65 6
      plugins/obs-filters/scale-filter.c

+ 1 - 0
plugins/obs-filters/data/locale/en-US.ini

@@ -7,6 +7,7 @@ ChromaKeyFilter="Chroma Key"
 ColorKeyFilter="Color Key"
 ColorKeyFilter="Color Key"
 SharpnessFilter="Sharpen"
 SharpnessFilter="Sharpen"
 ScaleFilter="Scaling/Aspect Ratio"
 ScaleFilter="Scaling/Aspect Ratio"
+UndistortCenter="Undistort center of image when scaling from ultrawide"
 NoiseGate="Noise Gate"
 NoiseGate="Noise Gate"
 NoiseSuppress="Noise Suppression"
 NoiseSuppress="Noise Suppression"
 Gain="Gain"
 Gain="Gain"

+ 65 - 6
plugins/obs-filters/scale-filter.c

@@ -8,6 +8,7 @@
 
 
 #define S_RESOLUTION                    "resolution"
 #define S_RESOLUTION                    "resolution"
 #define S_SAMPLING                      "sampling"
 #define S_SAMPLING                      "sampling"
+#define S_UNDISTORT                     "undistort"
 
 
 #define T_RESOLUTION                    obs_module_text("Resolution")
 #define T_RESOLUTION                    obs_module_text("Resolution")
 #define T_NONE                          obs_module_text("None")
 #define T_NONE                          obs_module_text("None")
@@ -16,6 +17,7 @@
 #define T_SAMPLING_BILINEAR             obs_module_text("ScaleFiltering.Bilinear")
 #define T_SAMPLING_BILINEAR             obs_module_text("ScaleFiltering.Bilinear")
 #define T_SAMPLING_BICUBIC              obs_module_text("ScaleFiltering.Bicubic")
 #define T_SAMPLING_BICUBIC              obs_module_text("ScaleFiltering.Bicubic")
 #define T_SAMPLING_LANCZOS              obs_module_text("ScaleFiltering.Lanczos")
 #define T_SAMPLING_LANCZOS              obs_module_text("ScaleFiltering.Lanczos")
+#define T_UNDISTORT                     obs_module_text("UndistortCenter")
 
 
 #define S_SAMPLING_POINT                "point"
 #define S_SAMPLING_POINT                "point"
 #define S_SAMPLING_BILINEAR             "bilinear"
 #define S_SAMPLING_BILINEAR             "bilinear"
@@ -27,7 +29,9 @@ struct scale_filter_data {
 	gs_effect_t                     *effect;
 	gs_effect_t                     *effect;
 	gs_eparam_t                     *image_param;
 	gs_eparam_t                     *image_param;
 	gs_eparam_t                     *dimension_param;
 	gs_eparam_t                     *dimension_param;
+	gs_eparam_t                     *undistort_factor_param;
 	struct vec2                     dimension_i;
 	struct vec2                     dimension_i;
+	double                          undistort_factor;
 	int                             cx_in;
 	int                             cx_in;
 	int                             cy_in;
 	int                             cy_in;
 	int                             cx_out;
 	int                             cx_out;
@@ -37,6 +41,7 @@ struct scale_filter_data {
 	bool                            aspect_ratio_only : 1;
 	bool                            aspect_ratio_only : 1;
 	bool                            target_valid : 1;
 	bool                            target_valid : 1;
 	bool                            valid : 1;
 	bool                            valid : 1;
+	bool                            undistort : 1;
 };
 };
 
 
 static const char *scale_filter_name(void *unused)
 static const char *scale_filter_name(void *unused)
@@ -80,6 +85,8 @@ static void scale_filter_update(void *data, obs_data_t *settings)
 	} else { /* S_SAMPLING_BICUBIC */
 	} else { /* S_SAMPLING_BICUBIC */
 		filter->sampling = OBS_SCALE_BICUBIC;
 		filter->sampling = OBS_SCALE_BICUBIC;
 	}
 	}
+
+	filter->undistort = obs_data_get_bool(settings, S_UNDISTORT);
 }
 }
 
 
 static void scale_filter_destroy(void *data)
 static void scale_filter_destroy(void *data)
@@ -146,11 +153,11 @@ static void scale_filter_tick(void *data, float seconds)
 	cx_f = (double)cx;
 	cx_f = (double)cx;
 	cy_f = (double)cy;
 	cy_f = (double)cy;
 
 
-	if (filter->aspect_ratio_only) {
-		double old_aspect = cx_f / cy_f;
-		double new_aspect =
-			(double)filter->cx_in / (double)filter->cy_in;
+	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) {
 		if (fabs(old_aspect - new_aspect) <= EPSILON) {
 			filter->target_valid = false;
 			filter->target_valid = false;
 			return;
 			return;
@@ -172,6 +179,12 @@ static void scale_filter_tick(void *data, float seconds)
 			1.0f / (float)cx,
 			1.0f / (float)cx,
 			1.0f / (float)cy);
 			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;
 	lower_than_2x = filter->cx_out < cx / 2 || filter->cy_out < cy / 2;
@@ -199,12 +212,22 @@ static void scale_filter_tick(void *data, float seconds)
 		filter->dimension_param = NULL;
 		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);
 	UNUSED_PARAMETER(seconds);
 }
 }
 
 
 static void scale_filter_render(void *data, gs_effect_t *effect)
 static void scale_filter_render(void *data, gs_effect_t *effect)
 {
 {
 	struct scale_filter_data *filter = data;
 	struct scale_filter_data *filter = data;
+	const char *technique = filter->undistort ?
+		"DrawUndistort" : "Draw";
 
 
 	if (!filter->valid || !filter->target_valid) {
 	if (!filter->valid || !filter->target_valid) {
 		obs_source_skip_video_filter(filter->context);
 		obs_source_skip_video_filter(filter->context);
@@ -219,12 +242,16 @@ static void scale_filter_render(void *data, gs_effect_t *effect)
 		gs_effect_set_vec2(filter->dimension_param,
 		gs_effect_set_vec2(filter->dimension_param,
 				&filter->dimension_i);
 				&filter->dimension_i);
 
 
+	if (filter->undistort_factor_param)
+		gs_effect_set_float(filter->undistort_factor_param,
+			(float)filter->undistort_factor);
+
 	if (filter->sampling == OBS_SCALE_POINT)
 	if (filter->sampling == OBS_SCALE_POINT)
 		gs_effect_set_next_sampler(filter->image_param,
 		gs_effect_set_next_sampler(filter->image_param,
 				filter->point_sampler);
 				filter->point_sampler);
 
 
-	obs_source_process_filter_end(filter->context, filter->effect,
-			filter->cx_out, filter->cy_out);
+	obs_source_process_filter_tech_end(filter->context, filter->effect,
+			filter->cx_out, filter->cy_out, technique);
 
 
 	UNUSED_PARAMETER(effect);
 	UNUSED_PARAMETER(effect);
 }
 }
@@ -254,6 +281,34 @@ static const char *aspects[] = {
 
 
 #define NUM_ASPECTS (sizeof(aspects) / sizeof(const char *))
 #define NUM_ASPECTS (sizeof(aspects) / sizeof(const char *))
 
 
+static bool sampling_modified(obs_properties_t *props, obs_property_t *p,
+	obs_data_t *settings)
+{
+	const char *sampling = obs_data_get_string(settings, S_SAMPLING);
+
+	bool has_undistort;
+	if (astrcmpi(sampling, S_SAMPLING_POINT) == 0) {
+		has_undistort = false;
+
+	}
+	else if (astrcmpi(sampling, S_SAMPLING_BILINEAR) == 0) {
+		has_undistort = false;
+
+	}
+	else if (astrcmpi(sampling, S_SAMPLING_LANCZOS) == 0) {
+		has_undistort = true;
+
+	}
+	else { /* S_SAMPLING_BICUBIC */
+		has_undistort = true;
+	}
+
+	obs_property_set_visible(obs_properties_get(props, S_UNDISTORT), has_undistort);
+
+	UNUSED_PARAMETER(p);
+	return true;
+}
+
 static obs_properties_t *scale_filter_properties(void *data)
 static obs_properties_t *scale_filter_properties(void *data)
 {
 {
 	obs_properties_t *props = obs_properties_create();
 	obs_properties_t *props = obs_properties_create();
@@ -280,6 +335,7 @@ static obs_properties_t *scale_filter_properties(void *data)
 
 
 	p = obs_properties_add_list(props, S_SAMPLING, T_SAMPLING,
 	p = obs_properties_add_list(props, S_SAMPLING, T_SAMPLING,
 			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
 			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
+	obs_property_set_modified_callback(p, sampling_modified);
 	obs_property_list_add_string(p, T_SAMPLING_POINT,    S_SAMPLING_POINT);
 	obs_property_list_add_string(p, T_SAMPLING_POINT,    S_SAMPLING_POINT);
 	obs_property_list_add_string(p, T_SAMPLING_BILINEAR, S_SAMPLING_BILINEAR);
 	obs_property_list_add_string(p, T_SAMPLING_BILINEAR, S_SAMPLING_BILINEAR);
 	obs_property_list_add_string(p, T_SAMPLING_BICUBIC,  S_SAMPLING_BICUBIC);
 	obs_property_list_add_string(p, T_SAMPLING_BICUBIC,  S_SAMPLING_BICUBIC);
@@ -301,6 +357,8 @@ static obs_properties_t *scale_filter_properties(void *data)
 		obs_property_list_add_string(p, str, str);
 		obs_property_list_add_string(p, str, str);
 	}
 	}
 
 
+	obs_properties_add_bool(props, S_UNDISTORT, T_UNDISTORT);
+
 	/* ----------------- */
 	/* ----------------- */
 
 
 	UNUSED_PARAMETER(data);
 	UNUSED_PARAMETER(data);
@@ -311,6 +369,7 @@ static void scale_filter_defaults(obs_data_t *settings)
 {
 {
 	obs_data_set_default_string(settings, S_SAMPLING, S_SAMPLING_BICUBIC);
 	obs_data_set_default_string(settings, S_SAMPLING, S_SAMPLING_BICUBIC);
 	obs_data_set_default_string(settings, S_RESOLUTION, T_NONE);
 	obs_data_set_default_string(settings, S_RESOLUTION, T_NONE);
+	obs_data_set_default_bool(settings, S_UNDISTORT, 0);
 }
 }
 
 
 static uint32_t scale_filter_width(void *data)
 static uint32_t scale_filter_width(void *data)