Skip to content

Commit fc626bf

Browse files
authored
Fix avformat, frei0r and openfx metadata (#1220)
* Fix avformat, frei0r and openfx metadata * cleanup yaml numeric id and special numeric * cleanup * Convert scientific notation to fixed-point decimal in YAML * improve scientific to fixed point conversion * clang-format
1 parent ea7e24d commit fc626bf

File tree

4 files changed

+133
-11
lines changed

4 files changed

+133
-11
lines changed

src/framework/mlt_properties.c

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,17 +2156,16 @@ static inline int has_reserved_char(const char *string)
21562156
{
21572157
return strchr(string, ':') || strchr(string, '[') || strchr(string, ']') || strchr(string, '{')
21582158
|| strchr(string, '}') || strchr(string, '\'') || strchr(string, '#')
2159-
|| strchr(string, ',');
2159+
|| strchr(string, ',') || strchr(string, '*');
21602160
}
21612161

2162-
static inline int is_numeric_string(const char *s)
2162+
static inline int is_numeric_identifier(const char *name, const char *s)
21632163
{
2164-
if (*s == '-' || *s == '+')
2165-
s++;
2166-
if (!*s)
2164+
if (strcmp(name, "identifier"))
21672165
return 0;
2166+
21682167
while (*s) {
2169-
if (!isdigit((unsigned char) *s) && *s != '.' && *s != 'e' && *s != 'E')
2168+
if (!isdigit((unsigned char) *s))
21702169
return 0;
21712170
s++;
21722171
}
@@ -2178,6 +2177,63 @@ static inline int is_yaml_keyword(const char *s)
21782177
return !strcmp(s, "null") || !strcmp(s, "~");
21792178
}
21802179

2180+
static inline int is_scientific_notation(const char *s)
2181+
{
2182+
char *end = NULL;
2183+
2184+
if (!s || !*s || !strpbrk(s, "eE"))
2185+
return 0;
2186+
2187+
strtod(s, &end);
2188+
return end != s && *end == '\0';
2189+
}
2190+
2191+
/** Write a scientific notation value as fixed-point decimal for kwalify compatibility.
2192+
*
2193+
* \private \memberof strbuf_s
2194+
* \param output a string buffer
2195+
* \param value a string in scientific notation (e.g. "1e-08")
2196+
*/
2197+
static void strbuf_write_fixed_point(strbuf output, const char *value)
2198+
{
2199+
double d;
2200+
const char *ep = strpbrk(value, "eE");
2201+
int exp = atoi(ep + 1);
2202+
int prec = (exp < 0 ? -exp : 0) + 7;
2203+
char buf[64];
2204+
2205+
#if defined(__GLIBC__) || defined(__APPLE__) \
2206+
|| (defined(__FreeBSD_version) && __FreeBSD_version >= 900506)
2207+
mlt_locale_t c_locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
2208+
mlt_locale_t orig_locale = c_locale ? uselocale(c_locale) : (mlt_locale_t) 0;
2209+
d = strtod(value, NULL);
2210+
snprintf(buf, sizeof(buf), "%.*f", prec, d);
2211+
if (c_locale) {
2212+
uselocale(orig_locale);
2213+
freelocale(c_locale);
2214+
}
2215+
#else
2216+
char *orig_localename = strdup(setlocale(LC_NUMERIC, NULL));
2217+
setlocale(LC_NUMERIC, "C");
2218+
d = strtod(value, NULL);
2219+
snprintf(buf, sizeof(buf), "%.*f", prec, d);
2220+
if (orig_localename) {
2221+
setlocale(LC_NUMERIC, orig_localename);
2222+
free(orig_localename);
2223+
}
2224+
#endif
2225+
2226+
// Strip trailing zeros after decimal point
2227+
if (strchr(buf, '.')) {
2228+
char *end = buf + strlen(buf) - 1;
2229+
while (*end == '0')
2230+
*end-- = '\0';
2231+
if (*end == '.')
2232+
*end = '\0';
2233+
}
2234+
strbuf_printf(output, "%s\n", buf);
2235+
}
2236+
21812237
/** Convert a line string into a YAML block literal.
21822238
*
21832239
* \private \memberof strbuf_s
@@ -2241,11 +2297,13 @@ static void serialise_yaml(mlt_properties self, strbuf output, int indent, int i
22412297
output_yaml_block_literal(output,
22422298
value,
22432299
indent + strlen(name) + strlen("|"));
2300+
} else if (is_scientific_notation(value)) {
2301+
strbuf_write_fixed_point(output, value);
22442302
} else if (has_reserved_char(value) || is_yaml_keyword(value)
2245-
|| (!strcmp(name, "identifier") && is_numeric_string(value))) {
2303+
|| is_numeric_identifier(name, value)) {
22462304
strbuf_printf(output, "\"");
22472305
strbuf_escape(output, value, '"');
2248-
strbuf_printf(output, "\"\n", value);
2306+
strbuf_printf(output, "\"\n");
22492307
} else if (strchr(value, '"')) {
22502308
strbuf_printf(output, "'%s'\n", value);
22512309
} else {
@@ -2280,8 +2338,10 @@ static void serialise_yaml(mlt_properties self, strbuf output, int indent, int i
22802338
if (strchr(value, '\n')) {
22812339
strbuf_printf(output, "|\n");
22822340
output_yaml_block_literal(output, value, indent + strlen(name) + strlen(": "));
2341+
} else if (is_scientific_notation(value)) {
2342+
strbuf_write_fixed_point(output, value);
22832343
} else if (has_reserved_char(value) || is_yaml_keyword(value)
2284-
|| (!strcmp(name, "identifier") && is_numeric_string(value))) {
2344+
|| is_numeric_identifier(name, value)) {
22852345
strbuf_printf(output, "\"");
22862346
strbuf_escape(output, value, '"');
22872347
strbuf_printf(output, "\"\n");

src/modules/frei0r/factory.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ static mlt_properties fill_param_info(mlt_service_type type, const char *service
172172
mlt_properties_set(metadata, "identifier", service_name);
173173
mlt_properties_set(metadata, "description", info.explanation);
174174
mlt_properties_set(metadata, "creator", info.author);
175+
mlt_properties_set(metadata, "language", "en");
175176
switch (type) {
176177
case mlt_service_producer_type:
177178
mlt_properties_set(metadata, "type", "producer");

src/modules/openfx/mlt_openfx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,9 +2146,9 @@ void *mltofx_fetch_params(OfxPlugin *plugin, mlt_properties params, mlt_properti
21462146
}
21472147

21482148
if (strcmp(coordinate_system, kOfxParamCoordinatesCanonical) == 0) {
2149-
mlt_properties_set_int(p, "normalized_coordinates", 0);
2149+
mlt_properties_set(p, "normalized_coordinates", "no");
21502150
} else if (strcmp(coordinate_system, kOfxParamCoordinatesNormalised) == 0) {
2151-
mlt_properties_set_int(p, "normalized_coordinates", 1);
2151+
mlt_properties_set(p, "normalized_coordinates", "yes");
21522152
}
21532153
}
21542154

src/tests/test_properties/test_properties.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,67 @@ private Q_SLOTS:
460460
free(serializedYaml);
461461
}
462462

463+
void SerializesScientificNotationAsFixedPoint()
464+
{
465+
// Negative exponent in a map value
466+
Properties p;
467+
p.set("minimum", "1e-08");
468+
char *yaml = p.serialise_yaml();
469+
QVERIFY(QString(yaml).contains("minimum: 0.00000001\n"));
470+
free(yaml);
471+
472+
// Negative exponent in a sequence value
473+
Properties seq;
474+
Properties child;
475+
child.set("1", "2.5e-3");
476+
seq.set("values", child.get_properties(), 0);
477+
yaml = seq.serialise_yaml();
478+
QVERIFY(QString(yaml).contains(" - 0.0025\n"));
479+
free(yaml);
480+
481+
// Positive exponent should also produce fixed-point
482+
Properties p2;
483+
p2.set("maximum", "1e+02");
484+
yaml = p2.serialise_yaml();
485+
QVERIFY(QString(yaml).contains("maximum: 100\n"));
486+
free(yaml);
487+
488+
// Non-numeric strings that merely start with digits must not be rewritten.
489+
Properties p3;
490+
p3.set("currency", "1euro");
491+
p3.set("example", "1example");
492+
yaml = p3.serialise_yaml();
493+
QVERIFY(QString(yaml).contains("currency: 1euro\n"));
494+
QVERIFY(QString(yaml).contains("example: 1example\n"));
495+
free(yaml);
496+
}
497+
498+
void SerializesScientificNotationUsingCLocale()
499+
{
500+
#if !defined(_WIN32) && (defined(__GLIBC__) || defined(__APPLE__))
501+
mlt_locale_t comma_locale = newlocale(LC_NUMERIC_MASK, "de_DE.UTF-8", NULL);
502+
if (!comma_locale)
503+
comma_locale = newlocale(LC_NUMERIC_MASK, "fr_FR.UTF-8", NULL);
504+
if (!comma_locale)
505+
QSKIP("No locale with comma decimal separator available");
506+
507+
mlt_locale_t orig_locale = uselocale(comma_locale);
508+
509+
Properties p;
510+
p.set("minimum", "1e-08");
511+
char *yaml = p.serialise_yaml();
512+
513+
uselocale(orig_locale);
514+
freelocale(comma_locale);
515+
516+
QVERIFY(QString(yaml).contains("minimum: 0.00000001\n"));
517+
QVERIFY(!QString(yaml).contains(","));
518+
free(yaml);
519+
#else
520+
QSKIP("Thread-local locale switching test not supported on this platform");
521+
#endif
522+
}
523+
463524
void ParsesYamlTiny()
464525
{
465526
QTemporaryFile tempFile;

0 commit comments

Comments
 (0)