static void chroma_key_render(void *data, gs_effect_t *effect) { struct chroma_key_filter_data *filter = data; obs_source_t *target = obs_filter_get_target(filter->context); uint32_t width = obs_source_get_base_width(target); uint32_t height = obs_source_get_base_height(target); struct vec2 pixel_size; obs_source_process_filter_begin(filter->context, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING); vec2_set(&pixel_size, 1.0f / (float)width, 1.0f / (float)height); gs_effect_set_vec4(filter->color_param, &filter->color); gs_effect_set_float(filter->contrast_param, filter->contrast); gs_effect_set_float(filter->brightness_param, filter->brightness); gs_effect_set_float(filter->gamma_param, filter->gamma); gs_effect_set_vec2(filter->chroma_param, &filter->chroma); gs_effect_set_vec4(filter->key_rgb_param, &filter->key_rgb); gs_effect_set_vec2(filter->pixel_size_param, &pixel_size); gs_effect_set_float(filter->similarity_param, filter->similarity); gs_effect_set_float(filter->smoothness_param, filter->smoothness); gs_effect_set_float(filter->spill_param, filter->spill); obs_source_process_filter_end(filter->context, filter->effect, 0, 0); UNUSED_PARAMETER(effect); }
static void calc_crop_dimensions(struct crop_filter_data *filter, struct vec2 *mul_val, struct vec2 *add_val) { obs_source_t *target = obs_filter_get_target(filter->context); uint32_t width; uint32_t height; uint32_t total; if (!target) { width = 0; height = 0; } else { width = obs_source_get_base_width(target); height = obs_source_get_base_height(target); } if (filter->absolute) { uint32_t max_abs_cx = (filter->left + filter->abs_cx); if (max_abs_cx > width) max_abs_cx = width; max_abs_cx -= filter->left; total = max_abs_cx < width ? (width - max_abs_cx) : 0; } else { total = filter->left + filter->right; } filter->width = total > width ? 0 : (width - total); if (filter->absolute) { uint32_t max_abs_cy = (filter->top + filter->abs_cy); if (max_abs_cy > height) max_abs_cy = height; max_abs_cy -= filter->top; total = max_abs_cy < height ? (height - max_abs_cy) : 0; } else { total = filter->top + filter->bottom; } filter->height = total > height ? 0 : (height - total); if (width && filter->width) { mul_val->x = (float)filter->width / (float)width; add_val->x = (float)filter->left / (float)width; } if (height && filter->height) { mul_val->y = (float)filter->height / (float)height; add_val->y = (float)filter->top / (float)height; } }
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); }