From e6c03148e1dc3b0e363c9f304b3ed93fbc1a91a9 Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Sun, 26 Jun 2005 21:04:26 +0000 Subject: [PATCH] src/framework/mlt_deque.c src/framework/mlt_deque.h + Added support for doubles src/framework/mlt_frame.c + Switched order of source/dest audio mix extraction (for transition as filter usage) src/framework/mlt_tractor.c - Removed warning introduced from previous checkin (missing ctype.h) + Temporary work around to allow frames to carry multiple frames (for transition as filter usage) src/modules/core/Makefile src/modules/core/configure src/modules/core/factory.c + Support for new transition filter :-) src/modules/core/transition_composite.c src/modules/core/transition_composite.h - Removed frame properties dependence for process/get_image state communication + Extended alpha blending modes to 'and' and 'xor' logic (may change property triggering soon) + Provided support for transition as filter usage + Cleaned up public copy region functionality git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@742 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/framework/mlt_deque.c | 70 +++++++++++++++++++++ src/framework/mlt_deque.h | 7 +++ src/framework/mlt_frame.c | 2 +- src/framework/mlt_tractor.c | 19 +++++- src/modules/core/Makefile | 1 + src/modules/core/configure | 1 + src/modules/core/factory.c | 3 + src/modules/core/transition_composite.c | 83 ++++++++++++++++++------- src/modules/core/transition_composite.h | 2 +- 9 files changed, 163 insertions(+), 25 deletions(-) diff --git a/src/framework/mlt_deque.c b/src/framework/mlt_deque.c index d5ec8d80..6deecffa 100644 --- a/src/framework/mlt_deque.c +++ b/src/framework/mlt_deque.c @@ -29,6 +29,7 @@ typedef union { void *addr; int value; + double floating; } deque_entry; @@ -216,6 +217,75 @@ int mlt_deque_peek_front_int( mlt_deque this ) return this->count > 0 ? this->list[ 0 ].value : 0; } +/** Push an item to the end. +*/ + +int mlt_deque_push_back_double( mlt_deque this, double item ) +{ + int error = mlt_deque_allocate( this ); + + if ( error == 0 ) + this->list[ this->count ++ ].floating = item; + + return error; +} + +/** Pop an item. +*/ + +double mlt_deque_pop_back_double( mlt_deque this ) +{ + return this->count > 0 ? this->list[ -- this->count ].floating : 0; +} + +/** Queue an item at the start. +*/ + +int mlt_deque_push_front_double( mlt_deque this, double item ) +{ + int error = mlt_deque_allocate( this ); + + if ( error == 0 ) + { + memmove( &this->list[ 1 ], this->list, ( this->count ++ ) * sizeof( deque_entry ) ); + this->list[ 0 ].floating = item; + } + + return error; +} + +/** Remove an item from the start. +*/ + +double mlt_deque_pop_front_double( mlt_deque this ) +{ + double item = 0; + + if ( this->count > 0 ) + { + item = this->list[ 0 ].floating; + memmove( this->list, &this->list[ 1 ], ( -- this->count ) * sizeof( deque_entry ) ); + } + + return item; +} + +/** Inquire on item at back of deque but don't remove. +*/ + +double mlt_deque_peek_back_double( mlt_deque this ) +{ + return this->count > 0 ? this->list[ this->count - 1 ].floating : 0; +} + +/** Inquire on item at front of deque but don't remove. +*/ + +double mlt_deque_peek_front_double( mlt_deque this ) +{ + return this->count > 0 ? this->list[ 0 ].floating : 0; +} + /** Close the queue. */ diff --git a/src/framework/mlt_deque.h b/src/framework/mlt_deque.h index f70a3901..91e20c05 100644 --- a/src/framework/mlt_deque.h +++ b/src/framework/mlt_deque.h @@ -39,6 +39,13 @@ extern int mlt_deque_pop_front_int( mlt_deque self ); extern int mlt_deque_peek_back_int( mlt_deque self ); extern int mlt_deque_peek_front_int( mlt_deque self ); +extern int mlt_deque_push_back_double( mlt_deque self, double item ); +extern double mlt_deque_pop_back_double( mlt_deque self ); +extern int mlt_deque_push_front_double( mlt_deque self, double item ); +extern double mlt_deque_pop_front_double( mlt_deque self ); +extern double mlt_deque_peek_back_double( mlt_deque self ); +extern double mlt_deque_peek_front_double( mlt_deque self ); + extern void mlt_deque_close( mlt_deque self ); #endif diff --git a/src/framework/mlt_frame.c b/src/framework/mlt_frame.c index 12a66d6b..712c8c25 100644 --- a/src/framework/mlt_frame.c +++ b/src/framework/mlt_frame.c @@ -971,8 +971,8 @@ int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight_start, flo int i, j; double d = 0, s = 0; - mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest ); mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src ); + mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest ); int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 ); diff --git a/src/framework/mlt_tractor.c b/src/framework/mlt_tractor.c index ce678cfe..b319a048 100644 --- a/src/framework/mlt_tractor.c +++ b/src/framework/mlt_tractor.c @@ -28,6 +28,7 @@ #include #include #include +#include /** Forward references to static methods. */ @@ -252,6 +253,8 @@ static void destroy_data_queue( void *arg ) } /** Get the next frame. + + TODO: This function needs to be redesigned... */ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track ) @@ -408,10 +411,24 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra // Pick up first video and audio frames if ( !done && !mlt_frame_is_test_audio( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 2 ) ) + { + // Order of frame creation is starting to get problematic + if ( audio != NULL ) + { + mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), producer_get_audio ); + mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), audio ); + } audio = temp; + } if ( !done && !mlt_frame_is_test_card( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 1 ) ) + { + if ( video != NULL ) + { + mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), producer_get_image ); + mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), video ); + } video = temp; - + } } // Now stack callbacks diff --git a/src/modules/core/Makefile b/src/modules/core/Makefile index af4551cd..1e4cab1f 100644 --- a/src/modules/core/Makefile +++ b/src/modules/core/Makefile @@ -18,6 +18,7 @@ OBJS = factory.o \ filter_region.o \ filter_rescale.o \ filter_resize.o \ + filter_transition.o \ filter_watermark.o \ transition_composite.o \ transition_luma.o \ diff --git a/src/modules/core/configure b/src/modules/core/configure index 49ea0d6a..fe80cd07 100755 --- a/src/modules/core/configure +++ b/src/modules/core/configure @@ -22,6 +22,7 @@ obscure libmltcore$LIBSUF region libmltcore$LIBSUF rescale libmltcore$LIBSUF resize libmltcore$LIBSUF +transition libmltcore$LIBSUF watermark libmltcore$LIBSUF EOF diff --git a/src/modules/core/factory.c b/src/modules/core/factory.c index 87b8ee42..fc76dc87 100644 --- a/src/modules/core/factory.c +++ b/src/modules/core/factory.c @@ -34,6 +34,7 @@ #include "filter_rescale.h" #include "filter_resize.h" #include "filter_region.h" +#include "filter_transition.h" #include "filter_watermark.h" #include "transition_composite.h" #include "transition_luma.h" @@ -78,6 +79,8 @@ void *mlt_create_filter( char *id, void *arg ) return filter_rescale_init( arg ); if ( !strcmp( id, "resize" ) ) return filter_resize_init( arg ); + else if ( !strcmp( id, "transition" ) ) + return filter_transition_init( arg ); if ( !strcmp( id, "watermark" ) ) return filter_watermark_init( arg ); return NULL; diff --git a/src/modules/core/transition_composite.c b/src/modules/core/transition_composite.c index 6e20144b..21909e8e 100644 --- a/src/modules/core/transition_composite.c +++ b/src/modules/core/transition_composite.c @@ -185,17 +185,13 @@ static int position_calculate( mlt_transition this, mlt_position position ) /** Calculate the field delta for this frame - position between two frames. */ -static inline double delta_calculate( mlt_transition this, mlt_frame frame ) +static inline double delta_calculate( mlt_transition this, mlt_frame frame, mlt_position position ) { // Get the in and out position mlt_position in = mlt_transition_get_in( this ); mlt_position out = mlt_transition_get_out( this ); double length = out - in + 1; - // Get the position of the frame - char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( this ), "_unique_id" ); - mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), name ); - // Now do the calcs double x = ( double )( position - in ) / length; double y = ( double )( position + 1 - in ) / length; @@ -414,6 +410,46 @@ static void composite_line_yuv_or( uint8_t *dest, uint8_t *src, int width, uint8 } } +static void composite_line_yuv_and( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int softness ) +{ + register int j; + register int a; + register int mix; + + for ( j = 0; j < width; j ++ ) + { + a = *alpha_b ++ & *alpha_a; + mix = ( luma == NULL ) ? weight : smoothstep( luma[ j ], luma[ j ] + softness, weight + softness ); + mix = ( mix * a ) >> 8; + *dest = ( *src++ * mix + *dest * ( ( 1 << 16 ) - mix ) ) >> 16; + dest++; + *dest = ( *src++ * mix + *dest * ( ( 1 << 16 ) - mix ) ) >> 16; + dest++; + *alpha_a = mix | *alpha_a; + alpha_a ++; + } +} + +static void composite_line_yuv_xor( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int softness ) +{ + register int j; + register int a; + register int mix; + + for ( j = 0; j < width; j ++ ) + { + a = *alpha_b ++ ^ *alpha_a; + mix = ( luma == NULL ) ? weight : smoothstep( luma[ j ], luma[ j ] + softness, weight + softness ); + mix = ( mix * a ) >> 8; + *dest = ( *src++ * mix + *dest * ( ( 1 << 16 ) - mix ) ) >> 16; + dest++; + *dest = ( *src++ * mix + *dest * ( ( 1 << 16 ) - mix ) ) >> 16; + dest++; + *alpha_a = mix | *alpha_a; + alpha_a ++; + } +} + /** Composite function. */ @@ -853,7 +889,7 @@ mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_pos // Will need to know region to copy struct geometry_s result; - double delta = delta_calculate( this, a_frame ); + double delta = delta_calculate( this, a_frame, frame_position ); // Calculate the region now composite_calculate( this, &result, a_frame, position + delta / 2 ); @@ -938,6 +974,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f mlt_transition this = mlt_frame_pop_service( a_frame ); // Get in and out + double position = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( a_frame ) ); int out = mlt_frame_pop_service_int( a_frame ); int in = mlt_frame_pop_service_int( a_frame ); @@ -968,14 +1005,20 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f struct geometry_s result; // Calculate the position - double position = mlt_properties_get_double( b_props, "relative_position" ); - double delta = delta_calculate( this, a_frame ); + double delta = delta_calculate( this, a_frame, position ); // Get the image from the b frame uint8_t *image_b = NULL; int width_b = *width; int height_b = *height; + // Composites always need scaling... defaulting to lowest + char *rescale = mlt_properties_get( a_props, "rescale.interp" ); + if ( rescale == NULL || !strcmp( rescale, "none" ) ) + rescale = "nearest"; + mlt_properties_set( a_props, "rescale.interp", rescale ); + mlt_properties_set( b_props, "rescale.interp", rescale ); + // Do the calculation composite_calculate( this, &result, a_frame, position ); @@ -996,6 +1039,9 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f return 0; } + if ( a_frame == b_frame ) + get_b_frame_image( this, b_frame, &image_b, &width_b, &height_b, &result ); + // Get the image from the a frame mlt_frame_get_image( a_frame, image, format, width, height, 1 ); @@ -1026,7 +1072,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f height_b = mlt_properties_get_int( a_props, "dest_height" ); } - if ( get_b_frame_image( this, b_frame, &image_b, &width_b, &height_b, &result ) == 0 ) + if ( image_b != NULL || get_b_frame_image( this, b_frame, &image_b, &width_b, &height_b, &result ) == 0 ) { uint8_t *dest = *image; uint8_t *src = image_b; @@ -1043,6 +1089,10 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f if ( mlt_properties_get_int( properties, "or" ) ) line_fn = composite_line_yuv_or; + if ( mlt_properties_get_int( properties, "and" ) ) + line_fn = composite_line_yuv_and; + if ( mlt_properties_get_int( properties, "xor" ) ) + line_fn = composite_line_yuv_xor; if ( mlt_properties_get( properties, "alpha_a" ) ) memset( alpha_a, mlt_properties_get_int( properties, "alpha_a" ), *width * *height ); @@ -1089,30 +1139,19 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f static mlt_frame composite_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame ) { - // Get a unique name to store the frame position - char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( this ), "_unique_id" ); - // UGH - this is a TODO - find a more reliable means of obtaining in/out for the always_active case if ( mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "always_active" ) == 0 ) { mlt_frame_push_service_int( a_frame, mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "in" ) ); mlt_frame_push_service_int( a_frame, mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "out" ) ); - - // Assign the current position to the name - mlt_properties_set_position( MLT_FRAME_PROPERTIES( a_frame ), name, mlt_frame_get_position( a_frame ) ); - - // Propogate the transition properties to the b frame - mlt_properties_set_double( MLT_FRAME_PROPERTIES( b_frame ), "relative_position", position_calculate( this, mlt_frame_get_position( a_frame ) ) ); + mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( a_frame ), position_calculate( this, mlt_frame_get_position( a_frame ) ) ); } else { mlt_properties props = mlt_properties_get_data( MLT_FRAME_PROPERTIES( b_frame ), "_producer", NULL ); mlt_frame_push_service_int( a_frame, mlt_properties_get_int( props, "in" ) ); mlt_frame_push_service_int( a_frame, mlt_properties_get_int( props, "out" ) ); - mlt_properties_set_int( MLT_FRAME_PROPERTIES( b_frame ), "relative_position", mlt_properties_get_int( props, "_frame" ) - mlt_properties_get_int( props, "in" ) ); - - // Assign the current position to the name - mlt_properties_set_position( MLT_FRAME_PROPERTIES( a_frame ), name, mlt_properties_get_position( MLT_FRAME_PROPERTIES( b_frame ), "relative_position" ) ); + mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( a_frame ), mlt_properties_get_int( props, "_frame" ) - mlt_properties_get_int( props, "in" ) ); } mlt_frame_push_service( a_frame, this ); diff --git a/src/modules/core/transition_composite.h b/src/modules/core/transition_composite.h index 28ba6bad..091fdd0a 100644 --- a/src/modules/core/transition_composite.h +++ b/src/modules/core/transition_composite.h @@ -26,6 +26,6 @@ extern mlt_transition transition_composite_init( char *arg ); // Courtesy functionality - allows regionalised filtering -extern mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_position position ); +extern mlt_frame composite_copy_region( mlt_transition, mlt_frame, mlt_position ); #endif -- 2.39.2