Oddities
- There seems to be a discrepancy between audio and video pts (time
- stamps) which causes audio seeking to be unreliable in some cases.
- If audio playback is broken, try adding discrepancy=3 as a
- property.
-
- Not sure of the exact reasons, but am investigating.
+ MPEG video remains elusive.
Known Bugs
mlt_field.o \
mlt_tractor.o \
mlt_factory.o \
- mlt_repository.o
+ mlt_repository.o \
+ mlt_pool.o
SRCS := $(OBJS:.o=.c)
// Store the prefix for later retrieval
mlt_prefix = strdup( prefix );
+ // Initialise the pool
+ mlt_pool_init( );
+
// Create the object list.
object_list = mlt_properties_new( );
mlt_properties_close( object_list );
free( mlt_prefix );
mlt_prefix = NULL;
+ mlt_pool_close( );
}
}
}
else
{
+ void *release = NULL;
uint8_t *p;
uint8_t *q;
int size = 0;
*buffer = NULL;
break;
case mlt_image_rgb24:
- // IRRIGATE ME
size *= 3;
size += *width * 3;
- *buffer = malloc( size );
+ *buffer = mlt_pool_allocate( size, &release );
if ( *buffer )
memset( *buffer, 255, size );
break;
case mlt_image_rgb24a:
- // IRRIGATE ME
size *= 4;
size += *width * 4;
- *buffer = malloc( size );
+ *buffer = mlt_pool_allocate( size, &release );
if ( *buffer )
memset( *buffer, 255, size );
break;
case mlt_image_yuv422:
- // IRRIGATE ME
size *= 2;
size += *width * 2;
- *buffer = malloc( size );
+ *buffer = mlt_pool_allocate( size, &release );
p = *buffer;
q = p + size;
while ( p != NULL && p != q )
break;
case mlt_image_yuv420p:
size = size * 3 / 2;
- *buffer = malloc( size );
- if ( *buffer )
+ *buffer = mlt_pool_allocate( size, &release );
+ if ( *buffer )
memset( *buffer, 255, size );
break;
}
- mlt_properties_set_data( properties, "image", *buffer, size, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", *buffer, size, NULL, NULL );
mlt_properties_set_int( properties, "test_image", 1 );
}
else
{
int size = 0;
+ void *release = NULL;
*samples = *samples <= 0 ? 1920 : *samples;
*channels = *channels <= 0 ? 2 : *channels;
*frequency = *frequency <= 0 ? 48000 : *frequency;
size = *samples * *channels * sizeof( int16_t );
- *buffer = malloc( size );
+ *buffer = mlt_pool_allocate( size, &release );
if ( *buffer != NULL )
memset( *buffer, 0, size );
- mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL );
+ mlt_properties_set_data( properties, "audio_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "audio", *buffer, size, NULL, NULL );
mlt_properties_set_int( properties, "test_audio", 1 );
}
return 0;
if ( iwidth != owidth || iheight != oheight )
{
// Create the output image
- // IRRIGATE ME
- uint8_t *output = malloc( owidth * ( oheight + 1 ) * 2 );
+ void *release = NULL;
+ uint8_t *output = mlt_pool_allocate( owidth * ( oheight + 1 ) * 2, &release );
// Call the generic resize
mlt_resize_yuv422( output, owidth, oheight, input, iwidth, iheight );
// Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, NULL, NULL );
mlt_properties_set_int( properties, "width", owidth );
mlt_properties_set_int( properties, "height", oheight );
if ( iwidth != owidth || iheight != oheight )
{
// Create the output image
- // IRRIGATE ME
- uint8_t *output = malloc( owidth * ( oheight + 1 ) * 2 );
+ void *release = NULL;
+ uint8_t *output = mlt_pool_allocate( owidth * ( oheight + 1 ) * 2, &release );
// Calculate strides
int istride = iwidth * 2;
}
// Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * oheight * 2, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, NULL, NULL );
mlt_properties_set_int( properties, "width", owidth );
mlt_properties_set_int( properties, "height", oheight );
--- /dev/null
+/*
+ * mlt_pool.c -- memory pooling functionality
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "mlt_properties.h"
+#include "mlt_deque.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+/** Singleton repositories
+*/
+
+static mlt_properties pools = NULL;
+
+/** Private pooling structure.
+*/
+
+typedef struct mlt_pool_s
+{
+ pthread_mutex_t lock;
+ mlt_deque stack;
+ int size;
+}
+*mlt_pool;
+
+/** Private release structure
+*/
+
+typedef struct mlt_release_s
+{
+ void *ptr;
+ mlt_pool pool;
+}
+*mlt_release;
+
+/** Create a pool.
+*/
+
+static mlt_pool pool_init( int size )
+{
+ // Create the pool
+ mlt_pool this = calloc( 1, sizeof( struct mlt_pool_s ) );
+
+ // Initialise it
+ if ( this != NULL )
+ {
+ // Initialise the mutex
+ pthread_mutex_init( &this->lock, NULL );
+
+ // Create the stack
+ this->stack = mlt_deque_init( );
+
+ // Assign the size
+ this->size = size;
+ }
+
+ // Return it
+ return this;
+}
+
+/** Get an item from the pool.
+*/
+
+static mlt_release pool_fetch( mlt_pool this )
+{
+ // We will generate a release object
+ mlt_release release = NULL;
+
+ // Sanity check
+ if ( this != NULL )
+ {
+ // Lock the pool
+ pthread_mutex_lock( &this->lock );
+
+ // Check if the stack is empty
+ if ( mlt_deque_count( this->stack ) != 0 )
+ {
+ // Pop the top of the stack
+ release = mlt_deque_pop_back( this->stack );
+ }
+ else
+ {
+ // We need to generate a release item
+ release = calloc( 1, sizeof( struct mlt_release_s ) );
+
+ // Initialise it
+ if ( release != NULL )
+ {
+ // Allocate the real memory
+ release->ptr = malloc( this->size );
+
+ // Assign the pool
+ release->pool = this;
+ }
+ }
+
+ // Unlock the pool
+ pthread_mutex_unlock( &this->lock );
+ }
+
+ // Return the generated release object
+ return release;
+}
+
+/** Return an item to the pool.
+*/
+
+static void pool_return( mlt_pool this, mlt_release that )
+{
+ // Sanity checks
+ if ( this != NULL && that != NULL )
+ {
+ // Ensure that the pools match
+ if ( this == that->pool )
+ {
+ // Lock the pool
+ pthread_mutex_lock( &this->lock );
+
+ // Push the that back back on to the stack
+ mlt_deque_push_back( this->stack, that );
+
+ // Unlock the pool
+ pthread_mutex_unlock( &this->lock );
+
+ // Ensure that we don't clean up
+ that = NULL;
+ }
+ }
+
+ // Tidy up - this will only occur if the returned item is incorrect
+ if ( that != NULL )
+ {
+ // Free the memory
+ free( that->ptr );
+
+ // Free the release itself
+ free( that );
+ }
+}
+
+/** Destroy a pool.
+*/
+
+static void pool_close( mlt_pool this )
+{
+ if ( this != NULL )
+ {
+ // We need to free up all items in the pool
+ mlt_release release = NULL;
+
+ // Iterate through the stack until depleted
+ while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
+ {
+ // We'll return this item to NULL
+ pool_return( NULL, release );
+ }
+
+ // We can now close the stack
+ mlt_deque_close( this->stack );
+
+ // Destroy the mutex
+ pthread_mutex_destroy( &this->lock );
+
+ // Close the pool
+ free( this );
+ }
+}
+
+/** Initialise the pool.
+*/
+
+void mlt_pool_init( )
+{
+ // Loop variable used to create the pools
+ int i = 0;
+
+ // Create the pools
+ pools = mlt_properties_new( );
+
+ // Create the pools
+ for ( i = 8; i < 32; i ++ )
+ {
+ // Each properties item needs a name
+ char name[ 32 ];
+
+ // Construct a pool
+ mlt_pool pool = pool_init( 1 << i );
+
+ // Generate a name
+ sprintf( name, "%d", i );
+
+ // Register with properties
+ mlt_properties_set_data( pools, name, pool, 0, ( mlt_destructor )pool_close, NULL );
+ }
+}
+
+/** Allocate size bytes from the pool.
+*/
+
+void *mlt_pool_allocate( int size, void **release )
+{
+ // This is the real release structure we'll return
+ mlt_release real = NULL;
+
+ // This will be used to obtain the pool to use
+ mlt_pool pool = NULL;
+
+ // Determines the index of the pool to use
+ int index = 1;
+
+ // Minimum size pooled is 256 bytes
+ size = size >> 8;
+ while ( ( 1 << index ) < size )
+ index ++;
+
+ // Now get the pool at the index
+ pool = mlt_properties_get_data_at( pools, index + 1, NULL );
+
+ // Now get the real item
+ real = pool_fetch( pool );
+
+ // Deal with return
+ if ( real != NULL )
+ {
+ // Assign to release
+ *release = real;
+
+ // Return the pointer
+ return real->ptr;
+ }
+
+ // Otherwise return a NULL to indicate failure
+ return NULL;
+}
+
+/** Release the allocated memory.
+*/
+
+void mlt_pool_release( void *release )
+{
+ // Sanity check
+ if ( release != NULL )
+ {
+ // Get the real release structure
+ mlt_release real = release;
+
+ // Return to the pool
+ pool_return( real->pool, real );
+ }
+}
+
+/** Close the pool.
+*/
+
+void mlt_pool_close( )
+{
+ // Close the properties
+ mlt_properties_close( pools );
+}
+
--- /dev/null
+/*
+ * mlt_pool.h -- memory pooling functionality
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MLT_POOL_H
+#define _MLT_POOL_H
+
+extern void mlt_pool_init( );
+extern void *mlt_pool_allocate( int size, void **release );
+extern void mlt_pool_release( void *release );
+extern void mlt_pool_close( );
+
+#endif
return NULL;
}
+/** Get a data value by index.
+*/
+
+void *mlt_properties_get_data_at( mlt_properties this, int index, int *size )
+{
+ property_list *list = this->private;
+ if ( index >= 0 && index < list->count )
+ return mlt_property_get_data( list->value[ index ], size );
+ return NULL;
+}
+
/** Return the number of items in the list.
*/
extern char *mlt_properties_get( mlt_properties this, char *name );
extern char *mlt_properties_get_name( mlt_properties this, int index );
extern char *mlt_properties_get_value( mlt_properties this, int index );
+extern void *mlt_properties_get_data_at( mlt_properties this, int index, int *size );
extern int mlt_properties_get_int( mlt_properties this, char *name );
extern int mlt_properties_set_int( mlt_properties this, char *name, int value );
extern double mlt_properties_get_double( mlt_properties this, char *name );
#include <stdint.h>
+#include "mlt_pool.h"
+
typedef enum
{
mlt_whence_relative_start,
if ( output == NULL )
{
int size = avpicture_get_size( PIX_FMT_YUV422, *width, *height );
- // IRRIGATE ME
+ void *frame_release = NULL;
+ void *buffer_release = NULL;
size += *width * 2;
- uint8_t *buf = malloc( size );
- output = malloc( sizeof( AVPicture ) );
+ uint8_t *buf = mlt_pool_allocate( size, &buffer_release );
+ output = mlt_pool_allocate( sizeof( AVPicture ), &frame_release );
+ memset( output, 0, sizeof( AVPicture ) );
avpicture_fill( output, buf, PIX_FMT_YUV422, *width, *height );
- mlt_properties_set_data( properties, "video_output_frame", output, 0, av_free, NULL );
- mlt_properties_set_data( properties, "video_output_buffer", buf, 0, free, NULL );
+ mlt_properties_set_data( properties, "video_output_frame_release", frame_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "video_output_buffer_release", buffer_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "video_output_frame", output, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "video_output_buffer", buf, 0, NULL, NULL );
}
// Seek if necessary
uint8_t *image = mlt_properties_get_data( properties, "current_image", &size );
// Duplicate it
- // IRRIGATE ME
- *buffer = malloc( size );
+ void *release = NULL;
+ *buffer = mlt_pool_allocate( size, &release );
memcpy( *buffer, image, size );
// Set this on the frame properties
- mlt_properties_set_data( frame_properties, "image", *buffer, size, free, NULL );
+ mlt_properties_set_data( frame_properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( frame_properties, "image", *buffer, size, NULL, NULL );
}
else
{
{
// Get current image and size
int size = 0;
+ void *release = NULL;
uint8_t *image = mlt_properties_get_data( properties, "current_image", &size );
if ( image == NULL || size != *width * *height * 2 )
{
+ void *current_image_release = NULL;
size = *width * ( *height + 1 ) * 2;
- // IRRIGATE ME
- image = malloc( size );
- mlt_properties_set_data( properties, "current_image", image, size, free, NULL );
+ image = mlt_pool_allocate( size, ¤t_image_release );
+ mlt_properties_set_data( properties, "current_image_release", current_image_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "current_image", image, size, NULL, NULL );
}
- // IRRIGATE ME
- *buffer = malloc( size );
+ *buffer = mlt_pool_allocate( size, &release );
img_convert( output, PIX_FMT_YUV422, (AVPicture *)&frame, codec_context->pix_fmt, *width, *height );
memcpy( image, output->data[ 0 ], size );
memcpy( *buffer, output->data[ 0 ], size );
- mlt_properties_set_data( frame_properties, "image", *buffer, size, free, NULL );
+ mlt_properties_set_data( frame_properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( frame_properties, "image", *buffer, size, NULL, NULL );
if ( current_time == 0 && source_fps != 0 )
{
// Check for audio buffer and create if necessary
if ( audio_buffer == NULL )
{
+ // Audio buffer release pointer
+ void *buffer_release = NULL;
+
// Allocate the audio buffer
- audio_buffer = malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t ) );
+ audio_buffer = mlt_pool_allocate( AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t ), &buffer_release );
// And store it on properties for reuse
- mlt_properties_set_data( properties, "audio_buffer", audio_buffer, 0, free, NULL );
+ mlt_properties_set_data( properties, "audio_buffer_release", buffer_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "audio_buffer", audio_buffer, 0, NULL, NULL );
}
// Seek if necessary
{
int ret = 0;
int got_audio = 0;
- int16_t temp[ AVCODEC_MAX_AUDIO_FRAME_SIZE / 2 ];
+ void *temp_release = NULL;
+ int16_t *temp = mlt_pool_allocate( sizeof( int16_t ) * AVCODEC_MAX_AUDIO_FRAME_SIZE, &temp_release );
memset( &pkt, 0, sizeof( pkt ) );
// Now handle the audio if we have enough
if ( audio_used >= *samples )
{
- *buffer = malloc( *samples * *channels * sizeof( int16_t ) );
+ void *buffer_release = NULL;
+ *buffer = mlt_pool_allocate( *samples * *channels * sizeof( int16_t ), &buffer_release );
memcpy( *buffer, audio_buffer, *samples * *channels * sizeof( int16_t ) );
audio_used -= *samples;
memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( frame_properties, "audio", *buffer, 0, free, NULL );
+ mlt_properties_set_data( frame_properties, "audio_release", buffer_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( frame_properties, "audio", *buffer, 0, NULL, NULL );
}
else
{
// Store the number of audio samples still available
mlt_properties_set_int( properties, "audio_used", audio_used );
+
+ // Release the temporary audio
+ mlt_pool_release( temp_release );
}
else
{
int owidth = *width;
int oheight = *height;
+ // Hmmm...
+ char *rescale = mlt_properties_get( properties, "rescale.interp" );
+ if ( rescale != NULL && !strcmp( rescale, "none" ) )
+ return mlt_frame_get_image( this, image, format, width, height, writable );
+
if ( mlt_properties_get( properties, "distort" ) == NULL )
{
// Now do additional calcs based on real_width/height etc
}
if ( input_ar == output_ar && scaled_height == normalised_height )
+ {
scaled_width = normalised_width;
+ }
+ else if ( ( real_height * 2 ) == normalised_height )
+ {
+ scaled_width = normalised_width;
+ scaled_height = normalised_height;
+ }
// Now calculate the actual image size that we want
owidth = scaled_width * owidth / normalised_width;
// Convert to requested format
if ( *format == mlt_image_yuv422 )
{
- // IRRIGATE ME
- uint8_t *image = malloc( *width * ( *height + 1 ) * 2 );
+ void *release = NULL;
+ uint8_t *image = mlt_pool_allocate( *width * ( *height + 1 ) * 2, &release );
mlt_convert_rgb24_to_yuv422( rgb, *width, *height, *width * 3, image );
- mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 2, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 2, NULL, NULL );
*buffer = image;
}
else if ( *format == mlt_image_rgb24 )
// Read the video
if ( video != NULL && read_ppm_header( video, &width, &height ) == 2 )
{
-
// Allocate an image
- // IRRIGATE ME
- uint8_t *image = malloc( width * ( height + 1 ) * 3 );
+ void *release = NULL;
+ uint8_t *image = mlt_pool_allocate( width * ( height + 1 ) * 3, &release );
// Read it
fread( image, width * height * 3, 1, video );
// Pass the data on the frame properties
- mlt_properties_set_data( properties, "image", image, width * ( height + 1 ) * 3, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", image, width * ( height + 1 ) * 3, NULL, NULL );
mlt_properties_set_int( properties, "width", width );
mlt_properties_set_int( properties, "height", height );
mlt_properties_set_int( properties, "has_image", 1 );
static void luma_read_pgm( FILE *f, float **map, int *width, int *height )
{
+ void *release = NULL;
uint8_t *data = NULL;
while (1)
{
bpp = maxval > 255 ? 2 : 1;
// allocate temporary storage for the raw data
- // IRRIGATE ME
- data = malloc( *width * *height * bpp );
+ data = mlt_pool_allocate( *width * *height * bpp, &release );
if ( data == NULL )
break;
// allocate the luma bitmap
// IRRIGATE ME
+ // Difficult here - need to change the function prototype....
*map = p = (float*) malloc( *width * *height * sizeof( float ) );
if ( *map == NULL )
break;
break;
}
- if ( data != NULL )
- free( data );
+ if ( release != NULL )
+ mlt_pool_release( release );
}
static int producer_collect_info( producer_libdv this )
{
int valid = 0;
- // IRRIGATE ME
- uint8_t *dv_data = malloc( frame_size_625_50 );
+
+ void *release = NULL;
+ uint8_t *dv_data = mlt_pool_allocate( frame_size_625_50, &release );
if ( dv_data != NULL )
{
mlt_properties_set_double( properties, "aspect_ratio", dv_format_wide( this->dv_decoder ) ? 16.0/9.0 : 4.0/3.0 );
}
- free( dv_data );
+ mlt_pool_release( release );
}
return valid;
if ( *format == mlt_image_yuv422 )
{
// Allocate an image
- // IRRIGATE ME
- uint8_t *image = malloc( *width * ( *height + 1 ) * 2 );
+ void *release = NULL;
+ uint8_t *image = mlt_pool_allocate( *width * ( *height + 1 ) * 2, &release );
// Pass to properties for clean up
- mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 2, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 2, NULL, NULL );
// Decode the image
pitches[ 0 ] = *width * 2;
else if ( *format == mlt_image_rgb24 )
{
// Allocate an image
- // IRRIGATE ME
- uint8_t *image = malloc( *width * ( *height + 1 ) * 3 );
+ void *release = NULL;
+ uint8_t *image = mlt_pool_allocate( *width * ( *height + 1 ) * 3, &release );
// Pass to properties for clean up
- mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 3, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 3, NULL, NULL );
// Decode the frame
pitches[ 0 ] = 720 * 3;
static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
+ void *release = NULL;
int16_t *p;
int i, j;
+ void *audio_release[ 4 ] = { NULL, NULL, NULL, NULL };
int16_t *audio_channels[ 4 ];
// Get the frames properties
// Create a temporary workspace
for ( i = 0; i < 4; i++ )
- audio_channels[ i ] = malloc( DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
+ audio_channels[ i ] = mlt_pool_allocate( DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), &audio_release[ i ] );
// Create a workspace for the result
- *buffer = malloc( *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
+ *buffer = mlt_pool_allocate( *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), &release );
// Pass the allocated audio buffer as a property
- mlt_properties_set_data( properties, "audio", *buffer, *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), free, NULL );
+ mlt_properties_set_data( properties, "audio_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "audio", *buffer, *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), NULL, NULL );
// Decode the audio
dv_decode_full_audio( decoder, dv_data, audio_channels );
// Free the temporary work space
for ( i = 0; i < 4; i++ )
- free( audio_channels[ i ] );
+ mlt_pool_release( audio_release[ i ] );
return 0;
}
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
{
producer_libdv this = producer->child;
- uint8_t *data = malloc( frame_size_625_50 );
+ void *release = NULL;
+ uint8_t *data = mlt_pool_allocate( frame_size_625_50, &release );
// Obtain the current frame number
uint64_t position = mlt_producer_frame( producer );
mlt_properties_set_data( properties, "dv_decoder", this->dv_decoder, 0, NULL, NULL );
// Pass the dv data
- mlt_properties_set_data( properties, "dv_data", data, frame_size_625_50, free, NULL );
+ mlt_properties_set_data( properties, "dv_data_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "dv_data", data, frame_size_625_50, NULL, NULL );
// Update other info on the frame
mlt_properties_set_int( properties, "width", 720 );
}
else
{
- free( data );
+ mlt_pool_release( release );
}
// Update timecode on the frame we're creating
if ( video != NULL && read_ffmpeg_header( this, &width, &height ) == 2 )
{
// Allocate an image
- // IRRIGATE ME
- uint8_t *image = malloc( width * ( height + 1 ) * 2 );
+ void *release = NULL;
+ uint8_t *image = mlt_pool_allocate( width * ( height + 1 ) * 2, &release );
// Read it
while( skip -- )
mlt_convert_yuv420p_to_yuv422( this->buffer, width, height, width, image );
// Pass the data on the frame properties
- mlt_properties_set_data( properties, "image", image, width * ( height + 1 ) * 2, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", image, width * ( height + 1 ) * 2, NULL, NULL );
mlt_properties_set_int( properties, "width", width );
mlt_properties_set_int( properties, "height", height );
mlt_properties_set_int( properties, "has_image", 1 );
if ( *format == mlt_image_yuv422 && strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) )
{
// Create the output image
- // IRRIGATE ME
- uint8_t *output = malloc( owidth * ( oheight + 1 ) * 2 );
+ void *release = NULL;
+ uint8_t *output = mlt_pool_allocate( owidth * ( oheight + 1 ) * 2, &release );
// Calculate strides
int istride = iwidth * 2;
yuv422_scale_simple( output, owidth, oheight, ostride, input, iwidth, iheight, istride, interp );
// Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, NULL, NULL );
mlt_properties_set_int( properties, "width", owidth );
mlt_properties_set_int( properties, "height", oheight );
int bpp = (*format == mlt_image_rgb24a ? 4 : 3 );
// Create the yuv image
- // IRRIGATE ME
- uint8_t *output = malloc( owidth * ( oheight + 1 ) * 2 );
+ void *release = NULL;
+ uint8_t *output = mlt_pool_allocate( owidth * ( oheight + 1 ) * 2, &release );
if ( strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) )
{
if ( bpp == 4 )
{
// Allocate the alpha mask
- // IRRIGATE ME
- uint8_t *alpha = malloc( owidth * ( oheight + 1 ) );
+ void *alpha_release = NULL;
+ uint8_t *alpha = mlt_pool_allocate( owidth * ( oheight + 1 ), &alpha_release );
// Convert the image and extract alpha
mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( scaled ),
gdk_pixbuf_get_rowstride( scaled ),
output, alpha );
- mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), free, NULL );
+ mlt_properties_set_data( properties, "alpha_release", alpha_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), NULL, NULL );
}
else
{
if ( bpp == 4 )
{
// Allocate the alpha mask
- // IRRIGATE ME
- uint8_t *alpha = malloc( owidth * ( oheight + 1 ) );
+ void *alpha_release = NULL;
+ uint8_t *alpha = mlt_pool_allocate( owidth * ( oheight + 1 ), &alpha_release );
// Convert the image and extract alpha
mlt_convert_rgb24a_to_yuv422( input,
owidth * 4,
output, alpha );
- mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), free, NULL );
+ mlt_properties_set_data( properties, "alpha_release", alpha_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), NULL, NULL );
}
else
{
}
// Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, NULL, NULL );
mlt_properties_set_int( properties, "width", owidth );
mlt_properties_set_int( properties, "height", oheight );
struct mlt_producer_s parent;
int width;
int height;
+ void *image_release;
uint8_t *image;
+ void *alpha_release;
uint8_t *alpha;
char *fgcolor;
char *bgcolor;
rgba_color fgcolor = parse_color( this->fgcolor );
rgba_color bgcolor = parse_color( this->bgcolor );
- free( this->image );
- free( this->alpha );
+ mlt_pool_release( this->image_release );
+ mlt_pool_release( this->alpha_release );
+ this->image_release = NULL;
+ this->alpha_release = NULL;
this->image = NULL;
this->alpha = NULL;
}
else if ( width > 0 && ( this->image == NULL || width != this->width || height != this->height ) )
{
- free( this->image );
- free( this->alpha );
+ mlt_pool_release( this->image_release );
+ mlt_pool_release( this->alpha_release );
+ this->image_release = NULL;
+ this->alpha_release = NULL;
this->image = NULL;
this->alpha = NULL;
this->height = height;
// Allocate/define image
- // IRRIGATE ME
- uint8_t *image = malloc( width * ( height + 1 ) * 2 );
- uint8_t *alpha = NULL;
-
- // Allocate the alpha mask
- alpha = malloc( this->width * this->height );
+ this->image = mlt_pool_allocate( width * ( height + 1 ) * 2, &this->image_release );
+ this->alpha = mlt_pool_allocate( this->width * this->height, &this->alpha_release );
// Convert the image
mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
this->width, this->height,
gdk_pixbuf_get_rowstride( pixbuf ),
- image, alpha );
+ this->image, this->alpha );
// Finished with pixbuf now
g_object_unref( pixbuf );
-
- // reference the image in the producer
- this->image = image;
- this->alpha = alpha;
}
// Set width/height
if ( writable )
{
// Clone our image
- // IRRIGATE ME
- uint8_t *copy = malloc( size );
+ void *release = NULL;
+ uint8_t *copy = mlt_pool_allocate( size, &release );
memcpy( copy, image, size );
// We're going to pass the copy on
image = copy;
// Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", copy, size, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", copy, size, NULL, NULL );
}
// Pass on the image
static void producer_close( mlt_producer parent )
{
producer_pango this = parent->child;
- free( this->image );
- free( this->alpha );
+ mlt_pool_release( this->image_release );
+ mlt_pool_release( this->alpha_release );
free( this->fgcolor );
free( this->bgcolor );
free( this->markup );
uint8_t *src = NULL;
uint8_t* dest = NULL;
int stride;
+ void *release = NULL;
pango_ft2_font_map_set_resolution( fontmap, 72, 72 );
pango_layout_set_width( layout, -1 ); // set wrapping constraints
bitmap.width = w;
bitmap.pitch = 32 * ( ( w + 31 ) / 31 );
bitmap.rows = h;
- bitmap.buffer = ( unsigned char * ) calloc( 1, h * bitmap.pitch );
+ bitmap.buffer = mlt_pool_allocate( h * bitmap.pitch, &release );
bitmap.num_grays = 256;
bitmap.pixel_mode = ft_pixel_mode_grays;
+ memset( bitmap.buffer, 0, h * bitmap.pitch );
+
pango_ft2_render_layout( &bitmap, layout, 0, 0 );
src = bitmap.buffer;
}
dest += stride;
}
- free( bitmap.buffer );
-
+ mlt_pool_release( release );
g_object_unref( layout );
g_object_unref( context );
g_object_unref( fontmap );
#include <unistd.h>
#include <dirent.h>
+typedef struct producer_pixbuf_s *producer_pixbuf;
+
+struct producer_pixbuf_s
+{
+ struct mlt_producer_s parent;
+
+ // File name list
+ char **filenames;
+ int count;
+ int image_idx;
+
+ int width;
+ int height;
+ void *image_release;
+ uint8_t *image;
+ void *alpha_release;
+ uint8_t *alpha;
+};
+
static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
static void producer_close( mlt_producer parent );
if ( width != this->width || height != this->height )
{
pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL );
- free( this->image );
- free( this->alpha );
+ mlt_pool_release( this->image_release );
+ mlt_pool_release( this->alpha_release );
+ this->image_release = NULL;
+ this->alpha_release = NULL;
this->image = NULL;
this->alpha = NULL;
}
}
else if ( this->image == NULL || image_idx != this->image_idx )
{
- free( this->image );
- free( this->alpha );
+ mlt_pool_release( this->image_release );
+ mlt_pool_release( this->alpha_release );
+ this->image_release = NULL;
+ this->alpha_release = NULL;
this->image = NULL;
this->alpha = NULL;
else if ( strcmp( interps, "hyper" ) == 0 )
interp = GDK_INTERP_HYPER;
-// fprintf( stderr, "SCALING PIXBUF from %dx%d to %dx%d was %dx%d\n", gdk_pixbuf_get_width( pixbuf ), gdk_pixbuf_get_height( pixbuf ), width, height, this->width, this->height );
-
// Note - the original pixbuf is already safe and ready for destruction
pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, interp );
this->height = height;
// Allocate/define image
- // IRRIGATE ME
- uint8_t *image = malloc( width * ( height + 1 ) * 2 );
- uint8_t *alpha = NULL;
+ this->image = mlt_pool_allocate( width * ( height + 1 ) * 2, &this->image_release );
// Extract YUV422 and alpha
if ( gdk_pixbuf_get_has_alpha( pixbuf ) )
{
// Allocate the alpha mask
- alpha = malloc( this->width * this->height );
+ this->alpha = mlt_pool_allocate( this->width * this->height, &this->alpha_release );
// Convert the image
mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
this->width, this->height,
gdk_pixbuf_get_rowstride( pixbuf ),
- image, alpha );
+ this->image, this->alpha );
}
else
{
mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
this->width, this->height,
gdk_pixbuf_get_rowstride( pixbuf ),
- image );
+ this->image );
}
// Finished with pixbuf now
g_object_unref( pixbuf );
-
- // Assign images to producer
- this->image = image;
- this->alpha = alpha;
}
// Set width/height of frame
//if ( writable )
{
// Clone our image
- // IRRIGATE ME
- uint8_t *copy = malloc( size );
+ void *release = NULL;
+ uint8_t *copy = mlt_pool_allocate( size, &release );
memcpy( copy, image, size );
// We're going to pass the copy on
image = copy;
// Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", copy, size, free, NULL );
+ mlt_properties_set_data( properties, "image_release", release, 0, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "image", copy, size, NULL, NULL );
}
// Pass on the image
#include <framework/mlt_producer.h>
-typedef struct producer_pixbuf_s *producer_pixbuf;
-
-struct producer_pixbuf_s
-{
- struct mlt_producer_s parent;
-
- // File name list
- char **filenames;
- int count;
- int image_idx;
-
- int width;
- int height;
- uint8_t *image;
- uint8_t *alpha;
-};
-
extern mlt_producer producer_pixbuf_init( char *filename );
#endif
{
if ( data.output_frames_gen > *samples )
{
- *buffer = (int16_t*) malloc( data.output_frames_gen * *channels * 2 );
- mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, free, NULL );
+ void *release = NULL;
+ *buffer = mlt_pool_allocate( data.output_frames_gen * *channels * sizeof( int16_t ), &release );
+ mlt_properties_set_data( properties, "audio_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, NULL, NULL );
}
*samples = data.output_frames_gen;
*frequency = output_rate;
SRC_STATE *state = src_new( RESAMPLE_TYPE, 2 /* channels */, &error );
if ( error == 0 )
{
+ void *input_release = NULL;
+ void *input_buffer = mlt_pool_allocate( BUFFER_LEN, &input_release );
+ void *output_release = NULL;
+ void *output_buffer = mlt_pool_allocate( BUFFER_LEN, &output_release );
this->process = filter_process;
if ( arg != NULL )
mlt_properties_set_int( mlt_filter_properties( this ), "frequency", atoi( arg ) );
mlt_properties_set_int( mlt_filter_properties( this ), "channels", 2 );
mlt_properties_set_data( mlt_filter_properties( this ), "state", state, 0, (mlt_destructor)src_delete, NULL );
- mlt_properties_set_data( mlt_filter_properties( this ), "input_buffer",
- malloc( BUFFER_LEN ), BUFFER_LEN, free, NULL );
- mlt_properties_set_data( mlt_filter_properties( this ), "output_buffer",
- malloc( BUFFER_LEN ), BUFFER_LEN, free, NULL );
+ mlt_properties_set_data( mlt_filter_properties( this ), "input_release", input_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( mlt_filter_properties( this ), "input_buffer", input_buffer, BUFFER_LEN, NULL, NULL );
+ mlt_properties_set_data( mlt_filter_properties( this ), "output_release", output_release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( mlt_filter_properties( this ), "output_buffer", output_buffer, BUFFER_LEN, NULL, NULL );
}
else
{
// Check for audio buffer and create if necessary
if ( audio_buffer == NULL )
{
+ // Release pointer
+ void *release = NULL;
+
// Allocate the audio buffer
- audio_buffer = malloc( 131072 * sizeof( int16_t ) );
+ audio_buffer = mlt_pool_allocate( 131072 * sizeof( int16_t ), &release );
// And store it on properties for reuse
- mlt_properties_set_data( properties, "audio_buffer", audio_buffer, 0, free, NULL );
+ mlt_properties_set_data( properties, "audio_buffer_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "audio_buffer", audio_buffer, 0, NULL, NULL );
}
// Seek if necessary
// Now handle the audio if we have enough
if ( audio_used >= *samples )
{
- *buffer = malloc( *samples * *channels * sizeof( int16_t ) );
+ void *release = NULL;
+ *buffer = mlt_pool_allocate( *samples * *channels * sizeof( int16_t ), &release );
memcpy( *buffer, audio_buffer, *samples * *channels * sizeof( int16_t ) );
audio_used -= *samples;
memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( frame_properties, "audio", *buffer, 0, free, NULL );
+ mlt_properties_set_data( frame_properties, "audio_release", release, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_properties_set_data( frame_properties, "audio", *buffer, 0, NULL, NULL );
}
else
{