]> git.sesse.net Git - mlt/commitdiff
field and playlist enhancements, producer pixbuf reorg
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Thu, 25 Dec 2003 20:25:35 +0000 (20:25 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Thu, 25 Dec 2003 20:25:35 +0000 (20:25 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@16 d19143bc-622f-0410-bfdd-b5b2a6649095

28 files changed:
mlt/src/framework/mlt_field.c
mlt/src/framework/mlt_field.h
mlt/src/framework/mlt_filter.c
mlt/src/framework/mlt_filter.h
mlt/src/framework/mlt_playlist.c
mlt/src/modules/core/Makefile
mlt/src/modules/core/configure
mlt/src/modules/core/factory.c
mlt/src/modules/core/filter_resize.c [new file with mode: 0644]
mlt/src/modules/core/filter_resize.h [new file with mode: 0644]
mlt/src/modules/gtk2/producer_pixbuf.c
mlt/src/modules/gtk2/producer_pixbuf.h
mlt/src/modules/sdl/consumer_sdl.c
mlt/src/tests/charlie.c
src/framework/mlt_field.c
src/framework/mlt_field.h
src/framework/mlt_filter.c
src/framework/mlt_filter.h
src/framework/mlt_playlist.c
src/modules/core/Makefile
src/modules/core/configure
src/modules/core/factory.c
src/modules/core/filter_resize.c [new file with mode: 0644]
src/modules/core/filter_resize.h [new file with mode: 0644]
src/modules/gtk2/producer_pixbuf.c
src/modules/gtk2/producer_pixbuf.h
src/modules/sdl/consumer_sdl.c
src/tests/charlie.c

index dfa15f4db7998debe4f44ab0ca9af7bee17e672c..a54d97e19e1cf4672672efc3702461d0b36d3833 100644 (file)
@@ -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 <stdlib.h>
 #include <string.h>
 
 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 );
 }
 
index 427032fcd540ac231e7167a7566d3a7f025ee36d..6fef29606890b9174f36f2f669aeddc4f33f3c77 100644 (file)
@@ -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 );
index af4a3c63a41971fd6d7b333b27cb07ce945dd322..9c0a295234443da8b29cf4105fe6313eb04f6e8c 100644 (file)
@@ -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.
 */
index df5b6414fdb8086c0aac1706165ffff6a883844f..e3f0f74dccdb4586dacb0b0a1a2e97627a325644 100644 (file)
@@ -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 );
index f786d31d0c10e45296af3feb593fefe1bcef0708..eb89f04c2c9ed4d1283388b127d049d029dc80ba 100644 (file)
@@ -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 );
 }
index 5ef6eb2dfa0b280b4216c0a8cee44a175fcfb778..fe4a0bbb965103799eea42bb9dbb3420a0e0e830 100644 (file)
@@ -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
index 43f278069e70167ec6880d9a2b07da0a7b62580a..2f3457e631d1d594cd541c5c0e90bdab8c3157bd 100755 (executable)
@@ -10,6 +10,7 @@ EOF
 cat << EOF >> ../filters.dat
 deinterlace            libmltcore.so
 greyscale              libmltcore.so
+resize                 libmltcore.so
 EOF
 
 cat << EOF >> ../transitions.dat
index 2f517b80ffcea0da5be17e5f9f0bb9811937825e..eb190494cd1511b90392776665a5f1dc163731b8 100644 (file)
@@ -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 (file)
index 0000000..1ebb741
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * filter_resize.c -- resizing filter
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * 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 <framework/mlt_frame.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+/** 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 (file)
index 0000000..cdac48b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * filter_resize.h -- resizing filter
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * 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 <framework/mlt_filter.h>
+
+extern mlt_filter filter_deinterlace_init( void *arg );
+
+#endif
index 97a6fc3ecdf5ffd4533be32bbf49232f1d10df52..484f83a38a075301d483a85f3a18016a6aeb5c79 100644 (file)
 
 #include "producer_pixbuf.h"
 #include <framework/mlt_frame.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 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 )
index c7f76ef31f597284e80dc15d9a7bf8ac6fefd6b7..346a65441b31142445767c5059632d75f2cf0cd6 100644 (file)
@@ -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;
index c75237e7d10eb0e824ee9760e3e676860115e8a9..764cab36f556727edacec4af67f0105259dc649e 100644 (file)
@@ -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;
 
index 99fbdbf5c46546d31b64d8e48fd5a72598496383..f807b5d67e3c910d99031b3c92949d5268762481 100644 (file)
@@ -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
index dfa15f4db7998debe4f44ab0ca9af7bee17e672c..a54d97e19e1cf4672672efc3702461d0b36d3833 100644 (file)
@@ -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 <stdlib.h>
 #include <string.h>
 
 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 );
 }
 
index 427032fcd540ac231e7167a7566d3a7f025ee36d..6fef29606890b9174f36f2f669aeddc4f33f3c77 100644 (file)
@@ -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 );
index af4a3c63a41971fd6d7b333b27cb07ce945dd322..9c0a295234443da8b29cf4105fe6313eb04f6e8c 100644 (file)
@@ -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.
 */
index df5b6414fdb8086c0aac1706165ffff6a883844f..e3f0f74dccdb4586dacb0b0a1a2e97627a325644 100644 (file)
@@ -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 );
index f786d31d0c10e45296af3feb593fefe1bcef0708..eb89f04c2c9ed4d1283388b127d049d029dc80ba 100644 (file)
@@ -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 );
 }
index 5ef6eb2dfa0b280b4216c0a8cee44a175fcfb778..fe4a0bbb965103799eea42bb9dbb3420a0e0e830 100644 (file)
@@ -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
index 43f278069e70167ec6880d9a2b07da0a7b62580a..2f3457e631d1d594cd541c5c0e90bdab8c3157bd 100755 (executable)
@@ -10,6 +10,7 @@ EOF
 cat << EOF >> ../filters.dat
 deinterlace            libmltcore.so
 greyscale              libmltcore.so
+resize                 libmltcore.so
 EOF
 
 cat << EOF >> ../transitions.dat
index 2f517b80ffcea0da5be17e5f9f0bb9811937825e..eb190494cd1511b90392776665a5f1dc163731b8 100644 (file)
@@ -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 (file)
index 0000000..1ebb741
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * filter_resize.c -- resizing filter
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * 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 <framework/mlt_frame.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+/** 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 (file)
index 0000000..cdac48b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * filter_resize.h -- resizing filter
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * 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 <framework/mlt_filter.h>
+
+extern mlt_filter filter_deinterlace_init( void *arg );
+
+#endif
index 97a6fc3ecdf5ffd4533be32bbf49232f1d10df52..484f83a38a075301d483a85f3a18016a6aeb5c79 100644 (file)
 
 #include "producer_pixbuf.h"
 #include <framework/mlt_frame.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 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 )
index c7f76ef31f597284e80dc15d9a7bf8ac6fefd6b7..346a65441b31142445767c5059632d75f2cf0cd6 100644 (file)
@@ -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;
index c75237e7d10eb0e824ee9760e3e676860115e8a9..764cab36f556727edacec4af67f0105259dc649e 100644 (file)
@@ -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;
 
index 99fbdbf5c46546d31b64d8e48fd5a72598496383..f807b5d67e3c910d99031b3c92949d5268762481 100644 (file)
@@ -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