int mlt_animation_get_item( mlt_animation self, mlt_animation_item item, int position ) { int error = 0; // Need to find the nearest keyframe to the position specifed animation_node node = self->nodes; // Iterate through the keyframes until we reach last or have while ( node && node->next && position >= node->next->item.frame ) node = node->next; if ( node ) { item->keyframe_type = node->item.keyframe_type; // Position is before the first keyframe. if ( position < node->item.frame ) { item->is_key = 0; if ( item->property ) mlt_property_pass( item->property, node->item.property ); } // Item exists. else if ( position == node->item.frame ) { item->is_key = node->item.is_key; if ( item->property ) mlt_property_pass( item->property, node->item.property ); } // Position is after the last keyframe. else if ( !node->next ) { item->is_key = 0; if ( item->property ) mlt_property_pass( item->property, node->item.property ); } // Interpolation needed. else { double progress; mlt_property points[4]; points[0] = node->prev? node->prev->item.property : node->item.property; points[1] = node->item.property; points[2] = node->next->item.property; points[3] = node->next->next? node->next->next->item.property : node->next->item.property; progress = position - node->item.frame; progress /= node->next->item.frame - node->item.frame; mlt_property_interpolate( item->property, points, progress, self->fps, self->locale, item->keyframe_type ); item->is_key = 0; } } else { item->frame = item->is_key = 0; error = 1; } item->frame = position; return error; }
void mlt_animation_interpolate( mlt_animation self ) { // Parse all items to ensure non-keyframes are calculated correctly. if ( self->nodes ) { animation_node current = self->nodes; while ( current ) { if ( !current->item.is_key ) { double progress; mlt_property points[4]; animation_node prev = current->prev; animation_node next = current->next; while ( prev && !prev->item.is_key ) prev = prev->prev; while ( next && !next->item.is_key ) next = next->next; if ( !prev ) { current->item.is_key = 1; prev = current; } if ( !next ) { next = current; } points[0] = prev->prev? prev->prev->item.property : prev->item.property; points[1] = prev->item.property; points[2] = next->item.property; points[3] = next->next? next->next->item.property : next->item.property; progress = current->item.frame - prev->item.frame; progress /= next->item.frame - prev->item.frame; mlt_property_interpolate( current->item.property, points, progress, self->fps, self->locale, current->item.keyframe_type ); } // Move to the next item current = current->next; } } }