]> git.sesse.net Git - mlt/blobdiff - src/modules/sdl/consumer_sdl_audio.c
Replace glFinish with OpenGL fences.
[mlt] / src / modules / sdl / consumer_sdl_audio.c
index 266580e3d7ee1f3b493b301f5a6ba6c704b34eb2..e8036beddf659059ca7ede5b89301ae861d4a2ad 100644 (file)
@@ -57,6 +57,7 @@ struct consumer_sdl_s
        pthread_cond_t refresh_cond;
        pthread_mutex_t refresh_mutex;
        int refresh_count;
+       int is_purge;
 };
 
 /** Forward references to static functions.
@@ -65,6 +66,7 @@ struct consumer_sdl_s
 static int consumer_start( mlt_consumer parent );
 static int consumer_stop( mlt_consumer parent );
 static int consumer_is_stopped( mlt_consumer parent );
+static void consumer_purge( mlt_consumer parent );
 static void consumer_close( mlt_consumer parent );
 static void *consumer_thread( void * );
 static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer self, char *name );
@@ -76,7 +78,7 @@ static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer self, char *name
 mlt_consumer consumer_sdl_audio_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
        // Create the consumer object
-       consumer_sdl self = calloc( sizeof( struct consumer_sdl_s ), 1 );
+       consumer_sdl self = calloc( 1, sizeof( struct consumer_sdl_s ) );
 
        // If no malloc'd and consumer init ok
        if ( self != NULL && mlt_consumer_init( &self->parent, self, profile ) == 0 )
@@ -106,6 +108,7 @@ mlt_consumer consumer_sdl_audio_init( mlt_profile profile, mlt_service_type type
                // Default scaler (for now we'll use nearest)
                mlt_properties_set( self->properties, "rescale", "nearest" );
                mlt_properties_set( self->properties, "deinterlace_method", "onefield" );
+               mlt_properties_set_int( self->properties, "top_field_first", -1 );
 
                // Default buffer for low latency
                mlt_properties_set_int( self->properties, "buffer", 1 );
@@ -120,6 +123,7 @@ mlt_consumer consumer_sdl_audio_init( mlt_profile profile, mlt_service_type type
                parent->start = consumer_start;
                parent->stop = consumer_stop;
                parent->is_stopped = consumer_is_stopped;
+               parent->purge = consumer_purge;
 
                // Initialize the refresh handler
                pthread_cond_init( &self->refresh_cond, NULL );
@@ -143,7 +147,8 @@ static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer parent, char *na
        {
                consumer_sdl self = parent->child;
                pthread_mutex_lock( &self->refresh_mutex );
-               self->refresh_count = self->refresh_count <= 0 ? 1 : self->refresh_count + 1;
+               if ( self->refresh_count < 2 )
+                       self->refresh_count = self->refresh_count <= 0 ? 1 : self->refresh_count + 1;
                pthread_cond_broadcast( &self->refresh_cond );
                pthread_mutex_unlock( &self->refresh_mutex );
        }
@@ -218,6 +223,25 @@ int consumer_is_stopped( mlt_consumer parent )
        return !self->running;
 }
 
+void consumer_purge( mlt_consumer parent )
+{
+       consumer_sdl self = parent->child;
+       if ( self->running )
+       {
+               pthread_mutex_lock( &self->video_mutex );
+               mlt_frame frame = MLT_FRAME( mlt_deque_peek_back( self->queue ) );
+               // When playing rewind or fast forward then we need to keep one
+               // frame in the queue to prevent playback stalling.
+               double speed = frame? mlt_properties_get_double( MLT_FRAME_PROPERTIES(frame), "_speed" ) : 0;
+               int n = ( speed == 0.0 || speed == 1.0 ) ? 0 : 1;
+               while ( mlt_deque_count( self->queue ) > n )
+                       mlt_frame_close( mlt_deque_pop_back( self->queue ) );
+               self->is_purge = 1;
+               pthread_cond_broadcast( &self->video_cond );
+               pthread_mutex_unlock( &self->video_mutex );
+       }
+}
+
 static void sdl_fill_audio( void *udata, uint8_t *stream, int len )
 {
        consumer_sdl self = udata;
@@ -354,7 +378,6 @@ static int consumer_play_video( consumer_sdl self, mlt_frame frame )
        mlt_properties properties = self->properties;
        if ( self->running && !mlt_consumer_is_stopped( &self->parent ) )
                mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
-
        return 0;
 }
 
@@ -475,7 +498,10 @@ static void *consumer_thread( void *arg )
        int64_t playtime = 0;
        struct timespec tm = { 0, 100000 };
 //     int last_position = -1;
+
+       pthread_mutex_lock( &self->refresh_mutex );
        self->refresh_count = 0;
+       pthread_mutex_unlock( &self->refresh_mutex );
 
        // Loop until told not to
        while( self->running )
@@ -523,8 +549,16 @@ static void *consumer_thread( void *arg )
                        if ( self->running && speed )
                        {
                                pthread_mutex_lock( &self->video_mutex );
-                               mlt_deque_push_back( self->queue, frame );
-                               pthread_cond_broadcast( &self->video_cond );
+                               if ( self->is_purge && speed == 1.0 )
+                               {
+                                       mlt_frame_close( frame );
+                                       self->is_purge = 0;
+                               }
+                               else
+                               {
+                                       mlt_deque_push_back( self->queue, frame );
+                                       pthread_cond_broadcast( &self->video_cond );
+                               }
                                pthread_mutex_unlock( &self->video_mutex );
 
                                // Calculate the next playtime
@@ -533,7 +567,7 @@ static void *consumer_thread( void *arg )
                        else if ( self->running )
                        {
                                pthread_mutex_lock( &self->refresh_mutex );
-                               if ( refresh == 0 && self->refresh_count <= 0 )
+                               if ( ( refresh == 0 && self->refresh_count <= 0 ) || self->refresh_count > 1 )
                                {
                                        consumer_play_video( self, frame );
                                        pthread_cond_wait( &self->refresh_cond, &self->refresh_mutex );