X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fframework%2Fmlt_geometry.c;h=db9c877c66296298f2cf5770225afbd9785d326e;hb=780b62679560f15e2201ae42a28de77346729b7e;hp=8fa30b59afba20987e9996ff633435f2979488f9;hpb=702e73b84d90830062ebe07ba01b72ad59d48d93;p=melted diff --git a/src/framework/mlt_geometry.c b/src/framework/mlt_geometry.c index 8fa30b5..db9c877 100644 --- a/src/framework/mlt_geometry.c +++ b/src/framework/mlt_geometry.c @@ -1,26 +1,27 @@ /* - * mlt_geometry.h -- provides the geometry API + * mlt_geometry.c -- provides the geometry API * Copyright (C) 2004-2005 Ushodaya Enterprises Limited * Author: Charles Yates * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mlt_geometry.h" #include "mlt_tokeniser.h" #include "mlt_factory.h" +#include "mlt_profile.h" #include #include @@ -54,12 +55,8 @@ mlt_geometry mlt_geometry_init( ) if ( this->local != NULL ) { geometry self = this->local; - char *normalisation = mlt_environment( "MLT_NORMALISATION" ); self->nw = 720; - if ( normalisation == NULL || strcmp( normalisation, "NTSC" ) ) - self->nh = 576; - else - self->nh = 480; + self->nh = 576; } else { @@ -70,6 +67,90 @@ mlt_geometry mlt_geometry_init( ) return this; } +/** A linear step +*/ + +static inline double linearstep( double start, double end, double position, int length ) +{ + double o = ( end - start ) / length; + return start + position * o; +} + +static void mlt_geometry_virtual_refresh( mlt_geometry this ) +{ + geometry self = this->local; + + // Parse of all items to ensure unspecified keys are calculated correctly + if ( self->item != NULL ) + { + int i = 0; + for ( i = 0; i < 5; i ++ ) + { + geometry_item current = self->item; + while( current != NULL ) + { + int fixed = current->data.f[ i ]; + if ( !fixed ) + { + geometry_item prev = current->prev; + geometry_item next = current->next; + + double prev_value = 0; + double next_value = 0; + double value = 0; + + while( prev != NULL && !prev->data.f[ i ] ) prev = prev->prev; + while( next != NULL && !next->data.f[ i ] ) next = next->next; + + switch( i ) + { + case 0: + if ( prev ) prev_value = prev->data.x; + if ( next ) next_value = next->data.x; + break; + case 1: + if ( prev ) prev_value = prev->data.y; + if ( next ) next_value = next->data.y; + break; + case 2: + if ( prev ) prev_value = prev->data.w; + if ( next ) next_value = next->data.w; + break; + case 3: + if ( prev ) prev_value = prev->data.h; + if ( next ) next_value = next->data.h; + break; + case 4: + if ( prev ) prev_value = prev->data.mix; + if ( next ) next_value = next->data.mix; + break; + } + + // This should never happen + if ( prev == NULL ) + current->data.f[ i ] = 1; + else if ( next == NULL ) + value = prev_value; + else + value = linearstep( prev_value, next_value, current->data.frame - prev->data.frame, next->data.frame - prev->data.frame ); + + switch( i ) + { + case 0: current->data.x = value; break; + case 1: current->data.y = value; break; + case 2: current->data.w = value; break; + case 3: current->data.h = value; break; + case 4: current->data.mix = value; break; + } + } + + // Move to the next item + current = current->next; + } + } + } +} + static int mlt_geometry_drop( mlt_geometry this, geometry_item item ) { geometry self = this->local; @@ -79,6 +160,20 @@ static int mlt_geometry_drop( mlt_geometry this, geometry_item item ) self->item = item->next; if ( self->item != NULL ) self->item->prev = NULL; + // To ensure correct seeding, ensure all values are fixed + if ( self->item != NULL ) + { + self->item->data.f[0] = 1; + self->item->data.f[1] = 1; + self->item->data.f[2] = 1; + self->item->data.f[3] = 1; + self->item->data.f[4] = 1; + } + } + else if ( item->next != NULL && item->prev != NULL ) + { + item->prev->next = item->next; + item->next->prev = item->prev; } else if ( item->next != NULL ) { @@ -87,7 +182,6 @@ static int mlt_geometry_drop( mlt_geometry this, geometry_item item ) else if ( item->prev != NULL ) { item->prev->next = item->next; - item->next->prev = item->prev; } free( item ); @@ -184,7 +278,7 @@ void mlt_geometry_set_length( mlt_geometry this, int length ) // Get the local/private structure geometry self = this->local; - // return the length + // set the length self->length = length; } @@ -199,12 +293,16 @@ int mlt_geometry_parse_item( mlt_geometry this, mlt_geometry_item item, char *va { char *p = strchr( value, '=' ); int count = 0; - float temp; + double temp; // Determine if a position has been specified if ( p != NULL ) { - item->frame = atoi( value ); + temp = atof( value ); + if ( temp > -1 && temp < 1 ) + item->frame = temp * self->length; + else + item->frame = temp; value = p + 1; } @@ -216,6 +314,17 @@ int mlt_geometry_parse_item( mlt_geometry this, mlt_geometry_item item, char *va // frames to be created which don't specify all values mlt_geometry_fetch( this, item, item->frame ); + // Special case - when an empty string is specified, all values are fixed + // TODO: Check if this is logical - it's convenient, but it's also odd... + if ( !*value ) + { + item->f[0] = 1; + item->f[1] = 1; + item->f[2] = 1; + item->f[3] = 1; + item->f[4] = 1; + } + // Iterate through the remainder of value while( *value ) { @@ -236,7 +345,7 @@ int mlt_geometry_parse_item( mlt_geometry this, mlt_geometry_item item, char *va } // Special case - distort token - if ( *p == '!' ) + if ( *p == '!' || *p == '*' ) { p ++; item->distort = 1; @@ -248,11 +357,11 @@ int mlt_geometry_parse_item( mlt_geometry this, mlt_geometry_item item, char *va // Assign to the item switch( count ) { - case 0: item->x = temp; break; - case 1: item->y = temp; break; - case 2: item->w = temp; break; - case 3: item->h = temp; break; - case 4: item->mix = temp; break; + case 0: item->x = temp; item->f[0] = 1; break; + case 1: item->y = temp; item->f[1] = 1; break; + case 2: item->w = temp; item->f[2] = 1; break; + case 3: item->h = temp; item->f[3] = 1; break; + case 4: item->mix = temp; item->f[4] = 1; break; } } else @@ -273,15 +382,6 @@ int mlt_geometry_parse_item( mlt_geometry this, mlt_geometry_item item, char *va return ret; } -/** A linear step -*/ - -static inline float linearstep( float start, float end, float position, int length ) -{ - float o = ( end - start ) / length; - return start + position * o; -} - // Fetch a geometry item for an absolute position int mlt_geometry_fetch( mlt_geometry this, mlt_geometry_item item, float position ) { @@ -313,6 +413,11 @@ int mlt_geometry_fetch( mlt_geometry this, mlt_geometry_item item, float positio { memcpy( item, &key->data, sizeof( struct mlt_geometry_item_s ) ); item->key = 0; + item->f[ 0 ] = 0; + item->f[ 1 ] = 0; + item->f[ 2 ] = 0; + item->f[ 3 ] = 0; + item->f[ 4 ] = 0; } // Interpolation is needed - position > key and there is a following key else @@ -334,6 +439,7 @@ int mlt_geometry_fetch( mlt_geometry this, mlt_geometry_item item, float positio else { memset( item, 0, sizeof( struct mlt_geometry_item_s ) ); + item->frame = position; item->mix = 100; } @@ -373,6 +479,8 @@ int mlt_geometry_insert( mlt_geometry this, mlt_geometry_item item ) } else if ( item->frame > place->data.frame ) { + if ( place->next ) + place->next->prev = new; new->next = place->next; new->prev = place; place->next = new; @@ -385,9 +493,20 @@ int mlt_geometry_insert( mlt_geometry this, mlt_geometry_item item ) } else { + // Set the first item self->item = new; + + // To ensure correct seeding, ensure all values are fixed + self->item->data.f[0] = 1; + self->item->data.f[1] = 1; + self->item->data.f[2] = 1; + self->item->data.f[3] = 1; + self->item->data.f[4] = 1; } + // Refresh all geometries + mlt_geometry_virtual_refresh( this ); + // TODO: Error checking return 0; } @@ -403,17 +522,20 @@ int mlt_geometry_remove( mlt_geometry this, int position ) // Get the first item geometry_item place = self->item; - while( place != NULL && position < place->data.frame ) + while( place != NULL && position != place->data.frame ) place = place->next; if ( place != NULL && position == place->data.frame ) ret = mlt_geometry_drop( this, place ); + // Refresh all geometries + mlt_geometry_virtual_refresh( this ); + return ret; } // Get the key at the position or the next following -int mlt_geometry_key( mlt_geometry this, mlt_geometry_item item, int position ) +int mlt_geometry_next_key( mlt_geometry this, mlt_geometry_item item, int position ) { // Get the local/private geometry structure geometry self = this->local; @@ -430,8 +552,27 @@ int mlt_geometry_key( mlt_geometry this, mlt_geometry_item item, int position ) return place == NULL; } +// Get the key at the position or the previous key +int mlt_geometry_prev_key( mlt_geometry this, mlt_geometry_item item, int position ) +{ + // Get the local/private geometry structure + geometry self = this->local; + + // Get the first item + geometry_item place = self->item; + + while( place != NULL && place->next != NULL && position >= place->next->data.frame ) + place = place->next; + + if ( place != NULL ) + memcpy( item, &place->data, sizeof( struct mlt_geometry_item_s ) ); + + return place == NULL; +} + char *mlt_geometry_serialise_cut( mlt_geometry this, int in, int out ) { + geometry self = this->local; struct mlt_geometry_item_s item; char *ret = malloc( 1000 ); int used = 0; @@ -459,11 +600,26 @@ char *mlt_geometry_serialise_cut( mlt_geometry this, int in, int out ) { if ( mlt_geometry_fetch( this, &item, item.frame ) ) break; + + // If the first key is larger than the current position + // then do nothing here + if ( self->item->data.frame > item.frame ) + { + item.frame ++; + continue; + } + + // To ensure correct seeding, ensure all values are fixed + item.f[0] = 1; + item.f[1] = 1; + item.f[2] = 1; + item.f[3] = 1; + item.f[4] = 1; } // Typically, we move from key to key else if ( item.frame < out ) { - if ( mlt_geometry_key( this, &item, item.frame ) ) + if ( mlt_geometry_next_key( this, &item, item.frame ) ) break; // Special case - crop at the out point @@ -479,9 +635,18 @@ char *mlt_geometry_serialise_cut( mlt_geometry this, int in, int out ) if ( item.frame - in != 0 ) sprintf( temp, "%d=", item.frame - in ); - sprintf( temp + strlen( temp ), "%.0f,%.0f:%.0fx%.0f%s", item.x, item.y, item.w, item.h, item.distort ? "!" : "" ); - - if ( item.mix ) + if ( item.f[0] ) + sprintf( temp + strlen( temp ), "%.0f", item.x ); + strcat( temp, "," ); + if ( item.f[1] ) + sprintf( temp + strlen( temp ), "%.0f", item.y ); + strcat( temp, ":" ); + if ( item.f[2] ) + sprintf( temp + strlen( temp ), "%.0f", item.w ); + strcat( temp, "x" ); + if ( item.f[3] ) + sprintf( temp + strlen( temp ), "%.0f", item.h ); + if ( item.f[4] ) sprintf( temp + strlen( temp ), ":%.0f", item.mix ); if ( used + strlen( temp ) > size )