Fixes threaded pixbuf usage and removes flash when swicthing between sdl preview...
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Mon, 1 Nov 2004 13:14:57 +0000 (13:14 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Mon, 1 Nov 2004 13:14:57 +0000 (13:14 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@502 d19143bc-622f-0410-bfdd-b5b2a6649095

src/modules/gtk2/consumer_gtk2.c
src/modules/gtk2/producer_pixbuf.c
src/modules/sdl/consumer_sdl.c
src/modules/sdl/consumer_sdl_preview.c
src/modules/sdl/consumer_sdl_still.c

index 4da317c..f563ecf 100644 (file)
@@ -47,6 +47,7 @@ mlt_consumer consumer_gtk2_preview_init( GtkWidget *widget )
        if ( consumer != NULL )
        {
                mlt_properties properties = mlt_consumer_properties( consumer );
+               mlt_properties_set_int( properties, "app_locked", 1 );
                mlt_properties_set_data( properties, "app_lock", gdk_threads_enter, 0, NULL, NULL );
                mlt_properties_set_data( properties, "app_unlock", gdk_threads_leave, 0, NULL, NULL );
        }
index 4cd7a4c..be66990 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <pthread.h>
 #include <math.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <dirent.h>
 
+pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
+
 typedef struct producer_pixbuf_s *producer_pixbuf;
 
 struct producer_pixbuf_s
@@ -77,9 +80,6 @@ mlt_producer producer_pixbuf_init( char *filename )
                mlt_properties_set( properties, "resource", filename );
                mlt_properties_set_int( properties, "ttl", 25 );
                
-               // Initialise gobject types
-               g_type_init();
-
                return producer;
        }
        free( this );
@@ -113,6 +113,8 @@ static void refresh_image( mlt_frame frame, int width, int height )
        // Image index
        int image_idx = ( int )floor( ( double )position / ttl ) % this->count;
 
+       pthread_mutex_lock( &fastmutex );
+
     // optimization for subsequent iterations on single picture
        if ( width != 0 && this->image != NULL && image_idx == this->image_idx )
        {
@@ -206,6 +208,8 @@ static void refresh_image( mlt_frame frame, int width, int height )
        // pass the image data without destructor
        mlt_properties_set_data( properties, "image", this->image, this->width * ( this->height + 1 ) * 2, NULL, NULL );
        mlt_properties_set_data( properties, "alpha", this->alpha, this->width * this->height, NULL, NULL );
+
+       pthread_mutex_unlock( &fastmutex );
 }
 
 static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
index b707f78..b5c8fd1 100644 (file)
@@ -61,6 +61,7 @@ struct consumer_sdl_s
        SDL_Overlay *sdl_overlay;
        SDL_Rect rect;
        uint8_t *buffer;
+       int bpp;
 };
 
 /** Forward references to static functions.
@@ -118,7 +119,7 @@ mlt_consumer consumer_sdl_init( char *arg )
                mlt_properties_set_int( this->properties, "progressive", 0 );
 
                // Default audio buffer
-               mlt_properties_set_int( this->properties, "audio_buffer", 1024 );
+               mlt_properties_set_int( this->properties, "audio_buffer", 512 );
 
                // Get sample aspect ratio
                this->aspect_ratio = mlt_properties_get_double( this->properties, "aspect_ratio" );
@@ -417,14 +418,11 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                        }
                }
        
-               if ( width != this->width || height != this->height || 
-                        ( ( int )( this->last_frame_aspect * 1000 ) != ( int )( mlt_frame_get_aspect_ratio( frame ) * 1000 ) &&
-                        ( mlt_frame_get_aspect_ratio( frame ) != 1.0 || this->last_frame_aspect == 0.0 ) ) )
+               if ( width != this->width || height != this->height )
                {
-                       this->width = width;
-                       this->height = height;
-                       this->last_frame_aspect = mlt_frame_get_aspect_ratio( frame );
-                       changed = 1;
+                       if ( this->sdl_overlay != NULL )
+                               SDL_FreeYUVOverlay( this->sdl_overlay );
+                       this->sdl_overlay = NULL;
                }
 
                if ( this->running && ( this->sdl_screen == NULL || changed ) )
@@ -432,16 +430,28 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                        // Force an overlay recreation
                        if ( this->sdl_overlay != NULL )
                                SDL_FreeYUVOverlay( this->sdl_overlay );
+                       this->sdl_overlay = NULL;
 
                        // open SDL window with video overlay, if possible
                        sdl_lock_display();
-                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
+                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, this->bpp, this->sdl_flags );
                        sdl_unlock_display();
                        if ( consumer_get_dimensions( &this->window_width, &this->window_height ) )
-                               this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
+                               this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, this->bpp, this->sdl_flags );
                        //SDL_Flip( this->sdl_screen );
                        mlt_properties_set_int( properties, "changed", 0 );
+               }
+               else if ( mlt_properties_get_int( properties, "changed" ) )
+               {
+                       sdl_lock_display();
+                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, this->bpp, this->sdl_flags );
+                       SDL_SetClipRect( this->sdl_screen, &this->rect );
+                       sdl_unlock_display();
+                       mlt_properties_set_int( properties, "changed", 0 );
+               }
 
+               if ( 1 )
+               {
                        // Determine window's new display aspect ratio
                        float this_aspect = ( float )this->window_width / this->window_height;
 
@@ -501,22 +511,16 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                        mlt_properties_set_int( this->properties, "rect_w", this->rect.w );
                        mlt_properties_set_int( this->properties, "rect_h", this->rect.h );
 
-                       if ( this->sdl_screen != NULL )
-                       {
-                               SDL_SetClipRect( this->sdl_screen, &this->rect );
-                               sdl_lock_display();
-                               this->sdl_overlay = SDL_CreateYUVOverlay( this->width, this->height, SDL_YUY2_OVERLAY, this->sdl_screen );
-                               sdl_unlock_display();
-                       }
+                       SDL_SetClipRect( this->sdl_screen, &this->rect );
                }
-               else if ( mlt_properties_get_int( properties, "changed" ) )
+
+               if ( this->sdl_screen != NULL && this->sdl_overlay == NULL )
                {
-                       sdl_lock_display();
-                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
                        SDL_SetClipRect( this->sdl_screen, &this->rect );
-                       //SDL_Flip( this->sdl_screen );
+                       SDL_Flip( this->sdl_screen );
+                       sdl_lock_display();
+                       this->sdl_overlay = SDL_CreateYUVOverlay( this->width, this->height, SDL_YUY2_OVERLAY, this->sdl_screen );
                        sdl_unlock_display();
-                       mlt_properties_set_int( properties, "changed", 0 );
                }
 
                if ( this->sdl_screen != NULL && this->sdl_overlay != NULL )
@@ -641,6 +645,8 @@ static void *consumer_thread( void *arg )
        int64_t playtime = 0;
        struct timespec tm = { 0, 100000 };
 
+       this->bpp = mlt_properties_get_int( this->properties, "bpp" );
+
        if ( mlt_properties_get_int( mlt_consumer_properties( consumer ), "sdl_started" ) == 0 )
        {
                if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 )
@@ -655,7 +661,11 @@ static void *consumer_thread( void *arg )
        else
        {
                if ( SDL_GetVideoSurface( ) != NULL )
+               {
+                       this->sdl_screen = SDL_GetVideoSurface( );
                        consumer_get_dimensions( &this->window_width, &this->window_height );
+                       mlt_properties_set_int( this->properties, "changed", 0 );
+               }
        }
 
        if ( !mlt_properties_get_int( mlt_consumer_properties( consumer ), "audio_off" ) )
index 5415ed3..84a2c30 100644 (file)
@@ -139,11 +139,20 @@ static int consumer_stop( mlt_consumer parent )
 
        if ( this->joined == 0 )
        {
+               mlt_properties properties = mlt_consumer_properties( parent );
+               int app_locked = mlt_properties_get_int( properties, "app_locked" );
+               void ( *lock )( void ) = mlt_properties_get_data( properties, "app_lock", NULL );
+               void ( *unlock )( void ) = mlt_properties_get_data( properties, "app_unlock", NULL );
+
+               if ( app_locked && unlock ) unlock( );
+
                // Kill the thread and clean up
                this->running = 0;
 
                pthread_join( this->thread, NULL );
                this->joined = 1;
+
+               if ( app_locked && lock ) lock( );
        }
 
        return 0;
@@ -190,12 +199,14 @@ static void *consumer_thread( void *arg )
        mlt_properties_set_data( still, "transport_producer", mlt_properties_get_data( properties, "transport_producer", NULL ), 0, NULL, NULL );
        mlt_properties_set_data( play, "transport_callback", mlt_properties_get_data( properties, "transport_callback", NULL ), 0, NULL, NULL );
        mlt_properties_set_data( still, "transport_callback", mlt_properties_get_data( properties, "transport_callback", NULL ), 0, NULL, NULL );
+       mlt_properties_set_int( play, "resize", mlt_properties_get_int( properties, "resize" ) );
+       mlt_properties_set_int( still, "resize", mlt_properties_get_int( properties, "resize" ) );
        mlt_properties_set( play, "rescale", mlt_properties_get( properties, "rescale" ) );
        mlt_properties_set( still, "rescale", mlt_properties_get( properties, "rescale" ) );
-       mlt_properties_set( play, "width", mlt_properties_get( properties, "width" ) );
-       mlt_properties_set( still, "width", mlt_properties_get( properties, "width" ) );
-       mlt_properties_set( play, "height", mlt_properties_get( properties, "height" ) );
-       mlt_properties_set( still, "height", mlt_properties_get( properties, "height" ) );
+       mlt_properties_set_int( play, "width", mlt_properties_get_int( properties, "width" ) );
+       mlt_properties_set_int( still, "width", mlt_properties_get_int( properties, "width" ) );
+       mlt_properties_set_int( play, "height", mlt_properties_get_int( properties, "height" ) );
+       mlt_properties_set_int( still, "height", mlt_properties_get_int( properties, "height" ) );
 
        mlt_properties_set_int( play, "progressive", 1 );
        mlt_properties_set_int( still, "progressive", 1 );
index 3cf9d09..cdc2b0f 100644 (file)
@@ -224,6 +224,126 @@ static void sdl_unlock_display( )
                SDL_UnlockSurface( screen );
 }
 
+static inline void display_1( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
+{
+       // Generate the affine transform scaling values
+       int scale_width = ( width << 16 ) / rect.w;
+       int scale_height = ( height << 16 ) / rect.h;
+       int stride = width * 3;
+       int x, y, row_index;
+       uint8_t *q, *row;
+
+       // Constants defined for clarity and optimisation
+       int scanlength = screen->pitch;
+       uint8_t *start = ( uint8_t * )screen->pixels + rect.y * scanlength + rect.x;
+       uint8_t *p;
+
+       // Iterate through the screen using a very basic scaling algorithm
+       for ( y = 0; y < rect.h; y ++ )
+       {
+               p = start;
+               row_index = ( scale_height * y ) >> 16;
+               row = image + stride * row_index;
+               for ( x = 0; x < rect.w; x ++ )
+               {
+                       q = row + ( ( ( scale_width * x ) >> 16 ) * 3 );
+                       *p ++ = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
+               }
+               start += scanlength;
+       }
+}
+
+static inline void display_2( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
+{
+       // Generate the affine transform scaling values
+       int scale_width = ( width << 16 ) / rect.w;
+       int scale_height = ( height << 16 ) / rect.h;
+       int stride = width * 3;
+       int x, y, row_index;
+       uint8_t *q, *row;
+
+       // Constants defined for clarity and optimisation
+       int scanlength = screen->pitch / 2;
+       uint16_t *start = ( uint16_t * )screen->pixels + rect.y * scanlength + rect.x;
+       uint16_t *p;
+
+       // Iterate through the screen using a very basic scaling algorithm
+       for ( y = 0; y < rect.h; y ++ )
+       {
+               p = start;
+               row_index = ( scale_height * y ) >> 16;
+               row = image + stride * row_index;
+               for ( x = 0; x < rect.w; x ++ )
+               {
+                       q = row + ( ( ( scale_width * x ) >> 16 ) * 3 );
+                       *p ++ = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
+               }
+               start += scanlength;
+       }
+}
+
+static inline void display_3( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
+{
+       // Generate the affine transform scaling values
+       int scale_width = ( width << 16 ) / rect.w;
+       int scale_height = ( height << 16 ) / rect.h;
+       int stride = width * 3;
+       int x, y, row_index;
+       uint8_t *q, *row;
+
+       // Constants defined for clarity and optimisation
+       int scanlength = screen->pitch;
+       uint8_t *start = ( uint8_t * )screen->pixels + rect.y * scanlength + rect.x;
+       uint8_t *p;
+       uint32_t pixel;
+
+       // Iterate through the screen using a very basic scaling algorithm
+       for ( y = 0; y < rect.h; y ++ )
+       {
+               p = start;
+               row_index = ( scale_height * y ) >> 16;
+               row = image + stride * row_index;
+               for ( x = 0; x < rect.w; x ++ )
+               {
+                       q = row + ( ( ( scale_width * x ) >> 16 ) * 3 );
+                       pixel = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
+                       *p ++ = (pixel & 0xFF0000) >> 16;
+                       *p ++ = (pixel & 0x00FF00) >> 8;
+                       *p ++ = (pixel & 0x0000FF);
+               }
+               start += scanlength;
+       }
+}
+
+static inline void display_4( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
+{
+       // Generate the affine transform scaling values
+       int scale_width = ( width << 16 ) / rect.w;
+       int scale_height = ( height << 16 ) / rect.h;
+       int stride = width * 3;
+       int x, y, row_index;
+       uint8_t *q, *row;
+
+       // Constants defined for clarity and optimisation
+       int scanlength = screen->pitch / 4;
+       uint32_t *start = ( uint32_t * )screen->pixels + rect.y * scanlength + rect.x;
+       uint32_t *p;
+
+       // Iterate through the screen using a very basic scaling algorithm
+       for ( y = 0; y < rect.h; y ++ )
+       {
+               p = start;
+               row_index = ( scale_height * y ) >> 16;
+               row = image + stride * row_index;
+               for ( x = 0; x < rect.w; x ++ )
+               {
+                       q = row + ( ( ( scale_width * x ) >> 16 ) * 3 );
+                       *p ++ = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
+               }
+               start += scanlength;
+       }
+}
+
 static int consumer_play_video( consumer_sdl this, mlt_frame frame )
 {
        // Get the properties of this consumer
@@ -279,52 +399,23 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                }
        }
 
-       if ( ( ( int )( this->last_frame_aspect * 1000 ) != ( int )( mlt_frame_get_aspect_ratio( frame ) * 1000 ) &&
-                ( mlt_frame_get_aspect_ratio( frame ) != 1.0 || this->last_frame_aspect == 0.0 ) ) )
-       {
-               this->last_frame_aspect = mlt_frame_get_aspect_ratio( frame );
-               changed = 1;
-       }
-
        if ( this->sdl_screen == NULL || changed || mlt_properties_get_int( properties, "changed" ) == 2 )
        {
                // open SDL window 
-               this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 16, this->sdl_flags );
+               this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
                if ( consumer_get_dimensions( &this->window_width, &this->window_height ) )
-                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 16, this->sdl_flags );
+                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
 
                changed = 1;
                mlt_properties_set_int( properties, "changed", 0 );
-
-               // May as well use the mlt rescaler...
-               //if ( mlt_properties_get( properties, "rescale" ) != NULL && !strcmp( mlt_properties_get( properties, "rescale" ), "none" ) )
-                       //mlt_properties_set( properties, "rescale", "nearest" );
-
-               // Determine window's new display aspect ratio
-               float this_aspect = this->display_aspect / ( ( float )this->window_width / ( float )this->window_height );
-
-               this->rect.w = this_aspect * this->window_width;
-               this->rect.h = this->window_height;
-               if ( this->rect.w > this->window_width )
-               {
-                       this->rect.w = this->window_width;
-                       this->rect.h = ( 1.0 / this_aspect ) * this->window_height;
-               }
-
-               this->rect.x = ( this->window_width - this->rect.w ) / 2;
-               this->rect.y = ( this->window_height - this->rect.h ) / 2;
-
-               mlt_properties_set_int( this->properties, "rect_x", this->rect.x );
-               mlt_properties_set_int( this->properties, "rect_y", this->rect.y );
-               mlt_properties_set_int( this->properties, "rect_w", this->rect.w );
-               mlt_properties_set_int( this->properties, "rect_h", this->rect.h );
        }
        else
        {
                changed = mlt_properties_get_int( properties, "changed" ) | mlt_properties_get_int( mlt_frame_properties( frame ), "refresh" );
                mlt_properties_set_int( properties, "changed", 0 );
        }
-               
+
+       
        if ( changed == 0 &&
                 this->last_position == mlt_frame_get_position( frame ) &&
                 this->last_producer == mlt_properties_get_data( mlt_frame_properties( frame ), "_producer", NULL ) )
@@ -355,50 +446,62 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
        }
 
-       if ( this->sdl_screen != NULL )
+       if ( 1 )
        {
-               // Calculate the scan length
-               int scanlength = this->sdl_screen->pitch / 2;
-
-               // Obtain the clip rect from the screen
-               SDL_Rect rect = this->rect;
-
-               // Generate the affine transform scaling values
-               int scale_width = ( width << 16 ) / rect.w;
-               int scale_height = ( height << 16 ) / rect.h;
-
-               // Constants defined for clarity and optimisation
-               int stride = width * 3;
-               uint16_t *start = ( uint16_t * )this->sdl_screen->pixels + rect.y * scanlength + rect.x;
-
-               int x, y, row_index;
-               uint16_t *p;
-               uint8_t *q, *row;
-
-               // Iterate through the screen using a very basic scaling algorithm
-               for ( y = 0; y < rect.h && this->last_position != -1; y ++ )
+               char *rescale = mlt_properties_get( properties, "rescale" );
+               if ( rescale != NULL && strcmp( rescale, "none" ) )
                {
-                       // Obtain the pointer to the current screen row
-                       p = start;
-
-                       // Calculate the row_index
-                       row_index = ( scale_height * y ) >> 16;
-
-                       // Calculate the pointer for the y offset (positioned on B instead of R)
-                       row = image + stride * row_index;
-
-                       // Iterate through the screen width
-                       for ( x = 0; x < rect.w; x ++ )
+                       float this_aspect = this->display_aspect / ( ( float )this->window_width / ( float )this->window_height );
+                       this->rect.w = this_aspect * this->window_width;
+                       this->rect.h = this->window_height;
+                       if ( this->rect.w > this->window_width )
                        {
-                               // Obtain the pixel pointer
-                               q = row + ( ( ( scale_width * x ) >> 16 ) * 3 );
-
-                               // Map the BGR colour from the frame to the SDL format
-                               *p ++ = SDL_MapRGB( this->sdl_screen->format, *q, *( q + 1 ), *( q + 2 ) );
+                               this->rect.w = this->window_width;
+                               this->rect.h = ( 1.0 / this_aspect ) * this->window_height;
                        }
+               }
+               else
+               {
+                       float frame_aspect = mlt_frame_get_aspect_ratio( frame ) * width / height;
+                       this->rect.w = frame_aspect * this->window_height;
+                       this->rect.h = this->window_height;
+                       if ( this->rect.w > this->window_width )
+                       {
+                               this->rect.w = this->window_width;
+                               this->rect.h = ( 1.0 / frame_aspect ) * this->window_width;
+                       }
+               }
+
+               this->rect.x = ( this->window_width - this->rect.w ) / 2;
+               this->rect.y = ( this->window_height - this->rect.h ) / 2;
 
-                       // Move to the next row
-                       start += scanlength;
+               mlt_properties_set_int( this->properties, "rect_x", this->rect.x );
+               mlt_properties_set_int( this->properties, "rect_y", this->rect.y );
+               mlt_properties_set_int( this->properties, "rect_w", this->rect.w );
+               mlt_properties_set_int( this->properties, "rect_h", this->rect.h );
+       }
+       
+       if ( this->sdl_screen != NULL )
+       {
+               memset( this->sdl_screen->pixels, 0, this->window_width * this->window_height * this->sdl_screen->format->BytesPerPixel );
+
+               switch( this->sdl_screen->format->BytesPerPixel )
+               {
+                       case 1:
+                               display_1( this->sdl_screen, this->rect, image, width, height );
+                               break;
+                       case 2:
+                               display_2( this->sdl_screen, this->rect, image, width, height );
+                               break;
+                       case 3:
+                               display_3( this->sdl_screen, this->rect, image, width, height );
+                               break;
+                       case 4:
+                               display_4( this->sdl_screen, this->rect, image, width, height );
+                               break;
+                       default:
+                               fprintf( stderr, "Unsupported video depth %d\n", this->sdl_screen->format->BytesPerPixel );
+                               break;
                }
 
                // Flip it into sight
@@ -442,7 +545,11 @@ static void *consumer_thread( void *arg )
        {
                mlt_properties_set_int( mlt_consumer_properties( consumer ), "changed", 2 );
                if ( SDL_GetVideoSurface( ) != NULL )
+               {
+                       this->sdl_screen = SDL_GetVideoSurface( );
                        consumer_get_dimensions( &this->window_width, &this->window_height );
+                       mlt_properties_set_int( mlt_consumer_properties( consumer ), "changed", 0 );
+               }
        }
 
        // Loop until told not to