// Special case - allow for a cut of the entire producer (this will squeeze all other cuts to 0)
if ( in <= 0 )
in = 0;
- if ( ( out < 0 || out >= mlt_producer_get_playtime( parent ) ) && !mlt_producer_is_blank( this ) )
- out = mlt_producer_get_playtime( parent ) - 1;
+ if ( ( out < 0 || out >= mlt_producer_get_length( parent ) ) && !mlt_producer_is_blank( this ) )
+ out = mlt_producer_get_length( parent ) - 1;
mlt_properties_inc_ref( parent_props );
mlt_properties_set_int( properties, "_cut", 1 );
// Move the contents of this queue on to the output frames data queue
mlt_deque sub_queue = mlt_properties_get_data( MLT_FRAME_PROPERTIES( temp ), "data_queue", NULL );
mlt_deque temp = mlt_deque_init( );
- while ( mlt_deque_count( sub_queue ) )
+ while ( global_feed && mlt_deque_count( sub_queue ) )
{
mlt_properties p = mlt_deque_pop_back( sub_queue );
if ( mlt_properties_get_int( p, "final" ) )
// Obtain properties of producer
mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
+ // Parse the colour
+ rgba_color color = parse_color( mlt_properties_get( producer_props, "resource" ) );
+
// Get the current image and dimensions cached in the producer
uint8_t *image = mlt_properties_get_data( producer_props, "image", &size );
int current_width = mlt_properties_get_int( producer_props, "width" );
mlt_properties_set_int( producer_props, "height", *height );
// Color the image
- rgba_color color = parse_color( mlt_properties_get( producer_props, "resource" ) );
uint8_t y, u, v;
int i = 0;
RGB2YUV( color.r, color.g, color.b, y, u, v );
// Clone if necessary
if ( writable )
{
+ // Create the alpha channel
+ uint8_t *alpha = mlt_pool_alloc( size >> 1 );
+
// Clone our image
uint8_t *copy = mlt_pool_alloc( size );
memcpy( copy, image, size );
// We're going to pass the copy on
image = copy;
+ // Initialise the alpha
+ if ( alpha )
+ memset( alpha, color.a, size >> 1 );
+
// Now update properties so we free the copy after
mlt_properties_set_data( properties, "image", copy, size, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "alpha", alpha, size >> 1, mlt_pool_release, NULL );
}
// Pass on the image
#include <string.h>
#include <math.h>
-typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha, int weight, uint16_t *luma, int softness );
+typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha, uint8_t *full_alpha, int weight, uint16_t *luma, int softness );
/* mmx function declarations */
#ifdef USE_MMX
*/
static inline
-void composite_line_yuv( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha, int weight, uint16_t *luma, int softness )
+void composite_line_yuv( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha, uint8_t *full_alpha, int weight, uint16_t *luma, int softness )
{
register int j;
int a, mix;
dest++;
*dest = ( *src++ * mix + *dest * ( ( 1 << 16 ) - mix ) ) >> 16;
dest++;
+ if ( full_alpha && *full_alpha == 0 ) { *full_alpha = a; }
+ full_alpha ++;
}
}
/** Composite function.
*/
-static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint8_t *p_src, int width_src, int height_src, uint8_t *p_alpha, struct geometry_s geometry, int field, uint16_t *p_luma, int32_t softness, composite_line_fn line_fn )
+static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint8_t *p_src, int width_src, int height_src, uint8_t *p_alpha, uint8_t *full_alpha, struct geometry_s geometry, int field, uint16_t *p_luma, int32_t softness, composite_line_fn line_fn )
{
int ret = 0;
int i;
if ( p_alpha )
p_alpha += x_src + y_src * stride_src / bpp;
+ if ( full_alpha )
+ full_alpha += x + y * stride_dest / bpp;
+
// offset pointer into luma channel based upon cropping
if ( p_luma )
p_luma += x_src + y_src * stride_src / bpp;
p_src += stride_src;
if ( p_alpha )
p_alpha += stride_src / bpp;
+ if ( full_alpha )
+ full_alpha += stride_dest / bpp;
height_src--;
}
stride_src *= step;
stride_dest *= step;
int alpha_stride = stride_src / bpp;
+ int full_alpha_stride = stride_dest / bpp;
// Make sure than x and w are even
if ( x_uneven )
{
for ( i = 0; i < height_src; i += step )
{
- line_fn( p_dest, p_src, width_src, p_alpha, weight, p_luma, softness );
+ line_fn( p_dest, p_src, width_src, p_alpha, full_alpha, weight, p_luma, softness );
p_src += stride_src;
p_dest += stride_dest;
if ( p_alpha )
p_alpha += alpha_stride;
+ if ( full_alpha )
+ full_alpha += full_alpha_stride;
if ( p_luma )
p_luma += alpha_stride;
}
{
for ( i = 0; i < height_src; i += step )
{
- composite_line_yuv( p_dest, p_src, width_src, p_alpha, weight, p_luma, softness );
+ composite_line_yuv( p_dest, p_src, width_src, p_alpha, full_alpha, weight, p_luma, softness );
p_src += stride_src;
p_dest += stride_dest;
if ( p_alpha )
p_alpha += alpha_stride;
+ if ( full_alpha )
+ full_alpha += full_alpha_stride;
if ( p_luma )
p_luma += alpha_stride;
}
uint8_t *dest = *image;
uint8_t *src = image_b;
uint8_t *alpha = mlt_frame_get_alpha_mask( b_frame );
+ uint8_t *full_alpha = mlt_frame_get_alpha_mask( a_frame );
int progressive =
mlt_properties_get_int( a_props, "consumer_deinterlace" ) ||
mlt_properties_get_int( properties, "progressive" );
//composite_line_fn line_fn = mlt_properties_get_int( properties, "_MMX" ) ? composite_line_yuv_mmx : NULL;
composite_line_fn line_fn = NULL;
+ if ( full_alpha == NULL )
+ {
+ full_alpha = mlt_pool_alloc( *width * *height );
+ memset( full_alpha, 255, *width * *height );
+ a_frame->get_alpha_mask = NULL;
+ mlt_properties_set_data( a_props, "alpha", full_alpha, 0, mlt_pool_release, NULL );
+ }
+
for ( field = 0; field < ( progressive ? 1 : 2 ); field++ )
{
// Assume lower field (0) first
alignment_calculate( &result );
// Composite the b_frame on the a_frame
- composite_yuv( dest, *width, *height, src, width_b, height_b, alpha, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn );
+ composite_yuv( dest, *width, *height, src, width_b, height_b, alpha, full_alpha, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn );
}
}
}
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_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" ) );
.composite.luma=%luma01.pgm
.composite.softness=.3
.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
+.filter[0].resource=colour:0x6c0101ff
.filter[1]=watermark
.filter[1].resource=pango:
.filter[1].producer.text=
.composite.luma=%luma01.pgm
.composite.softness=.3
.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
+.filter[0].resource=colour:0x6c0101ff
.filter[1]=watermark
.filter[1].resource=pango:
.filter[1].producer.text=
.properties.length[0]=composite.out
.composite.geometry=-230,115:230x30;12=0
.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
+.filter[0].resource=colour:0x6c0101ff
.filter[1]=watermark
.filter[1].resource=pango:
.filter[1].producer.text=ETV Exclusive
.properties.length[0]=composite.out
.composite.geometry=590,160:80x25:0;12=,:x:100
.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
+.filter[0].resource=colour:0x6c0101ff
.filter[1]=watermark
.filter[1].resource=pango:
.filter[1].producer.text=File Shot
.properties.length[1]=filter[1].composite.out
.composite.geometry=465,375:255x35
.filter[0]=watermark
-.filter[0].resource=colour:0x6c010101
+.filter[0].resource=colour:0x6c0101ff
.filter[0].composite.geometry=100%,0%:100%x100%:0;12=0%,0%:x:100
.filter[1]=watermark
.filter[1].resource=pango:
.properties.length[0]=filter[1].composite.out
.composite.geometry=0,500:722x75
.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
+.filter[0].resource=colour:0x6c0101ff
.filter[0].composite.titles=1
.filter[1]=watermark
.filter[1].resource=pango:
return ret;
}
+static PangoFT2FontMap *fontmap = NULL;
+
mlt_producer producer_pango_init( const char *filename )
{
producer_pango this = calloc( sizeof( struct producer_pango_s ), 1 );
{
mlt_producer producer = &this->parent;
+ // THIS SHOULD BE MUTEXED...
+ if ( fontmap == NULL )
+ fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new();
+
producer->get_frame = producer_get_frame;
producer->close = ( mlt_destructor )producer_close;
}
}
-static PangoFT2FontMap *fontmap = NULL;
-
static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font, rgba_color fg, rgba_color bg, int pad, int align, int weight, int size )
{
- if ( fontmap == NULL )
- fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new();
-
PangoContext *context = pango_ft2_font_map_create_context( fontmap );
PangoLayout *layout = pango_layout_new( context );
int w, h, x;
mlt_frame_get_image( a_frame, image, format, width, height, writable );
mlt_properties_set_data( frame_properties, "affine_frame", a_frame, 0, (mlt_destructor)mlt_frame_close, NULL );
mlt_properties_set_data( frame_properties, "image", *image, *width * *height * 2, NULL, NULL );
+ mlt_properties_set_data( frame_properties, "alpha", mlt_frame_get_alpha_mask( a_frame ), *width * *height, NULL, NULL );
}
}
start = transition_parse_keys( this, normalised_width, normalised_height );
}
+ if ( *height & 1 )
+ *height ++;
+
// Fetch the a frame image
mlt_frame_get_image( a_frame, image, format, width, height, 1 );
float fix_shear_x = mlt_properties_get_double( properties, "fix_shear_x" );
float fix_shear_y = mlt_properties_get_double( properties, "fix_shear_y" );
float fix_shear_z = mlt_properties_get_double( properties, "fix_shear_z" );
+ float scale_x = mlt_properties_get_double( properties, "scale_x" );
+ float scale_y = mlt_properties_get_double( properties, "scale_y" );
float shear_x = mlt_properties_get_double( properties, "shear_x" );
float shear_y = mlt_properties_get_double( properties, "shear_y" );
float shear_z = mlt_properties_get_double( properties, "shear_z" );
int y_offset = ( int )result.h >> 1;
uint8_t *alpha = mlt_frame_get_alpha_mask( b_frame );
- uint8_t *mask = mlt_pool_alloc( b_width * b_height );
+ uint8_t *mask = mlt_frame_get_alpha_mask( a_frame );
uint8_t *pmask = mask;
float mix;
dz = MapZ( affine.matrix, 0, 0 );
- if ( mask != NULL )
- memset( mask, 0, b_width * b_height );
+ if ( mask == NULL )
+ {
+ mask = mlt_pool_alloc( *width * *height );
+ pmask = mask;
+ memset( mask, 255, *width * *height );
+ }
if ( ( int )abs( dz * 1000 ) < 25 )
goto getout;
if ( scale )
{
affine_max_output( affine.matrix, &sw, &sh, dz );
- affine_scale( affine.matrix, sw, sh );
+ affine_scale( affine.matrix, 1.0 / sw, 1.0 / sh );
+ }
+ else if ( scale_x != 0 && scale_y != 0 )
+ {
+ affine_scale( affine.matrix, scale_x, scale_y );
}
for ( y = lower_y; y < upper_y; y ++ )
{
if ( alpha == NULL )
{
- *pmask ++ = 255;
+ *pmask ++;
dx += dx & 1;
*p ++ = *( b_image + dy * b_stride + ( dx << 1 ) );
*p ++ = *( b_image + dy * b_stride + ( dx << 1 ) + ( ( x & 1 ) << 1 ) + 1 );
}
getout:
- b_frame->get_alpha_mask = NULL;
- mlt_properties_set_data( b_props, "alpha", mask, 0, mlt_pool_release, NULL );
+ a_frame->get_alpha_mask = NULL;
+ mlt_properties_set_data( a_props, "alpha", mask, 0, mlt_pool_release, NULL );
}
return 0;
// Get the speed of the frame
double speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" );
- // Determine which speed to use
- double use_speed = speed;
-
// Lock during the operation
mlt_service_lock( MLT_CONSUMER_SERVICE( consumer ) );
mlt_consumer_put_frame( this->active, frame );
}
// If we aren't playing normally, then use the still
- else if ( use_speed != 1 )
+ else if ( speed != 1 )
{
if ( !mlt_consumer_is_stopped( this->play ) )
mlt_consumer_stop( this->play );
if ( mlt_consumer_is_stopped( this->still ) )
{
- this->last_speed = use_speed;
+ this->last_speed = speed;
this->active = this->still;
this->ignore_change = 0;
mlt_consumer_start( this->still );
mlt_consumer_stop( this->still );
if ( mlt_consumer_is_stopped( this->play ) )
{
- this->last_speed = use_speed;
+ this->last_speed = speed;
this->active = this->play;
this->ignore_change = 25;
mlt_consumer_start( this->play );
if ( strcmp( mlt_type, "producer" ) == 0 )
{
char *mlt_service = mlt_properties_get( properties, "mlt_service" );
- if ( mlt_properties_get( properties, "westley" ) == NULL && !strcmp( mlt_service, "tractor" ) )
+ if ( mlt_properties_get( properties, "westley" ) == NULL && ( mlt_service != NULL && !strcmp( mlt_service, "tractor" ) ) )
{
context->pass = 0;
serialise_tractor( context, service, node );
for ( ; atts != NULL && *atts != NULL; atts += 2 )
mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), (char*) atts[0], atts[1] == NULL ? "" : (char*) atts[1] );
+ mlt_properties_set_int( MLT_TRACTOR_PROPERTIES( tractor ), "global_feed", 1 );
+
if ( mlt_properties_get( properties, "id" ) != NULL )
mlt_properties_set_data( context->producer_map, mlt_properties_get( properties, "id" ), service, 0, NULL, NULL );