]> git.sesse.net Git - mlt/commitdiff
Fix errors in caching + mem leaks, fix resize issue
authorj-b-m <jb@kdenlive.org>
Sun, 2 Aug 2009 17:14:35 +0000 (19:14 +0200)
committerj-b-m <jb@kdenlive.org>
Sun, 2 Aug 2009 17:14:35 +0000 (19:14 +0200)
modified:   kdenlivetitle_wrapper.cpp
modified:   kdenlivetitle_wrapper.h
modified:   producer_kdenlivetitle.c

src/modules/qimage/kdenlivetitle_wrapper.cpp
src/modules/qimage/kdenlivetitle_wrapper.h
src/modules/qimage/producer_kdenlivetitle.c

index 10478a0132cbf49502e34b5411d6681606d7d682..25694f7f0d7ced8dd6eaa9157967279a3cf0aaf5 100644 (file)
@@ -37,7 +37,6 @@
 #include <QtGui/QColor>
 #include <QtGui/QWidget>
 
-static QMutex g_mutex;
 static QApplication *app = NULL;
 
 class ImageItem: public QGraphicsRectItem
@@ -130,14 +129,9 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
        QTransform transform;
        if ( doc.documentElement().hasAttribute("width") ) {
            int originalWidth = doc.documentElement().attribute("width").toInt();
+           mlt_properties_set_int( producer_props, "_original_width", originalWidth );
            int originalHeight = doc.documentElement().attribute("height").toInt();
-           if (originalWidth != width || originalHeight != height) {
-#if QT_VERSION < 0x40500
-                   transform = QTransform().scale(  (double) width / originalWidth, (double) height / originalHeight );
-#else
-                   transform = QTransform::fromScale ( (double) width / originalWidth, (double) height / originalHeight);
-#endif
-           }
+           mlt_properties_set_int( producer_props, "_original_height", originalHeight );
        }
        if ( titles.size() )
        {
@@ -244,17 +238,16 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
                        {
                                QPointF p( items.item( i ).namedItem( "position" ).attributes().namedItem( "x" ).nodeValue().toDouble(),
                                           items.item( i ).namedItem( "position" ).attributes().namedItem( "y" ).nodeValue().toDouble() );
-                               if ( transform != QTransform() ) p = QPointF(p.x() * transform.m11(), p.y() * transform.m22());
                                gitem->setPos( p );
                                gitem->setTransform( stringToTransform( items.item( i ).namedItem( "position" ).firstChild().firstChild().nodeValue() ) );
                                int zValue = items.item( i ).attributes().namedItem( "z-index" ).nodeValue().toInt();
                                gitem->setZValue( zValue );
-                               if ( transform != QTransform() ) gitem->setTransform( transform, true );
-                               //gitem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
                        }
-                       if ( items.item( i ).nodeName() == "background" )
-                       {
-                               QColor color = QColor( stringToColor( items.item( i ).attributes().namedItem( "color" ).nodeValue() ) );
+               }
+       }
+       QDomNode n = doc.documentElement().firstChildElement("background");
+       if (!n.isNull()) {
+         QColor color = QColor( stringToColor( n.attributes().namedItem( "color" ).nodeValue() ) );
                                //color.setAlpha(items.item(i).attributes().namedItem("alpha").nodeValue().toInt());
                                QList<QGraphicsItem *> items = scene->items();
                                for ( int i = 0; i < items.size(); i++ )
@@ -265,126 +258,148 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
                                                break;
                                        }
                                }
-                       }
-                       else if ( items.item( i ).nodeName() == "startviewport" )
-                       {
-                               QString rect = items.item( i ).attributes().namedItem( "rect" ).nodeValue();
-                               if ( transform != QTransform() ) {
-                                   rect = rectTransform( rect, transform );
-                               }
-                               mlt_properties_set( producer_props, "_startrect", rect.toUtf8().data() );
-                       }
-                       else if ( items.item( i ).nodeName() == "endviewport" )
-                       {
-                               QString rect = items.item( i ).attributes().namedItem( "rect" ).nodeValue();
-                               if ( transform != QTransform() ) {
-                                   rect = rectTransform( rect, transform );
-                               }
-                               mlt_properties_set( producer_props, "_endrect", rect.toUtf8().data() );
-                       }
-               }
+         
+       }
+
+       QString startRect;
+       QString endRect;
+       n = doc.documentElement().firstChildElement( "startviewport" );
+       if (!n.isNull())
+       {
+               startRect = n.attributes().namedItem( "rect" ).nodeValue();
        }
