]> git.sesse.net Git - mlt/commitdiff
mlt_cache.[hc], mlt_types.h, mlt_service.[hc], mlt_factory.[hc], mlt.h: add mlt_cache...
authorddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
Tue, 10 Feb 2009 06:22:50 +0000 (06:22 +0000)
committerddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
Tue, 10 Feb 2009 06:22:50 +0000 (06:22 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@1344 d19143bc-622f-0410-bfdd-b5b2a6649095

configure
src/framework/Makefile
src/framework/mlt.h
src/framework/mlt_cache.c [new file with mode: 0644]
src/framework/mlt_cache.h [new file with mode: 0644]
src/framework/mlt_factory.c
src/framework/mlt_factory.h
src/framework/mlt_service.c
src/framework/mlt_service.h
src/framework/mlt_types.h

index 7e8f24654237f6984fb8c8516948d2e78da28870..c04e93afecd8abea9e24181bfe2060c30b4f7b32 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-export version=0.3.6
+export version=0.3.7
 export soversion=1
 
 show_help()
index 9112ff16e94a173487b8323ebb55cabf5dd48f68..58b3899c0e792777574315f829cf87442d86403f 100644 (file)
@@ -36,7 +36,8 @@ OBJS = mlt_frame.o \
           mlt_pool.o \
           mlt_tokeniser.o \
           mlt_profile.o \
-          mlt_log.o
+          mlt_log.o \
+          mlt_cache.o
 
 INCS = mlt_consumer.h \
           mlt_factory.h \
@@ -61,7 +62,8 @@ INCS = mlt_consumer.h \
           mlt_transition.h \
           mlt_tokeniser.h \
           mlt_profile.h \
-          mlt_log.h
+          mlt_log.h \
+          mlt_cache.h
 
 SRCS := $(OBJS:.o=.c)
 
index 72c8717b027fae1e13648177022dc14909889c2e..83650b4d0eaae4b3a4e6834820301b709fc623f6 100644 (file)
@@ -23,8 +23,8 @@
 #ifndef _MLT_H_
 #define _MLT_H_
 
-#define LIBMLT_VERSION_INT ((0<<16)+(3<<8)+6)
-#define LIBMLT_VERSION     0.3.6
+#define LIBMLT_VERSION_INT ((0<<16)+(3<<8)+7)
+#define LIBMLT_VERSION     0.3.7
 
 #ifdef __cplusplus
 extern "C"
diff --git a/src/framework/mlt_cache.c b/src/framework/mlt_cache.c
new file mode 100644 (file)
index 0000000..5a18871
--- /dev/null
@@ -0,0 +1,451 @@
+/**
+ * \file mlt_profile.c
+ * \brief least recently used cache
+ * \see mlt_profile_s
+ *
+ * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
+ * \author Dan Dennedy <dan@dennedy.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mlt_types.h"
+#include "mlt_log.h"
+#include "mlt_properties.h"
+#include "mlt_cache.h"
+
+#include <stdlib.h>
+#include <pthread.h>
+
+/** the maximum number of data objects to cache per line */
+#define CACHE_SIZE (10)
+
+/** \brief Cache item class
+ *
+ * A cache item is a structure holding information about a data object including
+ * a reference count that is used to control its lifetime. When you get a
+ * a cache item from the cache, you hold a reference that prevents the data
+ * from being released when the cache is full and something new is added.
+ * When you close the cache item, the reference count is decremented.
+ * The data object is destroyed when all cache items are closed and the cache
+ * releases its reference.
+ */
+
+typedef struct mlt_cache_item_s
+{
+       mlt_cache cache;           /**< a reference to the cache to which this belongs */
+       void *object;              /**< a parent object to the cache data that uniquely identifies this cached item */
+       void *data;                /**< the opaque pointer to the cached data */
+       int size;                  /**< the size of the cached data */
+       int refcount;              /**< a reference counter to control when destructor is called */
+       mlt_destructor destructor; /**< a function to release or destroy the cached data */
+} mlt_cache_item_s;
+
+/** \brief Cache class
+ *
+ * This is a utility class for implementing a Least Recently Used (LRU) cache
+ * of data blobs indexed by the address of some other object (e.g., a service).
+ * Instead of sorting and manipulating linked lists, it tries to be simple and
+ * elegant by copying pointers between two arrays of fixed size to shuffle the
+ * order of elements.
+ *
+ * This class is useful if you have a service that wants to cache something
+ * somewhat large, but will not scale if there are many instances of the service.
+ * Of course, the service will need to know how to recreate the cached element
+ * if it gets flushed from the cache,
+ *
+ * The most obvious examples are the pixbuf and qimage producers that cache their
+ * respective objects representing a picture read from a file. If the picture
+ * is no longer in the cache, it can simply re-read it from file. However, a
+ * picture is often repeated over many frames and makes sense to cache instead
+ * of continually reading, parsing, and decoding. On the other hand, you might
+ * want to load hundreds of pictures as individual producers, which would use
+ * a lot of memory if every picture is held in memory!
+ */
+
+struct mlt_cache_s
+{
+       int count;             /**< the number of items currently in the cache */
+       void* *current;        /**< pointer to the current array of pointers */
+       void* A[ CACHE_SIZE ];
+       void* B[ CACHE_SIZE ];
+       pthread_mutex_t mutex; /**< a mutex to prevent multi-threaded race conditions */
+       mlt_properties active; /**< a list of cache items some of which may no longer
+                                   be in \p current but to which there are
+                                   outstanding references */
+       mlt_properties garbage;/**< a list cache items pending release. A cache item
+                                   is copied to this list when it is updated but there
+                                   are outstanding references to the old data object. */
+};
+
+/** Get the data pointer from the cache item.
+ *
+ * \public \memberof mlt_cache_s
+ * \param item a cache item
+ * \param[out] size the number of bytes pointed at, if supplied when putting the data into the cache
+ * \return the data pointer
+ */
+
+void *mlt_cache_item_data( mlt_cache_item item, int *size )
+{
+       if ( size && item )
+               *size = item->size;
+       return item? item->data : NULL;
+}
+
+/** Close a cache item given its parent object pointer.
+ *
+ * \private \memberof mlt_cache_s
+ * \param cache a cache
+ * \param object the object to which the data object belongs
+ * \param data the data object, which might be in the garbage list (optional)
+ */
+
+static void cache_object_close( mlt_cache cache, void *object, void* data )
+{
+       char key[19];
+
+       // Fetch the cache item from the active list by its owner's address
+       sprintf( key, "%p", object );
+       pthread_mutex_lock( &cache->mutex );
+       mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL );
+       if ( item )
+       {
+               mlt_log( NULL, MLT_LOG_DEBUG, "%s: item %p object %p data %p refcount %d\n", __FUNCTION__,
+                       item, item->object, item->data, item->refcount );
+               if ( item->destructor && --item->refcount <= 0 )
+               {
+                       // Destroy the data object
+                       item->destructor( item->data );
+                       item->data = NULL;
+                       item->destructor = NULL;
+                       // Do not dispose of the cache item because it could likely be used
+                       // again.
+               }
+       }
+
+       // Fetch the cache item from the garbage collection by its data address
+       if ( data )
+       {
+               sprintf( key, "%p", data );
+               item = mlt_properties_get_data( cache->garbage, key, NULL );
+               if ( item )
+               {
+                       mlt_log( NULL, MLT_LOG_DEBUG, "collecting garbage item %p object %p data %p refcount %d\n",
+                               item, item->object, item->data, item->refcount );
+                       if ( item->destructor && --item->refcount <= 0 )
+                       {
+                               item->destructor( item->data );
+                               item->data = NULL;
+                               item->destructor = NULL;
+                               // We do not need the garbage-collected cache item
+                               mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL );
+                       }
+               }
+       }
+       pthread_mutex_unlock( &cache->mutex );
+}
+
+/** Close a cache item.
+ *
+ * Release a reference and call the destructor on the data object when all
+ * references are released.
+ *
+ * \public \memberof mlt_cache_item_s
+ * \param item a cache item
+ */
+
+void mlt_cache_item_close( mlt_cache_item item )
+{
+       if ( item )
+               cache_object_close( item->cache, item->object, item->data );
+}
+
+/** Create a new cache.
+ *
+ * \public \memberof mlt_cache_s
+ * \return a new cache or NULL if there was an error
+ */
+
+mlt_cache mlt_cache_init()
+{
+       mlt_cache result = calloc( 1, sizeof( struct mlt_cache_s ) );
+       if ( result )
+       {
+               result->current = result->A;
+               pthread_mutex_init( &result->mutex, NULL );
+               result->active = mlt_properties_new();
+               result->garbage = mlt_properties_new();
+       }
+       return result;
+}
+
+/** Destroy a cache.
+ *
+ * \public \memberof mlt_cache_s
+ * \param cache the cache to detroy
+ */
+
+void mlt_cache_close( mlt_cache cache )
+{
+       if ( cache )
+       {
+               while ( cache->count-- )
+               {
+                       void *object = cache->current[ cache->count ];
+                       mlt_log( NULL, MLT_LOG_DEBUG, "%s: %d = %p\n", __FUNCTION__, cache->count, object );
+                       cache_object_close( cache, object, NULL );
+               }
+               mlt_properties_close( cache->active );
+               mlt_properties_close( cache->garbage );
+               pthread_mutex_destroy( &cache->mutex );
+               free( cache );
+       }
+}
+
+/** Remove cache entries for an object.
+ *
+ * \public \memberof mlt_cache_s
+ * \param cache a cache
+ * \param object the object that owns the cached data
+ */
+
+void mlt_cache_purge( mlt_cache cache, void *object )
+{
+       pthread_mutex_lock( &cache->mutex );
+       if ( cache && object )
+       {
+               int i, j;
+               void **alt = cache->current == cache->A ? cache->B : cache->A;
+
+               for ( i = 0, j = 0; i < cache->count; i++ )
+               {
+                       void *o = cache->current[ i ];
+
+                       if ( o == object )
+                       {
+                               pthread_mutex_unlock( &cache->mutex );
+                               cache_object_close( cache, o, NULL );
+                               pthread_mutex_lock( &cache->mutex );
+                       }
+                       else
+                       {
+                               alt[ j++ ] = o;
+                       }
+               }
+               cache->count = j;
+               cache->current = alt;
+
+               // Remove the object's data from the active list regardless of refcount
+               char key[19];
+               sprintf( key, "%p", object );
+               mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL );
+               if ( item && item->destructor )
+               {
+                       item->destructor( item->data );
+                       item->data = NULL;
+                       item->destructor = NULL;
+                       mlt_properties_set_data( cache->active, key, NULL, 0, NULL, NULL );
+               }
+
+               // Remove the object's items from the garbage collection regardless of refcount
+               i = mlt_properties_count( cache->garbage );
+               while ( i-- )
+               {
+                       item = mlt_properties_get_data_at( cache->garbage, i, NULL );
+                       if ( object == item->object && item->destructor )
+                       {
+                               sprintf( key, "%p", item->data );
+                               item->destructor( item->data );
+                               item->data = NULL;
+                               item->destructor = NULL;
+                               mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL );
+                       }
+               }
+       }
+       pthread_mutex_unlock( &cache->mutex );
+}
+
+/** Shuffle the cache entries between the two arrays and return the cache entry for an object.
+ *
+ * \private \memberof mlt_cache_s
+ * \param cache a cache object
+ * \param object the object that owns the cached data
+ * \return a cache entry if there was a hit or NULL for a miss
+ */
+
+static void** shuffle_get_hit( mlt_cache cache, void *object )
+{
+       int i = cache->count;
+       int j = cache->count - 1;
+       void **hit = NULL;
+       void **alt = cache->current == cache->A ? cache->B : cache->A;
+
+       if ( cache->count > 0 && cache->count < CACHE_SIZE )
+       {
+               // first determine if we have a hit
+               while ( i-- && !hit )
+               {
+                       void **o = &cache->current[ i ];
+                       if ( *o == object )
+                               hit = o;
+               }
+               // if there was no hit, we will not be shuffling out an entry
+               // and are still filling the cache
+               if ( !hit )
+                       ++j;
+               // reset these
+               i = cache->count;
+               hit = NULL;
+       }
+
+       // shuffle the existing entries to the alternate array
+       while ( i-- )
+       {
+               void **o = &cache->current[ i ];
+
+               if ( !hit && *o == object )
+               {
+                       hit = o;
+               }
+               else if ( j > 0 )
+               {
+                       alt[ --j ] = *o;
+//                     mlt_log( NULL, MLT_LOG_DEBUG, "%s: shuffle %d = %p\n", __FUNCTION__, j, alt[j] );
+               }
+       }
+       return hit;
+}
+
+/** Put a chunk of data in the cache.
+ *
+ * \public \memberof mlt_cache_s
+ * \param cache a cache object
+ * \param object the object to which this data belongs
+ * \param data an opaque pointer to the data to cache
+ * \param size the size of the data in bytes
+ * \param destructor a pointer to a function that can destroy or release a reference to the data.
+ */
+
+void mlt_cache_put( mlt_cache cache, void *object, void* data, int size, mlt_destructor destructor )
+{
+       pthread_mutex_lock( &cache->mutex );
+       void **hit = shuffle_get_hit( cache, object );
+       void **alt = cache->current == cache->A ? cache->B : cache->A;
+
+       // add the object to the cache
+       if ( hit )
+       {
+               // release the old data
+               pthread_mutex_unlock( &cache->mutex );
+               cache_object_close( cache, *hit, NULL );
+               pthread_mutex_lock( &cache->mutex );
+               // the MRU end gets the updated data
+               hit = &alt[ cache->count - 1 ];
+       }
+       else if ( cache->count < CACHE_SIZE )
+       {
+               // more room in cache, add it to MRU end
+               hit = &alt[ cache->count++ ];
+       }
+       else
+       {
+               // release the entry at the LRU end
+               pthread_mutex_unlock( &cache->mutex );
+               cache_object_close( cache, cache->current[0], NULL );
+               pthread_mutex_lock( &cache->mutex );
+
+               // The MRU end gets the new item
+               hit = &alt[ cache->count - 1 ];
+       }
+       *hit = object;
+       mlt_log( NULL, MLT_LOG_DEBUG, "%s: put %d = %p, %p\n", __FUNCTION__, cache->count - 1, object, data );
+
+       // Fetch the cache item
+       char key[19];
+       sprintf( key, "%p", object );
+       mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL );
+       if ( !item )
+       {
+               item = calloc( 1, sizeof( mlt_cache_item_s ) );
+               if ( item )
+                       mlt_properties_set_data( cache->active, key, item, 0, free, NULL );
+       }
+       if ( item )
+       {
+               // If updating the cache item but not all references are released
+               // copy the item to the garbage collection.
+               if ( item->refcount > 0 && item->data )
+               {
+                       mlt_cache_item orphan = calloc( 1, sizeof( mlt_cache_item_s ) );
+                       if ( orphan )
+                       {
+                               mlt_log( NULL, MLT_LOG_DEBUG, "adding to garbage collection object %p data %p\n", item->object, item->data );
+                               *orphan = *item;
+                               sprintf( key, "%p", orphan->data );
+                               // We store in the garbage collection by data address, not the owner's!
+                               mlt_properties_set_data( cache->garbage, key, orphan, 0, free, NULL );
+                       }
+               }
+
+               // Set/update the cache item
+               item->cache = cache;
+               item->object = object;
+               item->data = data;
+               item->size = size;
+               item->destructor = destructor;
+               item->refcount = 1;
+       }
+       
+       // swap the current array
+       cache->current = alt;
+       pthread_mutex_unlock( &cache->mutex );
+}
+
+/** Get a chunk of data from the cache.
+ *
+ * \public \memberof mlt_cache_s
+ * \param cache a cache object
+ * \param object the object for which you are trying to locate the data
+ * \return a mlt_cache_item if found or NULL if not found or has been flushed from the cache
+ */
+
+mlt_cache_item mlt_cache_get( mlt_cache cache, void *object )
+{
+       mlt_cache_item result = NULL;
+       pthread_mutex_lock( &cache->mutex );
+       void **hit = shuffle_get_hit( cache, object );
+       void **alt = cache->current == cache->A ? cache->B : cache->A;
+
+       if ( hit )
+       {
+               // copy the hit to the MRU end
+               alt[ cache->count - 1 ] = *hit;
+               hit = &alt[ cache->count - 1 ];
+
+               char key[19];
+               sprintf( key, "%p", *hit );
+               result = mlt_properties_get_data( cache->active, key, NULL );
+               if ( result && result->data )
+                       result->refcount++;
+               mlt_log( NULL, MLT_LOG_DEBUG, "%s: get %d = %p, %p\n", __FUNCTION__, cache->count - 1, *hit, result->data );
+
+               // swap the current array
+               cache->current = alt;
+       }
+       pthread_mutex_unlock( &cache->mutex );
+       
+       return result;
+}
diff --git a/src/framework/mlt_cache.h b/src/framework/mlt_cache.h
new file mode 100644 (file)
index 0000000..aaec935
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * \file mlt_cache.h
+ * \brief least recently used cache
+ * \see mlt_cache_s
+ *
+ * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
+ * \author Dan Dennedy <dan@dennedy.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _MLT_CACHE_H
+#define _MLT_CACHE_H
+
+#include "mlt_types.h"
+
+extern void *mlt_cache_item_data( mlt_cache_item item, int *size );
+extern void mlt_cache_item_close( mlt_cache_item item );
+
+extern mlt_cache mlt_cache_init();
+extern void mlt_cache_close( mlt_cache cache );
+extern void mlt_cache_purge( mlt_cache cache, void *object );
+extern void mlt_cache_put( mlt_cache cache, void *object, void* data, int size, mlt_destructor destructor );
+extern mlt_cache_item mlt_cache_get( mlt_cache cache, void *object );
+
+#endif
index bb7619d081eea0aca5a3a6948e61c6ea19604c9c..c9bdb11c7fc2dd63bb83617739682ea66a86ea1a 100644 (file)
@@ -371,3 +371,8 @@ void mlt_factory_close( )
                mlt_pool_close( );
        }
 }
