]> git.sesse.net Git - mlt/commitdiff
Add mlt_properties_set/get_rect_pos for rect animation.
authorDan Dennedy <dan@dennedy.org>
Mon, 27 May 2013 19:10:44 +0000 (12:10 -0700)
committerDan Dennedy <dan@dennedy.org>
Fri, 31 May 2013 23:58:12 +0000 (16:58 -0700)
src/framework/mlt_animation.c
src/framework/mlt_properties.c
src/framework/mlt_properties.h
src/framework/mlt_property.c
src/framework/mlt_property.h
src/mlt++/MltProperties.cpp
src/mlt++/MltProperties.h
src/tests/test_properties/test_properties.cpp

index b0791bd8dac0e7c8a23d69a7257c92b06b85b75e..32cdb1d9adbd96dd1d74ee7b9f8db58c4c328eb3 100644 (file)
@@ -221,8 +221,15 @@ int mlt_animation_parse_item( mlt_animation self, mlt_animation_item item, const
                        else
                        {
                                // Parse an absolute time value.
-                               mlt_property_set_string( item->property, value );
+                               // Null terminate the string at the equal sign to prevent interpreting
+                               // a colon in the part to the right of the equal sign as indicative of a
+                               // a time value string.
+                               char *s = strdup( value );
+                               p = strchr( s, '=' );
+                               p[0] = '\0';
+                               mlt_property_set_string( item->property, s );
                                item->frame = mlt_property_get_int( item->property, self->fps, self->locale );
+                               free( s );
                        }
 
                        // The character preceeding the equal sign indicates interpolation method.
index 156316af7f624574365b5a47c6402bf914b200c8..63efda3a0a27746d3f914ae448cd200dc45b58c7 100644 (file)
@@ -2153,3 +2153,54 @@ extern mlt_rect mlt_properties_get_rect( mlt_properties self, const char* 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 );
 }