-       if ( !strcmp( mlt_properties_get( producer_props, "_startrect" ), mlt_properties_get( producer_props, "_endrect" ) ) )
-               mlt_properties_set( producer_props, "_endrect", "" );
+       n = doc.documentElement().firstChildElement( "endviewport" );
+       if (!n.isNull())
+       {
+               QString rect = n.attributes().namedItem( "rect" ).nodeValue();
+               if (startRect != rect)
+                       mlt_properties_set( producer_props, "_endrect", rect.toUtf8().data() );
+       }
+       if (!startRect.isEmpty()) {
+               mlt_properties_set( producer_props, "_startrect", startRect.toUtf8().data() );
+       }
+
        return;
 }
 
 
-void drawKdenliveTitle( producer_ktitle self, uint8_t * buffer, int width, int height, double position, int force_refresh )
+void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int height, double position, int force_refresh )
 {
-  
        // Obtain the producer 
        mlt_producer producer = &self->parent;
-       
-       // restore cached image if any
        mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
 
-       /*if ( force_refresh == 0 )
-       {
-               uint8_t * cache = ( uint8_t * )mlt_properties_get_data( producer_props, "image", NULL );
-               if (cache) {
-                   buffer = cache;
-                   return;
-               }
-       }*/
-       
-       // restore QGraphicsScene
-       QGraphicsScene *scene = static_cast<QGraphicsScene *> (mlt_properties_get_data( producer_props, "qscene", NULL ));
+       // Obtain properties of frame
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
-       if ( force_refresh == 1 && scene )
+       pthread_mutex_lock( &self->mutex );
+
+       QRectF start = stringToRect( QString( mlt_properties_get( producer_props, "_startrect" ) ) );
+       QRectF end = stringToRect( QString( mlt_properties_get( producer_props, "_endrect" ) ) );
+       
+       // Check if user wants us to reload the image
+       if ( force_refresh == 1 || width != self->current_width || height != self->current_height || !end.isNull())
        {
-               scene = NULL;
-               mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
+               //mlt_cache_item_close( self->image_cache );
+               
+               self->current_image = NULL;
+               mlt_properties_set_data( producer_props, "cached_image", NULL, 0, NULL, NULL );
+               mlt_properties_set_int( producer_props, "force_reload", 0 );
        }
+       
+       if (self->current_image == NULL) {
+               // restore QGraphicsScene
+               QGraphicsScene *scene = static_cast<QGraphicsScene *> (mlt_properties_get_data( producer_props, "qscene", NULL ));
+
+               if ( force_refresh == 1 && scene )
+               {
+                       scene = NULL;
+                       mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
+               }
  
-       if ( scene == NULL )
-       {
-               int argc = 1;
-               char* argv[1];
-               argv[0] = "xxx";
-               if (qApp) {
-                   app = qApp;
+               if ( scene == NULL )
+               {
+                       int argc = 1;
+                       char* argv[1];
+                       argv[0] = "xxx";
+                       if (qApp) {
+                               app = qApp;
+                       }
+                       else {
+                               app=new QApplication( argc,argv ); //, QApplication::Tty );
+                       }
+                       scene = new QGraphicsScene( app );
+                       loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ), width, height );
+                       mlt_properties_set_data( producer_props, "qscene", scene, 0, ( mlt_destructor )qscene_delete, NULL );
                }
-               else {
-                   app=new QApplication( argc,argv ); //, QApplication::Tty );
+       
+               int originalWidth = mlt_properties_get_int( producer_props, "_original_width" );
+               int originalHeight= mlt_properties_get_int( producer_props, "_original_height" );
+               const QRectF source( 0, 0, originalWidth, originalHeight );
+               if (start.isNull()) start = source;
+               
+               if (originalWidth != width || originalHeight != height)
+               {
+                       QTransform transform;
+#if QT_VERSION < 0x40500
+                       transform = QTransform().scale(  (double) width / originalWidth, (double) height / originalHeight );
+#else
+                       transform = QTransform::fromScale ( (double) width / originalWidth, (double) height / originalHeight);
+#endif
+                       start = transform.mapRect(start);
+                       if (!end.isNull()) end = transform.mapRect(end);
                }
-               scene = new QGraphicsScene( 0, 0, width, height, app );
-               loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ), width, height );
-               mlt_properties_set_data( producer_props, "qscene", scene, 0, ( mlt_destructor )qscene_delete, NULL );
-       }
-
-
-       //must be extracted from kdenlive title
-       QImage img( width, height, QImage::Format_ARGB32 );
-       img.fill( 0 );
-       QPainter p1;
-       p1.begin( &img );
-       p1.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing );
-       //| QPainter::SmoothPixmapTransform );
+       
+               //must be extracted from kdenlive title
+               QImage img( width, height, QImage::Format_ARGB32 );
+               img.fill( 0 );
+               QPainter p1;
+               p1.begin( &img );
+               p1.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing );
+               //| QPainter::SmoothPixmapTransform );
+
+               if (end.isNull())
+               {
+                       scene->render( &p1, start, source );
+               }
+               else
+               {
+                       QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * position;
+                       QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * position;
+                       const QRectF r1( topleft, bottomRight );
+                       scene->render( &p1, r1, source );
+               }
+               p1.end();
 
