From 440ed00f0eb850d21ef10c7ed4762f9ba4e2b69c Mon Sep 17 00:00:00 2001 From: ddennedy Date: Tue, 10 Feb 2009 06:34:15 +0000 Subject: [PATCH 1/1] producer_qimage.c, qimage_wrapper.{h,cpp}: enhance qimage producer to use the new mlt_cache (kdenlive-575) git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@1347 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/modules/qimage/producer_qimage.c | 41 ++++++++------- src/modules/qimage/qimage_wrapper.cpp | 92 +++++++++++++++++---------------- src/modules/qimage/qimage_wrapper.h | 8 ++- 3 files changed, 75 insertions(+), 66 deletions(-) diff --git a/src/modules/qimage/producer_qimage.c b/src/modules/qimage/producer_qimage.c index 022dd91..841b456 100644 --- a/src/modules/qimage/producer_qimage.c +++ b/src/modules/qimage/producer_qimage.c @@ -22,6 +22,7 @@ */ #include +#include #include "qimage_wrapper.h" #include @@ -68,12 +69,12 @@ mlt_producer producer_qimage_init( mlt_profile profile, mlt_service_type type, c if ( frame ) { mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); + pthread_mutex_init( &this->mutex, NULL ); mlt_properties_set_data( frame_properties, "producer_qimage", this, 0, NULL, NULL ); mlt_frame_set_position( frame, mlt_producer_position( producer ) ); mlt_properties_set_position( frame_properties, "qimage_position", mlt_producer_position( producer ) ); - refresh_qimage( frame, 0, 0 ); + refresh_qimage( this, frame, 0, 0 ); mlt_frame_close( frame ); - mlt_properties_set_data( properties, "_qimage", NULL, 0, NULL, NULL ); } } if ( this->current_width == 0 ) @@ -172,22 +173,18 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); - // We need to know the size of the image to clone it - int image_size = 0; - int alpha_size = 0; - - // Alpha channel - uint8_t *alpha = NULL; + // Obtain the producer for this frame + producer_qimage this = mlt_properties_get_data( properties, "producer_qimage", NULL ); *width = mlt_properties_get_int( properties, "rescale_width" ); *height = mlt_properties_get_int( properties, "rescale_height" ); // Refresh the image - refresh_qimage( frame, *width, *height ); + refresh_qimage( this, frame, *width, *height ); - // Get the image - *buffer = mlt_properties_get_data( properties, "image", &image_size ); - alpha = mlt_properties_get_data( properties, "alpha", &alpha_size ); + // We need to know the size of the image to clone it + int image_size = this->current_width * ( this->current_height + 1 ) * 2; + int alpha_size = this->current_width * this->current_height; // Get width and height (may have changed during the refresh) *width = mlt_properties_get_int( properties, "width" ); @@ -195,7 +192,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form // NB: Cloning is necessary with this producer (due to processing of images ahead of use) // The fault is not in the design of mlt, but in the implementation of the qimage producer... - if ( *buffer != NULL ) + if ( this->current_image != NULL ) { if ( *format == mlt_image_yuv422 || *format == mlt_image_yuv420p ) { @@ -203,11 +200,11 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form uint8_t *image_copy = mlt_pool_alloc( image_size ); uint8_t *alpha_copy = mlt_pool_alloc( alpha_size ); - memcpy( image_copy, *buffer, image_size ); + memcpy( image_copy, this->current_image, image_size ); // Copy or default the alpha - if ( alpha != NULL ) - memcpy( alpha_copy, alpha, alpha_size ); + if ( this->current_alpha ) + memcpy( alpha_copy, this->current_alpha, alpha_size ); else memset( alpha_copy, 255, alpha_size ); @@ -226,7 +223,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form uint8_t *image_copy = mlt_pool_alloc( image_size ); uint8_t *alpha_copy = mlt_pool_alloc( alpha_size ); - mlt_convert_yuv422_to_rgb24a(*buffer, image_copy, (*width)*(*height)); + mlt_convert_yuv422_to_rgb24a(this->current_image, image_copy, (*width)*(*height)); // Now update properties so we free the copy after mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); @@ -245,6 +242,11 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form *height = 50; } + // Release references and locks + pthread_mutex_unlock( &this->mutex ); + mlt_cache_item_close( this->image_cache ); + mlt_cache_item_close( this->alpha_cache ); + return 0; } @@ -286,7 +288,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_properties_set_position( properties, "qimage_position", mlt_producer_position( producer ) ); // Refresh the image - refresh_qimage( *frame, 0, 0 ); + refresh_qimage( this, *frame, 0, 0 ); // Set producer-specific frame properties mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( producer_properties, "progressive" ) ); @@ -308,9 +310,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i static void producer_close( mlt_producer parent ) { producer_qimage this = parent->child; + pthread_mutex_destroy( &this->mutex ); parent->close = NULL; - mlt_pool_release( this->current_image ); - mlt_pool_release( this->current_alpha ); mlt_producer_close( parent ); mlt_properties_close( this->filenames ); free( this ); diff --git a/src/modules/qimage/qimage_wrapper.cpp b/src/modules/qimage/qimage_wrapper.cpp index 2856324..d8722e0 100644 --- a/src/modules/qimage/qimage_wrapper.cpp +++ b/src/modules/qimage/qimage_wrapper.cpp @@ -47,6 +47,7 @@ extern "C" { #include +#include #ifdef USE_KDE static KInstance *instance = 0L; @@ -63,7 +64,7 @@ static void qimage_delete( void *data ) #endif } -QMutex mutex; +static QMutex g_mutex; #ifdef USE_KDE void init_qimage() @@ -75,23 +76,30 @@ void init_qimage() } #endif -void refresh_qimage( mlt_frame frame, int width, int height ) +void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int height ) { - // Obtain a previous assigned qimage (if it exists) - QImage *qimage = static_cast (mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "qimage", NULL )); - // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); - // Obtain the producer for this frame - producer_qimage self = ( producer_qimage )mlt_properties_get_data( properties, "producer_qimage", NULL ); - // Obtain the producer mlt_producer producer = &self->parent; // Obtain properties of producer mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); + // restore QImage + pthread_mutex_lock( &self->mutex ); + mlt_cache_item qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" ); + QImage *qimage = static_cast( mlt_cache_item_data( qimage_cache, NULL ) ); + + // restore scaled image + self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" ); + self->current_image = static_cast( mlt_cache_item_data( self->image_cache, NULL ) ); + + // restore alpha channel + self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" ); + self->current_alpha = static_cast( mlt_cache_item_data( self->alpha_cache, NULL ) ); + // Check if user wants us to reload the image if ( mlt_properties_get_int( producer_props, "force_reload" ) ) { @@ -119,7 +127,7 @@ void refresh_qimage( mlt_frame frame, int width, int height ) char image_key[ 10 ]; sprintf( image_key, "%d", image_idx ); - mutex.lock(); + g_mutex.lock(); // Check if the frame is already loaded if ( use_cache ) @@ -149,45 +157,28 @@ void refresh_qimage( mlt_frame frame, int width, int height ) } // optimization for subsequent iterations on single picture - if ( width != 0 && self->current_image != NULL && image_idx == self->image_idx ) - { - if ( width != self->current_width || height != self->current_height ) - { - qimage = static_cast(mlt_properties_get_data( producer_props, "_qimage", NULL )); - if ( !use_cache ) - { - mlt_pool_release( self->current_image ); - mlt_pool_release( self->current_alpha ); - } - self->current_image = NULL; - self->current_alpha = NULL; - } - } - else if ( qimage == NULL && ( self->current_image == NULL || image_idx != self->image_idx ) ) + if ( width != 0 && ( image_idx != self->image_idx || width != self->current_width || height != self->current_height ) ) + self->current_image = NULL; + if ( image_idx != self->image_idx ) + qimage = NULL; + if ( qimage == NULL && ( width == 0 || self->current_image == NULL ) ) { - if ( !use_cache ) - { - mlt_pool_release( self->current_image ); - mlt_pool_release( self->current_alpha ); - } self->current_image = NULL; - self->current_alpha = NULL; - self->image_idx = image_idx; qimage = new QImage( mlt_properties_get_value( self->filenames, image_idx ) ); if ( !qimage->isNull( ) ) { - QImage *frame_copy = new QImage( *qimage ); - - // Store the width/height of the pixbuf + // Store the width/height of the qimage self->current_width = qimage->width( ); self->current_height = qimage->height( ); // Register qimage for destruction and reuse + mlt_cache_item_close( qimage_cache ); + mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage", qimage, 0, ( mlt_destructor )qimage_delete ); + qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" ); + mlt_events_block( producer_props, NULL ); - mlt_properties_set_data( producer_props, "_qimage", qimage, 0, ( mlt_destructor )qimage_delete, NULL ); - mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "qimage", frame_copy, 0, ( mlt_destructor )qimage_delete, NULL ); mlt_properties_set_int( producer_props, "_real_width", self->current_width ); mlt_properties_set_int( producer_props, "_real_height", self->current_height ); mlt_events_unblock( producer_props, NULL ); @@ -235,14 +226,22 @@ void refresh_qimage( mlt_frame frame, int width, int height ) // Allocate/define image self->current_image = ( uint8_t * )mlt_pool_alloc( width * ( height + 1 ) * 2 ); - + if ( !use_cache ) + mlt_cache_item_close( self->image_cache ); + mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.image", self->current_image, width * ( height + 1 ) * 2, mlt_pool_release ); + self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" ); if (!hasAlpha) { mlt_convert_rgb24_to_yuv422( temp.bits(), self->current_width, self->current_height, temp.bytesPerLine(), self->current_image ); } else { // Allocate the alpha mask - self->current_alpha = ( uint8_t * )mlt_pool_alloc( self->current_width * self->current_height ); + self->current_alpha = ( uint8_t * )mlt_pool_alloc( width * height ); + if ( !use_cache ) + mlt_cache_item_close( self->alpha_cache ); + mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha", self->current_alpha, width * height, mlt_pool_release ); + self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" ); + #ifdef USE_QT4 if ( QSysInfo::ByteOrder == QSysInfo::BigEndian ) mlt_convert_argb_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine(), self->current_image, self->current_alpha ); @@ -263,16 +262,21 @@ void refresh_qimage( mlt_frame frame, int width, int height ) update_cache = use_cache; } + // release references no longer needed + mlt_cache_item_close( qimage_cache ); + if ( width == 0 ) + { + pthread_mutex_unlock( &self->mutex ); + mlt_cache_item_close( self->image_cache ); + mlt_cache_item_close( self->alpha_cache ); + } + // Set width/height of frame mlt_properties_set_int( properties, "width", self->current_width ); mlt_properties_set_int( properties, "height", self->current_height ); mlt_properties_set_int( properties, "real_width", mlt_properties_get_int( producer_props, "_real_width" ) ); mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "_real_height" ) ); - // pass the image data without destructor - mlt_properties_set_data( properties, "image", self->current_image, self->current_width * ( self->current_height + 1 ) * 2, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", self->current_alpha, self->current_width * self->current_height, NULL, NULL ); - if ( update_cache ) { mlt_frame cached = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) ); @@ -285,7 +289,7 @@ void refresh_qimage( mlt_frame frame, int width, int height ) mlt_properties_set_data( cached_props, "alpha", self->current_alpha, self->current_width * self->current_height, mlt_pool_release, NULL ); mlt_properties_set_data( cache, image_key, cached, 0, ( mlt_destructor )mlt_frame_close, NULL ); } - mutex.unlock(); - } + g_mutex.unlock(); } +} // extern "C" diff --git a/src/modules/qimage/qimage_wrapper.h b/src/modules/qimage/qimage_wrapper.h index 7e1711a..9c9243e 100644 --- a/src/modules/qimage/qimage_wrapper.h +++ b/src/modules/qimage/qimage_wrapper.h @@ -27,6 +27,7 @@ #include #include "config.h" +#include #ifdef __cplusplus extern "C" { @@ -41,12 +42,15 @@ struct producer_qimage_s uint8_t *current_image; uint8_t *current_alpha; int current_width; - int current_height; + int current_height; + mlt_cache_item image_cache; + mlt_cache_item alpha_cache; + pthread_mutex_t mutex; }; typedef struct producer_qimage_s *producer_qimage; -extern void refresh_qimage( mlt_frame, int width, int height ); +extern void refresh_qimage( producer_qimage, mlt_frame, int width, int height ); #ifdef USE_KDE extern void init_qimage(); #endif -- 1.7.4.4