+
+/** Set a property to a rectangle value at a frame position.
+ *
+ * \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_pos( mlt_properties self, const char *name, mlt_rect value, mlt_keyframe_type keyframe_type, int position, int length )
+{
+       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 )
+       {
+               mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+               double fps = mlt_profile_fps( profile );
+               property_list *list = self->local;
+               error = mlt_property_set_rect_pos( property, value, fps, list->locale, keyframe_type, position, length );
+               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_pos( mlt_properties self, const char *name, int position, int length )
+{
+       mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+       double fps = mlt_profile_fps( profile );
+       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_pos( value, fps, list->locale, position, length );
+}
index 45bbca1b751b31dbe82359583ab71054ded9f8db..5832ccfa8b6ec3a8b19c152ce7866526be277e7b 100644 (file)
@@ -96,4 +96,7 @@ extern int mlt_properties_set_int_pos( mlt_properties self, const char *name, in
 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 );
 
+extern int mlt_properties_set_rect_pos( mlt_properties self, const char *name, mlt_rect value, mlt_keyframe_type keyframe_type, int position, int length );
+extern mlt_rect mlt_properties_get_rect_pos( mlt_properties self, const char *name, int position, int length );
+
 #endif
index e86f2f1c1e332a081f15e2d89b478cecacb17f48..4fe9f4a9e52562648e197b86f13d1941d6cf3ce6 100644 (file)
@@ -463,7 +463,7 @@ static double mlt_property_atof( const char *value, double fps, locale_t locale
 #endif
                else
                        result = strtod( value, &end );
-               if ( *end && end[0] == '%' )
+               if ( end && end[0] == '%' )
                        result /= 100.0;
                return result;
        }
@@ -1000,66 +1000,42 @@ int mlt_property_interpolate( mlt_property self, mlt_property p[],
                        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 )
+                               if ( p[2] )
                                {
-                                       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;
+                                       points[1] = mlt_property_get_rect( p[2], locale );
+                                       value.x = linear_interpolate( points[0].x, points[1].x, progress );
+                                       value.y = linear_interpolate( points[0].y, points[1].y, progress );
+                                       value.w = linear_interpolate( points[0].w, points[1].w, progress );
+                                       value.h = linear_interpolate( points[0].h, points[1].h, progress );
+                                       value.o = linear_interpolate( points[0].o, points[1].o, progress );
+                               }
+                               else
+                               {
+                                       value = points[0];
                                }
                        }
                        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 )
+                               if ( p[2] )
+                               {
+                                       points[0] = p[0]? mlt_property_get_rect( p[0], 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;
+                                       value.x = catmull_rom_interpolate( points[0].x, points[1].x, points[2].x, points[3].x, progress );
+                                       value.y = catmull_rom_interpolate( points[0].y, points[1].y, points[2].y, points[3].y, progress );
+                                       value.w = catmull_rom_interpolate( points[0].w, points[1].w, points[2].w, points[3].w, progress );
+                                       value.h = catmull_rom_interpolate( points[0].h, points[1].h, points[2].h, points[3].h, progress );
+                                       value.o = catmull_rom_interpolate( points[0].o, points[1].o, points[2].o, points[3].o, progress );
+                               }
+                               else
                                {
-                                       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;
+                                       value = points[1];
                                }
                        }
                        error = mlt_property_set_rect( self, value );
@@ -1289,6 +1265,8 @@ mlt_rect mlt_property_get_rect( mlt_property self, locale_t locale )
                                temp = strtod( value, &p );
                        if ( p != value )
                        {
+                               if ( p[0] == '%' )
+                                       temp /= 100.0;
                                if ( *p ) p ++;
                                switch( count )
                                {
@@ -1309,3 +1287,52 @@ mlt_rect mlt_property_get_rect( mlt_property self, locale_t locale )
        }
        return rect;
 }
+
+/** Set a property animation keyframe to a rectangle.
+ *
+ * \public \memberof mlt_property_s
+ * \param self a property
+ * \param value a rectangle
+ * \return false if successful, true to indicate error
+ */
+
+int mlt_property_set_rect_pos( mlt_property self, mlt_rect value, double fps, locale_t locale,
+       mlt_keyframe_type keyframe_type, int position, int length )
+{
+       int result;
+       struct mlt_animation_item_s item;
+
+       item.property = mlt_property_init();
+       item.frame = position;
+       item.keyframe_type = keyframe_type;
+       mlt_property_set_rect( item.property, value );
+
+       refresh_animation( self, fps, locale, length );
+       result = mlt_animation_insert( self->animation, &item );
+       mlt_animation_interpolate( self->animation );
+       mlt_property_close( item.property );
+
+       return result;
+}
+
+mlt_rect mlt_property_get_rect_pos( mlt_property self, double fps, locale_t locale, int position, int length )
+{
+       mlt_rect result;
+       if ( self->animation || ( ( self->types & mlt_prop_string ) && self->prop_string ) )
+       {
+               struct mlt_animation_item_s item;
+               item.property = mlt_property_init();
+               item.property->types = mlt_prop_rect;
+
+               refresh_animation( self, fps, locale, length );
+               mlt_animation_get_item( self->animation, &item, position );
+               result = mlt_property_get_rect( item.property, locale );
+
+               mlt_property_close( item.property );
+       }
+       else
+       {
+               result = mlt_property_get_rect( self, locale );
+       }
+       return result;
+}
index e520389022b80c5a0057e823ad59f51696f55149..af0501f1d44e51bb83bafec127cd226667868b03 100644 (file)
@@ -64,4 +64,8 @@ extern int mlt_property_set_int_pos( mlt_property self, int value, double fps, l
                                      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 );
+extern int mlt_property_set_rect_pos( mlt_property self, mlt_rect value, double fps, locale_t locale,
+                                      mlt_keyframe_type keyframe_type, int position, int length );
+extern mlt_rect mlt_property_get_rect_pos( mlt_property self, double fps, locale_t locale, int position, int length );
+
 #endif
index 9657600a01b8cc63f5d293355ec19287f905f352..45f91cfc061da491a15eed790e5abc66c3163881 100644 (file)
@@ -362,3 +362,13 @@ mlt_rect Properties::get_rect( const char *name )
 {
        return mlt_properties_get_rect( get_properties(), name );
 }
+
+int Properties::set(const char *name, mlt_rect value, int position, int length, mlt_keyframe_type keyframe_type)
+{
+       return mlt_properties_set_rect_pos( get_properties(), name, value, keyframe_type, position, length );
+}
+
+mlt_rect Properties::get_rect(const char *name, int position, int length)
+{
+       return mlt_properties_get_rect_pos( get_properties(), name, position, length );
+}
index d867f67e82d4d5d64b6206d598421547033d6426..dc42fc843e483b979eb9015a49ff0c55f448e6f7 100644 (file)
@@ -103,6 +103,9 @@ namespace Mlt
                        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 );
