if ( mlt_properties_get( properties, "rescale" ) != NULL )
mlt_properties_set( frame_properties, "rescale.interp", mlt_properties_get( properties, "rescale" ) );
- // TODO: Aspect ratio and other jiggery pokery
+ // Aspect ratio and other jiggery pokery
mlt_properties_set_double( frame_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "aspect_ratio" ) );
mlt_properties_set_int( frame_properties, "consumer_progressive", mlt_properties_get_int( properties, "progressive" ) );
mlt_properties_set_position( properties, "in", 0 );
mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "track", 0 );
- mlt_properties_set( properties, "resource", "<filter>" );
return 0;
}
return 1;
}
+/** Create a new filter.
+*/
+
+mlt_filter mlt_filter_new( )
+{
+ mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
+ if ( this != NULL )
+ mlt_filter_init( this, NULL );
+ return this;
+}
+
/** Get the service associated to this filter
*/
*/
extern int mlt_filter_init( mlt_filter this, void *child );
+extern mlt_filter mlt_filter_new( );
extern mlt_service mlt_filter_service( mlt_filter this );
extern mlt_properties mlt_filter_properties( mlt_filter this );
extern mlt_frame mlt_filter_process( mlt_filter this, mlt_frame that );
mlt_properties_set_data( properties, "audio", NULL, 0, NULL, NULL );
mlt_properties_set_data( properties, "alpha", NULL, 0, NULL, NULL );
-
+ // Construct stacks for frames and methods
+ this->stack_get_image = mlt_deque_init( );
+ this->stack_frame = mlt_deque_init( );
}
+
return this;
}
int mlt_frame_push_get_image( mlt_frame this, mlt_get_image get_image )
{
- int ret = this->stack_get_image_size >= 10;
- if ( ret == 0 )
- this->stack_get_image[ this->stack_get_image_size ++ ] = get_image;
- return ret;
+ return mlt_deque_push_back( this->stack_get_image, get_image );
}
/** Pop a get_image callback.
mlt_get_image mlt_frame_pop_get_image( mlt_frame this )
{
- mlt_get_image result = NULL;
- if ( this->stack_get_image_size > 0 )
- result = this->stack_get_image[ -- this->stack_get_image_size ];
- return result;
+ return mlt_deque_pop_back( this->stack_get_image );
}
/** Push a frame.
int mlt_frame_push_frame( mlt_frame this, mlt_frame that )
{
- int ret = this->stack_frame_size >= 10;
- if ( ret == 0 )
- this->stack_frame[ this->stack_frame_size ++ ] = that;
- return ret;
+ return mlt_deque_push_back( this->stack_frame, that );
}
/** Pop a frame.
mlt_frame mlt_frame_pop_frame( mlt_frame this )
{
- mlt_frame result = NULL;
- if ( this->stack_frame_size > 0 )
- result = this->stack_frame[ -- this->stack_frame_size ];
- return result;
+ return mlt_deque_pop_back( this->stack_frame );
}
int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
void mlt_frame_close( mlt_frame this )
{
+ mlt_deque_close( this->stack_get_image );
+ mlt_deque_close( this->stack_frame );
mlt_properties_close( &this->parent );
free( this );
}
#define _MLT_FRAME_H_
#include "mlt_properties.h"
+#include "mlt_deque.h"
typedef enum
{
uint8_t * ( *get_alpha_mask )( mlt_frame this );
// Private properties
- mlt_get_image stack_get_image[ 10 ];
- int stack_get_image_size;
- mlt_frame stack_frame[ 10 ];
- int stack_frame_size;
+ mlt_deque stack_get_image;
+ mlt_deque stack_frame;
};
extern mlt_frame mlt_frame_init( );
static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
- mlt_frame_get_image( this, image, format, width, height, 1 );
- uint8_t *p = *image;
- uint8_t *q = *image + *width * *height * 2;
+ // Get the image
+ int error = mlt_frame_get_image( this, image, format, width, height, 1 );
- // Get the brightness level
- double level = mlt_properties_get_double( mlt_frame_properties( this ), "brightness.level" );
-
- while ( p != q )
+ // Only process if we have no error and a valid colour space
+ if ( error == 0 && *format == mlt_image_yuv422 )
{
- float x = (float) *p * level;
- *p = x < 16 ? 16 : x > 235 ? 235 : x;
- p += 2;
+ // Get the brightness level
+ double level = mlt_properties_get_double( mlt_frame_properties( this ), "brightness" );
+
+ // Only process if level is something other than 1
+ if ( level != 1.0 )
+ {
+ uint8_t *p = *image;
+ uint8_t *q = *image + *width * *height * 2;
+ int32_t x = 0;
+ int32_t m = level * ( 1 << 16 );
+
+ while ( p != q )
+ {
+ x = ( *p * m ) >> 16;
+ *p = x < 16 ? 16 : x > 235 ? 235 : x;
+ p += 2;
+ }
+ }
}
- return 0;
+ return error;
}
/** Filter processing.
static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
{
+ // Get the starting brightness level
double level = fabs( mlt_properties_get_double( mlt_filter_properties( this ), "start" ) );
// If there is an end adjust gain to the range
double end = fabs( mlt_properties_get_double( mlt_filter_properties( this ), "end" ) );
level += ( end - level ) * position;
}
+
+ // Push the frame filter
+ mlt_properties_set_double( mlt_frame_properties( frame ), "brightness", level );
mlt_frame_push_get_image( frame, filter_get_image );
- mlt_properties_set_double( mlt_frame_properties( frame ), "brightness.level", level );
+
return frame;
}
mlt_filter filter_brightness_init( char *arg )
{
- mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+ mlt_filter this = mlt_filter_new( );
if ( this != NULL )
{
- mlt_filter_init( this, NULL );
this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set_double( mlt_filter_properties( this ), "start", atof( arg ) );
+ mlt_properties_set( mlt_filter_properties( this ), "start", arg == NULL ? "1" : arg );
}
return this;
}
#include <string.h>
#include <stdlib.h>
-/** Deinterlace class.
-*/
-
-typedef struct
-{
- struct mlt_filter_s parent;
-}
-filter_deinterlace;
-
/* Linear Blend filter - C version contributed by Rogerio Brito.
This algorithm has the same interface as the other functions.
register int x, y;
register uint8_t *l0, *l1, *l2, *l3;
- l0 = pdst; /* target line */
- l1 = psrc; /* 1st source line */
- l2 = l1 + width; /* 2nd source line = line that follows l1 */
- l3 = l2 + width; /* 3rd source line = line that follows l2 */
+ l0 = pdst; // target line
+ l1 = psrc; // 1st source line
+ l2 = l1 + width; // 2nd source line = line that follows l1
+ l3 = l2 + width; // 3rd source line = line that follows l2
- /* Copy the first line */
+ // Copy the first line
memcpy(l0, l1, width);
l0 += width;
for (y = 1; y < height-1; ++y)
{
- /* computes avg of: l1 + 2*l2 + l3 */
+ // computes avg of: l1 + 2*l2 + l3
for (x = 0; x < width; ++x)
l0[x] = (l1[x] + (l2[x]<<1) + l3[x]) >> 2;
- /* updates the line pointers */
+ // updates the line pointers
l1 = l2; l2 = l3; l3 += width;
l0 += width;
}
- /* Copy the last line */
+ // Copy the last line
memcpy(l0, l1, width);
}
static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
- mlt_frame_get_image( this, image, format, width, height, 1 );
- deinterlace_yuv( *image, *image, *width * 2, *height );
- mlt_properties_set_int( mlt_frame_properties( this ), "progressive", 1 );
- return 0;
+ // Get the input image
+ int error = mlt_frame_get_image( this, image, format, width, height, 1 );
+
+ // Only continue if we have no error and the right colour space
+ if ( error == 0 && *format == mlt_image_yuv422 )
+ {
+ // Check that we want progressive and we aren't already progressive
+ if ( !mlt_properties_get_int( mlt_frame_properties( this ), "progressive" ) &&
+ mlt_properties_get_int( mlt_frame_properties( this ), "consumer_progressive" ) )
+ {
+ // Deinterlace the image
+ deinterlace_yuv( *image, *image, *width * 2, *height );
+
+ // Make sure that others know the frame is deinterlaced
+ mlt_properties_set_int( mlt_frame_properties( this ), "progressive", 1 );
+ }
+ }
+
+ return error;
}
/** Deinterlace filter processing - this should be lazy evaluation here...
mlt_filter filter_deinterlace_init( void *arg )
{
- filter_deinterlace *this = calloc( sizeof( filter_deinterlace ), 1 );
+ mlt_filter this = mlt_filter_new( );
if ( this != NULL )
- {
- mlt_filter filter = &this->parent;
- mlt_filter_init( filter, this );
- filter->process = deinterlace_process;
- return &this->parent;
- }
- return NULL;
+ this->process = deinterlace_process;
+ return this;
}
static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
- mlt_frame_get_image( this, image, format, width, height, 1 );
- uint8_t *p = *image;
- uint8_t *q = *image + *width * *height * 2;
+ int error = mlt_frame_get_image( this, image, format, width, height, 1 );
- // Get the gamma value
- double gamma = mlt_properties_get_double( mlt_frame_properties( this ), "gamma" );
+ if ( error != 0 && *format == mlt_image_yuv422 )
+ {
+ // Get the gamma value
+ double gamma = mlt_properties_get_double( mlt_frame_properties( this ), "gamma" );
- // Calculate the look up table
- double exp = 1 / gamma;
- uint8_t lookup[ 256 ];
- int i;
+ if ( gamma != 1.0 )
+ {
+ uint8_t *p = *image;
+ uint8_t *q = *image + *width * *height * 2;
- for( i = 0; i < 256; i ++ )
- lookup[ i ] = ( uint8_t )( pow( ( double )i / 255.0, exp ) * 255 );
+ // Calculate the look up table
+ double exp = 1 / gamma;
+ uint8_t lookup[ 256 ];
+ int i;
- while ( p != q )
- {
- *p = lookup[ *p ];
- p += 2;
+ for( i = 0; i < 256; i ++ )
+ lookup[ i ] = ( uint8_t )( pow( ( double )i / 255.0, exp ) * 255 );
+
+ while ( p != q )
+ {
+ *p = lookup[ *p ];
+ p += 2;
+ }
+ }
}
return 0;
static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
{
double gamma = mlt_properties_get_double( mlt_filter_properties( this ), "gamma" );
- gamma = gamma <= 0 ? 2 : gamma;
- mlt_frame_push_get_image( frame, filter_get_image );
+ gamma = gamma <= 0 ? 1 : gamma;
mlt_properties_set_double( mlt_frame_properties( frame ), "gamma", gamma );
+ mlt_frame_push_get_image( frame, filter_get_image );
return frame;
}
mlt_filter filter_gamma_init( char *arg )
{
- mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+ mlt_filter this = mlt_filter_new( );
if ( this != NULL )
{
- mlt_filter_init( this, NULL );
this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set_double( mlt_filter_properties( this ), "gamma", atof( arg ) );
+ mlt_properties_set( mlt_filter_properties( this ), "gamma", arg == NULL ? "1" : arg );
}
return this;
}
#include <stdio.h>
#include <stdlib.h>
-/** Greyscale class.
-*/
-
-typedef struct
-{
- struct mlt_filter_s parent;
-}
-filter_greyscale;
-
/** Do it :-).
*/
static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
- mlt_frame_get_image( this, image, format, width, height, 1 );
- uint8_t *p = *image;
- uint8_t *q = *image + *width * *height * 2;
- while ( p ++ != q )
- *p ++ = 128;
- return 0;
+ int error = mlt_frame_get_image( this, image, format, width, height, 1 );
+ if ( error == 0 && *format == mlt_image_yuv422 )
+ {
+ uint8_t *p = *image;
+ uint8_t *q = *image + *width * *height * 2;
+ while ( p ++ != q )
+ *p ++ = 128;
+ }
+ return error;
}
/** Filter processing.
mlt_filter filter_greyscale_init( void *arg )
{
- filter_greyscale *this = calloc( sizeof( filter_greyscale ), 1 );
+ mlt_filter this = mlt_filter_new( );
if ( this != NULL )
- {
- mlt_filter filter = &this->parent;
- mlt_filter_init( filter, this );
- filter->process = filter_process;
- }
- return ( mlt_filter )this;
+ this->process = filter_process;
+ return this;
}
/** The averaging function...
*/
-void obscure_average( uint8_t *start, int width, int height, int stride, uint8_t *alpha )
+void obscure_average( uint8_t *start, int width, int height, int stride )
{
int y;
int x;
- int Y = ( *start + *( start + 2 ) ) / 2;
- int U = *( start + 1 );
- int V = *( start + 3 );
+ register int Y = ( *start + *( start + 2 ) ) / 2;
+ register int U = *( start + 1 );
+ register int V = *( start + 3 );
+ register uint8_t *p;
for ( y = 0; y < height; y ++ )
{
- uint8_t *p = start + y * stride;
+ p = start + y * stride;
for ( x = 0; x < width / 2; x ++ )
{
Y = ( Y + *p ++ ) / 2;
for ( y = 0; y < height; y ++ )
{
- uint8_t *p = start + y * stride;
- uint8_t *z = alpha;
-
- if ( z != NULL )
- z += y * stride / 2;
+ p = start + y * stride;
for ( x = 0; x < width / 2; x ++ )
{
- if ( z == NULL || ( z != NULL && *z++ > 127 ) )
- {
- *p ++ = Y;
- *p ++ = U;
- }
- else
- {
- p += 2;
- }
-
- if ( z == NULL || ( z != NULL && *z++ > 127 ) )
- {
-
- *p ++ = Y;
- *p ++ = V;
- }
- else
- {
- p += 2;
- }
+ *p ++ = Y;
+ *p ++ = U;
+ *p ++ = Y;
+ *p ++ = V;
}
}
}
/** The obscurer rendering function...
*/
-static void obscure_render( uint8_t *image, int width, int height, struct geometry_s result, uint8_t *alpha )
+static void obscure_render( uint8_t *image, int width, int height, struct geometry_s result )
{
int area_x = result.x;
int area_y = result.y;
int mh = result.mask_h;
int w;
int h;
+ int aw;
+ int ah;
uint8_t *p = image + area_y * width * 2 + area_x * 2;
- uint8_t *z = alpha;
- if ( z != NULL )
- z += area_y * width + area_x;
for ( w = 0; w < area_w; w += mw )
{
for ( h = 0; h < area_h; h += mh )
{
- int aw = w + mw > area_w ? mw - ( w + mw - area_w ) : mw;
- int ah = h + mh > area_h ? mh - ( h + mh - area_h ) : mh;
+ aw = w + mw > area_w ? mw - ( w + mw - area_w ) : mw;
+ ah = h + mh > area_h ? mh - ( h + mh - area_h ) : mh;
if ( aw > 1 && ah > 1 )
- obscure_average( p + h * width * 2 + w * 2, aw, ah, width * 2,
- ( z == NULL ? z : z + h * width + w ) );
+ obscure_average( p + h * width * 2 + w * 2, aw, ah, width * 2 );
}
}
}
geometry_calculate( &result, &start, &end, position, *width, *height );
// Now actually render it
- obscure_render( *image, *width, *height, result, mlt_frame_get_alpha_mask( frame ) );
+ obscure_render( *image, *width, *height, result );
}
}
mlt_filter filter_obscure_init( void *arg )
{
- mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
- mlt_properties properties = mlt_filter_properties( this );
- mlt_filter_init( this, NULL );
- this->process = filter_process;
- mlt_properties_set( properties, "start", arg != NULL ? arg : "0%,0%:100%x100%" );
- mlt_properties_set( properties, "end", "" );
+ mlt_filter this = mlt_filter_new( );
+ if ( this != NULL )
+ {
+ mlt_properties properties = mlt_filter_properties( this );
+ this->process = filter_process;
+ mlt_properties_set( properties, "start", arg != NULL ? arg : "0%,0%:100%x100%" );
+ mlt_properties_set( properties, "end", "" );
+ }
return this;
}
static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
+ int error = 0;
+
// Get the properties from the frame
mlt_properties properties = mlt_frame_properties( this );
scaled_width = input_ar / output_ar * normalised_width;
scaled_height = normalised_height;
}
- //fprintf( stderr, "resize: %dx%d from %dx%d input aspect %f output aspect %f\n",
- // scaled_width, scaled_height, normalised_width, normalised_height, input_ar, output_ar );
-
-#if 0
- int real_width = get_value( properties, "real_height", "height" );
- int real_height = get_value( properties, "real_height", "height" );
- // DRD> Why?
- if ( ( real_height * 2 ) == normalised_height )
- {
- scaled_width = normalised_width;
- scaled_height = normalised_height;
- }
-#endif
// Now calculate the actual image size that we want
owidth = scaled_width * owidth / normalised_width;
mlt_properties_set_int( properties, "resize_height", *height );
// Now get the image
- mlt_frame_get_image( this, image, format, &owidth, &oheight, writable );
-
- // Correct field order if needed
- if ( mlt_properties_get_int( properties, "top_field_first" ) == 1 )
+ error = mlt_frame_get_image( this, image, format, &owidth, &oheight, writable );
+
+ // We only know how to process yuv422 at the moment
+ if ( error == 0 && *format == mlt_image_yuv422 )
{
- // Get the input image, width and height
- int size;
- uint8_t *image = mlt_properties_get_data( properties, "image", &size );
+ // Correct field order if needed
+ if ( mlt_properties_get_int( properties, "top_field_first" ) == 1 )
+ {
+ // Get the input image, width and height
+ int size;
+ uint8_t *image = mlt_properties_get_data( properties, "image", &size );
- // Keep the original image around to be destroyed on frame close
- mlt_properties_rename( properties, "image", "original_image" );
+ // Keep the original image around to be destroyed on frame close
+ mlt_properties_rename( properties, "image", "original_image" );
- // Offset the image pointer by one line
- image += owidth * 2;
- size -= owidth * 2;
+ // Offset the image pointer by one line
+ image += owidth * 2;
+ size -= owidth * 2;
- // Set the new image pointer with no destructor
- mlt_properties_set_data( properties, "image", image, size, NULL, NULL );
+ // Set the new image pointer with no destructor
+ mlt_properties_set_data( properties, "image", image, size, NULL, NULL );
- // Set the normalised field order
- mlt_properties_set_int( properties, "top_field_first", 0 );
- }
+ // Set the normalised field order
+ mlt_properties_set_int( properties, "top_field_first", 0 );
+ }
- if ( !strcmp( mlt_properties_get( properties, "resize.scale" ), "affine" ) )
- *image = mlt_frame_rescale_yuv422( this, *width, *height );
- else if ( strcmp( mlt_properties_get( properties, "resize.scale" ), "none" ) != 0 )
- *image = mlt_frame_resize_yuv422( this, *width, *height );
- else
- {
- *width = owidth;
- *height = oheight;
+ if ( !strcmp( mlt_properties_get( properties, "resize.scale" ), "affine" ) )
+ {
+ *image = mlt_frame_rescale_yuv422( this, *width, *height );
+ }
+ else if ( strcmp( mlt_properties_get( properties, "resize.scale" ), "none" ) != 0 )
+ {
+ *image = mlt_frame_resize_yuv422( this, *width, *height );
+ }
+ else
+ {
+ *width = owidth;
+ *height = oheight;
+ }
}
+
return 0;
}
scaled_height = normalised_height;
}
-#if 0
- // DRD> Why?
- // Special case
- if ( scaled_height == normalised_height )
- scaled_width = normalised_width;
-#endif
-
// Now we need to align to the geometry
if ( scaled_width <= geometry->w && scaled_height <= geometry->h )
{
mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
// Now attach normalising filters
+ last = create_filter( tractor, last, "deinterlace" );
last = create_filter( tractor, last, "rescale" );
last = create_filter( tractor, last, "resize" );
last = create_filter( tractor, last, "resample" );
double ttl = mlt_properties_get_int( producer_props, "ttl" );
// Image index
- int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count;
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( frame, mlt_producer_position( producer ) );
+ int image_idx = ( int )floor( mlt_frame_get_position( frame ) / ttl ) % this->count;
// optimization for subsequent iterations on single picture
if ( width != 0 && this->image != NULL && image_idx == this->image_idx )
// Set the producer on the frame properties
mlt_properties_set_data( properties, "producer_pixbuf", this, 0, NULL, NULL );
+ // Update timecode on the frame we're creating
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
+
// Refresh the image
refresh_image( *frame, 0, 0 );
mlt_properties_set( this->properties, "rescale", "nearest" );
// Default progressive true
- mlt_properties_set_int( this->properties, "progressive", 1 );
+ mlt_properties_set_int( this->properties, "progressive", 0 );
// Get aspect ratio
this->aspect_ratio = mlt_properties_get_double( this->properties, "aspect_ratio" );