Example #1
0
static int mlt_animation_drop( mlt_animation self, animation_node node )
{
	if ( node == self->nodes )
	{
		self->nodes = node->next;
		if ( self->nodes ) {
			self->nodes->prev = NULL;
			self->nodes->item.is_key = 1;
		}
	}
	else if ( node->next && node->prev )
	{
		node->prev->next = node->next;
		node->next->prev = node->prev;
	}
	else if ( node->next )
	{
		node->next->prev = node->prev;
	}
	else if ( node->prev )
	{
		node->prev->next = node->next;
	}
	mlt_property_close( node->item.property );
	free( node );

	return 0;
}
Example #2
0
int mlt_animation_insert( mlt_animation self, mlt_animation_item item )
{
	int error = 0;
	animation_node node = calloc( 1, sizeof( *node ) );
	node->item.frame = item->frame;
	node->item.is_key = 1;
	node->item.keyframe_type = item->keyframe_type;
	node->item.property = mlt_property_init();
	mlt_property_pass( node->item.property, item->property );

	// Determine if we need to insert or append to the list, or if it's a new list
	if ( self->nodes )
	{
		// Get the first item
		animation_node current = self->nodes;

		// Locate an existing nearby item
		while ( current->next && item->frame > current->item.frame )
			current = current->next;

		if ( item->frame < current->item.frame )
		{
			if ( current == self->nodes )
				self->nodes = node;
			if ( current->prev )
				current->prev->next = node;
			node->next = current;
			node->prev = current->prev;
			current->prev = node;
		}
		else if ( item->frame > current->item.frame )
		{
			if ( current->next )
				current->next->prev = node;
			node->next = current->next;
			node->prev = current;
			current->next = node;
		}
		else
		{
			// Update matching node.
			current->item.frame = item->frame;
			current->item.is_key = 1;
			current->item.keyframe_type = item->keyframe_type;
			mlt_property_close( current->item.property );
			current->item.property = node->item.property;
			free( node );
		}
	}
	else
	{
		// Set the first item
		self->nodes = node;
	}

	return error;
}
Example #3
0
static void serialize_localmotions(StabData* data, LocalMotions &vectors, mlt_position pos)
{
	mlt_animation_item_s item;

	// Initialize animation item
	item.is_key = 1;
	item.frame = data->md.frameNum;
	item.keyframe_type = mlt_keyframe_discrete;
	item.property = mlt_property_init();

	mlt_property_set_data(item.property, &vectors, 1, lm_destructor, (mlt_serialiser) lm_serializer);
	mlt_animation_insert(data->animation, &item);
	mlt_property_close(item.property);
}
Example #4
0
int mlt_animation_parse(mlt_animation self, const char *data, int length, double fps, locale_t locale )
{
	int error = 0;
	int i = 0;
	struct mlt_animation_item_s item;
	mlt_tokeniser tokens = mlt_tokeniser_init( );

	// Clean the existing geometry
	mlt_animation_clean( self );

	// Update the info on the data
	if ( data )
		self->data = strdup( data );
	self->length = length;
	self->fps = fps;
	self->locale = locale;
	item.property = mlt_property_init();

	// Tokenise
	if ( data )
		mlt_tokeniser_parse_new( tokens, (char*) data, ";" );

	// Iterate through each token
	for ( i = 0; i < mlt_tokeniser_count( tokens ); i++ )
	{
		char *value = mlt_tokeniser_get_string( tokens, i );

		// If no data in keyframe, drop it (trailing semicolon)
		if ( !value || !strcmp( value, "" ) )
			continue;

		// Reset item
		item.frame = item.is_key = 0;

		// Now parse the item
		mlt_animation_parse_item( self, &item, value );

		// Now insert into place
		mlt_animation_insert( self, &item );
	}
	mlt_animation_interpolate( self );

	// Cleanup
	mlt_tokeniser_close( tokens );
	mlt_property_close( item.property );

	return error;
}
Example #5
0
char *mlt_animation_serialize_cut( mlt_animation self, int in, int out )
{
	struct mlt_animation_item_s item;
	char *ret = malloc( 1000 );
	size_t used = 0;
	size_t size = 1000;

	item.property = mlt_property_init();
	if ( in == -1 )
		in = 0;
	if ( out == -1 )
		out = mlt_animation_get_length( self );

	if ( ret )
	{
		strcpy( ret, "" );

		item.frame = in;

		while ( 1 )
		{
			size_t item_len = 0;

			// If it's the first frame, then it's not necessarily a key
			if ( item.frame == in )
			{
				if ( mlt_animation_get_item( self, &item, item.frame ) )
					break;

				// If the first keyframe is larger than the current position
				// then do nothing here
				if ( self->nodes->item.frame > item.frame )
				{
					item.frame ++;
					continue;
				}

				// To ensure correct seeding
				item.is_key = 1;
			}
			// Typically, we move from keyframe to keyframe
			else if ( item.frame <= out )
			{
				if ( mlt_animation_next_key( self, &item, item.frame ) )
					break;

				// Special case - crop at the out point
				if ( item.frame > out )
					mlt_animation_get_item( self, &item, out );
			}
			// We've handled the last keyframe
			else
			{
				break;
			}

			// Determine length of string to be appended.
			if ( item.frame - in != 0 )
				item_len += 20;
			if ( item.is_key )
				item_len += strlen( mlt_property_get_string_l( item.property, self->locale ) );

			// Reallocate return string to be long enough.
			while ( used + item_len + 2 > size ) // +2 for ';' and NULL
			{
				size += 1000;
				ret = realloc( ret, size );
			}

			// Append item delimiter (;) if needed.
			if ( ret && used > 0 )
			{
				used ++;
				strcat( ret, ";" );
			}
			if ( ret )
			{
				// Append keyframe time and keyframe/value delimiter (=).
				const char *s;
				switch (item.keyframe_type) {
				case mlt_keyframe_discrete:
					s = "|";
					break;
				case mlt_keyframe_smooth:
					s = "~";
					break;
				default:
					s = "";
					break;
				}
				sprintf( ret + used, "%d%s=", item.frame - in, s );

				// Append item value.
				if ( item.is_key )
					strcat( ret, mlt_property_get_string_l( item.property, self->locale ) );
				used = strlen( ret );
			}
			item.frame ++;
		}
	}
	mlt_property_close( item.property );

	return ret;
}