-       const QRectF start = stringToRect( QString( mlt_properties_get( producer_props, "_startrect" ) ) );
-       const QRectF end = stringToRect( QString( mlt_properties_get( producer_props, "_endrect" ) ) );
-       const QRectF source( 0, 0, width, height );
+               int size = width * height * 4;
+               uint8_t *pointer=img.bits();
+               QRgb* src = ( QRgb* ) pointer;
+               self->current_image = ( uint8_t * )mlt_pool_alloc( size );
+               uint8_t *dst = self->current_image;
+       
+               for ( int i = 0; i < width * height * 4; i += 4 )
+               {
+                       *dst++=qRed( *src );
+                       *dst++=qGreen( *src );
+                       *dst++=qBlue( *src );
+                       *dst++=qAlpha( *src );
+                       src++;
+               }
 
-       if (end.isNull()) {
-               if (start.isNull())
-                       scene->render( &p1, source, source );
-               else
-                       scene->render( &p1, start, source );
-       }
-       else {
-           QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * position;
-           QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * position;
-           const QRectF r1( topleft, bottomRight );
-           scene->render( &p1, r1, source );
-       }
-       p1.end();
-       g_mutex.lock();
-       uint8_t *pointer=img.bits();
-       QRgb* src = ( QRgb* ) pointer;
-       int size = width * height * 4;
-       for ( int i = 0; i < width * height * 4; i += 4 )
-       {
-               *buffer++=qRed( *src );
-               *buffer++=qGreen( *src );
-               *buffer++=qBlue( *src );
-               *buffer++=qAlpha( *src );
-               src++;
+               mlt_properties_set_data( producer_props, "cached_image", self->current_image, size, mlt_pool_release, NULL );
+               self->current_width = width;
+               self->current_height = height;
+       
+               if ( end.isNull() )
+               {
+                       // Clear scene, we don't need it anymore
+                       mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
+               }
        }
 
-       if ( end.isNull() )
-       {
-           // No animation, cache image for further requests
-           self->current_image = (uint8_t *)mlt_pool_alloc( size );
-           self->current_image = buffer;
-           mlt_properties_set_data( producer_props, "image", self->current_image, width * height * 4, NULL, NULL );
-           
-           // Clear scene, we don't need it anymore
-           mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
-       }
-       g_mutex.unlock();
+       pthread_mutex_unlock( &self->mutex );
+       mlt_properties_set_int( properties, "width", self->current_width );
+       mlt_properties_set_int( properties, "height", self->current_height );
 }
 
 