+
+mlt_properties mlt_global_properties( )
+{
+       return global_properties;
+}
index d9279e5beb3f77c7e9c4647e3016cc6962b68d69..cd0dc7fb98ee9dbe1e6ae053e97b0742dd8bd650 100644 (file)
@@ -49,5 +49,6 @@ extern mlt_transition mlt_factory_transition( mlt_profile profile, const char *n
 extern mlt_consumer mlt_factory_consumer( mlt_profile profile, const char *name, void *input );
 extern void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor );
 extern void mlt_factory_close( );
+extern mlt_properties mlt_global_properties( );
 
 #endif
index d693f23298e4cd935d0a39a89c913b4af9adcf5b..b5e8f827b350f8cc8719472f27df074b9841d064 100644 (file)
 #include "mlt_service.h"
 #include "mlt_filter.h"
 #include "mlt_frame.h"
+#include "mlt_cache.h"
+#include "mlt_factory.h"
+#include "mlt_log.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
 
+
 /*  IMPORTANT NOTES
 
        The base service implements a null frame producing service - as such,
@@ -61,6 +66,7 @@ static void mlt_service_disconnect( mlt_service this );
 static void mlt_service_connect( mlt_service this, mlt_service that );
 static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
 static void mlt_service_property_changed( mlt_listener, mlt_properties owner, mlt_service this, void **args );
+static void purge_cache( mlt_service self );
 
 /** Initialize a service.
  *
@@ -629,6 +635,7 @@ void mlt_service_close( mlt_service this )
                        free( base->in );
                        pthread_mutex_destroy( &base->mutex );
                        free( base );
+                       purge_cache( this );
                        mlt_properties_close( &this->parent );
                }
        }
@@ -637,3 +644,95 @@ void mlt_service_close( mlt_service this )
                mlt_service_unlock( this );
        }
 }
+
+/** Release a service's cache items.
+ *
+ * \private \memberof mlt_service_s
+ * \param self a service
+ */
+
+static void purge_cache( mlt_service self )
+{
+       mlt_properties caches = mlt_properties_get_data( mlt_global_properties(), "caches", NULL );
+
+       if ( caches )
+       {
+               int i = mlt_properties_count( caches );
+               while ( i-- )
+               {
+                       mlt_cache_purge( mlt_properties_get_data_at( caches, i, NULL ), self );
+                       mlt_properties_set_data( mlt_global_properties(), mlt_properties_get_name( caches, i ), NULL, 0, NULL, NULL );
+               }
+       }
+}
+
+/** Lookup the cache object for a service.
+ *
+ * \private \memberof mlt_service_s
+ * \param self a service
+ * \param name a name for the object
+ * \return a cache
+ */
+
+static mlt_cache get_cache( mlt_service self, const char *name )
+{
+       mlt_cache result = NULL;
+       mlt_properties caches = mlt_properties_get_data( mlt_global_properties(), "caches", NULL );
+
+       if ( !caches )
+       {
+               caches = mlt_properties_new();
+               mlt_properties_set_data( mlt_global_properties(), "caches", caches, 0, ( mlt_destructor )mlt_properties_close, NULL );
+       }
+       if ( caches )
+       {
+               result = mlt_properties_get_data( caches, name, NULL );
+               if ( !result )
+               {
+                       result = mlt_cache_init();
+                       mlt_properties_set_data( caches, name, result, 0, ( mlt_destructor )mlt_cache_close, NULL );
+               }
+       }
+       
+       return result;
+}
+
+/** Put an object into a service's cache.
+ *
+ * \public \memberof mlt_service_s
+ * \param self a service
+ * \param name a name for the object that is unique to the service class, but not to the instance
+ * \param data an opaque pointer to the object to put into the cache
+ * \param size the number of bytes pointed to by data
+ * \param destructor a function that releases the data
+ */
+
+void mlt_service_cache_put( mlt_service self, const char *name, void* data, int size, mlt_destructor destructor )
+{
+       mlt_log( self, MLT_LOG_DEBUG, "%s: name %s object %p data %p\n", __FUNCTION__, name, self, data );
+       mlt_cache cache = get_cache( self, name );
+
+       if ( cache )
+               mlt_cache_put( cache, self, data, size, destructor );
+}
+
+/** Get an object from a service's cache.
+ *
+ * \public \memberof mlt_service_s
+ * \param self a service
+ * \param name a name for the object that is unique to the service class, but not to the instance
+ * \return a cache item or NULL if an object is not found
+ * \see mlt_cache_item_data
+ */
+
+mlt_cache_item mlt_service_cache_get( mlt_service self, const char *name )
+{
+       mlt_log( self, MLT_LOG_DEBUG, "%s: name %s object %p\n", __FUNCTION__, name, self );
+       mlt_cache_item result = NULL;
+       mlt_cache cache = get_cache( self, name );
+
+       if ( cache )
+               result = mlt_cache_get( cache, self );
+
+       return result;
+}
index 19306314d4ba7c445ec09b7e21fda6df1ffd2f00..ea451bff06b3f23da99b439d11c3b9bef35da9a1 100644 (file)
@@ -25,7 +25,7 @@
 #define _MLT_SERVICE_H_
 
 #include "mlt_properties.h"
