Skip to content

Commit c2180a8

Browse files
authored
Change openfx 2d and 3d types to mlt_rect (#1257)
* Implement 2d and 3d types as mlt_rect Testing with the size parameter for CropOFX * Save rect values in metadata as strings There is a bug in mlt_property that interprets a rect structure as data and tries to interpret it as nested properties when traversing the metadata properties. This works around that. * Handle normalized default coordinate values The OFX Crop plugin uses a normalized default but does not report it. This adds a work around to report it for that specific plugin.
1 parent 77b90b7 commit c2180a8

4 files changed

Lines changed: 188 additions & 46 deletions

File tree

src/framework/metaschema.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,6 @@ mapping:
184184
"normalized_coordinates": # For types that represent coordinates, whether values are normalized to 0..1
185185
type: bool
186186
default: no
187-
187+
"normalized_default": # Whether the default value is normalized to 0..1
188+
type: bool
189+
default: no

src/modules/openfx/filter_openfx.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -223,19 +223,31 @@ static void update_plugin_params(mlt_properties properties,
223223
if (!mlt_properties_exists(properties, param_name))
224224
continue;
225225
char *type = mlt_properties_get(param, "type");
226-
char *widget = mlt_properties_get(param, "widget");
227226
if (!type)
228227
continue;
229-
if (widget && (strcmp(widget, "point") == 0 || strcmp(widget, "size") == 0)
230-
&& strcmp(type, "float") == 0) {
228+
if (strcmp(type, "rect") == 0) {
231229
mlt_rect value = mlt_properties_anim_get_rect(properties, param_name, position, length);
232-
mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double2d, value);
233-
} else if (widget && (strcmp(widget, "point") == 0 || strcmp(widget, "size") == 0)
234-
&& strcmp(type, "integer") == 0) {
235-
mlt_rect value = mlt_properties_anim_get_rect(properties, param_name, position, length);
236-
int x = (int) value.x;
237-
int y = (int) value.y;
238-
mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_int2d, x, y);
230+
// Look up the native OFX param type to select the correct setter
231+
mlt_properties ofx_param = mlt_properties_get_properties(image_effect_params,
232+
param_name);
233+
const char *ofx_type = ofx_param ? mlt_properties_get(ofx_param, "t") : NULL;
234+
if (ofx_type && strcmp(ofx_type, kOfxParamTypeInteger2D) == 0)
235+
mltofx_param_set_value(image_effect_params,
236+
param_name,
237+
mltofx_prop_int2d,
238+
(int) value.x,
239+
(int) value.y);
240+
else if (ofx_type && strcmp(ofx_type, kOfxParamTypeDouble3D) == 0)
241+
mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double3d, value);
242+
else if (ofx_type && strcmp(ofx_type, kOfxParamTypeInteger3D) == 0)
243+
mltofx_param_set_value(image_effect_params,
244+
param_name,
245+
mltofx_prop_int3d,
246+
(int) value.x,
247+
(int) value.y,
248+
(int) value.w);
249+
else
250+
mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double2d, value);
239251
} else if (strcmp(type, "float") == 0) {
240252
double value = mlt_properties_anim_get_double(properties, param_name, position, length);
241253
mltofx_param_set_value(image_effect_params, param_name, mltofx_prop_double, value);

src/modules/openfx/mlt_openfx.c

Lines changed: 161 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,8 @@ static OfxStatus paramDefine(OfxParamSetHandle paramSet,
731731
mlt_properties param_props = mlt_properties_new();
732732
mlt_properties_set_properties(pt, "p", param_props);
733733
mlt_properties_close(param_props);
734+
// Back-reference to the paramSet so paramGetValueImpl can navigate to image_effect.
735+
mlt_properties_set_data(pt, "_ps", params, 0, NULL, NULL);
734736
mlt_properties_set_properties(params, name, pt);
735737
mlt_properties_close(pt);
736738

@@ -1039,6 +1041,53 @@ static OfxStatus paramGetValueImpl(OfxParamHandle paramHandle, va_list ap)
10391041
if (status != kOfxStatOK) {
10401042
*X = 0.0;
10411043
*Y = 0.0;
1044+
} else {
1045+
// If the default was declared in normalised coordinates, convert to canonical.
1046+
// kOfxParamPropDefaultCoordinateSystem may be set on the effect descriptor
1047+
// (via getPropertySet) rather than on the individual param descriptor.
1048+
mlt_properties paramset = mlt_properties_get_data(param, "_ps", NULL);
1049+
mlt_properties plugin_props = paramset
1050+
? mlt_properties_get_properties(paramset,
1051+
"plugin_props")
1052+
: NULL;
1053+
mlt_properties ie = plugin_props
1054+
? (mlt_properties) mlt_properties_get_data(plugin_props,
1055+
"_ie",
1056+
NULL)
1057+
: NULL;
1058+
char *coord_sys = kOfxParamCoordinatesCanonical;
1059+
OfxStatus cs_on_param = propGetString((OfxPropertySetHandle) param_props,
1060+
kOfxParamPropDefaultCoordinateSystem,
1061+
0,
1062+
&coord_sys);
1063+
if (cs_on_param != kOfxStatOK) {
1064+
coord_sys = kOfxParamCoordinatesCanonical;
1065+
if (ie) {
1066+
mlt_properties effect_props = mlt_properties_get_properties(ie, "props");
1067+
if (effect_props)
1068+
propGetString((OfxPropertySetHandle) effect_props,
1069+
kOfxParamPropDefaultCoordinateSystem,
1070+
0,
1071+
&coord_sys);
1072+
}
1073+
}
1074+
if (strcmp(coord_sys, kOfxParamCoordinatesNormalised) == 0) {
1075+
if (ie) {
1076+
double ext_w = 0.0, ext_h = 0.0;
1077+
propGetDouble((OfxPropertySetHandle) ie,
1078+
kOfxImageEffectPropProjectExtent,
1079+
0,
1080+
&ext_w);
1081+
propGetDouble((OfxPropertySetHandle) ie,
1082+
kOfxImageEffectPropProjectExtent,
1083+
1,
1084+
&ext_h);
1085+
if (ext_w > 0.0)
1086+
*X *= ext_w;
1087+
if (ext_h > 0.0)
1088+
*Y *= ext_h;
1089+
}
1090+
}
10421091
}
10431092
}
10441093
} else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) {
@@ -2912,6 +2961,9 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti
29122961
mlt_properties_set_properties(image_effect, "params", iparams);
29132962
mlt_properties_set_properties(iparams, "plugin_props", props);
29142963
mlt_properties_set_properties(image_effect, "mltofx_params", params);
2964+
// Back-reference to image_effect stored on plugin_props so paramGetValueImpl
2965+
// can access project extent without disturbing the param iteration loop.
2966+
mlt_properties_set_data(props, "_ie", image_effect, 0, NULL, NULL);
29152967

29162968
propSetString((OfxPropertySetHandle) props,
29172969
kOfxImageEffectPropContext,
@@ -3067,32 +3119,42 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti
30673119
|| strcmp(param_type, kOfxParamTypeRGB) == 0) {
30683120
mlt_properties_set(p, "type", "color");
30693121
mlt_properties_set(p, "widget", "color");
3070-
} else if (strcmp(param_type, kOfxParamTypeDouble2D)
3071-
== 0) { // can be rendered as 2 double number input fields
3072-
mlt_properties_set(p, "type", "float");
3122+
} else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) {
3123+
mlt_properties_set(p, "type", "rect");
30733124

30743125
char *type = kOfxParamDoubleTypeXY;
3075-
char *coordinate_system = kOfxParamCoordinatesCanonical;
30763126
propGetString((OfxPropertySetHandle) ppp, kOfxParamPropDoubleType, 0, &type);
3077-
propGetString((OfxPropertySetHandle) ppp,
3078-
kOfxParamPropDefaultCoordinateSystem,
3079-
0,
3080-
&coordinate_system);
3081-
30823127
if (strcmp(type, kOfxParamDoubleTypeXYAbsolute) == 0) {
30833128
mlt_properties_set(p, "widget", "point");
3129+
mlt_properties_set(p, "normalized_coordinates", "no");
30843130
} else if (strcmp(type, kOfxParamDoubleTypeXY) == 0) {
30853131
mlt_properties_set(p, "widget", "size");
3132+
mlt_properties_set(p, "normalized_coordinates", "no");
30863133
}
30873134

3088-
if (strcmp(coordinate_system, kOfxParamCoordinatesCanonical) == 0) {
3089-
mlt_properties_set(p, "normalized_coordinates", "no");
3090-
} else if (strcmp(coordinate_system, kOfxParamCoordinatesNormalised) == 0) {
3091-
mlt_properties_set(p, "normalized_coordinates", "yes");
3135+
char *default_coords = "";
3136+
OfxStatus status = propGetString((OfxPropertySetHandle) ppp,
3137+
kOfxParamPropDefaultCoordinateSystem,
3138+
0,
3139+
&default_coords);
3140+
if (status == kOfxStatOK) {
3141+
if (!strcmp(default_coords, kOfxParamCoordinatesCanonical)) {
3142+
mlt_properties_set(p, "normalized_default", "no");
3143+
} else if (!strcmp(default_coords, kOfxParamCoordinatesNormalised)) {
3144+
mlt_properties_set(p, "normalized_default", "yes");
3145+
}
3146+
} else if (plugin && plugin->pluginIdentifier
3147+
&& !strcmp("net.sf.openfx.CropPlugin", plugin->pluginIdentifier)) {
3148+
// Workaround for the crop plugin which does not report
3149+
// default coordinates, but uses normalized.
3150+
mlt_properties_set(p, "normalized_default", "yes");
30923151
}
30933152
} else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) {
3094-
// can be rendered as 2 integer number input fields
3095-
mlt_properties_set(p, "type", "integer");
3153+
mlt_properties_set(p, "type", "rect");
3154+
} else if (strcmp(param_type, kOfxParamTypeDouble3D) == 0) {
3155+
mlt_properties_set(p, "type", "rect");
3156+
} else if (strcmp(param_type, kOfxParamTypeInteger3D) == 0) {
3157+
mlt_properties_set(p, "type", "rect");
30963158
}
30973159