-
-
index 0660915a78fc10d3abc3c6781a466aadd97ca88b..1044d92a35c08546c5ad242025d155c10dc9b42f 100644 (file)
@@ -33,12 +33,15 @@ struct producer_ktitle_s
 {
        struct mlt_producer_s parent;
        uint8_t *current_image;
+       int current_width;
+       int current_height;
+       mlt_cache_item image_cache;
        pthread_mutex_t mutex;
 };
 
 typedef struct producer_ktitle_s *producer_ktitle;
 
-extern void drawKdenliveTitle( producer_ktitle self, uint8_t*, int, int, double, int );
+extern void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int, int, double, int );
 
 
 #ifdef __cplusplus
index 92b7ee178cffe76aae164667c1387e6d5948113a..5e914e25d6a2c4c1724f46e4df772e2ee6781b57 100644 (file)
@@ -25,8 +25,6 @@
 #include <string.h>
 
 
-extern void refresh_kdenlivetitle( mlt_producer producer, uint8_t*, int, int, double, int );
-
 void read_xml(mlt_properties properties)
 {
        FILE *f = fopen( mlt_properties_get( properties, "resource" ), "r");
@@ -59,41 +57,40 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        /* Obtain properties of producer */
        mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( &this->parent );
        
-       *width = mlt_properties_get_int( properties, "width" );
-       *height = mlt_properties_get_int( properties, "height" );
+       *width = mlt_properties_get_int( properties, "rescale_width" );
+       *height = mlt_properties_get_int( properties, "rescale_height" );
        
        /* Allocate the image */
        int size = *width * ( *height ) * 4;
 
-       *buffer = mlt_pool_alloc( size );
+       /* Allocate the image */
+       *format = mlt_image_rgb24a;
+       mlt_position in = mlt_producer_get_in( &this->parent );
+       mlt_position out = mlt_producer_get_out( &this->parent );
+       mlt_position time = mlt_producer_position( &this->parent );
+       double position = ( double )( time - in ) / ( double )( out - in + 1 );
+       if ( mlt_properties_get_int( producer_props, "force_reload" ) ) {
+               if (mlt_properties_get_int( producer_props, "force_reload" ) > 1) read_xml(producer_props);
+               mlt_properties_set_int( producer_props, "force_reload", 0 );
+               drawKdenliveTitle( this, frame, *width, *height, position, 1);
+       }
+       else drawKdenliveTitle( this, frame, *width, *height, position, 0);
 
-       mlt_properties_set_int( properties, "width", *width );
-       mlt_properties_set_int( properties, "height", *height );
-       
+       // Get width and height (may have changed during the refresh)
+       *width = mlt_properties_get_int( properties, "width" );
+       *height = mlt_properties_get_int( properties, "height" );
+               
        if ( this->current_image )
        {
-               // Clone the image
-               uint8_t *image_copy = mlt_pool_alloc( size );
-               memcpy( image_copy, this->current_image, size );
+               // Clone the image and the alpha
+               int image_size = this->current_width * ( this->current_height ) * 4;
+               uint8_t *image_copy = mlt_pool_alloc( image_size );
+               memcpy( image_copy, this->current_image, image_size );
                // Now update properties so we free the copy after
-               mlt_properties_set_data( properties, "image", image_copy, size, mlt_pool_release, NULL );
+               mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL );
                // We're going to pass the copy on
-               *buffer = image_copy;
-       }
-       else
-       {
-               /* Allocate the image */
-               *format = mlt_image_rgb24a;
-               mlt_position in = mlt_producer_get_in( &this->parent );
-               mlt_position out = mlt_producer_get_out( &this->parent );
-               mlt_position time = mlt_producer_position( &this->parent );
-               double position = ( double )( time - in ) / ( double )( out - in + 1 );
-               if ( mlt_properties_get_int( producer_props, "force_reload" ) ) {
-                       if (mlt_properties_get_int( producer_props, "force_reload" ) > 1) read_xml(producer_props);
-                       mlt_properties_set_int( producer_props, "force_reload", 0 );
-                       drawKdenliveTitle( this, *buffer, *width, *height, position, 1);
-               }
-               else drawKdenliveTitle( this, *buffer, *width, *height, position, 0);
+               *buffer = image_copy;           
+               
                /* Update the frame */
                mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL );