31.01.15 23:50, Dan Dennedy написав(ла):
On Thu, Jan 29, 2015 at 8:24 AM, Maksym Veremeyenko <ve...@m1stereo.tv <mailto:ve...@m1stereo.tv>> wrote:Hi, attached patch implement caching converted image produced by pango producer. 1.) It does not use mlt_cache, which means that if someone uses many pango producers (perhaps they wrote something to read a subtitle) it will consumer a lot of memory. 2.) +// convert +mlt_frame_get_image( frame, &image, format, &this->cached.width, &this->cached.height, 0 ); You cannot call mlt_frame_get_image() here to do a conversion like that because it affects mlt_frame.stack_image. I recall we have done that in the past, but it caused problems, I think with tractor and/or transitions (21a3f68). It would take more analysis to determine if it only affects filters and not producers, but I just prefer to be safe and use frame->convert_image() instead of this function that potentially affects the image stack. 3.) +//*format = mlt_image_rgb24a; Remove commented-out code.
i rewritten a code, please review. -- ________________________________________ Maksym Veremeyenko
>From 8485668ff10f1595a13c3d1f57998f51d3d0b135 Mon Sep 17 00:00:00 2001 From: Maksym Veremeyenko <ve...@m1stereo.tv> Date: Mon, 2 Feb 2015 20:28:31 +0200 Subject: [PATCH] implement caching images --- src/modules/gtk2/factory.c | 5 ++ src/modules/gtk2/producer_pango.c | 130 +++++++++++++++++++++++++++++++++-- src/modules/gtk2/producer_pango.yml | 3 + 3 files changed, 131 insertions(+), 7 deletions(-) diff --git a/src/modules/gtk2/factory.c b/src/modules/gtk2/factory.c index 90a886d..02ade91 100644 --- a/src/modules/gtk2/factory.c +++ b/src/modules/gtk2/factory.c @@ -49,6 +49,11 @@ static void initialise( ) mlt_service_cache_set_size( NULL, "pixbuf.alpha", n ); mlt_service_cache_set_size( NULL, "pixbuf.pixbuf", n ); } + if ( getenv("MLT_PANGO_PRODUCER_CACHE") ) + { + int n = atoi( getenv("MLT_PANGO_PRODUCER_CACHE" ) ); + mlt_service_cache_set_size( NULL, "pango.image", n ); + } } } diff --git a/src/modules/gtk2/producer_pango.c b/src/modules/gtk2/producer_pango.c index 669d9be..9163a49 100644 --- a/src/modules/gtk2/producer_pango.c +++ b/src/modules/gtk2/producer_pango.c @@ -20,6 +20,7 @@ #include <framework/mlt_producer.h> #include <framework/mlt_frame.h> #include <framework/mlt_geometry.h> +#include <framework/mlt_cache.h> #include <stdlib.h> #include <string.h> #include <gdk-pixbuf/gdk-pixbuf.h> @@ -40,6 +41,26 @@ typedef enum static pthread_mutex_t pango_mutex = PTHREAD_MUTEX_INITIALIZER; +struct pango_cached_image_s +{ + uint8_t *image, *alpha; + mlt_image_format format; + int width, height; +}; + +static void pango_cached_image_destroy( void* p ) +{ + struct pango_cached_image_s* i = p; + + if ( !i ) + return; + if ( i->image ) + mlt_pool_release( i->image ); + if ( i->alpha ) + mlt_pool_release( i->alpha ); + mlt_pool_release( i ); +}; + struct producer_pango_s { struct mlt_producer_s parent; @@ -61,6 +82,11 @@ struct producer_pango_s int weight; }; +static void clean_cached( producer_pango self ) +{ + mlt_service_cache_put( MLT_PRODUCER_SERVICE( &self->parent ), "pango.image", NULL, 0, NULL ); +} + // special color type used by internal pango routines typedef struct { @@ -425,6 +451,7 @@ static void refresh_image( mlt_frame frame, int width, int height ) if ( this->pixbuf ) g_object_unref( this->pixbuf ); this->pixbuf = NULL; + clean_cached( this ); // Convert from specified encoding to UTF-8 if ( encoding != NULL && !strncaseeq( encoding, "utf-8", 5 ) && !strncaseeq( encoding, "utf8", 4 ) ) @@ -464,6 +491,7 @@ static void refresh_image( mlt_frame frame, int width, int height ) if ( this->pixbuf ) g_object_unref( this->pixbuf ); this->pixbuf = NULL; + clean_cached( this ); pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL ); } @@ -484,6 +512,7 @@ static void refresh_image( mlt_frame frame, int width, int height ) // Note - the original pixbuf is already safe and ready for destruction this->pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, interp ); + clean_cached( this ); // Store width and height this->width = width; @@ -515,18 +544,104 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form // Get width and height *width = this->width; *height = this->height; - *format = mlt_image_rgb24a; // Always clone here to allow 'animated' text if ( this->pixbuf ) { - // Clone the image - int image_size = this->width * this->height * 4; - *buffer = mlt_pool_alloc( image_size ); - memcpy( *buffer, gdk_pixbuf_get_pixels( this->pixbuf ), image_size ); + int size, bpp; + uint8_t *buf; + mlt_cache_item cached_item = mlt_service_cache_get( MLT_PRODUCER_SERVICE( &this->parent ), "pango.image" ); + struct pango_cached_image_s* cached = mlt_cache_item_data( cached_item, NULL ); - // Now update properties so we free the copy after - mlt_frame_set_image( frame, *buffer, image_size, mlt_pool_release ); + // destroy cached data if request is differ + if ( !cached || ( cached && (cached->format != *format || cached->width != *width || cached->height != *height ))) + { + mlt_cache_item_close( cached_item ); + cached_item = NULL; + cached = NULL; + clean_cached( this ); + }; + + // create cached image + if ( !cached ) + { + int dst_stride, src_stride; + + cached = mlt_pool_alloc( sizeof( struct pango_cached_image_s )); + cached->width = this->width; + cached->height = this->height; + cached->format = gdk_pixbuf_get_has_alpha( this->pixbuf ) ? mlt_image_rgb24a : mlt_image_rgb24; + cached->alpha = NULL; + cached->image = NULL; + + src_stride = gdk_pixbuf_get_rowstride( this->pixbuf ); + dst_stride = this->width * ( mlt_image_rgb24a == cached->format ? 4 : 3 ); + + size = dst_stride * ( this->height + 1 ); + buf = mlt_pool_alloc( size ); + + if ( src_stride != dst_stride ) + { + int y = this->height; + uint8_t *src = gdk_pixbuf_get_pixels( this->pixbuf ); + uint8_t *dst = buf; + while ( y-- ) + { + memcpy( dst, src, dst_stride ); + dst += dst_stride; + src += src_stride; + }; + } + else + { + memcpy( buf, gdk_pixbuf_get_pixels( this->pixbuf ), src_stride * this->height ); + }; + + // convert image + if(frame->convert_image && cached->format != *format) + { + frame->convert_image( frame, &buf, &cached->format, *format ); + *format = cached->format; + }; + + size = mlt_image_format_size(cached->format, cached->width, cached->height, &bpp ); + cached->image = mlt_pool_alloc( size ); + memcpy( cached->image, buf, size ); + + if ( ( buf = mlt_frame_get_alpha_mask( frame ) ) ) + { + size = cached->width * cached->height; + cached->alpha = mlt_pool_alloc( size ); + memcpy( cached->alpha, buf, size ); + }; + }; + + if ( cached ) + { + // clone image surface + size = mlt_image_format_size(cached->format, cached->width, cached->height, &bpp ); + buf = mlt_pool_alloc( size ); + memcpy( buf, cached->image, size ); + + // set image surface + mlt_frame_set_image( frame, buf, size, mlt_pool_release ); + *buffer = buf; + + // set alpha + if ( cached->alpha ) + { + size = cached->width * cached->height; + buf = mlt_pool_alloc( size ); + memcpy( buf, cached->alpha, size ); + mlt_frame_set_alpha( frame, buf, size, mlt_pool_release ); + } + }; + + if ( cached_item ) + mlt_cache_item_close( cached_item ); + else + mlt_service_cache_put( MLT_PRODUCER_SERVICE( &this->parent ), "pango.image", + cached, sizeof( struct pango_cached_image_s ), pango_cached_image_destroy ); } else { @@ -586,6 +701,7 @@ static void producer_close( mlt_producer parent ) producer_pango this = parent->child; if ( this->pixbuf ) g_object_unref( this->pixbuf ); + mlt_service_cache_purge( MLT_PRODUCER_SERVICE(parent) ); free( this->fgcolor ); free( this->bgcolor ); free( this->olcolor ); diff --git a/src/modules/gtk2/producer_pango.yml b/src/modules/gtk2/producer_pango.yml index fda674f..0096322 100644 --- a/src/modules/gtk2/producer_pango.yml +++ b/src/modules/gtk2/producer_pango.yml @@ -23,6 +23,9 @@ notes: > whatever the consumer requests. Therefore, it will lose its aspect ratio if so requested, and it is up to the consumer to request a proper width and height that maintains the image aspect. + + Environment variable MLT_PANGO_PRODUCER_CACHE could be used to override and + increase the size of cached converted images of simultaneous use. parameters: - identifier: argument -- 1.7.7.6
------------------------------------------------------------------------------ Dive into the World of Parallel Programming. The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________ Mlt-devel mailing list Mlt-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mlt-devel