+static void *video_thread( void *arg )
+{
+ // Identify the arg
+ consumer_sdl this = arg;
+
+ // Obtain time of thread start
+ struct timeval now;
+ int64_t start = 0;
+ int64_t elapsed = 0;
+ struct timespec tm;
+ mlt_frame next = NULL;
+ mlt_properties properties = NULL;
+ double speed = 0;
+ int skipped = 0;
+
+ // Get the current time
+ gettimeofday( &now, NULL );
+
+ // Determine start time
+ start = ( int64_t )now.tv_sec * 1000000 + now.tv_usec;
+
+ while ( this->running )
+ {
+ // Pop the next frame
+ pthread_mutex_lock( &this->video_mutex );
+ while ( ( next = mlt_deque_pop_front( this->queue ) ) == NULL && this->running )
+ pthread_cond_wait( &this->video_cond, &this->video_mutex );
+ pthread_mutex_unlock( &this->video_mutex );
+
+ // 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 ( 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 ( difference > -10000 || speed != 1.0 || mlt_deque_count( this->queue ) < 2 )
+ consumer_play_video( this, next );
+ else
+ skipped ++;
+
+ // If the queue is empty, recalculate start to allow build up again
+ if ( mlt_deque_count( this->queue ) == 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 );
+ }
+
+ return NULL;
+}
+