]> git.sesse.net Git - mlt/blobdiff - src/modules/gtk2/producer_pixbuf.c
Avoid unnecessary compilation when running "./configure; make; make install" multiple...
[mlt] / src / modules / gtk2 / producer_pixbuf.c
index d1b3517f7e1e0f050ad419dda8fb0530de08bcc7..1ec705e3e6fd4e8e24d3524079accccfadda1760 100644 (file)
 #include <framework/mlt_frame.h>
 #include <framework/mlt_cache.h>
 #include <framework/mlt_log.h>
+#include <framework/mlt_tokeniser.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
-#include "config.h"
-
 #ifdef USE_EXIF
 #include <libexif/exif-data.h>
 #endif
@@ -39,6 +38,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <dirent.h>
+#include <ctype.h>
 
 // this protects concurrent access to gdk_pixbuf
 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -72,7 +72,7 @@ static void producer_close( mlt_producer parent );
 
 mlt_producer producer_pixbuf_init( char *filename )
 {
-       producer_pixbuf self = calloc( sizeof( struct producer_pixbuf_s ), 1 );
+       producer_pixbuf self = calloc( 1, sizeof( struct producer_pixbuf_s ) );
        if ( self != NULL && mlt_producer_init( &self->parent, self ) == 0 )
        {
                mlt_producer producer = &self->parent;
@@ -89,6 +89,8 @@ mlt_producer producer_pixbuf_init( char *filename )
                mlt_properties_set_int( properties, "ttl", 25 );
                mlt_properties_set_int( properties, "aspect_ratio", 1 );
                mlt_properties_set_int( properties, "progressive", 1 );
+               mlt_properties_set_int( properties, "seekable", 1 );
+               mlt_properties_set_int( properties, "loop", 1 );
 
                // Validate the resource
                if ( filename )
@@ -101,8 +103,8 @@ mlt_producer producer_pixbuf_init( char *filename )
                                mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
                                mlt_properties_set_data( frame_properties, "producer_pixbuf", self, 0, NULL, NULL );
                                mlt_frame_set_position( frame, mlt_producer_position( producer ) );
-                               mlt_properties_set_position( frame_properties, "pixbuf_position", mlt_producer_position( producer ) );
                                refresh_pixbuf( self, frame );
+                               mlt_cache_item_close( self->pixbuf_cache );
                                mlt_frame_close( frame );
                        }
                }
@@ -153,7 +155,7 @@ static int load_svg( producer_pixbuf self, mlt_properties properties, const char
        return result;
 }
 
