static int position_compare( const void *p1, const void *p2 )
{
- return *( int64_t * )p1 - *( int64_t * )p2;
+ return *( mlt_position * )p1 - *( mlt_position * )p2;
}
static int add_unique( mlt_position *array, int size, mlt_position position )
mlt_position position = 0;
int i = 0;
int j = 0;
- int64_t *map = malloc( 1000 * sizeof( mlt_position ) );
+ mlt_position *map = malloc( 1000 * sizeof( mlt_position ) );
int count = 0;
for ( i = 0; i < this->count; i ++ )
}
// Now sort the map
- qsort( map, count, sizeof( int64_t ), position_compare );
+ qsort( map, count, sizeof( mlt_position ), position_compare );
// Now locate the requested index
switch( whence )
return pool_fetch( pool );
}
+/** Allocate size bytes from the pool.
+*/
+
+void *mlt_pool_realloc( void *ptr, int size )
+{
+ // Result to return
+ void *result = NULL;
+
+ // Check if we actually have an address
+ if ( ptr != NULL )
+ {
+ // Get the release pointer
+ mlt_release that = ptr - sizeof( struct mlt_release_s );
+
+ // If the current pool this ptr belongs to is big enough
+ if ( size > that->pool->size - sizeof( struct mlt_release_s ) )
+ {
+ // Allocate
+ result = mlt_pool_alloc( size );
+
+ // Copy
+ memcpy( result, ptr, that->pool->size - sizeof( struct mlt_release_s ) );
+
+ // Release
+ mlt_pool_release( ptr );
+ }
+ else
+ {
+ // Nothing to do
+ result = ptr;
+ }
+ }
+ else
+ {
+ // Simply allocate
+ result = mlt_pool_alloc( size );
+ }
+
+ return result;
+}
+
/** Release the allocated memory.
*/
extern void mlt_pool_init( );
extern void *mlt_pool_alloc( int size );
+extern void *mlt_pool_realloc( void *ptr, int size );
extern void mlt_pool_release( void *release );
extern void mlt_pool_close( );
typedef struct
{
+ int hash[ 199 ];
char **name;
mlt_property *value;
int count;
return this;
}
+static inline int generate_hash( char *name )
+{
+ int hash = 0;
+ int i = 1;
+ while ( *name )
+ hash = ( hash + ( i ++ * ( *name ++ & 31 ) ) ) % 199;
+ return hash;
+}
+
/** Special case - when a container (such as fezzik) is protecting another
producer, we need to ensure that properties are passed through to the
real producer.
/** Locate a property by name
*/
-static mlt_property mlt_properties_find( mlt_properties this, char *name )
+static inline mlt_property mlt_properties_find( mlt_properties this, char *name )
{
- mlt_property value = NULL;
property_list *list = this->private;
+ mlt_property value = NULL;
int i = 0;
+ int key = generate_hash( name );
+
+ // Check if we're hashed
+ if ( list->count > 0 &&
+ name[ 0 ] == list->name[ list->hash[ key ] ][ 0 ] &&
+ !strcmp( list->name[ list->hash[ key ] ], name ) )
+ value = list->value[ list->hash[ key ] ];
// Locate the item
for ( i = 0; value == NULL && i < list->count; i ++ )
- if ( !strcmp( list->name[ i ], name ) )
+ if ( name[ 0 ] == list->name[ i ][ 0 ] && !strcmp( list->name[ i ], name ) )
value = list->value[ i ];
return value;
static mlt_property mlt_properties_add( mlt_properties this, char *name )
{
property_list *list = this->private;
+ int key = generate_hash( name );
// Check that we have space and resize if necessary
if ( list->count == list->size )
list->name[ list->count ] = strdup( name );
list->value[ list->count ] = mlt_property_init( );
+ // Assign to hash table
+ list->hash[ key ] = list->count;
+
// Return and increment count accordingly
return list->value[ list->count ++ ];
}
mlt_property mlt_property_init( )
{
- return calloc( sizeof( struct mlt_property_s ), 1 );
+ return calloc( 1, sizeof( struct mlt_property_s ) );
}
/** Clear a property.
{
this->types |= mlt_prop_string;
this->prop_string = malloc( 32 );
- sprintf( this->prop_string, "%lld", this->prop_position );
+ sprintf( this->prop_string, "%d", this->prop_position );
}
else if ( this->types & mlt_prop_int64 )
{
return mlt_properties_init( &this->parent, this );
}
-/** Return the properties object.
-*/
-
-mlt_properties mlt_service_properties( mlt_service this )
-{
- return &this->parent;
-}
-
/** Connect a producer service.
Returns: > 0 warning, == 0 success, < 0 serious error
1 = this service does not accept input
*/
extern int mlt_service_init( mlt_service this, void *child );
-extern mlt_properties mlt_service_properties( mlt_service this );
+//extern mlt_properties mlt_service_properties( mlt_service this );
extern int mlt_service_connect_producer( mlt_service this, mlt_service producer, int index );
extern mlt_service_state mlt_service_get_state( mlt_service this );
extern void mlt_service_close( mlt_service this );
extern int mlt_service_is_active( mlt_service this );
extern mlt_service mlt_service_get_producer( mlt_service this );
+/** Return the properties object.
+*/
+
+static inline mlt_properties mlt_service_properties( mlt_service this )
+{
+ return &this->parent;
+}
+
#endif
}
mlt_whence;
-typedef int64_t mlt_position;
+typedef int32_t mlt_position;
typedef struct mlt_frame_s *mlt_frame, **mlt_frame_ptr;
typedef struct mlt_properties_s *mlt_properties;
typedef struct mlt_service_s *mlt_service;
if ( time == last )
break;
last = time;
- fprintf( stderr, "%d: %lld\n", i, time );
+ fprintf( stderr, "%d: %d\n", i, time );
}
}
break;
transport_action( producer, ( char * )&value );
if ( mlt_properties_get_int( properties, "stats_off" ) == 0 )
- fprintf( stderr, "Current Position: %10lld\r", mlt_producer_position( producer ) );
+ fprintf( stderr, "Current Position: %10d\r", mlt_producer_position( producer ) );
}
fprintf( stderr, "\n" );
static int avformat_initialised = 0;
static pthread_mutex_t avformat_mutex;
+void *av_malloc( unsigned int size )
+{
+ return mlt_pool_alloc( size );
+}
+
+void *av_realloc( void *ptr, unsigned int size )
+{
+ return mlt_pool_realloc( ptr, size );
+}
+
+void av_free( void *ptr )
+{
+ return mlt_pool_release( ptr );
+}
+
/** Constructor for libavformat.
*/
// Initialise avformat if necessary
if ( avformat_initialised == 0 )
{
- pthread_mutex_init( &avformat_mutex, NULL );
avformat_initialised = 1;
+ pthread_mutex_init( &avformat_mutex, NULL );
av_register_all( );
}
// Counstruct key
sprintf( key, "%s.", name );
+ // Just in case, let's assume that the filter here has a composite
+ mlt_properties_set( mlt_filter_properties( filter ), "composite.start", "0%,0%:100%x100%" );
+ mlt_properties_set( mlt_filter_properties( filter ), "composite.fill", "true" );
+
// Pass all the key properties on the filter down
mlt_properties_pass( mlt_filter_properties( filter ), properties, key );
// Look for the first filter
mlt_filter filter = mlt_properties_get_data( properties, "_filter_0", NULL );
+ // Get the unique id of the filter (used to reacquire the producer position)
+ char *name = mlt_properties_get( properties, "_unique_id" );
+
+ // Get the original producer position
+ mlt_position position = mlt_properties_get_position( mlt_frame_properties( frame ), name );
+
// Create a composite if we don't have one
if ( composite == NULL )
{
// Only continue if we have both filter and composite
if ( composite != NULL && filter != NULL )
{
+ // Get the resource of this filter (could be a shape [rectangle/circle] or an alpha provider of choice
+ char *resource = mlt_properties_get( properties, "resource" );
+
// String to hold the filter to query on
char id[ 256 ];
int i = 0;
// We will get the 'b frame' from the composite
- mlt_frame b_frame = composite_copy_region( composite, frame );
+ mlt_frame b_frame = composite_copy_region( composite, frame, position );
// Make sure the filter is in the correct position
while ( filter != NULL )
filter = mlt_properties_get_data( properties, id, NULL );
}
+ // Hmm - this is probably going to go wrong....
+ mlt_frame_set_position( frame, position );
+
// Get the b frame and process with composite if successful
mlt_transition_process( composite, frame, b_frame );
- // See if we have a shape producer
- // Copy the alpha mask from the shape frame to the b_frame
- char *resource = mlt_properties_get( properties, "resource" );
-
+ // If we have a shape producer copy the alpha mask from the shape frame to the b_frame
if ( strcmp( resource, "rectangle" ) != 0 )
{
- if ( strcmp( resource, "circle" ) == 0 )
- {
- resource = strdup( "pixbuf" );
- mlt_properties_set( properties, "producer.resource", "<svg width='100' height='100'><circle cx='50' cy='50' r='50' fill='black'/></svg>" );
- }
-
// Get the producer from the filter
mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );
+ // If We have no producer then create one
if ( producer == NULL )
{
// Get the factory producer service
char *factory = mlt_properties_get( properties, "factory" );
- // Create the producer
+ // Special case circle resource
+ if ( strcmp( resource, "circle" ) == 0 )
+ {
+ // Special case to ensure that fezzik produces a pixbuf with a NULL constructor
+ resource = "pixbuf";
+
+ // Specify the svg circle
+ mlt_properties_set( properties, "producer.resource", "<svg width='100' height='100'><circle cx='50' cy='50' r='50' fill='black'/></svg>" );
+ }
+
+ // Create the producer
producer = mlt_factory_producer( factory, resource );
// If we have one
}
}
+ // Now use the shape producer
if ( producer != NULL )
{
// We will get the alpha frame from the producer
mlt_frame shape_frame = NULL;
- // Get the unique id of the filter (used to reacquire the producer position)
- char *name = mlt_properties_get( properties, "_unique_id" );
-
- // Get the original producer position
- mlt_position position = mlt_properties_get_position( mlt_frame_properties( frame ), name );
-
// Make sure the producer is in the correct position
mlt_producer_seek( producer, position );
b_frame->get_alpha_mask = filter_get_alpha_mask;
}
- // Get the image
- error = mlt_frame_get_image( frame, image, format, width, height, 0 );
-
- // Close the b frame
- mlt_frame_close( b_frame );
- b_frame = NULL;
-
- // Close the shape frame
- mlt_frame_close( shape_frame );
+ // Ensure that the shape frame will be closed
+ mlt_properties_set_data( mlt_frame_properties( b_frame ), "shape_frame", shape_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
}
}
}
- if ( b_frame != NULL )
- {
- // Get the image
- error = mlt_frame_get_image( frame, image, format, width, height, 0 );
- // Close the b frame
- mlt_frame_close( b_frame );
- }
+ // Get the image
+ error = mlt_frame_get_image( frame, image, format, width, height, 0 );
+
+ // Close the b frame
+ mlt_frame_close( b_frame );
}
return error;
static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
{
+ // Get the properties of the frame
+ mlt_properties properties = mlt_frame_properties( frame );
+
+ // Get a unique name to store the frame position
+ char *name = mlt_properties_get( mlt_filter_properties( this ), "_unique_id" );
+
+ // Assign the current position to the name
+ mlt_properties_set_position( properties, name, mlt_frame_get_position( frame ) );
+
// Push the filter on to the frame
mlt_frame_push_service( frame, this );
/** Calculate the position for this frame.
*/
-static float position_calculate( mlt_transition this, mlt_frame frame )
+static float position_calculate( mlt_transition this, mlt_position position )
{
// Get the in and out position
mlt_position in = mlt_transition_get_in( this );
mlt_position out = mlt_transition_get_out( this );
- // Get the position
- mlt_position position = mlt_frame_get_position( frame );
-
// Now do the calcs
return ( float )( position - in ) / ( float )( out - in + 1 );
}
return start;
}
-mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame )
+mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_position frame_position )
{
// Create a frame to return
mlt_frame b_frame = mlt_frame_init( );
mlt_properties b_props = mlt_frame_properties( b_frame );
// Get the position
- float position = position_calculate( this, a_frame );
+ float position = position_calculate( this, frame_position );
// Destination image
uint8_t *dest = NULL;
mlt_properties_set_int( b_props, "width", w );
mlt_properties_set_int( b_props, "height", h );
+ // Assign this position to the b frame
+ mlt_frame_set_position( b_frame, frame_position );
+
// Return the frame
return b_frame;
}
static mlt_frame composite_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
{
// Propogate the transition properties to the b frame
- mlt_properties_set_double( mlt_frame_properties( b_frame ), "relative_position", position_calculate( this, a_frame ) );
+ mlt_properties_set_double( mlt_frame_properties( b_frame ), "relative_position", position_calculate( this, mlt_frame_get_position( a_frame ) ) );
mlt_frame_push_service( a_frame, this );
mlt_frame_push_get_image( a_frame, transition_get_image );
mlt_frame_push_frame( a_frame, b_frame );
extern mlt_transition transition_composite_init( char *arg );
// Courtesy functionality - allows regionalised filtering
-extern mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame );
+extern mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_position position );
#endif
mlt_pool_release( this->image );
parent->close = NULL;
mlt_producer_close( parent );
- while ( *this->filenames )
- {
- free( *this->filenames );
- this->filenames++;
- }
+ while ( this->count -- )
+ free( this->filenames[ this->count ] );
+ free( this->filenames );
free( this );
}
SDL_Surface *sdl_screen;
SDL_Overlay *sdl_overlay;
uint8_t *buffer;
+ int time_taken;
};
/** Forward references to static functions.
mlt_properties_set_position( mlt_frame_properties( frame ), "playtime", playtime );
mlt_properties_set_double( mlt_frame_properties( frame ), "consumer_scale", ( double )height / mlt_properties_get_double( properties, "height" ) );
+ if ( !this->playing )
+ {
+ struct timeb render;
+ mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
+ ftime( &render );
+ this->time_taken = ( ( int64_t )render.time * 1000 + render.millitm ) - ( ( int64_t )before.time * 1000 + before.millitm );
+ mlt_properties_set( mlt_frame_properties( frame ), "rendered", "true" );
+ }
+
// Push this frame to the back of the queue
mlt_deque_push_back( this->queue, frame );
frame = NULL;
{
frame = mlt_deque_pop_front( this->queue );
}
- else if ( playtime > elapsed + 60 || mlt_deque_count( this->queue ) < 12 )
+ else if ( playtime > elapsed + 100 )
{
// no frame to show or remove
frame = NULL;
}
else if ( playtime < elapsed - 20 )
{
- if ( candidate != NULL )
- mlt_frame_close( candidate );
+ mlt_frame_close( candidate );
candidate = mlt_deque_pop_front( this->queue );
+ if ( mlt_properties_get( mlt_frame_properties( frame ), "rendered" ) == NULL )
+ {
+ mlt_frame_close( candidate );
+ candidate = NULL;
+ }
frame = NULL;
}
else
mlt_frame_close( candidate );
}
+ struct timeb render;
+ ftime( &render );
+
if ( this->playing && frame != NULL )
{
- struct timeb after;
// Get the image, width and height
mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
-
- ftime( &after );
- //fprintf( stderr, "showing %lld at %lld\n", playtime, elapsed );
- int processing = ( ( int64_t )after.time * 1000 + after.millitm ) - ( ( int64_t )before.time * 1000 + before.millitm );
-
- int delay = playtime - elapsed - processing;
- struct timespec slow = { 0, ( delay % 1000 ) * 500000 };
- if ( slow.tv_nsec > 1000000 )
- nanosleep( &slow, NULL );
+ ftime( &render );
+ if ( mlt_properties_get( mlt_frame_properties( frame ), "rendered" ) == NULL )
+ this->time_taken = ( ( int64_t )render.time * 1000 + render.millitm ) - ( ( int64_t )before.time * 1000 + before.millitm );
// Handle events
if ( this->sdl_screen != NULL )
if ( frame != NULL )
mlt_frame_close( frame );
+ struct timeb after;
+ ftime( &after );
+ int processing = ( ( int64_t )after.time * 1000 + after.millitm ) - ( ( int64_t )render.time * 1000 + render.millitm );
+ int delay = playtime - elapsed - processing;
+
+ if ( delay > this->time_taken && mlt_deque_count( this->queue ) )
+ {
+ mlt_frame next = mlt_deque_peek_front( this->queue );
+ playtime = mlt_properties_get_position( mlt_frame_properties( next ), "playtime" );
+ if ( playtime > elapsed + delay )
+ {
+ struct timeb render;
+ mlt_frame_get_image( next, &image, &vfmt, &width, &height, 0 );
+ ftime( &render );
+ this->time_taken = ( ( int64_t )render.time * 1000 + render.millitm ) - ( ( int64_t )after.time * 1000 + after.millitm );
+ mlt_properties_set( mlt_frame_properties( next ), "rendered", "true" );
+ }
+ else
+ {
+ this->time_taken /= 2;
+ }
+ }
+ else
+ {
+ this->time_taken /= 2;
+ }
+
return 0;
}
char length[ 20 ];
length[ 19 ] = '\0';
xmlNode *entry = xmlNewChild( child, NULL, "blank", NULL );
- snprintf( length, 19, "%lld", info.frame_count );
+ snprintf( length, 19, "%d", info.frame_count );
xmlNewProp( entry, "length", length );
}
else