#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
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 )
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 );
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;
return result;
}
-static int load_sequence2( producer_pixbuf self, mlt_properties properties, const char *filename )
+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, '%' ) ) )
{
strncpy( s, start, n );
mlt_properties_set( properties, "begin", s );
free( s );
- s = calloc( 1, strlen( filename ) );
+ s = calloc( 1, strlen( filename ) + 2 );
strncpy( s, filename, start - filename );
sprintf( s + ( start - filename ), ".%d%s", n, end );
- result = load_sequence( self, properties, s );
+ 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;
self->filenames = mlt_properties_new( );
if (!load_svg( self, properties, filename ) &&
- !load_sequence( self, properties, filename ) &&
- !load_sequence2( 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 );
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 ];
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 );
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 ) );
// 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 );