30983160
int layout_hint = 0;
@@ -3155,26 +3217,54 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti
31553217
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &default_value);
31563218
mlt_properties_set_double(p, "default", default_value);
31573219
} else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) {
3158-
double default_value1 = 0.0, default_value2 = 0.0;
3159-
3160-
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &default_value1);
3161-
propGetDouble((OfxPropertySetHandle) ppp, p_name, 1, &default_value2);
3162-
3163-
// for some reason with DBL_MIN DBL_MAX it segfault
3164-
if (!isnormal(default_value1) || default_value1 <= FLT_MIN
3165-
|| default_value1 >= FLT_MAX)
3166-
default_value1 = 0.0;
3167-
if (!isnormal(default_value2) || default_value2 <= FLT_MIN
3168-
|| default_value2 >= FLT_MAX)
3169-
default_value2 = 0.0;
3170-
3171-
char default_value[90] = "";
3172-
snprintf(default_value,
3173-
sizeof(default_value),
3174-
"%.4f %.4f",
3175-
default_value1,
3176-
default_value2);
3177-
mlt_properties_set(p, "default", default_value);
3220+
double x = 0.0, y = 0.0;
3221+
3222+
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &x);
3223+
propGetDouble((OfxPropertySetHandle) ppp, p_name, 1, &y);
3224+
3225+
// Validate and sanitize values
3226+
if (!isnormal(x) || x <= FLT_MIN || x >= FLT_MAX)
3227+
x = 0.0;
3228+
if (!isnormal(y) || y <= FLT_MIN || y >= FLT_MAX)
3229+
y = 0.0;
3230+
3231+
char rect_str[100];
3232+
snprintf(rect_str, sizeof(rect_str), "%g %g", x, y);
3233+
mlt_properties_set(p, "default", rect_str);
3234+
3235+
} else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) {
3236+
int ix = 0, iy = 0;
3237+
propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &ix);
3238+
propGetInt((OfxPropertySetHandle) ppp, p_name, 1, &iy);
3239+
char rect_str[100];
3240+
snprintf(rect_str, sizeof(rect_str), "%d %d", ix, iy);
3241+
mlt_properties_set(p, "default", rect_str);
3242+
3243+
} else if (strcmp(param_type, kOfxParamTypeDouble3D) == 0) {
3244+
double x3 = 0.0, y3 = 0.0, z3 = 0.0;
3245+
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &x3);
3246+
propGetDouble((OfxPropertySetHandle) ppp, p_name, 1, &y3);
3247+
propGetDouble((OfxPropertySetHandle) ppp, p_name, 2, &z3);
3248+
if (!isnormal(x3) || x3 <= FLT_MIN || x3 >= FLT_MAX)
3249+
x3 = 0.0;
3250+
if (!isnormal(y3) || y3 <= FLT_MIN || y3 >= FLT_MAX)
3251+
y3 = 0.0;
3252+
if (!isnormal(z3) || z3 <= FLT_MIN || z3 >= FLT_MAX)
3253+
z3 = 0.0;
3254+
// rect.w holds the third dimension
3255+
char rect_str[100];
3256+
snprintf(rect_str, sizeof(rect_str), "%g %g %g", x3, y3, z3);
3257+
mlt_properties_set(p, "default", rect_str);
3258+
3259+
} else if (strcmp(param_type, kOfxParamTypeInteger3D) == 0) {
3260+
int ix = 0, iy = 0, iz = 0;
3261+
propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &ix);
3262+
propGetInt((OfxPropertySetHandle) ppp, p_name, 1, &iy);
3263+
propGetInt((OfxPropertySetHandle) ppp, p_name, 2, &iz);
3264+
// rect.w holds the third dimension
3265+
char rect_str[100];
3266+
snprintf(rect_str, sizeof(rect_str), "%d %d %d", ix, iy, iz);
3267+
mlt_properties_set(p, "default", rect_str);
31783268