+                       int set( const char *name, mlt_rect value, int position, int length,
+                               mlt_keyframe_type keyframe_type = mlt_keyframe_linear );
+                       mlt_rect get_rect( const char *name, int position, int length );
        };
 }
 
index 5ce0228786bd876d189d8a48383fc44254cfbd11..9a061643bd340eed1f64033bb29de77d7a4f555e 100644 (file)
@@ -731,6 +731,68 @@ private Q_SLOTS:
         QCOMPARE(r.h, 4.4);
         QCOMPARE(r.o, 5.5);
     }
+
+    void RectAnimation()
+    {
+        int len = 50;
+        mlt_rect r1 = { 0, 0, 200, 200, 0 };
+        mlt_rect r2 = { 100, 100, 400, 400, 1.0 };
+        Properties p;
+        p.set_lcnumeric("POSIX");
+
+        // Construct animation from scratch
+        p.set("key", r1,  0, len);
+        p.set("key", r2, 50, len);
+        QCOMPARE(p.get_rect("key",  0, len).x, 0.0);
+        QCOMPARE(p.get_rect("key", 25, len).x, 50.0);
+        QCOMPARE(p.get_rect("key", 25, len).y, 50.0);
+        QCOMPARE(p.get_rect("key", 25, len).w, 300.0);
+        QCOMPARE(p.get_rect("key", 25, len).h, 300.0);
+        QCOMPARE(p.get_rect("key", 25, len).o, 0.5);
+        QCOMPARE(p.get_rect("key", 50, len).x, 100.0);
+        QCOMPARE(p.get("key"), "0=0 0 200 200 0;50=100 100 400 400 1");
+
+        // Animation from string value
+        QCOMPARE(p.get_rect("key",  0, len).x, 0.0);
+        QCOMPARE(p.get_rect("key",  0, len).y, 0.0);
+        QCOMPARE(p.get_rect("key",  0, len).w, 200.0);
+        QCOMPARE(p.get_rect("key",  0, len).h, 200.0);
+        QCOMPARE(p.get_rect("key",  0, len).o, 0.0);
+        QCOMPARE(p.get_rect("key", 50, len).x, 100.0);
+        QCOMPARE(p.get_rect("key", 50, len).y, 100.0);
+        QCOMPARE(p.get_rect("key", 50, len).w, 400.0);
+        QCOMPARE(p.get_rect("key", 50, len).h, 400.0);
+        QCOMPARE(p.get_rect("key", 50, len).o, 1.0);
+        QCOMPARE(p.get_rect("key", 15, len).x, 30.0);
+        QCOMPARE(p.get_rect("key", 15, len).y, 30.0);
+        QCOMPARE(p.get_rect("key", 15, len).w, 260.0);
+        QCOMPARE(p.get_rect("key", 15, len).h, 260.0);
+        QCOMPARE(p.get_rect("key", 15, len).o, 0.3);
+
+        // Smooth animation
+        p.set("key", "0~=0/0:200x200:0; 50=100/100:400x400:1");
+        QCOMPARE(p.get_rect("key",  0, len).x, 0.0);
+        QCOMPARE(p.get_rect("key",  0, len).y, 0.0);
+        QCOMPARE(p.get_rect("key",  0, len).w, 200.0);
+        QCOMPARE(p.get_rect("key",  0, len).h, 200.0);
+        QCOMPARE(p.get_rect("key",  0, len).o, 0.0);
+        QCOMPARE(p.get_rect("key", 50, len).x, 100.0);
+        QCOMPARE(p.get_rect("key", 50, len).y, 100.0);
+        QCOMPARE(p.get_rect("key", 50, len).w, 400.0);
+        QCOMPARE(p.get_rect("key", 50, len).h, 400.0);
+        QCOMPARE(p.get_rect("key", 50, len).o, 1.0);
+        QCOMPARE(p.get_rect("key", 15, len).x, 25.8);
+        QCOMPARE(p.get_rect("key", 15, len).y, 25.8);
+        QCOMPARE(p.get_rect("key", 15, len).w, 251.6);
+        QCOMPARE(p.get_rect("key", 15, len).h, 251.6);
+        QCOMPARE(p.get_rect("key", 15, len).o, 0.258);
+
+        // Using percentages
+        p.set("key", "0=0 0; 50=100% 200%");
+        QCOMPARE(p.get_rect("key", 25, len).x, 0.5);
+        QCOMPARE(p.get_rect("key", 25, len).y, 1.0);
+    }
+
 };
 
 QTEST_APPLESS_MAIN(TestProperties)