+ // Pop the next frame
+ pthread_mutex_lock( &this->video_mutex );
+ next = mlt_deque_pop_front( this->queue );
+ while ( next == NULL && this->running )
+ {
+ pthread_cond_wait( &this->video_cond, &this->video_mutex );
+ next = mlt_deque_pop_front( this->queue );
+ }
+ pthread_mutex_unlock( &this->video_mutex );
+
+ if ( !this->running || next == NULL ) break;
+
+ // Get the properties
+ properties = MLT_FRAME_PROPERTIES( next );
+
+ // Get the speed of the frame
+ speed = mlt_properties_get_double( properties, "_speed" );
+
+ // Get the current time
+ gettimeofday( &now, NULL );
+
+ // Get the elapsed time
+ elapsed = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - start;
+
+ // See if we have to delay the display of the current frame
+ if ( mlt_properties_get_int( properties, "rendered" ) == 1 && this->running )
+ {
+ // Obtain the scheduled playout time
+ mlt_position scheduled = mlt_properties_get_position( properties, "playtime" );
+
+ // Determine the difference between the elapsed time and the scheduled playout time
+ mlt_position difference = scheduled - elapsed;
+
+ // Smooth playback a bit
+ if ( real_time && ( difference > 20000 && speed == 1.0 ) )
+ {
+ tm.tv_sec = difference / 1000000;
+ tm.tv_nsec = ( difference % 1000000 ) * 500;
+ nanosleep( &tm, NULL );
+ }
+
+ // Show current frame if not too old
+ if ( !real_time || ( difference > -10000 || speed != 1.0 || mlt_deque_count( this->queue ) < 2 ) )
+ consumer_play_video( this, next );
+
+ // If the queue is empty, recalculate start to allow build up again
+ if ( real_time && ( mlt_deque_count( this->queue ) == 0 && speed == 1.0 ) )
+ {
+ gettimeofday( &now, NULL );
+ start = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - scheduled + 20000;
+ }
+ }
+
+ // This frame can now be closed
+ mlt_frame_close( next );
+ next = NULL;