-#include "mlt_profile.h"
+#include "mlt_types.h"
 
 /** \brief Service abstract base class
  *
@@ -93,6 +93,8 @@ extern void mlt_service_apply_filters( mlt_service self, mlt_frame frame, int in
 extern mlt_filter mlt_service_filter( mlt_service self, int index );
 extern mlt_profile mlt_service_profile( mlt_service self );
 extern void mlt_service_close( mlt_service self );
+extern void mlt_service_cache_put( mlt_service self, const char *name, void* data, int size, mlt_destructor destructor );
+extern mlt_cache_item mlt_service_cache_get( mlt_service self, const char *name );
 
 #endif
 
index 035fadabfd134e64d7ffef16b1598022c7268077..921dd4799bae00fd9f9be3adfedad9830d9e8406 100644 (file)
@@ -107,6 +107,8 @@ typedef struct mlt_geometry_s *mlt_geometry;            /**< pointer to Geometry
 typedef struct mlt_geometry_item_s *mlt_geometry_item;  /**< pointer to Geometry Item object */
 typedef struct mlt_profile_s *mlt_profile;              /**< pointer to Profile object */
 typedef struct mlt_repository_s *mlt_repository;        /**< pointer to Repository object */
+typedef struct mlt_cache_s *mlt_cache;                  /**< pointer to Cache object */
+typedef struct mlt_cache_item_s *mlt_cache_item;        /**< pointer to CacheItem object */
 
 typedef void ( *mlt_destructor )( void * );             /**< pointer to destructor function */
 typedef char *( *mlt_serialiser )( void *, int length );/**< pointer to serialization function */