From: lilo_booter Date: Thu, 25 Dec 2003 20:25:35 +0000 (+0000) Subject: field and playlist enhancements, producer pixbuf reorg X-Git-Url: http://research.m1stereo.tv/gitweb?a=commitdiff_plain;h=e4c9ccbcef39cadaccbad655bc6e36e825bf3dde;p=melted field and playlist enhancements, producer pixbuf reorg git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@16 d19143bc-622f-0410-bfdd-b5b2a6649095 --- diff --git a/mlt/src/framework/mlt_field.c b/mlt/src/framework/mlt_field.c index dfa15f4..a54d97e 100644 --- a/mlt/src/framework/mlt_field.c +++ b/mlt/src/framework/mlt_field.c @@ -22,6 +22,8 @@ #include "mlt_service.h" #include "mlt_filter.h" #include "mlt_transition.h" +#include "mlt_multitrack.h" +#include "mlt_tractor.h" #include #include @@ -31,49 +33,41 @@ struct mlt_field_s { - // We extending service here - struct mlt_service_s parent; - // This is the producer we're connected to mlt_service producer; -}; -/** Forward declarations -*/ + // Multitrack + mlt_multitrack multitrack; -static int service_get_frame( mlt_service service, mlt_frame_ptr frame, int index ); - -/** Constructor. This service needs to know its producer at construction. + // Tractor + mlt_tractor tractor; +}; - When the first filter or transition is planted, we connect it immediately to - the producer of the field, and all subsequent plants are then connected to the - previous plant. This immediate connection requires the producer prior to the first - plant. +/** Constructor. - It's a kind of arbitrary decsion - we could generate a dummy service here and - then connect the dummy in the normal connect manner. Behaviour may change in the - future (say, constructing a dummy when producer service is NULL). However, the - current solution is quite clean, if slightly out of sync with the rest of the - mlt framework. + We construct a multitrack and a tractor here. */ -mlt_field mlt_field_init( mlt_service producer ) +mlt_field mlt_field_init( ) { // Initialise the field mlt_field this = calloc( sizeof( struct mlt_field_s ), 1 ); - // Get the service - mlt_service service = &this->parent; + // Initialise it + if ( this != NULL ) + { + // Construct a multitrack + this->multitrack = mlt_multitrack_init( ); - // Initialise the service - mlt_service_init( service, this ); + // Construct a tractor + this->tractor = mlt_tractor_init( ); - // Override the get_frame method - service->get_frame = service_get_frame; + // The first plant will be connected to the mulitrack + this->producer = mlt_multitrack_service( this->multitrack ); - // Connect to the producer immediately - if ( mlt_service_connect_producer( service, producer, 0 ) == 0 ) - this->producer = producer; + // Connect the tractor to the multitrack + mlt_tractor_connect( this->tractor, this->producer ); + } // Return this return this; @@ -84,7 +78,15 @@ mlt_field mlt_field_init( mlt_service producer ) mlt_service mlt_field_service( mlt_field this ) { - return &this->parent; + return mlt_tractor_service( this->tractor ); +} + +/** Get the multi track. +*/ + +mlt_multitrack mlt_field_multitrack( mlt_field this ) +{ + return this->multitrack; } /** Get the properties associated to this field. @@ -92,7 +94,7 @@ mlt_service mlt_field_service( mlt_field this ) mlt_properties mlt_field_properties( mlt_field this ) { - return mlt_service_properties( &this->parent ); + return mlt_service_properties( mlt_field_service( this ) ); } /** Plant a filter. @@ -106,8 +108,11 @@ int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track ) // If sucessful, then we'll use this for connecting in the future if ( result == 0 ) { - // Update last + // This is now the new producer this->producer = mlt_filter_service( that ); + + // Reconnect tractor to new producer + mlt_tractor_connect( this->tractor, this->producer ); } return result; @@ -124,28 +129,23 @@ int mlt_field_plant_transition( mlt_field this, mlt_transition that, int a_track // If sucessful, then we'll use this for connecting in the future if ( result == 0 ) { - // Update last + // This is now the new producer this->producer = mlt_transition_service( that ); + + // Reconnect tractor to new producer + mlt_tractor_connect( this->tractor, this->producer ); } return 0; } -/** Get a frame. -*/ - -static int service_get_frame( mlt_service service, mlt_frame_ptr frame, int index ) -{ - mlt_field this = service->child; - return mlt_service_get_frame( this->producer, frame, index ); -} - /** Close the field. */ void mlt_field_close( mlt_field this ) { - mlt_service_close( &this->parent ); + mlt_tractor_close( this->tractor ); + mlt_multitrack_close( this->multitrack ); free( this ); } diff --git a/mlt/src/framework/mlt_field.h b/mlt/src/framework/mlt_field.h index 427032f..6fef296 100644 --- a/mlt/src/framework/mlt_field.h +++ b/mlt/src/framework/mlt_field.h @@ -23,8 +23,9 @@ #include "mlt_types.h" -extern mlt_field mlt_field_init( mlt_service producer ); +extern mlt_field mlt_field_init( ); extern mlt_service mlt_field_service( mlt_field this ); +extern mlt_multitrack mlt_field_multitrack( mlt_field this ); extern mlt_properties mlt_field_properties( mlt_field this ); extern int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track ); extern int mlt_field_plant_transition( mlt_field this, mlt_transition that, int a_track, int b_track ); diff --git a/mlt/src/framework/mlt_filter.c b/mlt/src/framework/mlt_filter.c index af4a3c6..9c0a295 100644 --- a/mlt/src/framework/mlt_filter.c +++ b/mlt/src/framework/mlt_filter.c @@ -62,6 +62,11 @@ mlt_service mlt_filter_service( mlt_filter this ) return &this->parent; } +mlt_properties mlt_filter_properties( mlt_filter this ) +{ + return mlt_service_properties( mlt_filter_service( this ) ); +} + /** Connect this filter to a producers track. Note that a filter only operates on a single track, and by default it operates on the entirety of that track. */ diff --git a/mlt/src/framework/mlt_filter.h b/mlt/src/framework/mlt_filter.h index df5b641..e3f0f74 100644 --- a/mlt/src/framework/mlt_filter.h +++ b/mlt/src/framework/mlt_filter.h @@ -39,9 +39,6 @@ struct mlt_filter_s // track and in/out points mlt_service producer; - //int track; - //mlt_timecode in; - //mlt_timecode out; // Protected void *child; @@ -52,6 +49,7 @@ struct mlt_filter_s extern int mlt_filter_init( mlt_filter this, void *child ); extern mlt_service mlt_filter_service( mlt_filter this ); +extern mlt_properties mlt_filter_properties( mlt_filter this ); extern int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ); extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out ); extern int mlt_filter_get_track( mlt_filter this ); diff --git a/mlt/src/framework/mlt_playlist.c b/mlt/src/framework/mlt_playlist.c index f786d31..eb89f04 100644 --- a/mlt/src/framework/mlt_playlist.c +++ b/mlt/src/framework/mlt_playlist.c @@ -42,14 +42,11 @@ playlist_entry; struct mlt_playlist_s { struct mlt_producer_s parent; + struct mlt_producer_s blank; + int size; int count; - mlt_producer *list; - mlt_producer blank; - - int virtual_size; - int virtual_count; - playlist_entry **virtual_list; + playlist_entry **list; }; /** Forward declarations @@ -73,11 +70,8 @@ mlt_playlist mlt_playlist_init( ) // Override the producer get_frame producer->get_frame = producer_get_frame; - // Create a producer - this->blank = calloc( sizeof( struct mlt_producer_s ), 1 ); - - // Initialise it - mlt_producer_init( this->blank, NULL ); + // Initialise blank + mlt_producer_init( &this->blank, NULL ); } return this; @@ -99,56 +93,27 @@ mlt_service mlt_playlist_service( mlt_playlist this ) return mlt_producer_service( &this->parent ); } -/** Store a producer in the playlist. +/** Append to the virtual playlist. */ -static int mlt_playlist_store( mlt_playlist this, mlt_producer producer ) +static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, mlt_timecode in, mlt_timecode out ) { - int i; - - // If it's already added, return the index - for ( i = 0; i < this->count; i ++ ) - { - if ( producer == this->list[ i ] ) - return i; - } - // Check that we have room if ( this->count >= this->size ) { - this->list = realloc( this->list, ( this->size + 10 ) * sizeof( mlt_producer ) ); + int i; + this->list = realloc( this->list, ( this->size + 10 ) * sizeof( playlist_entry * ) ); for ( i = this->size; i < this->size + 10; i ++ ) this->list[ i ] = NULL; this->size += 10; } - // Add this producer to the list - this->list[ this->count ] = producer; + this->list[ this->count ] = calloc( sizeof( playlist_entry ), 1 ); + this->list[ this->count ]->producer = producer; + this->list[ this->count ]->in = in; + this->list[ this->count ]->playtime = out - in; - return this->count ++; -} - -/** Append to the virtual playlist. -*/ - -static int mlt_playlist_virtual_append( mlt_playlist this, int position, mlt_timecode in, mlt_timecode out ) -{ - // Check that we have room - if ( this->virtual_count >= this->virtual_size ) - { - int i; - this->virtual_list = realloc( this->virtual_list, ( this->virtual_size + 10 ) * sizeof( playlist_entry * ) ); - for ( i = this->virtual_size; i < this->virtual_size + 10; i ++ ) - this->virtual_list[ i ] = NULL; - this->virtual_size += 10; - } - - this->virtual_list[ this->virtual_count ] = malloc( sizeof( playlist_entry ) ); - this->virtual_list[ this->virtual_count ]->producer = this->list[ position ]; - this->virtual_list[ this->virtual_count ]->in = in; - this->virtual_list[ this->virtual_count ]->playtime = out - in; - - this->virtual_count ++; + this->count ++; return 0; } @@ -159,7 +124,7 @@ static int mlt_playlist_virtual_append( mlt_playlist this, int position, mlt_tim static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) { // Default producer to blank - mlt_producer producer = this->blank; + mlt_producer producer = &this->blank; // Map playlist position to real producer in virtual playlist mlt_timecode position = mlt_producer_position( &this->parent ); @@ -167,19 +132,19 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) // Loop through the virtual playlist int i = 0; - for ( i = 0; i < this->virtual_count; i ++ ) + for ( i = 0; i < this->count; i ++ ) { - if ( position < this->virtual_list[ i ]->playtime ) + if ( position < this->list[ i ]->playtime ) { // Found it, now break - producer = this->virtual_list[ i ]->producer; - position += this->virtual_list[ i ]->in; + producer = this->list[ i ]->producer; + position += this->list[ i ]->in; break; } else { // Decrement position by length of this entry - position -= this->virtual_list[ i ]->playtime; + position -= this->list[ i ]->playtime; } } @@ -194,13 +159,8 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) int mlt_playlist_append( mlt_playlist this, mlt_producer producer ) { - // Get the position of the producer in the list - int position = mlt_playlist_store( this, producer ); - // Append to virtual list - mlt_playlist_virtual_append( this, position, 0, mlt_producer_get_playtime( producer ) ); - - return 0; + return mlt_playlist_virtual_append( this, producer, 0, mlt_producer_get_playtime( producer ) ); } /** Append a blank to the playlist of a given length. @@ -208,13 +168,8 @@ int mlt_playlist_append( mlt_playlist this, mlt_producer producer ) int mlt_playlist_blank( mlt_playlist this, mlt_timecode length ) { - // Get the position of the producer in the list - int position = mlt_playlist_store( this, this->blank ); - // Append to the virtual list - mlt_playlist_virtual_append( this, position, 0, length ); - - return 0; + return mlt_playlist_virtual_append( this, &this->blank, 0, length ); } /** Get the current frame. @@ -246,7 +201,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i void mlt_playlist_close( mlt_playlist this ) { mlt_producer_close( &this->parent ); - mlt_producer_close( this->blank ); - free( this->blank ); + mlt_producer_close( &this->blank ); free( this ); } diff --git a/mlt/src/modules/core/Makefile b/mlt/src/modules/core/Makefile index 5ef6eb2..fe4a0bb 100644 --- a/mlt/src/modules/core/Makefile +++ b/mlt/src/modules/core/Makefile @@ -5,6 +5,7 @@ OBJS = factory.o \ producer_ppm.o \ filter_deinterlace.o \ filter_greyscale.o \ + filter_resize.o \ transition_composite.o CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread diff --git a/mlt/src/modules/core/configure b/mlt/src/modules/core/configure index 43f2780..2f3457e 100755 --- a/mlt/src/modules/core/configure +++ b/mlt/src/modules/core/configure @@ -10,6 +10,7 @@ EOF cat << EOF >> ../filters.dat deinterlace libmltcore.so greyscale libmltcore.so +resize libmltcore.so EOF cat << EOF >> ../transitions.dat diff --git a/mlt/src/modules/core/factory.c b/mlt/src/modules/core/factory.c index 2f517b8..eb19049 100644 --- a/mlt/src/modules/core/factory.c +++ b/mlt/src/modules/core/factory.c @@ -22,6 +22,7 @@ #include "filter_deinterlace.h" #include "filter_greyscale.h" +#include "filter_resize.h" #include "producer_ppm.h" #include "transition_composite.h" @@ -38,6 +39,8 @@ void *mlt_create_filter( char *id, void *arg ) return filter_deinterlace_init( arg ); if ( !strcmp( id, "greyscale" ) ) return filter_greyscale_init( arg ); + if ( !strcmp( id, "resize" ) ) + return filter_resize_init( arg ); return NULL; } diff --git a/mlt/src/modules/core/filter_resize.c b/mlt/src/modules/core/filter_resize.c new file mode 100644 index 0000000..1ebb741 --- /dev/null +++ b/mlt/src/modules/core/filter_resize.c @@ -0,0 +1,66 @@ +/* + * filter_resize.c -- resizing filter + * Copyright (C) 2003-2004 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 program 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. + * + * 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. + */ + +#include "filter_resize.h" + +#include + +#include +#include + +/** Do it :-). +*/ + +static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +{ + int owidth = *width; + int oheight = *height; + mlt_frame_get_image( this, image, format, &owidth, &oheight, 0 ); + if ( !strcmp( mlt_properties_get( mlt_frame_properties( this ), "resize.scale" ), "affine" ) ) + *image = mlt_frame_rescale_yuv422( this, *width, *height ); + else + *image = mlt_frame_resize_yuv422( this, *width, *height ); + return 0; +} + +/** Filter processing. +*/ + +static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) +{ + mlt_frame_push_get_image( frame, filter_get_image ); + mlt_properties_set( mlt_frame_properties( frame ), "resize.scale", mlt_properties_get( mlt_filter_properties( this ), "scale" ) ); + return frame; +} + +/** Constructor for the filter. +*/ + +mlt_filter filter_resize_init( void *arg ) +{ + mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 ); + if ( mlt_filter_init( this, this ) == 0 ) + { + this->process = filter_process; + mlt_properties_set( mlt_filter_properties( this ), "scale", "off" ); + } + return this; +} + diff --git a/mlt/src/modules/core/filter_resize.h b/mlt/src/modules/core/filter_resize.h new file mode 100644 index 0000000..cdac48b --- /dev/null +++ b/mlt/src/modules/core/filter_resize.h @@ -0,0 +1,28 @@ +/* + * filter_resize.h -- resizing filter + * Copyright (C) 2003-2004 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 program 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. + * + * 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. + */ + +#ifndef _FILTER_RESIZE_H_ +#define _FILTER_RESIZE_H_ + +#include + +extern mlt_filter filter_deinterlace_init( void *arg ); + +#endif diff --git a/mlt/src/modules/gtk2/producer_pixbuf.c b/mlt/src/modules/gtk2/producer_pixbuf.c index 97a6fc3..484f83a 100644 --- a/mlt/src/modules/gtk2/producer_pixbuf.c +++ b/mlt/src/modules/gtk2/producer_pixbuf.c @@ -20,10 +20,15 @@ #include "producer_pixbuf.h" #include +#include + #include #include #include -#include +#include +#include +#include +#include static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index ); static void producer_close( mlt_producer parent ); @@ -44,15 +49,44 @@ mlt_producer producer_pixbuf_init( const char *filename ) producer->get_frame = producer_get_frame; producer->close = producer_close; - this->filename = strdup( filename ); - this->counter = -1; - // Get the properties interface mlt_properties properties = mlt_producer_properties( &this->parent ); // Set the default properties mlt_properties_set_int( properties, "video_standard", mlt_video_standard_pal ); + mlt_properties_set_double( properties, "ttl", 5 ); + // Obtain filenames + if ( strchr( filename, '%' ) != NULL ) + { + // handle picture sequences + int i = 0; + int gap = 0; + char full[1024]; + + while ( gap < 100 ) + { + struct stat buf; + snprintf( full, 1023, filename, i ++ ); + if ( stat( full, &buf ) == 0 ) + { + this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); + this->filenames[ this->count ++ ] = strdup( full ); + gap = 0; + } + else + { + gap ++; + } + } + } + else + { + this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); + this->filenames[ this->count ++ ] = strdup( filename ); + } + + // Initialise gobject types g_type_init(); return producer; @@ -117,8 +151,17 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Obtain properties of frame mlt_properties properties = mlt_frame_properties( *frame ); + // Get the time to live for each frame + double ttl = mlt_properties_get_double( mlt_producer_properties( producer ), "ttl" ); + + // Image index + int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count; + + // Update timecode on the frame we're creating + mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + // optimization for subsequent iterations on single picture - if ( this->image != NULL ) + if ( this->image != NULL && image_idx == this->image_idx ) { // Set width/height mlt_properties_set_int( properties, "width", this->width ); @@ -135,31 +178,19 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_frame_push_get_image( *frame, producer_get_image ); } - else if ( strchr( this->filename, '%' ) != NULL ) - { - // handle picture sequences - char filename[1024]; - filename[1023] = 0; - int current = this->counter; - do - { - ++this->counter; - snprintf( filename, 1023, this->filename, this->counter ); - pixbuf = gdk_pixbuf_new_from_file( filename, &error ); - // allow discontinuity in frame numbers up to 99 - error = NULL; - } while ( pixbuf == NULL && ( this->counter - current ) < 100 ); - } - else + else { - pixbuf = gdk_pixbuf_new_from_file( this->filename, &error ); + free( this->image ); + free( this->alpha ); + this->image_idx = image_idx; + pixbuf = gdk_pixbuf_new_from_file( this->filenames[ image_idx ], &error ); } // If we have a pixbuf if ( pixbuf ) { // Scale to adjust for sample aspect ratio - if ( mlt_properties_get_int( properties, "video_stadnard" ) == mlt_video_standard_pal ) + if ( mlt_properties_get_int( properties, "video_standard" ) == mlt_video_standard_pal ) { GdkPixbuf *temp = pixbuf; GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf, @@ -215,22 +246,12 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_properties_set_int( properties, "height", this->height ); // Pass alpha and image on properties with or without destructor - if ( this->counter >= 0 ) - { - // if picture sequence pass the image and alpha data with destructor - mlt_properties_set_data( properties, "image", image, 0, free, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, 0, free, NULL ); - } - else - { - // if single picture, reference the image and alpha in the producer - this->image = image; - this->alpha = alpha; + this->image = image; + this->alpha = alpha; - // pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", image, 0, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL ); - } + // pass the image and alpha data without destructor + mlt_properties_set_data( properties, "image", image, 0, NULL, NULL ); + mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL ); // Set alpha call back ( *frame )->get_alpha_mask = producer_get_alpha_mask; @@ -239,9 +260,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_frame_push_get_image( *frame, producer_get_image ); } - // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); - // Calculate the next timecode mlt_producer_prepare_next( producer ); @@ -251,8 +269,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i static void producer_close( mlt_producer parent ) { producer_pixbuf this = parent->child; - if ( this->filename ) - free( this->filename ); if ( this->image ) free( this->image ); if ( this->alpha ) diff --git a/mlt/src/modules/gtk2/producer_pixbuf.h b/mlt/src/modules/gtk2/producer_pixbuf.h index c7f76ef..346a654 100644 --- a/mlt/src/modules/gtk2/producer_pixbuf.h +++ b/mlt/src/modules/gtk2/producer_pixbuf.h @@ -28,8 +28,12 @@ typedef struct producer_pixbuf_s *producer_pixbuf; struct producer_pixbuf_s { struct mlt_producer_s parent; - char *filename; - int counter; + + // File name list + char **filenames; + int count; + int image_idx; + int width; int height; uint8_t *image; diff --git a/mlt/src/modules/sdl/consumer_sdl.c b/mlt/src/modules/sdl/consumer_sdl.c index c75237e..764cab3 100644 --- a/mlt/src/modules/sdl/consumer_sdl.c +++ b/mlt/src/modules/sdl/consumer_sdl.c @@ -114,7 +114,7 @@ static void sdl_unlock_display( ) SDL_UnlockSurface( screen ); } -void sdl_fill_audio( void *udata, Uint8 *stream, int len ) +void sdl_fill_audio( void *udata, uint8_t *stream, int len ) { consumer_sdl this = udata; diff --git a/mlt/src/tests/charlie.c b/mlt/src/tests/charlie.c index 99fbdbf..f807b5d 100644 --- a/mlt/src/tests/charlie.c +++ b/mlt/src/tests/charlie.c @@ -81,7 +81,6 @@ int main( int argc, char **argv ) mlt_service service = NULL; mlt_consumer consumer = NULL; mlt_multitrack multitrack = NULL; - mlt_tractor tractor = NULL; mlt_producer producer = NULL; mlt_playlist playlist = NULL; mlt_field field = NULL; @@ -91,14 +90,15 @@ int main( int argc, char **argv ) // Set up containers playlist = mlt_playlist_init( ); - multitrack = mlt_multitrack_init( ); - tractor = mlt_tractor_init( ); - // Field must be connected on construction - field = mlt_field_init( mlt_multitrack_service( multitrack ) ); + // Construct the field + field = mlt_field_init( ); mlt_properties properties = mlt_field_properties( field ); mlt_properties_set_int( properties, "registered", 0 ); + // Get the multitrack from the field + multitrack = mlt_field_multitrack( field ); + // Parse the arguments for ( i = 1; i < argc; i ++ ) { @@ -133,25 +133,21 @@ int main( int argc, char **argv ) consumer= mlt_factory_consumer( "sdl", NULL ); // Connect producer to playlist - mlt_playlist_append( playlist, producer ); + if ( producer != NULL ) + mlt_playlist_append( playlist, producer ); // Connect multitrack to producer mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), 0 ); - // Connect tractor to field - mlt_tractor_connect( tractor, mlt_field_service( field ) ); - // Connect consumer to tractor - mlt_consumer_connect( consumer, mlt_tractor_service( tractor ) ); + mlt_consumer_connect( consumer, mlt_field_service( field ) ); // Transport functionality - transport( producer ); + transport( mlt_multitrack_producer( multitrack ) ); // Close the services mlt_consumer_close( consumer ); - mlt_tractor_close( tractor ); mlt_field_close( field ); - mlt_multitrack_close( multitrack ); mlt_producer_close( producer ); // Close the factory diff --git a/src/framework/mlt_field.c b/src/framework/mlt_field.c index dfa15f4..a54d97e 100644 --- a/src/framework/mlt_field.c +++ b/src/framework/mlt_field.c @@ -22,6 +22,8 @@ #include "mlt_service.h" #include "mlt_filter.h" #include "mlt_transition.h" +#include "mlt_multitrack.h" +#include "mlt_tractor.h" #include #include @@ -31,49 +33,41 @@ struct mlt_field_s { - // We extending service here - struct mlt_service_s parent; - // This is the producer we're connected to mlt_service producer; -}; -/** Forward declarations -*/ + // Multitrack + mlt_multitrack multitrack; -static int service_get_frame( mlt_service service, mlt_frame_ptr frame, int index ); - -/** Constructor. This service needs to know its producer at construction. + // Tractor + mlt_tractor tractor; +}; - When the first filter or transition is planted, we connect it immediately to - the producer of the field, and all subsequent plants are then connected to the - previous plant. This immediate connection requires the producer prior to the first - plant. +/** Constructor. - It's a kind of arbitrary decsion - we could generate a dummy service here and - then connect the dummy in the normal connect manner. Behaviour may change in the - future (say, constructing a dummy when producer service is NULL). However, the - current solution is quite clean, if slightly out of sync with the rest of the - mlt framework. + We construct a multitrack and a tractor here. */ -mlt_field mlt_field_init( mlt_service producer ) +mlt_field mlt_field_init( ) { // Initialise the field mlt_field this = calloc( sizeof( struct mlt_field_s ), 1 ); - // Get the service - mlt_service service = &this->parent; + // Initialise it + if ( this != NULL ) + { + // Construct a multitrack + this->multitrack = mlt_multitrack_init( ); - // Initialise the service - mlt_service_init( service, this ); + // Construct a tractor + this->tractor = mlt_tractor_init( ); - // Override the get_frame method - service->get_frame = service_get_frame; + // The first plant will be connected to the mulitrack + this->producer = mlt_multitrack_service( this->multitrack ); - // Connect to the producer immediately - if ( mlt_service_connect_producer( service, producer, 0 ) == 0 ) - this->producer = producer; + // Connect the tractor to the multitrack + mlt_tractor_connect( this->tractor, this->producer ); + } // Return this return this; @@ -84,7 +78,15 @@ mlt_field mlt_field_init( mlt_service producer ) mlt_service mlt_field_service( mlt_field this ) { - return &this->parent; + return mlt_tractor_service( this->tractor ); +} + +/** Get the multi track. +*/ + +mlt_multitrack mlt_field_multitrack( mlt_field this ) +{ + return this->multitrack; } /** Get the properties associated to this field. @@ -92,7 +94,7 @@ mlt_service mlt_field_service( mlt_field this ) mlt_properties mlt_field_properties( mlt_field this ) { - return mlt_service_properties( &this->parent ); + return mlt_service_properties( mlt_field_service( this ) ); } /** Plant a filter. @@ -106,8 +108,11 @@ int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track ) // If sucessful, then we'll use this for connecting in the future if ( result == 0 ) { - // Update last + // This is now the new producer this->producer = mlt_filter_service( that ); + + // Reconnect tractor to new producer + mlt_tractor_connect( this->tractor, this->producer ); } return result; @@ -124,28 +129,23 @@ int mlt_field_plant_transition( mlt_field this, mlt_transition that, int a_track // If sucessful, then we'll use this for connecting in the future if ( result == 0 ) { - // Update last + // This is now the new producer this->producer = mlt_transition_service( that ); + + // Reconnect tractor to new producer + mlt_tractor_connect( this->tractor, this->producer ); } return 0; } -/** Get a frame. -*/ - -static int service_get_frame( mlt_service service, mlt_frame_ptr frame, int index ) -{ - mlt_field this = service->child; - return mlt_service_get_frame( this->producer, frame, index ); -} - /** Close the field. */ void mlt_field_close( mlt_field this ) { - mlt_service_close( &this->parent ); + mlt_tractor_close( this->tractor ); + mlt_multitrack_close( this->multitrack ); free( this ); } diff --git a/src/framework/mlt_field.h b/src/framework/mlt_field.h index 427032f..6fef296 100644 --- a/src/framework/mlt_field.h +++ b/src/framework/mlt_field.h @@ -23,8 +23,9 @@ #include "mlt_types.h" -extern mlt_field mlt_field_init( mlt_service producer ); +extern mlt_field mlt_field_init( ); extern mlt_service mlt_field_service( mlt_field this ); +extern mlt_multitrack mlt_field_multitrack( mlt_field this ); extern mlt_properties mlt_field_properties( mlt_field this ); extern int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track ); extern int mlt_field_plant_transition( mlt_field this, mlt_transition that, int a_track, int b_track ); diff --git a/src/framework/mlt_filter.c b/src/framework/mlt_filter.c index af4a3c6..9c0a295 100644 --- a/src/framework/mlt_filter.c +++ b/src/framework/mlt_filter.c @@ -62,6 +62,11 @@ mlt_service mlt_filter_service( mlt_filter this ) return &this->parent; } +mlt_properties mlt_filter_properties( mlt_filter this ) +{ + return mlt_service_properties( mlt_filter_service( this ) ); +} + /** Connect this filter to a producers track. Note that a filter only operates on a single track, and by default it operates on the entirety of that track. */ diff --git a/src/framework/mlt_filter.h b/src/framework/mlt_filter.h index df5b641..e3f0f74 100644 --- a/src/framework/mlt_filter.h +++ b/src/framework/mlt_filter.h @@ -39,9 +39,6 @@ struct mlt_filter_s // track and in/out points mlt_service producer; - //int track; - //mlt_timecode in; - //mlt_timecode out; // Protected void *child; @@ -52,6 +49,7 @@ struct mlt_filter_s extern int mlt_filter_init( mlt_filter this, void *child ); extern mlt_service mlt_filter_service( mlt_filter this ); +extern mlt_properties mlt_filter_properties( mlt_filter this ); extern int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ); extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out ); extern int mlt_filter_get_track( mlt_filter this ); diff --git a/src/framework/mlt_playlist.c b/src/framework/mlt_playlist.c index f786d31..eb89f04 100644 --- a/src/framework/mlt_playlist.c +++ b/src/framework/mlt_playlist.c @@ -42,14 +42,11 @@ playlist_entry; struct mlt_playlist_s { struct mlt_producer_s parent; + struct mlt_producer_s blank; + int size; int count; - mlt_producer *list; - mlt_producer blank; - - int virtual_size; - int virtual_count; - playlist_entry **virtual_list; + playlist_entry **list; }; /** Forward declarations @@ -73,11 +70,8 @@ mlt_playlist mlt_playlist_init( ) // Override the producer get_frame producer->get_frame = producer_get_frame; - // Create a producer - this->blank = calloc( sizeof( struct mlt_producer_s ), 1 ); - - // Initialise it - mlt_producer_init( this->blank, NULL ); + // Initialise blank + mlt_producer_init( &this->blank, NULL ); } return this; @@ -99,56 +93,27 @@ mlt_service mlt_playlist_service( mlt_playlist this ) return mlt_producer_service( &this->parent ); } -/** Store a producer in the playlist. +/** Append to the virtual playlist. */ -static int mlt_playlist_store( mlt_playlist this, mlt_producer producer ) +static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, mlt_timecode in, mlt_timecode out ) { - int i; - - // If it's already added, return the index - for ( i = 0; i < this->count; i ++ ) - { - if ( producer == this->list[ i ] ) - return i; - } - // Check that we have room if ( this->count >= this->size ) { - this->list = realloc( this->list, ( this->size + 10 ) * sizeof( mlt_producer ) ); + int i; + this->list = realloc( this->list, ( this->size + 10 ) * sizeof( playlist_entry * ) ); for ( i = this->size; i < this->size + 10; i ++ ) this->list[ i ] = NULL; this->size += 10; } - // Add this producer to the list - this->list[ this->count ] = producer; + this->list[ this->count ] = calloc( sizeof( playlist_entry ), 1 ); + this->list[ this->count ]->producer = producer; + this->list[ this->count ]->in = in; + this->list[ this->count ]->playtime = out - in; - return this->count ++; -} - -/** Append to the virtual playlist. -*/ - -static int mlt_playlist_virtual_append( mlt_playlist this, int position, mlt_timecode in, mlt_timecode out ) -{ - // Check that we have room - if ( this->virtual_count >= this->virtual_size ) - { - int i; - this->virtual_list = realloc( this->virtual_list, ( this->virtual_size + 10 ) * sizeof( playlist_entry * ) ); - for ( i = this->virtual_size; i < this->virtual_size + 10; i ++ ) - this->virtual_list[ i ] = NULL; - this->virtual_size += 10; - } - - this->virtual_list[ this->virtual_count ] = malloc( sizeof( playlist_entry ) ); - this->virtual_list[ this->virtual_count ]->producer = this->list[ position ]; - this->virtual_list[ this->virtual_count ]->in = in; - this->virtual_list[ this->virtual_count ]->playtime = out - in; - - this->virtual_count ++; + this->count ++; return 0; } @@ -159,7 +124,7 @@ static int mlt_playlist_virtual_append( mlt_playlist this, int position, mlt_tim static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) { // Default producer to blank - mlt_producer producer = this->blank; + mlt_producer producer = &this->blank; // Map playlist position to real producer in virtual playlist mlt_timecode position = mlt_producer_position( &this->parent ); @@ -167,19 +132,19 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) // Loop through the virtual playlist int i = 0; - for ( i = 0; i < this->virtual_count; i ++ ) + for ( i = 0; i < this->count; i ++ ) { - if ( position < this->virtual_list[ i ]->playtime ) + if ( position < this->list[ i ]->playtime ) { // Found it, now break - producer = this->virtual_list[ i ]->producer; - position += this->virtual_list[ i ]->in; + producer = this->list[ i ]->producer; + position += this->list[ i ]->in; break; } else { // Decrement position by length of this entry - position -= this->virtual_list[ i ]->playtime; + position -= this->list[ i ]->playtime; } } @@ -194,13 +159,8 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) int mlt_playlist_append( mlt_playlist this, mlt_producer producer ) { - // Get the position of the producer in the list - int position = mlt_playlist_store( this, producer ); - // Append to virtual list - mlt_playlist_virtual_append( this, position, 0, mlt_producer_get_playtime( producer ) ); - - return 0; + return mlt_playlist_virtual_append( this, producer, 0, mlt_producer_get_playtime( producer ) ); } /** Append a blank to the playlist of a given length. @@ -208,13 +168,8 @@ int mlt_playlist_append( mlt_playlist this, mlt_producer producer ) int mlt_playlist_blank( mlt_playlist this, mlt_timecode length ) { - // Get the position of the producer in the list - int position = mlt_playlist_store( this, this->blank ); - // Append to the virtual list - mlt_playlist_virtual_append( this, position, 0, length ); - - return 0; + return mlt_playlist_virtual_append( this, &this->blank, 0, length ); } /** Get the current frame. @@ -246,7 +201,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i void mlt_playlist_close( mlt_playlist this ) { mlt_producer_close( &this->parent ); - mlt_producer_close( this->blank ); - free( this->blank ); + mlt_producer_close( &this->blank ); free( this ); } diff --git a/src/modules/core/Makefile b/src/modules/core/Makefile index 5ef6eb2..fe4a0bb 100644 --- a/src/modules/core/Makefile +++ b/src/modules/core/Makefile @@ -5,6 +5,7 @@ OBJS = factory.o \ producer_ppm.o \ filter_deinterlace.o \ filter_greyscale.o \ + filter_resize.o \ transition_composite.o CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread diff --git a/src/modules/core/configure b/src/modules/core/configure index 43f2780..2f3457e 100755 --- a/src/modules/core/configure +++ b/src/modules/core/configure @@ -10,6 +10,7 @@ EOF cat << EOF >> ../filters.dat deinterlace libmltcore.so greyscale libmltcore.so +resize libmltcore.so EOF cat << EOF >> ../transitions.dat diff --git a/src/modules/core/factory.c b/src/modules/core/factory.c index 2f517b8..eb19049 100644 --- a/src/modules/core/factory.c +++ b/src/modules/core/factory.c @@ -22,6 +22,7 @@ #include "filter_deinterlace.h" #include "filter_greyscale.h" +#include "filter_resize.h" #include "producer_ppm.h" #include "transition_composite.h" @@ -38,6 +39,8 @@ void *mlt_create_filter( char *id, void *arg ) return filter_deinterlace_init( arg ); if ( !strcmp( id, "greyscale" ) ) return filter_greyscale_init( arg ); + if ( !strcmp( id, "resize" ) ) + return filter_resize_init( arg ); return NULL; } diff --git a/src/modules/core/filter_resize.c b/src/modules/core/filter_resize.c new file mode 100644 index 0000000..1ebb741 --- /dev/null +++ b/src/modules/core/filter_resize.c @@ -0,0 +1,66 @@ +/* + * filter_resize.c -- resizing filter + * Copyright (C) 2003-2004 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 program 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. + * + * 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. + */ + +#include "filter_resize.h" + +#include + +#include +#include + +/** Do it :-). +*/ + +static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +{ + int owidth = *width; + int oheight = *height; + mlt_frame_get_image( this, image, format, &owidth, &oheight, 0 ); + if ( !strcmp( mlt_properties_get( mlt_frame_properties( this ), "resize.scale" ), "affine" ) ) + *image = mlt_frame_rescale_yuv422( this, *width, *height ); + else + *image = mlt_frame_resize_yuv422( this, *width, *height ); + return 0; +} + +/** Filter processing. +*/ + +static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) +{ + mlt_frame_push_get_image( frame, filter_get_image ); + mlt_properties_set( mlt_frame_properties( frame ), "resize.scale", mlt_properties_get( mlt_filter_properties( this ), "scale" ) ); + return frame; +} + +/** Constructor for the filter. +*/ + +mlt_filter filter_resize_init( void *arg ) +{ + mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 ); + if ( mlt_filter_init( this, this ) == 0 ) + { + this->process = filter_process; + mlt_properties_set( mlt_filter_properties( this ), "scale", "off" ); + } + return this; +} + diff --git a/src/modules/core/filter_resize.h b/src/modules/core/filter_resize.h new file mode 100644 index 0000000..cdac48b --- /dev/null +++ b/src/modules/core/filter_resize.h @@ -0,0 +1,28 @@ +/* + * filter_resize.h -- resizing filter + * Copyright (C) 2003-2004 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 program 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. + * + * 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. + */ + +#ifndef _FILTER_RESIZE_H_ +#define _FILTER_RESIZE_H_ + +#include + +extern mlt_filter filter_deinterlace_init( void *arg ); + +#endif diff --git a/src/modules/gtk2/producer_pixbuf.c b/src/modules/gtk2/producer_pixbuf.c index 97a6fc3..484f83a 100644 --- a/src/modules/gtk2/producer_pixbuf.c +++ b/src/modules/gtk2/producer_pixbuf.c @@ -20,10 +20,15 @@ #include "producer_pixbuf.h" #include +#include + #include #include #include -#include +#include +#include +#include +#include static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index ); static void producer_close( mlt_producer parent ); @@ -44,15 +49,44 @@ mlt_producer producer_pixbuf_init( const char *filename ) producer->get_frame = producer_get_frame; producer->close = producer_close; - this->filename = strdup( filename ); - this->counter = -1; - // Get the properties interface mlt_properties properties = mlt_producer_properties( &this->parent ); // Set the default properties mlt_properties_set_int( properties, "video_standard", mlt_video_standard_pal ); + mlt_properties_set_double( properties, "ttl", 5 ); + // Obtain filenames + if ( strchr( filename, '%' ) != NULL ) + { + // handle picture sequences + int i = 0; + int gap = 0; + char full[1024]; + + while ( gap < 100 ) + { + struct stat buf; + snprintf( full, 1023, filename, i ++ ); + if ( stat( full, &buf ) == 0 ) + { + this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); + this->filenames[ this->count ++ ] = strdup( full ); + gap = 0; + } + else + { + gap ++; + } + } + } + else + { + this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); + this->filenames[ this->count ++ ] = strdup( filename ); + } + + // Initialise gobject types g_type_init(); return producer; @@ -117,8 +151,17 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Obtain properties of frame mlt_properties properties = mlt_frame_properties( *frame ); + // Get the time to live for each frame + double ttl = mlt_properties_get_double( mlt_producer_properties( producer ), "ttl" ); + + // Image index + int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count; + + // Update timecode on the frame we're creating + mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + // optimization for subsequent iterations on single picture - if ( this->image != NULL ) + if ( this->image != NULL && image_idx == this->image_idx ) { // Set width/height mlt_properties_set_int( properties, "width", this->width ); @@ -135,31 +178,19 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_frame_push_get_image( *frame, producer_get_image ); } - else if ( strchr( this->filename, '%' ) != NULL ) - { - // handle picture sequences - char filename[1024]; - filename[1023] = 0; - int current = this->counter; - do - { - ++this->counter; - snprintf( filename, 1023, this->filename, this->counter ); - pixbuf = gdk_pixbuf_new_from_file( filename, &error ); - // allow discontinuity in frame numbers up to 99 - error = NULL; - } while ( pixbuf == NULL && ( this->counter - current ) < 100 ); - } - else + else { - pixbuf = gdk_pixbuf_new_from_file( this->filename, &error ); + free( this->image ); + free( this->alpha ); + this->image_idx = image_idx; + pixbuf = gdk_pixbuf_new_from_file( this->filenames[ image_idx ], &error ); } // If we have a pixbuf if ( pixbuf ) { // Scale to adjust for sample aspect ratio - if ( mlt_properties_get_int( properties, "video_stadnard" ) == mlt_video_standard_pal ) + if ( mlt_properties_get_int( properties, "video_standard" ) == mlt_video_standard_pal ) { GdkPixbuf *temp = pixbuf; GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf, @@ -215,22 +246,12 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_properties_set_int( properties, "height", this->height ); // Pass alpha and image on properties with or without destructor - if ( this->counter >= 0 ) - { - // if picture sequence pass the image and alpha data with destructor - mlt_properties_set_data( properties, "image", image, 0, free, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, 0, free, NULL ); - } - else - { - // if single picture, reference the image and alpha in the producer - this->image = image; - this->alpha = alpha; + this->image = image; + this->alpha = alpha; - // pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", image, 0, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL ); - } + // pass the image and alpha data without destructor + mlt_properties_set_data( properties, "image", image, 0, NULL, NULL ); + mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL ); // Set alpha call back ( *frame )->get_alpha_mask = producer_get_alpha_mask; @@ -239,9 +260,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_frame_push_get_image( *frame, producer_get_image ); } - // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); - // Calculate the next timecode mlt_producer_prepare_next( producer ); @@ -251,8 +269,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i static void producer_close( mlt_producer parent ) { producer_pixbuf this = parent->child; - if ( this->filename ) - free( this->filename ); if ( this->image ) free( this->image ); if ( this->alpha ) diff --git a/src/modules/gtk2/producer_pixbuf.h b/src/modules/gtk2/producer_pixbuf.h index c7f76ef..346a654 100644 --- a/src/modules/gtk2/producer_pixbuf.h +++ b/src/modules/gtk2/producer_pixbuf.h @@ -28,8 +28,12 @@ typedef struct producer_pixbuf_s *producer_pixbuf; struct producer_pixbuf_s { struct mlt_producer_s parent; - char *filename; - int counter; + + // File name list + char **filenames; + int count; + int image_idx; + int width; int height; uint8_t *image; diff --git a/src/modules/sdl/consumer_sdl.c b/src/modules/sdl/consumer_sdl.c index c75237e..764cab3 100644 --- a/src/modules/sdl/consumer_sdl.c +++ b/src/modules/sdl/consumer_sdl.c @@ -114,7 +114,7 @@ static void sdl_unlock_display( ) SDL_UnlockSurface( screen ); } -void sdl_fill_audio( void *udata, Uint8 *stream, int len ) +void sdl_fill_audio( void *udata, uint8_t *stream, int len ) { consumer_sdl this = udata; diff --git a/src/tests/charlie.c b/src/tests/charlie.c index 99fbdbf..f807b5d 100644 --- a/src/tests/charlie.c +++ b/src/tests/charlie.c @@ -81,7 +81,6 @@ int main( int argc, char **argv ) mlt_service service = NULL; mlt_consumer consumer = NULL; mlt_multitrack multitrack = NULL; - mlt_tractor tractor = NULL; mlt_producer producer = NULL; mlt_playlist playlist = NULL; mlt_field field = NULL; @@ -91,14 +90,15 @@ int main( int argc, char **argv ) // Set up containers playlist = mlt_playlist_init( ); - multitrack = mlt_multitrack_init( ); - tractor = mlt_tractor_init( ); - // Field must be connected on construction - field = mlt_field_init( mlt_multitrack_service( multitrack ) ); + // Construct the field + field = mlt_field_init( ); mlt_properties properties = mlt_field_properties( field ); mlt_properties_set_int( properties, "registered", 0 ); + // Get the multitrack from the field + multitrack = mlt_field_multitrack( field ); + // Parse the arguments for ( i = 1; i < argc; i ++ ) { @@ -133,25 +133,21 @@ int main( int argc, char **argv ) consumer= mlt_factory_consumer( "sdl", NULL ); // Connect producer to playlist - mlt_playlist_append( playlist, producer ); + if ( producer != NULL ) + mlt_playlist_append( playlist, producer ); // Connect multitrack to producer mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), 0 ); - // Connect tractor to field - mlt_tractor_connect( tractor, mlt_field_service( field ) ); - // Connect consumer to tractor - mlt_consumer_connect( consumer, mlt_tractor_service( tractor ) ); + mlt_consumer_connect( consumer, mlt_field_service( field ) ); // Transport functionality - transport( producer ); + transport( mlt_multitrack_producer( multitrack ) ); // Close the services mlt_consumer_close( consumer ); - mlt_tractor_close( tractor ); mlt_field_close( field ); - mlt_multitrack_close( multitrack ); mlt_producer_close( producer ); // Close the factory