-static int load_sequence( producer_pixbuf self, mlt_properties properties, const char *filename )
+static int load_sequence_sprintf( producer_pixbuf self, mlt_properties properties, const char *filename )
 {
        int result = 0;
 
@@ -191,6 +193,57 @@ static int load_sequence( producer_pixbuf self, mlt_properties properties, const
        return result;
 }
 
+static int load_sequence_deprecated( producer_pixbuf self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+       const char *start;
+
+       // This approach is deprecated in favor of the begin querystring parameter.
+       // Obtain filenames with pattern containing a begin value, e.g. foo%1234d.png
+       if ( ( start = strchr( filename, '%' ) ) )
+       {
+               const char *end = ++start;
+               while ( isdigit( *end ) ) end++;
+               if ( end > start && ( end[0] == 'd' || end[0] == 'i' || end[0] == 'u' ) )
+               {
+                       int n = end - start;
+                       char *s = calloc( 1, n + 1 );
+                       strncpy( s, start, n );
+                       mlt_properties_set( properties, "begin", s );
+                       free( s );
+                       s = calloc( 1, strlen( filename ) + 2 );
+                       strncpy( s, filename, start - filename );
+                       sprintf( s + ( start - filename ), ".%d%s", n, end );
+                       result = load_sequence_sprintf( self, properties, s );
+                       free( s );
+               }
+       }
+       return result;
+}
+
+static int load_sequence_querystring( producer_pixbuf self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+
+       // Obtain filenames with pattern and begin value in query string
+       if ( strchr( filename, '%' ) && strchr( filename, '?' ) )
+       {
+               // Split filename into pattern and query string
+               char *s = strdup( filename );
+               char *querystring = strrchr( s, '?' );
+               *querystring++ = '\0';
+               if ( strstr( filename, "begin=" ) )
+                       mlt_properties_set( properties, "begin", strstr( querystring, "begin=" ) + 6 );
+               else if ( strstr( filename, "begin:" ) )
+                       mlt_properties_set( properties, "begin", strstr( querystring, "begin:" ) + 6 );
+               // Coerce to an int value so serialization does not have any extra query string cruft
+               mlt_properties_set_int( properties, "begin", mlt_properties_get_int( properties, "begin" ) );
+               result = load_sequence_sprintf( self, properties, s );
+               free( s );
+       }
+       return result;
+}
+
 static int load_folder( producer_pixbuf self, mlt_properties properties, const char *filename )
 {
        int result = 0;
@@ -219,7 +272,9 @@ static void load_filenames( producer_pixbuf self, mlt_properties properties )
        self->filenames = mlt_properties_new( );
 
        if (!load_svg( self, properties, filename ) &&
-               !load_sequence( self, properties, filename ) &&
+               !load_sequence_querystring( self, properties, filename ) &&
+               !load_sequence_sprintf( self, properties, filename ) &&
+               !load_sequence_deprecated( self, properties, filename ) &&
                !load_folder( self, properties, filename ) )
        {
                mlt_properties_set( self->filenames, "0", filename );
@@ -311,11 +366,17 @@ static int refresh_pixbuf( producer_pixbuf self, mlt_frame frame )
        double ttl = mlt_properties_get_int( producer_props, "ttl" );
 
        // Get the original position of this frame
-       mlt_position position = mlt_properties_get_position( properties, "pixbuf_position" );
+       mlt_position position = mlt_frame_original_position( frame );
        position += mlt_producer_get_in( producer );
 
        // Image index
-       int current_idx = ( int )floor( ( double )position / ttl ) % self->count;
+       int loop = mlt_properties_get_int( producer_props, "loop" );
+       int current_idx;
+       if (loop) {
+               current_idx = ( int )floor( ( double )position / ttl ) % self->count;
+       } else {
+               current_idx = MIN(( double )position / ttl, self->count - 1);
+       }
 
        // Key for the cache
        char image_key[ 10 ];
@@ -384,14 +445,19 @@ static void refresh_image( producer_pixbuf self, mlt_frame frame, mlt_image_form
        if ( self->pixbuf && ( !self->image || ( format != mlt_image_none && format != self->format ) ) )
        {
                char *interps = mlt_properties_get( properties, "rescale.interp" );
+               if ( interps ) interps = strdup( interps );
                int interp = GDK_INTERP_BILINEAR;
 
-               if ( strcmp( interps, "nearest" ) == 0 )
+               if ( !interps ) {
+                       // Keep bilinear by default
+               }
+               else if ( strcmp( interps, "nearest" ) == 0 )
                        interp = GDK_INTERP_NEAREST;
                else if ( strcmp( interps, "tiles" ) == 0 )
                        interp = GDK_INTERP_TILES;
                else if ( strcmp( interps, "hyper" ) == 0 || strcmp( interps, "bicubic" ) == 0 )
                        interp = GDK_INTERP_HYPER;
+               if ( interps ) free( interps );
 
                // Note - the original pixbuf is already safe and ready for destruction
                pthread_mutex_lock( &g_mutex );
@@ -407,6 +473,7 @@ static void refresh_image( producer_pixbuf self, mlt_frame frame, mlt_image_form
                int dst_stride = self->width * ( has_alpha ? 4 : 3 );
                int image_size = dst_stride * ( height + 1 );
                self->image = mlt_pool_alloc( image_size );
+               self->alpha = NULL;
                self->format = has_alpha ? mlt_image_rgb24a : mlt_image_rgb24;
 
                if ( src_stride != dst_stride )
@@ -454,13 +521,18 @@ static void refresh_image( producer_pixbuf self, mlt_frame frame, mlt_image_form
                        }
                }
 
+               // Update the cache
                mlt_cache_item_close( self->image_cache );
                mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image", self->image, image_size, mlt_pool_release );
                self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" );
                self->image_idx = current_idx;
                mlt_cache_item_close( self->alpha_cache );
-               mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha", self->alpha, width * height, mlt_pool_release );
-               self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" );
+               self->alpha_cache = NULL;
+               if ( self->alpha )
+               {
+                       mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha", self->alpha, width * height, mlt_pool_release );
+                       self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" );
+               }
 
                // Finished with pixbuf now
                g_object_unref( pixbuf );
@@ -481,8 +553,10 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        mlt_producer producer = &self->parent;
 
        // Use the width and height suggested by the rescale filter because we can do our own scaling.
-       *width = mlt_properties_get_int( properties, "rescale_width" );
-       *height = mlt_properties_get_int( properties, "rescale_height" );
+       if ( mlt_properties_get_int( properties, "rescale_width" ) > 0 )
+               *width = mlt_properties_get_int( properties, "rescale_width" );
+       if ( mlt_properties_get_int( properties, "rescale_height" ) > 0 )
+               *height = mlt_properties_get_int( properties, "rescale_height" );
 
        // Restore pixbuf and image
        mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) );
@@ -562,9 +636,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                // Update timecode on the frame we're creating
                mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
 
-               // Ensure that we have a way to obtain the position in the get_image
-               mlt_properties_set_position( properties, "pixbuf_position", mlt_producer_position( producer ) );
-
                // Refresh the pixbuf
                self->pixbuf_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf" );
                self->pixbuf = mlt_cache_item_data( self->pixbuf_cache, NULL );