From b06a58294325a64adca1e065850a8a2401218429 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Sun, 26 May 2013 22:28:17 -0700 Subject: [PATCH] Add mlt_rect and mlt_properties_set/get_rect. --- src/framework/mlt_properties.c | 46 ++++ src/framework/mlt_properties.h | 3 + src/framework/mlt_property.c | 223 ++++++++++++++++-- src/framework/mlt_property.h | 3 +- src/framework/mlt_types.h | 8 + src/mlt++/MltProperties.cpp | 16 ++ src/mlt++/MltProperties.h | 3 + src/tests/test_properties/test_properties.cpp | 125 ++++++---- 8 files changed, 369 insertions(+), 58 deletions(-) diff --git a/src/framework/mlt_properties.c b/src/framework/mlt_properties.c index e96a1307..156316af 100644 --- a/src/framework/mlt_properties.c +++ b/src/framework/mlt_properties.c @@ -39,6 +39,7 @@ #include #include #include +#include #define PRESETS_DIR "/presets" @@ -2107,3 +2108,48 @@ int mlt_properties_set_int_pos( mlt_properties self, const char *name, int value return error; } +/** Set a property to a rectangle value. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to set + * \param value the rectangle + * \return true if error + */ + +extern int mlt_properties_set_rect( mlt_properties self, const char *name, mlt_rect value ) +{ + int error = 1; + + if ( !self || !name ) return error; + + // Fetch the property to work with + mlt_property property = mlt_properties_fetch( self, name ); + + // Set it if not NULL + if ( property != NULL ) + { + error = mlt_property_set_rect( property, value ); + mlt_properties_do_mirror( self, name ); + } + + mlt_events_fire( self, "property-changed", name, NULL ); + + return error; +} + +/** Get a rectangle associated to the name. + * + * \public \memberof mlt_properties_s + * \param self a properties list + * \param name the property to get + * \return The rectangle value, the rectangle fields will be DBL_MIN if not found + */ + +extern mlt_rect mlt_properties_get_rect( mlt_properties self, const char* name ) +{ + property_list *list = self->local; + mlt_property value = mlt_properties_find( self, name ); + mlt_rect rect = { DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN }; + return value == NULL ? rect : mlt_property_get_rect( value, list->locale ); +} diff --git a/src/framework/mlt_properties.h b/src/framework/mlt_properties.h index 8aaa8a4b..45bbca1b 100644 --- a/src/framework/mlt_properties.h +++ b/src/framework/mlt_properties.h @@ -93,4 +93,7 @@ extern char *mlt_properties_get_time( mlt_properties, const char* name, mlt_time extern int mlt_properties_get_int_pos( mlt_properties self, const char *name, int position, int length ); extern int mlt_properties_set_int_pos( mlt_properties self, const char *name, int value, mlt_keyframe_type keyframe_type, int position, int length ); +extern int mlt_properties_set_rect( mlt_properties self, const char *name, mlt_rect value ); +extern mlt_rect mlt_properties_get_rect( mlt_properties self, const char *name ); + #endif diff --git a/src/framework/mlt_property.c b/src/framework/mlt_property.c index 8604e31f..e86f2f1c 100644 --- a/src/framework/mlt_property.c +++ b/src/framework/mlt_property.c @@ -34,6 +34,7 @@ #include #include #include +#include /** Bit pattern used internally to indicated representations available. @@ -47,7 +48,8 @@ typedef enum mlt_prop_position = 4,//!< set as a position mlt_prop_double = 8, //!< set as a floating point mlt_prop_data = 16, //!< set as opaque binary - mlt_prop_int64 = 32 //!< set as a 64-bit integer + mlt_prop_int64 = 32, //!< set as a 64-bit integer + mlt_prop_rect = 64 //!< set as a mlt_rect } mlt_property_type; @@ -422,6 +424,8 @@ int mlt_property_get_int( mlt_property self, double fps, locale_t locale ) return ( int )self->prop_position; else if ( self->types & mlt_prop_int64 ) return ( int )self->prop_int64; + else if ( self->types & mlt_prop_rect && self->data ) + return ( int ) ( (mlt_rect*) self->data )->x; else if ( ( self->types & mlt_prop_string ) && self->prop_string ) return mlt_property_atoi( self->prop_string, fps, locale ); return 0; @@ -484,6 +488,8 @@ double mlt_property_get_double( mlt_property self, double fps, locale_t locale ) return ( double )self->prop_position; else if ( self->types & mlt_prop_int64 ) return ( double )self->prop_int64; + else if ( self->types & mlt_prop_rect && self->data ) + return ( (mlt_rect*) self->data )->x; else if ( ( self->types & mlt_prop_string ) && self->prop_string ) return mlt_property_atof( self->prop_string, fps, locale ); return 0; @@ -509,6 +515,8 @@ mlt_position mlt_property_get_position( mlt_property self, double fps, locale_t return ( mlt_position )self->prop_double; else if ( self->types & mlt_prop_int64 ) return ( mlt_position )self->prop_int64; + else if ( self->types & mlt_prop_rect && self->data ) + return ( mlt_position ) ( (mlt_rect*) self->data )->x; else if ( ( self->types & mlt_prop_string ) && self->prop_string ) return ( mlt_position )mlt_property_atoi( self->prop_string, fps, locale ); return 0; @@ -549,6 +557,8 @@ int64_t mlt_property_get_int64( mlt_property self ) return ( int64_t )self->prop_double; else if ( self->types & mlt_prop_position ) return ( int64_t )self->prop_position; + else if ( self->types & mlt_prop_rect && self->data ) + return ( int64_t ) ( (mlt_rect*) self->data )->x; else if ( ( self->types & mlt_prop_string ) && self->prop_string ) return mlt_property_atoll( self->prop_string ); return 0; @@ -752,6 +762,16 @@ void mlt_property_pass( mlt_property self, mlt_property that ) if ( that->prop_string != NULL ) self->prop_string = strdup( that->prop_string ); } + else if ( that->types & mlt_prop_rect ) + { + mlt_property_clear( self ); + self->types = mlt_prop_rect | mlt_prop_data; + self->length = that->length; + self->data = calloc( 1, self->length ); + memcpy( self->data, that->data, self->length ); + self->destructor = free; + self->serialiser = that->serialiser; + } else if ( self->types & mlt_prop_data && self->serialiser != NULL ) { self->types = mlt_prop_string; @@ -932,7 +952,8 @@ static int is_property_numeric( mlt_property self, locale_t locale ) int result = ( self->types & mlt_prop_int ) || ( self->types & mlt_prop_int64 ) || ( self->types & mlt_prop_double ) || - ( self->types & mlt_prop_position ); + ( self->types & mlt_prop_position ) || + ( self->types & mlt_prop_rect ); // If not already numeric but string is numeric. if ( ( !result && self->types & mlt_prop_string ) && self->prop_string ) @@ -974,24 +995,96 @@ int mlt_property_interpolate( mlt_property self, mlt_property p[], if ( interp != mlt_keyframe_discrete && is_property_numeric( p[1], locale ) && is_property_numeric( p[2], locale ) ) { - double value; - if ( interp == mlt_keyframe_linear ) + if ( self->types & mlt_prop_rect ) { - double points[2]; - points[0] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0; - points[1] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0; - value = p[2]? linear_interpolate( points[0], points[1], progress ) : points[0]; + mlt_rect value = { DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN }; + if ( interp == mlt_keyframe_linear ) + { + int i = 5; + mlt_rect points[2]; + mlt_rect zero = {0, 0, 0, 0, 0}; + points[0] = p[1]? mlt_property_get_rect( p[1], locale ) : zero; + points[1] = p[2]? mlt_property_get_rect( p[2], locale ) : zero; + while ( i-- ) switch ( i ) + { + case 0: value.x = p[2]? + linear_interpolate( points[0].x, points[1].x, progress ): + points[0].x; + break; + case 1: value.y = p[2]? + linear_interpolate( points[0].y, points[1].y, progress ): + points[0].y; + break; + case 2: value.w = p[2]? + linear_interpolate( points[0].w, points[1].w, progress ): + points[0].w; + break; + case 3: value.h = p[2]? + linear_interpolate( points[0].h, points[1].h, progress ): + points[0].h; + break; + case 4: value.o = p[2]? + linear_interpolate( points[0].o, points[1].o, progress ): + points[0].o; + break; + } + } + else if ( interp == mlt_keyframe_smooth ) + { + int i = 5; + mlt_rect points[4]; + mlt_rect zero = {0, 0, 0, 0, 0}; + points[0] = p[0]? mlt_property_get_rect( p[0], locale ) : zero; + points[1] = p[1]? mlt_property_get_rect( p[1], locale ) : zero; + points[2] = p[2]? mlt_property_get_rect( p[2], locale ) : zero; + points[3] = p[3]? mlt_property_get_rect( p[3], locale ) : zero; + while ( i-- ) switch ( i ) + { + case 0: value.x = p[2]? + catmull_rom_interpolate( points[0].x, points[1].x, points[2].x, points[3].x, progress ): + points[1].x; + break; + case 1: value.y = p[2]? + catmull_rom_interpolate( points[0].y, points[1].y, points[2].y, points[3].y, progress ): + points[1].y; + break; + case 2: value.w = p[2]? + catmull_rom_interpolate( points[0].w, points[1].w, points[2].w, points[3].w, progress ): + points[1].w; + break; + case 3: value.h = p[2]? + catmull_rom_interpolate( points[0].h, points[1].h, points[2].h, points[3].h, progress ): + points[1].h; + break; + case 4: value.o = p[2]? + catmull_rom_interpolate( points[0].o, points[1].o, points[2].o, points[3].o, progress ): + points[1].o; + break; + } + } + error = mlt_property_set_rect( self, value ); } - else if ( interp == mlt_keyframe_smooth ) + else { - double points[4]; - points[0] = p[0]? mlt_property_get_double( p[0], fps, locale ) : 0; - points[1] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0; - points[2] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0; - points[3] = p[3]? mlt_property_get_double( p[3], fps, locale ) : 0; - value = p[2]? catmull_rom_interpolate( points[0], points[1], points[2], points[3], progress ) : points[1]; + double value; + if ( interp == mlt_keyframe_linear ) + { + double points[2]; + points[0] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0; + points[1] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0; + value = p[2]? linear_interpolate( points[0], points[1], progress ) : points[0]; + } + else if ( interp == mlt_keyframe_smooth ) + { + double points[4]; + points[0] = p[0]? mlt_property_get_double( p[0], fps, locale ) : 0; + points[1] = p[1]? mlt_property_get_double( p[1], fps, locale ) : 0; + points[2] = p[2]? mlt_property_get_double( p[2], fps, locale ) : 0; + points[3] = p[3]? mlt_property_get_double( p[3], fps, locale ) : 0; + value = p[2]? catmull_rom_interpolate( points[0], points[1], points[2], points[3], progress ) : points[1]; + } + error = mlt_property_set_double( self, value ); } - error = mlt_property_set_double( self, value ); } else { @@ -1118,3 +1211,101 @@ int mlt_property_set_int_pos( mlt_property self, int value, double fps, locale_t return result; } + +static char* serialise_mlt_rect( mlt_rect *rect, int length ) +{ + char* result = calloc( 1, 100 ); + if ( rect->x != DBL_MIN ) + sprintf( result + strlen( result ), "%g", rect->x ); + if ( rect->y != DBL_MIN ) + sprintf( result + strlen( result ), " %g", rect->y ); + if ( rect->w != DBL_MIN ) + sprintf( result + strlen( result ), " %g", rect->w ); + if ( rect->h != DBL_MIN ) + sprintf( result + strlen( result ), " %g", rect->h ); + if ( rect->o != DBL_MIN ) + sprintf( result + strlen( result ), " %g", rect->o ); + return result; +} + +/** Set a property to a mlt_rect rectangle. + * + * \public \memberof mlt_property_s + * \param self a property + * \param value a mlt_rect + * \return false + */ + +int mlt_property_set_rect( mlt_property self, mlt_rect value ) +{ + pthread_mutex_lock( &self->mutex ); + mlt_property_clear( self ); + self->types = mlt_prop_rect | mlt_prop_data; + self->length = sizeof(value); + self->data = calloc( 1, self->length ); + memcpy( self->data, &value, self->length ); + self->destructor = free; + self->serialiser = (mlt_serialiser) serialise_mlt_rect; + pthread_mutex_unlock( &self->mutex ); + return 0; +} + +/** Get the property as a floating point. + * + * \public \memberof mlt_property_s + * \param self a property + * \param fps frames per second, used when converting from time value + * \param locale the locale to use for this conversion + * \return a rectangle value + */ + +mlt_rect mlt_property_get_rect( mlt_property self, locale_t locale ) +{ + mlt_rect rect = { DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN, DBL_MIN }; + if ( self->types & mlt_prop_rect ) + rect = *( (mlt_rect*) self->data ); + else if ( self->types & mlt_prop_double ) + rect.x = self->prop_double; + else if ( self->types & mlt_prop_int ) + rect.x = ( double )self->prop_int; + else if ( self->types & mlt_prop_position ) + rect.x = ( double )self->prop_position; + else if ( self->types & mlt_prop_int64 ) + rect.x = ( double )self->prop_int64; + else if ( ( self->types & mlt_prop_string ) && self->prop_string ) + { + //return mlt_property_atof( self->prop_string, fps, locale ); + char *value = self->prop_string; + char *p = NULL; + int count = 0; + while ( *value ) + { + double temp; +#if defined(__GLIBC__) || defined(__DARWIN__) + if ( locale ) + temp = strtod_l( value, &p, locale ); +#endif + else + temp = strtod( value, &p ); + if ( p != value ) + { + if ( *p ) p ++; + switch( count ) + { + case 0: rect.x = temp; break; + case 1: rect.y = temp; break; + case 2: rect.w = temp; break; + case 3: rect.h = temp; break; + case 4: rect.o = temp; break; + } + } + else + { + p++; + } + value = p; + count ++; + } + } + return rect; +} diff --git a/src/framework/mlt_property.h b/src/framework/mlt_property.h index 07fe6631..e5203890 100644 --- a/src/framework/mlt_property.h +++ b/src/framework/mlt_property.h @@ -62,5 +62,6 @@ extern int mlt_property_set_double_pos( mlt_property self, double value, double mlt_keyframe_type keyframe_type, int position, int length ); extern int mlt_property_set_int_pos( mlt_property self, int value, double fps, locale_t locale, mlt_keyframe_type keyframe_type, int position, int length ); - +extern int mlt_property_set_rect( mlt_property self, mlt_rect value ); +extern mlt_rect mlt_property_get_rect( mlt_property self, locale_t locale ); #endif diff --git a/src/framework/mlt_types.h b/src/framework/mlt_types.h index 41e42c8d..fbd41900 100644 --- a/src/framework/mlt_types.h +++ b/src/framework/mlt_types.h @@ -123,6 +123,14 @@ typedef double mlt_position; typedef int32_t mlt_position; #endif +typedef struct { + double x; /**< X coordinate */ + double y; /**< Y coordinate */ + double w; /**< width */ + double h; /**< height */ + double o; /**< opacity / mix-level */ +} mlt_rect; + typedef struct mlt_frame_s *mlt_frame, **mlt_frame_ptr; /**< pointer to Frame object */ typedef struct mlt_property_s *mlt_property; /**< pointer to Property object */ typedef struct mlt_properties_s *mlt_properties; /**< pointer to Properties object */ diff --git a/src/mlt++/MltProperties.cpp b/src/mlt++/MltProperties.cpp index 734d2c3b..9657600a 100644 --- a/src/mlt++/MltProperties.cpp +++ b/src/mlt++/MltProperties.cpp @@ -346,3 +346,19 @@ int Properties::set( const char *name, int value, int position, int length, mlt_ { return mlt_properties_set_int_pos( get_properties(), name, value, keyframe_type, position, length ); } + +int Properties::set( const char *name, mlt_rect value ) +{ + return mlt_properties_set_rect( get_properties(), name, value ); +} + +int Properties::set( const char *name, double x, double y, double w, double h, double opacity ) +{ + mlt_rect value = { x, y, w, h, opacity }; + return mlt_properties_set_rect( get_properties(), name, value ); +} + +mlt_rect Properties::get_rect( const char *name ) +{ + return mlt_properties_get_rect( get_properties(), name ); +} diff --git a/src/mlt++/MltProperties.h b/src/mlt++/MltProperties.h index a174708a..d867f67e 100644 --- a/src/mlt++/MltProperties.h +++ b/src/mlt++/MltProperties.h @@ -100,6 +100,9 @@ namespace Mlt int get_int( const char *name, int position, int length ); int set( const char *name, int value, int position, int length, mlt_keyframe_type keyframe_type = mlt_keyframe_linear ); + int set( const char *name, mlt_rect value ); + int set( const char *name, double x, double y, double w, double h, double opacity = 1.0 ); + mlt_rect get_rect( const char* name ); }; } diff --git a/src/tests/test_properties/test_properties.cpp b/src/tests/test_properties/test_properties.cpp index 296b7f35..5ce02287 100644 --- a/src/tests/test_properties/test_properties.cpp +++ b/src/tests/test_properties/test_properties.cpp @@ -27,13 +27,19 @@ extern "C" { #include #include } +#include class TestProperties: public QObject { Q_OBJECT + locale_t locale; public: - TestProperties() {} + TestProperties() { +#if defined(__linux__) || defined(__DARWIN__) + locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); +#endif + } private Q_SLOTS: void InstantiationIsAReference() @@ -313,10 +319,6 @@ private Q_SLOTS: void DoubleAnimation() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_animation a = mlt_animation_new(); struct mlt_animation_item_s item; @@ -354,10 +356,6 @@ private Q_SLOTS: void IntAnimation() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_animation a = mlt_animation_new(); struct mlt_animation_item_s item; @@ -395,10 +393,6 @@ private Q_SLOTS: void AnimationWithTimeValueKeyframes() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_animation a = mlt_animation_new(); struct mlt_animation_item_s item; @@ -436,10 +430,6 @@ private Q_SLOTS: void DiscreteIntAnimation() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_animation a = mlt_animation_new(); struct mlt_animation_item_s item; @@ -484,10 +474,6 @@ private Q_SLOTS: void StringAnimation() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_animation a = mlt_animation_new(); struct mlt_animation_item_s item; @@ -524,10 +510,6 @@ private Q_SLOTS: void test_property_get_double_pos() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_property p = mlt_property_init(); mlt_property_set_string(p, "10=100; 20=200"); @@ -545,10 +527,6 @@ private Q_SLOTS: void test_property_get_int_pos() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_property p = mlt_property_init(); mlt_property_set_string(p, "10=100; 20=200"); @@ -566,10 +544,6 @@ private Q_SLOTS: void SmoothIntAnimation() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_animation a = mlt_animation_new(); struct mlt_animation_item_s item; @@ -614,10 +588,6 @@ private Q_SLOTS: void test_property_set_double_pos() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_property p = mlt_property_init(); mlt_property_set_string(p, "10=100; 20=200"); @@ -633,10 +603,6 @@ private Q_SLOTS: void test_property_set_int_pos() { - locale_t locale; -#if defined(__linux__) || defined(__DARWIN__) - locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL ); -#endif double fps = 25.0; mlt_property p = mlt_property_init(); mlt_property_set_string(p, "10=100; 20=200"); @@ -688,6 +654,83 @@ private Q_SLOTS: QCOMPARE(p.get_int("foo", 25, len), 150); QCOMPARE(p.get_int("foo", 50, len), 200); } + + void test_mlt_rect() + { + mlt_property p = mlt_property_init(); + mlt_rect r = { 1, 2, 3, 4, 5 }; + + mlt_property_set_rect( p, r ); + QCOMPARE(mlt_property_get_string(p), "1 2 3 4 5"); + r.o = DBL_MIN; + mlt_property_set_rect( p, r ); + QCOMPARE(mlt_property_get_string(p), "1 2 3 4"); + r.w = DBL_MIN; + r.h = DBL_MIN; + mlt_property_set_rect( p, r ); + QCOMPARE(mlt_property_get_string(p), "1 2"); + + mlt_property_set_string(p, "1.1/2.2:3.3x4.4:5.5"); + r = mlt_property_get_rect(p, locale); + QCOMPARE(r.x, 1.1); + QCOMPARE(r.y, 2.2); + QCOMPARE(r.w, 3.3); + QCOMPARE(r.h, 4.4); + QCOMPARE(r.o, 5.5); + + mlt_property_set_string(p, "1.1 2.2"); + r = mlt_property_get_rect(p, locale); + QCOMPARE(r.x, 1.1); + QCOMPARE(r.y, 2.2); + QCOMPARE(r.w, DBL_MIN); + + mlt_property_set_int64(p, UINT_MAX); + r = mlt_property_get_rect(p, locale); + QCOMPARE(r.x, double(UINT_MAX)); + + mlt_property_close(p); + } + + void SetAndGetRect() + { + Properties p; + mlt_rect r; + r.x = 1.1; + r.y = 2.2; + r.w = 3.3; + r.h = 4.4; + r.o = 5.5; + p.set("key", r); + mlt_rect q = p.get_rect("key"); + QCOMPARE(q.x, 1.1); + QCOMPARE(q.y, 2.2); + QCOMPARE(q.w, 3.3); + QCOMPARE(q.h, 4.4); + QCOMPARE(q.o, 5.5); + p.set("key", 10, 20, 30, 40); + q = p.get_rect("key"); + QCOMPARE(q.x, 10.0); + QCOMPARE(q.y, 20.0); + QCOMPARE(q.w, 30.0); + QCOMPARE(q.h, 40.0); + } + + void RectFromString() + { + Properties p; + p.set_lcnumeric("POSIX"); + const char *s = "1.1 2.2 3.3 4.4 5.5"; + mlt_rect r = { 1.1, 2.2, 3.3, 4.4, 5.5 }; + p.set("key", r); + QCOMPARE(p.get("key"), s); + p.set("key", s); + r = p.get_rect("key"); + QCOMPARE(r.x, 1.1); + QCOMPARE(r.y, 2.2); + QCOMPARE(r.w, 3.3); + QCOMPARE(r.h, 4.4); + QCOMPARE(r.o, 5.5); + } }; QTEST_APPLESS_MAIN(TestProperties) -- 2.39.2