]> git.sesse.net Git - mlt/commitdiff
Fix playing all frames at end of project (kdenlive-1207).
authorDan Dennedy <dan@dennedy.org>
Fri, 26 Feb 2010 03:46:39 +0000 (19:46 -0800)
committerDan Dennedy <dan@dennedy.org>
Fri, 26 Feb 2010 03:46:39 +0000 (19:46 -0800)
src/modules/sdl/consumer_sdl_preview.c

index ba2866573d60da6f910f8f54bfa99fe19b22e3fe..a046bb92abfa926f46f9d98a1c6c6da0c975f8ce 100644 (file)
@@ -208,6 +208,7 @@ static int consumer_start( mlt_consumer parent )
 
                mlt_properties_set_int( play, "put_mode", 1 );
                mlt_properties_set_int( still, "put_mode", 1 );
+               mlt_properties_set_int( play, "terminate_on_pause", 1 );
 
                // Start the still producer just to initialise the gui
                mlt_consumer_start( this->still );
@@ -268,8 +269,9 @@ static void *consumer_thread( void *arg )
        // Identify the arg
        consumer_sdl this = arg;
 
-       // Get the consumer
+       // Get the consumer and producer
        mlt_consumer consumer = &this->parent;
+       mlt_producer producer = MLT_PRODUCER( mlt_service_get_producer( MLT_CONSUMER_SERVICE( consumer ) ) );
 
        // Get the properties
        mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
@@ -278,6 +280,7 @@ static void *consumer_thread( void *arg )
        int first = 1;
        mlt_frame frame = NULL;
        int last_position = -1;
+       int eof_threshold = 10 + mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( this->play ), "buffer" );
 
        // Determine if the application is dealing with the preview
        int preview_off = mlt_properties_get_int( properties, "preview_off" );
@@ -329,37 +332,58 @@ static void *consumer_thread( void *arg )
                                last_position = -1;
                        }
 
-                       // If we're not the first frame and both consumers are stopped, then stop ourselves
-                       if ( !first && mlt_consumer_is_stopped( this->play ) && mlt_consumer_is_stopped( this->still ) )
-                       {
-                               this->running = 0;
-                               mlt_frame_close( frame );
-                       }
-                       // Allow a little grace time before switching consumers on speed changes
-                       else if ( this->ignore_change -- > 0 && this->active != NULL && !mlt_consumer_is_stopped( this->active ) )
-                       {
-                               mlt_consumer_put_frame( this->active, frame );
-                       }
                        // If we aren't playing normally, then use the still
-                       else if ( speed != 1 )
+                       if ( speed != 1 )
                        {
-                               if ( !mlt_consumer_is_stopped( this->play ) )
+                               mlt_position duration = mlt_producer_get_playtime( producer );
+
+                               // Do not interrupt the normal consumer near the end
+                               if ( !mlt_consumer_is_stopped( this->play ) && ( duration - this->last_position ) > eof_threshold )
                                        mlt_consumer_stop( this->play );
+
+                               // Switch to the still consumer
                                if ( mlt_consumer_is_stopped( this->still ) )
                                {
-                                       mlt_producer producer = mlt_service_get_producer( MLT_CONSUMER_SERVICE( consumer ) );
+                                       // If near the end, wait for the normal consumer to play out its buffers
+                                       if ( ! mlt_consumer_is_stopped( this->play ) && speed == 0.0 )
+                                       {
+                                               // This frame with speed=0 will tell normal consumer to terminate
+                                               mlt_consumer_put_frame( this->play, frame );
+                                               while ( ! mlt_consumer_is_stopped( this->play ) )
+                                               {
+                                                       struct timespec tm = { 0, 10000000L }; // 10 ms
+                                                       nanosleep( &tm, NULL );
+                                               }
+
+                                               // We want to be positioned at the end
+                                               if ( duration - this->last_position < 10 )
+                                                       this->last_position = duration - 1;
+                                       }
+                                       else
+                                       {
+                                               // We will need a new frame at the correct position
+                                               mlt_frame_close( frame );
+                                       }
+
+                                       // Get a new frame at the sought position
                                        if ( producer )
                                                mlt_producer_seek( producer, this->last_position );
+                                       frame = mlt_consumer_get_frame( consumer );
+
+                                       // Start the still consumer
                                        this->last_speed = speed;
                                        this->active = this->still;
-                                       this->ignore_change = 0;
+                                       this->ignore_change = 25;
                                        mlt_consumer_start( this->still );
-                                       mlt_frame_close( frame );
                                }
-                               else
-                               {
+                               // Use the still consumer
+                               if ( frame )
                                        mlt_consumer_put_frame( this->still, frame );
-                               }
+                       }
+                       // Allow a little grace time before switching consumers on speed changes
+                       else if ( this->ignore_change -- > 0 && this->active != NULL && !mlt_consumer_is_stopped( this->active ) )
+                       {
+                               mlt_consumer_put_frame( this->active, frame );
                        }
                        // Otherwise use the normal player
                        else
@@ -370,7 +394,7 @@ static void *consumer_thread( void *arg )
                                {
                                        this->last_speed = speed;
                                        this->active = this->play;
-                                       this->ignore_change = 25;
+                                       this->ignore_change = 0;
                                        mlt_consumer_start( this->play );
                                }
                                mlt_consumer_put_frame( this->play, frame );