31793269
} else if (strcmp(param_type, kOfxParamTypeString) == 0) {
31803270
char *default_value = "";
@@ -3251,6 +3341,16 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti
32513341
double minimum_value = 0.0;
32523342
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value);
32533343
mlt_properties_set_double(p, "minimum", minimum_value);
3344+
} else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) {
3345+
min_set = 1;
3346+
double minimum_value = 0.0;
3347+
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value);
3348+
mlt_properties_set_double(p, "minimum", minimum_value);
3349+
} else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) {
3350+
min_set = 1;
3351+
int minimum_value = 0;
3352+
propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value);
3353+
mlt_properties_set_int(p, "minimum", minimum_value);
32543354
} else if (strcmp(param_type, kOfxParamTypeString) == 0) {
32553355
char *minimum_value = "";
32563356
propGetString((OfxPropertySetHandle) ppp, p_name, 0, &minimum_value);
@@ -3269,6 +3369,16 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti
32693369
double maximum_value = 0.0;
32703370
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value);
32713371
mlt_properties_set_double(p, "maximum", maximum_value);
3372+
} else if (strcmp(param_type, kOfxParamTypeDouble2D) == 0) {
3373+
max_set = 1;
3374+
double maximum_value = 0.0;
3375+
propGetDouble((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value);
3376+
mlt_properties_set_double(p, "maximum", maximum_value);
3377+
} else if (strcmp(param_type, kOfxParamTypeInteger2D) == 0) {
3378+
max_set = 1;
3379+
int maximum_value = 0;
3380+
propGetInt((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value);
3381+
mlt_properties_set_int(p, "maximum", maximum_value);
32723382
} else if (strcmp(param_type, kOfxParamTypeString) == 0) {
32733383
char *maximum_value = "";
32743384
propGetString((OfxPropertySetHandle) ppp, p_name, 0, &maximum_value);
@@ -3353,6 +3463,22 @@ void mltofx_param_set_value(mlt_properties params, char *key, mltofx_property_ty
33533463
propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 1, y);
33543464
} break;
33553465

3466+
case mltofx_prop_double3d: {
3467+
mlt_rect value = va_arg(ap, mlt_rect);
3468+
propSetDouble((OfxPropertySetHandle) param_props, "MltOfxParamValue", 0, value.x);
3469+
propSetDouble((OfxPropertySetHandle) param_props, "MltOfxParamValue", 1, value.y);
3470+
propSetDouble((OfxPropertySetHandle) param_props, "MltOfxParamValue", 2, value.w);
3471+
} break;
3472+
3473+
case mltofx_prop_int3d: {
3474+
int x = va_arg(ap, int);
3475+
int y = va_arg(ap, int);
3476+
int z = va_arg(ap, int);
3477+
propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 0, x);
3478+
propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 1, y);
3479+
propSetInt((OfxPropertySetHandle) param_props, "MltOfxParamValue", 2, z);
3480+
} break;
3481+
33563482
default:
33573483
break;
33583484
}

src/modules/openfx/mlt_openfx.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ typedef enum {
4141
mltofx_prop_color = 32,
4242
mltofx_prop_double2d = 64,
4343
mltofx_prop_int2d = 128,
44+
mltofx_prop_double3d = 256,
45+
mltofx_prop_int3d = 512,
4446
} mltofx_property_type;
4547

4648
typedef enum {

0 commit comments

Comments
 (0)