From: ddennedy Date: Fri, 2 Jan 2004 20:44:28 +0000 (+0000) Subject: fixup and optimize edge conditions of composite; updated property handling of produce... X-Git-Url: http://research.m1stereo.tv/gitweb?a=commitdiff_plain;h=163b1bf05b39b9d2f226b63a370badd233612656;p=melted fixup and optimize edge conditions of composite; updated property handling of producer_pango git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@35 d19143bc-622f-0410-bfdd-b5b2a6649095 --- diff --git a/mlt/src/framework/mlt_frame.c b/mlt/src/framework/mlt_frame.c index 368e861..16d51f8 100644 --- a/mlt/src/framework/mlt_frame.c +++ b/mlt/src/framework/mlt_frame.c @@ -394,15 +394,18 @@ int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y, float weight ) { int ret = 0; - int x_start = 0; int width_src, height_src; int width_dest, height_dest; mlt_image_format format_src, format_dest; uint8_t *p_src, *p_dest; - int x_end; int i, j; int stride_src; int stride_dest; + int x_src = 0, y_src = 0; + + // optimization point - no work to do + if ( ( x < 0 && -x >= width_src ) || ( y < 0 && -y >= height_src ) ) + return ret; format_src = mlt_image_yuv422; format_dest = mlt_image_yuv422; @@ -410,52 +413,68 @@ int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y, float mlt_frame_get_image( this, &p_dest, &format_dest, &width_dest, &height_dest, 1 /* writable */ ); mlt_frame_get_image( that, &p_src, &format_src, &width_src, &height_src, 0 /* writable */ ); - x_end = width_src; - stride_src = width_src * 2; stride_dest = width_dest * 2; - uint8_t *lower = p_dest; - uint8_t *upper = p_dest + height_dest * stride_dest; - - p_dest += ( y * stride_dest ) + ( x * 2 ); - + + // crop overlay off the left edge of frame if ( x < 0 ) { - x_start = -x; - x_end += x_start; + x_src = -x; + width_src -= x_src; + x = 0; + } + + // crop overlay beyond right edge of frame + else if ( x + width_src > width_dest ) + width_src = width_dest - x; + + // crop overlay off the top edge of the frame + if ( y < 0 ) + { + y_src = -y; + height_src -= y_src; } + // crop overlay below bottom edge of frame + else if ( y + height_src > height_dest ) + height_src = height_dest - y; + + // offset pointer into overlay buffer based on cropping + p_src += x_src * 2 + y_src * stride_src; + + // offset pointer into frame buffer based upon positive, even coordinates only! +// if ( interlaced && y % 2 ) +// ++y; + p_dest += ( x < 0 ? 0 : x ) * 2 + ( y < 0 ? 0 : y ) * stride_dest; + + // Get the alpha channel of the overlay + uint8_t *p_alpha = mlt_frame_get_alpha_mask( that ); - uint8_t *z = mlt_frame_get_alpha_mask( that ); + // offset pointer into alpha channel based upon cropping + if ( p_alpha ) + p_alpha += x_src + y_src * stride_src / 2; + // now do the compositing only to cropped extents for ( i = 0; i < height_src; i++ ) { uint8_t *p = p_src; uint8_t *q = p_dest; uint8_t *o = p_dest; + uint8_t *z = p_alpha; for ( j = 0; j < width_src; j ++ ) { - if ( q >= lower && q < upper && j >= x_start && j < x_end ) - { uint8_t y = *p ++; uint8_t uv = *p ++; uint8_t a = ( z == NULL ) ? 255 : *z ++; float value = ( weight * ( float ) a / 255.0 ); *o ++ = (uint8_t)( y * value + *q++ * ( 1 - value ) ); *o ++ = (uint8_t)( uv * value + *q++ * ( 1 - value ) ); - } - else - { - p += 2; - o += 2; - q += 2; - if ( z != NULL ) - z += 1; - } } p_src += stride_src; p_dest += stride_dest; + if ( p_alpha ) + p_alpha += stride_src / 2; } return ret; diff --git a/mlt/src/modules/core/transition_composite.c b/mlt/src/modules/core/transition_composite.c index 8418f2f..f56c677 100644 --- a/mlt/src/modules/core/transition_composite.c +++ b/mlt/src/modules/core/transition_composite.c @@ -48,20 +48,20 @@ static int transition_get_image( mlt_frame this, uint8_t **image, mlt_image_form mlt_properties b_props = mlt_frame_properties( b_frame ); // Arbitrary composite defaults - int x = 50; - int y = 50; - double weight = 1.0; + int x = 0; + int y = 0; + double mix = 1.0; // Override from b frame properties if provided if ( mlt_properties_get( b_props, "x" ) != NULL ) x = mlt_properties_get_int( b_props, "x" ); if ( mlt_properties_get( b_props, "y" ) != NULL ) y = mlt_properties_get_int( b_props, "y" ); - if ( mlt_properties_get( b_props, "weight" ) != NULL ) - weight = mlt_properties_get_double( b_props, "weight" ); + if ( mlt_properties_get( b_props, "mix" ) != NULL ) + mix = mlt_properties_get_double( b_props, "mix" ); // Composite the b_frame on the a_frame - mlt_frame_composite_yuv( this, b_frame, x, y, weight ); + mlt_frame_composite_yuv( this, b_frame, x, y, mix ); // Extract the a_frame image info *width = mlt_properties_get_int( a_props, "width" ); diff --git a/mlt/src/modules/gtk2/producer_pango.c b/mlt/src/modules/gtk2/producer_pango.c index d113ce6..5877d52 100644 --- a/mlt/src/modules/gtk2/producer_pango.c +++ b/mlt/src/modules/gtk2/producer_pango.c @@ -26,6 +26,22 @@ #include #include +struct producer_pango_s +{ + struct mlt_producer_s parent; + int width; + int height; + uint8_t *image; + uint8_t *alpha; + int fgcolor; + int bgcolor; + int align; + int pad; + char *markup; + char *text; + char *font; +}; + // special color type used by internal pango routines typedef struct { @@ -36,7 +52,8 @@ typedef struct static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index ); static void producer_close( mlt_producer parent ); static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg ); -static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align ); +static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font, + rgba_color fg, rgba_color bg, int pad, int align ); mlt_producer producer_pango_init( const char *markup ) { @@ -48,7 +65,7 @@ mlt_producer producer_pango_init( const char *markup ) producer->get_frame = producer_get_frame; producer->close = producer_close; - this->markup = strdup( markup ); + // This is required to initialise gdk-pixbuf g_type_init(); // Get the properties interface @@ -60,6 +77,12 @@ mlt_producer producer_pango_init( const char *markup ) mlt_properties_set_int( properties, "bgcolor", 0x00000000 ); mlt_properties_set_int( properties, "align", pango_align_left ); mlt_properties_set_int( properties, "pad", 0 ); + mlt_properties_set( properties, "markup", ( char * ) ( markup == NULL ? "" : markup ) ); + mlt_properties_set( properties, "text", "" ); + mlt_properties_set( properties, "font", "Sans 48" ); + mlt_properties_set_int( properties, "x", 0 ); + mlt_properties_set_int( properties, "y", 0 ); + mlt_properties_set_double( properties, "mix", 1.0 ); return producer; } @@ -119,37 +142,54 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Generate a frame *frame = mlt_frame_init( ); - // Obtain properties of frame + // Obtain properties of frame and producer mlt_properties properties = mlt_frame_properties( *frame ); - - // optimization for subsequent iterations on single picture - if ( this->image != NULL ) + mlt_properties producer_props = mlt_producer_properties( producer ); + + // Get producer properties + int fg = mlt_properties_get_int( producer_props, "fgcolor" ); + int bg = mlt_properties_get_int( producer_props, "bgcolor" ); + int align = mlt_properties_get_int( producer_props, "align" ); + int pad = mlt_properties_get_int( producer_props, "pad" ); + char *markup = mlt_properties_get( producer_props, "markup" ); + char *text = mlt_properties_get( producer_props, "text" ); + char *font = mlt_properties_get( producer_props, "font" ); + + // See if any properties changed + int property_changed = ( fg != this->fgcolor ); + property_changed = property_changed || ( bg != this->bgcolor ); + property_changed = property_changed || ( align != this->align ); + property_changed = property_changed || ( pad != this->pad ); + property_changed = property_changed || ( markup && this->markup && strcmp( markup, this->markup ) ); + property_changed = property_changed || ( text && this->text && strcmp( text, this->text ) ); + property_changed = property_changed || ( font && this->font && strcmp( font, this->font ) ); + + // Save the properties for next comparison + this->fgcolor = fg; + this->bgcolor = bg; + this->align = align; + this->pad = pad; + if ( markup != NULL ) { - // Set width/height - mlt_properties_set_int( properties, "width", this->width ); - mlt_properties_set_int( properties, "height", this->height ); - - // if picture sequence pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL ); - - // Set alpha mask call back - ( *frame )->get_alpha_mask = producer_get_alpha_mask; - - // Stack the get image callback - mlt_frame_push_get_image( *frame, producer_get_image ); - + if ( this->markup != NULL ) + free( this->markup ); + this->markup = strdup( markup ); } - else + if ( text != NULL ) + { + if ( this->text != NULL ) + free( this->text ); + this->text = strdup( text ); + } + if ( font != NULL ) + { + if ( this->font != NULL ) + free( this->font ); + this->font = strdup( font ); + } + + if ( property_changed ) { - // Obtain properties of producer - mlt_properties props = mlt_producer_properties( producer ); - - // Get properties - int fg = mlt_properties_get_int( props, "fgcolor" ); - int bg = mlt_properties_get_int( props, "bgcolor" ); - int align = mlt_properties_get_int( props, "align" ); - int pad = mlt_properties_get_int( props, "pad" ); rgba_color fgcolor = { ( fg & 0xff000000 ) >> 24, @@ -164,9 +204,9 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i ( bg & 0x0000ff00 ) >> 8, ( bg & 0x000000ff ) }; - + // Render the title - pixbuf = pango_get_pixbuf( this->markup, fgcolor, bgcolor, pad, align ); + pixbuf = pango_get_pixbuf( markup, text, font, fgcolor, bgcolor, pad, align ); } // If we have a pixbuf @@ -223,23 +263,36 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Finished with pixbuf now g_object_unref( pixbuf ); + + // if single picture, reference the image and alpha in the producer + if ( this->image != NULL ) + free( this->image ); + this->image = image; + if ( this->alpha != NULL ) + free( this->alpha ); + this->alpha = alpha; + + } - // Set width/height of frame + if ( this->image != NULL ) + { + // Set width/height mlt_properties_set_int( properties, "width", this->width ); mlt_properties_set_int( properties, "height", this->height ); - // if single picture, reference the image and alpha in the producer - this->image = image; - this->alpha = alpha; + // Set the compositing properties + mlt_properties_set_int( properties, "x", mlt_properties_get_int( producer_props, "x" ) ); + mlt_properties_set_int( properties, "y", mlt_properties_get_int( producer_props, "y" ) ); + mlt_properties_set_double( properties, "mix", mlt_properties_get_double( producer_props, "mix" ) ); - // pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", image, 0, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL ); + // if picture sequence pass the image and alpha data without destructor + mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL ); + mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL ); - // Set alpha call back + // Set alpha mask call back ( *frame )->get_alpha_mask = producer_get_alpha_mask; - // Push the get_image method + // Stack the get image callback mlt_frame_push_get_image( *frame, producer_get_image ); } @@ -255,12 +308,16 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i static void producer_close( mlt_producer parent ) { producer_pango this = parent->child; - if ( this->markup ) - free( this->markup ); - if ( this->image ) + if ( this->image != NULL ) free( this->image ); - if ( this->alpha ) + if ( this->alpha != NULL ) free( this->alpha ); + if ( this->markup != NULL ) + free( this->markup ); + if ( this->text != NULL ) + free( this->text ); + if ( this->font != NULL ) + free( this->font ); parent->close = NULL; mlt_producer_close( parent ); free( this ); @@ -285,12 +342,11 @@ static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg ) } } -static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align ) +static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font, rgba_color fg, rgba_color bg, int pad, int align ) { PangoFT2FontMap *fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new(); PangoContext *context = pango_ft2_font_map_create_context( fontmap ); PangoLayout *layout = pango_layout_new( context ); -// PangoFontDescription *font; int w, h, x; int i, j; GdkPixbuf *pixbuf = NULL; @@ -301,10 +357,15 @@ static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_colo pango_ft2_font_map_set_resolution( fontmap, 72, 72 ); pango_layout_set_width( layout, -1 ); // set wrapping constraints -// pango_layout_set_font_description( layout, "Sans 48" ); + pango_layout_set_font_description( layout, pango_font_description_from_string( font ) ); // pango_layout_set_spacing( layout, space ); pango_layout_set_alignment( layout, ( PangoAlignment ) align ); - pango_layout_set_markup( layout, markup, (markup == NULL ? 0 : strlen( markup ) ) ); + if ( markup != NULL && strcmp( markup, "" ) != 0 ) + pango_layout_set_markup( layout, markup, strlen( markup ) ); + else if ( text != NULL && strcmp( text, "" ) != 0 ) + pango_layout_set_text( layout, text, strlen( text ) ); + else + return NULL; pango_layout_get_pixel_size( layout, &w, &h ); pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE /* has alpha */, 8, w + 2 * pad, h + 2 * pad ); diff --git a/mlt/src/modules/gtk2/producer_pango.h b/mlt/src/modules/gtk2/producer_pango.h index 1e2b1c8..ade1977 100644 --- a/mlt/src/modules/gtk2/producer_pango.h +++ b/mlt/src/modules/gtk2/producer_pango.h @@ -25,16 +25,6 @@ typedef struct producer_pango_s *producer_pango; -struct producer_pango_s -{ - struct mlt_producer_s parent; - char *markup; - int width; - int height; - uint8_t *image; - uint8_t *alpha; -}; - typedef enum { pango_align_left = 0, diff --git a/mlt/src/tests/dan.c b/mlt/src/tests/dan.c index cdfd211..8e499bc 100644 --- a/mlt/src/tests/dan.c +++ b/mlt/src/tests/dan.c @@ -18,8 +18,8 @@ int main( int argc, char **argv ) // Start the consumer... int vstd = mlt_video_standard_ntsc; - mlt_consumer consumer = mlt_factory_consumer( "bluefish", &vstd ); - mlt_properties_set_int( mlt_consumer_properties( consumer ), "video_standard", mlt_video_standard_ntsc ); + //mlt_consumer consumer = mlt_factory_consumer( "bluefish", &vstd ); + mlt_consumer consumer = mlt_factory_consumer( "sdl", "NTSC" ); // Create the producer(s) mlt_producer dv1 = mlt_factory_producer( "mcmpeg", file1 ); @@ -38,10 +38,15 @@ int main( int argc, char **argv ) //mlt_producer dv1 = producer_pixbuf_init( file1 ); //mlt_producer dv2 = producer_libdv_init( file2 ); //mlt_producer dv2 = mlt_factory_producer( "pixbuf", file2 ); - mlt_producer dv2 = mlt_factory_producer( "pango", "Mutton Lettuce Tomato" ); + mlt_producer dv2 = mlt_factory_producer( "pango", NULL ); //"Mutton Lettuce Tomato" ); + mlt_properties_set( mlt_producer_properties( dv2 ), "font", "Sans Bold 36" ); + mlt_properties_set( mlt_producer_properties( dv2 ), "text", "Mutton Lettuce\nTomato" ); mlt_properties_set_int( mlt_producer_properties( dv2 ), "video_standard", mlt_video_standard_ntsc ); mlt_properties_set_int( mlt_producer_properties( dv2 ), "bgcolor", 0x0000007f ); mlt_properties_set_int( mlt_producer_properties( dv2 ), "pad", 8 ); + mlt_properties_set_int( mlt_producer_properties( dv2 ), "align", 1 ); + mlt_properties_set_int( mlt_producer_properties( dv2 ), "x", -20 ); + mlt_properties_set_int( mlt_producer_properties( dv2 ), "y", 40 ); // Register producers(s) with a multitrack object mlt_multitrack multitrack = mlt_multitrack_init( ); @@ -49,14 +54,14 @@ int main( int argc, char **argv ) mlt_multitrack_connect( multitrack, dv2, 1 ); // Create a filter and associate it to track 0 -// mlt_filter filter = mlt_factory_filter( "deinterlace", NULL ); -// mlt_filter_connect( filter, mlt_multitrack_service( multitrack ), 0 ); -// mlt_filter_set_in_and_out( filter, 0, 1000 ); + mlt_filter filter = mlt_factory_filter( "deinterlace", NULL ); + mlt_filter_connect( filter, mlt_multitrack_service( multitrack ), 0 ); + mlt_filter_set_in_and_out( filter, 0, 1000 ); // Define a transition mlt_transition transition = mlt_factory_transition( "composite", NULL ); - mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 ); - mlt_transition_set_in_and_out( transition, 0, 1000 ); + mlt_transition_connect( transition, mlt_filter_service( filter ), 0, 1 ); + mlt_transition_set_in_and_out( transition, 0, 5.0 ); // Buy a tractor and connect it to the filter mlt_tractor tractor = mlt_tractor_init( ); @@ -69,6 +74,13 @@ int main( int argc, char **argv ) fprintf( stderr, "Press return to continue\n" ); fgets( temp, 132, stdin ); + mlt_properties_set( mlt_producer_properties( dv2 ), "font", "Sans Oblique 36" ); + mlt_properties_set( mlt_producer_properties( dv2 ), "text", "Mutton\nLettuce Tomato" ); + + // Do stuff until we're told otherwise... + fprintf( stderr, "Press return to continue\n" ); + fgets( temp, 132, stdin ); + // Close everything... mlt_consumer_close( consumer ); mlt_tractor_close( tractor ); diff --git a/src/framework/mlt_frame.c b/src/framework/mlt_frame.c index 368e861..16d51f8 100644 --- a/src/framework/mlt_frame.c +++ b/src/framework/mlt_frame.c @@ -394,15 +394,18 @@ int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y, float weight ) { int ret = 0; - int x_start = 0; int width_src, height_src; int width_dest, height_dest; mlt_image_format format_src, format_dest; uint8_t *p_src, *p_dest; - int x_end; int i, j; int stride_src; int stride_dest; + int x_src = 0, y_src = 0; + + // optimization point - no work to do + if ( ( x < 0 && -x >= width_src ) || ( y < 0 && -y >= height_src ) ) + return ret; format_src = mlt_image_yuv422; format_dest = mlt_image_yuv422; @@ -410,52 +413,68 @@ int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y, float mlt_frame_get_image( this, &p_dest, &format_dest, &width_dest, &height_dest, 1 /* writable */ ); mlt_frame_get_image( that, &p_src, &format_src, &width_src, &height_src, 0 /* writable */ ); - x_end = width_src; - stride_src = width_src * 2; stride_dest = width_dest * 2; - uint8_t *lower = p_dest; - uint8_t *upper = p_dest + height_dest * stride_dest; - - p_dest += ( y * stride_dest ) + ( x * 2 ); - + + // crop overlay off the left edge of frame if ( x < 0 ) { - x_start = -x; - x_end += x_start; + x_src = -x; + width_src -= x_src; + x = 0; + } + + // crop overlay beyond right edge of frame + else if ( x + width_src > width_dest ) + width_src = width_dest - x; + + // crop overlay off the top edge of the frame + if ( y < 0 ) + { + y_src = -y; + height_src -= y_src; } + // crop overlay below bottom edge of frame + else if ( y + height_src > height_dest ) + height_src = height_dest - y; + + // offset pointer into overlay buffer based on cropping + p_src += x_src * 2 + y_src * stride_src; + + // offset pointer into frame buffer based upon positive, even coordinates only! +// if ( interlaced && y % 2 ) +// ++y; + p_dest += ( x < 0 ? 0 : x ) * 2 + ( y < 0 ? 0 : y ) * stride_dest; + + // Get the alpha channel of the overlay + uint8_t *p_alpha = mlt_frame_get_alpha_mask( that ); - uint8_t *z = mlt_frame_get_alpha_mask( that ); + // offset pointer into alpha channel based upon cropping + if ( p_alpha ) + p_alpha += x_src + y_src * stride_src / 2; + // now do the compositing only to cropped extents for ( i = 0; i < height_src; i++ ) { uint8_t *p = p_src; uint8_t *q = p_dest; uint8_t *o = p_dest; + uint8_t *z = p_alpha; for ( j = 0; j < width_src; j ++ ) { - if ( q >= lower && q < upper && j >= x_start && j < x_end ) - { uint8_t y = *p ++; uint8_t uv = *p ++; uint8_t a = ( z == NULL ) ? 255 : *z ++; float value = ( weight * ( float ) a / 255.0 ); *o ++ = (uint8_t)( y * value + *q++ * ( 1 - value ) ); *o ++ = (uint8_t)( uv * value + *q++ * ( 1 - value ) ); - } - else - { - p += 2; - o += 2; - q += 2; - if ( z != NULL ) - z += 1; - } } p_src += stride_src; p_dest += stride_dest; + if ( p_alpha ) + p_alpha += stride_src / 2; } return ret; diff --git a/src/modules/core/transition_composite.c b/src/modules/core/transition_composite.c index 8418f2f..f56c677 100644 --- a/src/modules/core/transition_composite.c +++ b/src/modules/core/transition_composite.c @@ -48,20 +48,20 @@ static int transition_get_image( mlt_frame this, uint8_t **image, mlt_image_form mlt_properties b_props = mlt_frame_properties( b_frame ); // Arbitrary composite defaults - int x = 50; - int y = 50; - double weight = 1.0; + int x = 0; + int y = 0; + double mix = 1.0; // Override from b frame properties if provided if ( mlt_properties_get( b_props, "x" ) != NULL ) x = mlt_properties_get_int( b_props, "x" ); if ( mlt_properties_get( b_props, "y" ) != NULL ) y = mlt_properties_get_int( b_props, "y" ); - if ( mlt_properties_get( b_props, "weight" ) != NULL ) - weight = mlt_properties_get_double( b_props, "weight" ); + if ( mlt_properties_get( b_props, "mix" ) != NULL ) + mix = mlt_properties_get_double( b_props, "mix" ); // Composite the b_frame on the a_frame - mlt_frame_composite_yuv( this, b_frame, x, y, weight ); + mlt_frame_composite_yuv( this, b_frame, x, y, mix ); // Extract the a_frame image info *width = mlt_properties_get_int( a_props, "width" ); diff --git a/src/modules/gtk2/producer_pango.c b/src/modules/gtk2/producer_pango.c index d113ce6..5877d52 100644 --- a/src/modules/gtk2/producer_pango.c +++ b/src/modules/gtk2/producer_pango.c @@ -26,6 +26,22 @@ #include #include +struct producer_pango_s +{ + struct mlt_producer_s parent; + int width; + int height; + uint8_t *image; + uint8_t *alpha; + int fgcolor; + int bgcolor; + int align; + int pad; + char *markup; + char *text; + char *font; +}; + // special color type used by internal pango routines typedef struct { @@ -36,7 +52,8 @@ typedef struct static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index ); static void producer_close( mlt_producer parent ); static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg ); -static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align ); +static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font, + rgba_color fg, rgba_color bg, int pad, int align ); mlt_producer producer_pango_init( const char *markup ) { @@ -48,7 +65,7 @@ mlt_producer producer_pango_init( const char *markup ) producer->get_frame = producer_get_frame; producer->close = producer_close; - this->markup = strdup( markup ); + // This is required to initialise gdk-pixbuf g_type_init(); // Get the properties interface @@ -60,6 +77,12 @@ mlt_producer producer_pango_init( const char *markup ) mlt_properties_set_int( properties, "bgcolor", 0x00000000 ); mlt_properties_set_int( properties, "align", pango_align_left ); mlt_properties_set_int( properties, "pad", 0 ); + mlt_properties_set( properties, "markup", ( char * ) ( markup == NULL ? "" : markup ) ); + mlt_properties_set( properties, "text", "" ); + mlt_properties_set( properties, "font", "Sans 48" ); + mlt_properties_set_int( properties, "x", 0 ); + mlt_properties_set_int( properties, "y", 0 ); + mlt_properties_set_double( properties, "mix", 1.0 ); return producer; } @@ -119,37 +142,54 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Generate a frame *frame = mlt_frame_init( ); - // Obtain properties of frame + // Obtain properties of frame and producer mlt_properties properties = mlt_frame_properties( *frame ); - - // optimization for subsequent iterations on single picture - if ( this->image != NULL ) + mlt_properties producer_props = mlt_producer_properties( producer ); + + // Get producer properties + int fg = mlt_properties_get_int( producer_props, "fgcolor" ); + int bg = mlt_properties_get_int( producer_props, "bgcolor" ); + int align = mlt_properties_get_int( producer_props, "align" ); + int pad = mlt_properties_get_int( producer_props, "pad" ); + char *markup = mlt_properties_get( producer_props, "markup" ); + char *text = mlt_properties_get( producer_props, "text" ); + char *font = mlt_properties_get( producer_props, "font" ); + + // See if any properties changed + int property_changed = ( fg != this->fgcolor ); + property_changed = property_changed || ( bg != this->bgcolor ); + property_changed = property_changed || ( align != this->align ); + property_changed = property_changed || ( pad != this->pad ); + property_changed = property_changed || ( markup && this->markup && strcmp( markup, this->markup ) ); + property_changed = property_changed || ( text && this->text && strcmp( text, this->text ) ); + property_changed = property_changed || ( font && this->font && strcmp( font, this->font ) ); + + // Save the properties for next comparison + this->fgcolor = fg; + this->bgcolor = bg; + this->align = align; + this->pad = pad; + if ( markup != NULL ) { - // Set width/height - mlt_properties_set_int( properties, "width", this->width ); - mlt_properties_set_int( properties, "height", this->height ); - - // if picture sequence pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL ); - - // Set alpha mask call back - ( *frame )->get_alpha_mask = producer_get_alpha_mask; - - // Stack the get image callback - mlt_frame_push_get_image( *frame, producer_get_image ); - + if ( this->markup != NULL ) + free( this->markup ); + this->markup = strdup( markup ); } - else + if ( text != NULL ) + { + if ( this->text != NULL ) + free( this->text ); + this->text = strdup( text ); + } + if ( font != NULL ) + { + if ( this->font != NULL ) + free( this->font ); + this->font = strdup( font ); + } + + if ( property_changed ) { - // Obtain properties of producer - mlt_properties props = mlt_producer_properties( producer ); - - // Get properties - int fg = mlt_properties_get_int( props, "fgcolor" ); - int bg = mlt_properties_get_int( props, "bgcolor" ); - int align = mlt_properties_get_int( props, "align" ); - int pad = mlt_properties_get_int( props, "pad" ); rgba_color fgcolor = { ( fg & 0xff000000 ) >> 24, @@ -164,9 +204,9 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i ( bg & 0x0000ff00 ) >> 8, ( bg & 0x000000ff ) }; - + // Render the title - pixbuf = pango_get_pixbuf( this->markup, fgcolor, bgcolor, pad, align ); + pixbuf = pango_get_pixbuf( markup, text, font, fgcolor, bgcolor, pad, align ); } // If we have a pixbuf @@ -223,23 +263,36 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Finished with pixbuf now g_object_unref( pixbuf ); + + // if single picture, reference the image and alpha in the producer + if ( this->image != NULL ) + free( this->image ); + this->image = image; + if ( this->alpha != NULL ) + free( this->alpha ); + this->alpha = alpha; + + } - // Set width/height of frame + if ( this->image != NULL ) + { + // Set width/height mlt_properties_set_int( properties, "width", this->width ); mlt_properties_set_int( properties, "height", this->height ); - // if single picture, reference the image and alpha in the producer - this->image = image; - this->alpha = alpha; + // Set the compositing properties + mlt_properties_set_int( properties, "x", mlt_properties_get_int( producer_props, "x" ) ); + mlt_properties_set_int( properties, "y", mlt_properties_get_int( producer_props, "y" ) ); + mlt_properties_set_double( properties, "mix", mlt_properties_get_double( producer_props, "mix" ) ); - // pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", image, 0, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL ); + // if picture sequence pass the image and alpha data without destructor + mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL ); + mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL ); - // Set alpha call back + // Set alpha mask call back ( *frame )->get_alpha_mask = producer_get_alpha_mask; - // Push the get_image method + // Stack the get image callback mlt_frame_push_get_image( *frame, producer_get_image ); } @@ -255,12 +308,16 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i static void producer_close( mlt_producer parent ) { producer_pango this = parent->child; - if ( this->markup ) - free( this->markup ); - if ( this->image ) + if ( this->image != NULL ) free( this->image ); - if ( this->alpha ) + if ( this->alpha != NULL ) free( this->alpha ); + if ( this->markup != NULL ) + free( this->markup ); + if ( this->text != NULL ) + free( this->text ); + if ( this->font != NULL ) + free( this->font ); parent->close = NULL; mlt_producer_close( parent ); free( this ); @@ -285,12 +342,11 @@ static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg ) } } -static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align ) +static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font, rgba_color fg, rgba_color bg, int pad, int align ) { PangoFT2FontMap *fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new(); PangoContext *context = pango_ft2_font_map_create_context( fontmap ); PangoLayout *layout = pango_layout_new( context ); -// PangoFontDescription *font; int w, h, x; int i, j; GdkPixbuf *pixbuf = NULL; @@ -301,10 +357,15 @@ static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_colo pango_ft2_font_map_set_resolution( fontmap, 72, 72 ); pango_layout_set_width( layout, -1 ); // set wrapping constraints -// pango_layout_set_font_description( layout, "Sans 48" ); + pango_layout_set_font_description( layout, pango_font_description_from_string( font ) ); // pango_layout_set_spacing( layout, space ); pango_layout_set_alignment( layout, ( PangoAlignment ) align ); - pango_layout_set_markup( layout, markup, (markup == NULL ? 0 : strlen( markup ) ) ); + if ( markup != NULL && strcmp( markup, "" ) != 0 ) + pango_layout_set_markup( layout, markup, strlen( markup ) ); + else if ( text != NULL && strcmp( text, "" ) != 0 ) + pango_layout_set_text( layout, text, strlen( text ) ); + else + return NULL; pango_layout_get_pixel_size( layout, &w, &h ); pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE /* has alpha */, 8, w + 2 * pad, h + 2 * pad ); diff --git a/src/modules/gtk2/producer_pango.h b/src/modules/gtk2/producer_pango.h index 1e2b1c8..ade1977 100644 --- a/src/modules/gtk2/producer_pango.h +++ b/src/modules/gtk2/producer_pango.h @@ -25,16 +25,6 @@ typedef struct producer_pango_s *producer_pango; -struct producer_pango_s -{ - struct mlt_producer_s parent; - char *markup; - int width; - int height; - uint8_t *image; - uint8_t *alpha; -}; - typedef enum { pango_align_left = 0, diff --git a/src/tests/dan.c b/src/tests/dan.c index cdfd211..8e499bc 100644 --- a/src/tests/dan.c +++ b/src/tests/dan.c @@ -18,8 +18,8 @@ int main( int argc, char **argv ) // Start the consumer... int vstd = mlt_video_standard_ntsc; - mlt_consumer consumer = mlt_factory_consumer( "bluefish", &vstd ); - mlt_properties_set_int( mlt_consumer_properties( consumer ), "video_standard", mlt_video_standard_ntsc ); + //mlt_consumer consumer = mlt_factory_consumer( "bluefish", &vstd ); + mlt_consumer consumer = mlt_factory_consumer( "sdl", "NTSC" ); // Create the producer(s) mlt_producer dv1 = mlt_factory_producer( "mcmpeg", file1 ); @@ -38,10 +38,15 @@ int main( int argc, char **argv ) //mlt_producer dv1 = producer_pixbuf_init( file1 ); //mlt_producer dv2 = producer_libdv_init( file2 ); //mlt_producer dv2 = mlt_factory_producer( "pixbuf", file2 ); - mlt_producer dv2 = mlt_factory_producer( "pango", "Mutton Lettuce Tomato" ); + mlt_producer dv2 = mlt_factory_producer( "pango", NULL ); //"Mutton Lettuce Tomato" ); + mlt_properties_set( mlt_producer_properties( dv2 ), "font", "Sans Bold 36" ); + mlt_properties_set( mlt_producer_properties( dv2 ), "text", "Mutton Lettuce\nTomato" ); mlt_properties_set_int( mlt_producer_properties( dv2 ), "video_standard", mlt_video_standard_ntsc ); mlt_properties_set_int( mlt_producer_properties( dv2 ), "bgcolor", 0x0000007f ); mlt_properties_set_int( mlt_producer_properties( dv2 ), "pad", 8 ); + mlt_properties_set_int( mlt_producer_properties( dv2 ), "align", 1 ); + mlt_properties_set_int( mlt_producer_properties( dv2 ), "x", -20 ); + mlt_properties_set_int( mlt_producer_properties( dv2 ), "y", 40 ); // Register producers(s) with a multitrack object mlt_multitrack multitrack = mlt_multitrack_init( ); @@ -49,14 +54,14 @@ int main( int argc, char **argv ) mlt_multitrack_connect( multitrack, dv2, 1 ); // Create a filter and associate it to track 0 -// mlt_filter filter = mlt_factory_filter( "deinterlace", NULL ); -// mlt_filter_connect( filter, mlt_multitrack_service( multitrack ), 0 ); -// mlt_filter_set_in_and_out( filter, 0, 1000 ); + mlt_filter filter = mlt_factory_filter( "deinterlace", NULL ); + mlt_filter_connect( filter, mlt_multitrack_service( multitrack ), 0 ); + mlt_filter_set_in_and_out( filter, 0, 1000 ); // Define a transition mlt_transition transition = mlt_factory_transition( "composite", NULL ); - mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 ); - mlt_transition_set_in_and_out( transition, 0, 1000 ); + mlt_transition_connect( transition, mlt_filter_service( filter ), 0, 1 ); + mlt_transition_set_in_and_out( transition, 0, 5.0 ); // Buy a tractor and connect it to the filter mlt_tractor tractor = mlt_tractor_init( ); @@ -69,6 +74,13 @@ int main( int argc, char **argv ) fprintf( stderr, "Press return to continue\n" ); fgets( temp, 132, stdin ); + mlt_properties_set( mlt_producer_properties( dv2 ), "font", "Sans Oblique 36" ); + mlt_properties_set( mlt_producer_properties( dv2 ), "text", "Mutton\nLettuce Tomato" ); + + // Do stuff until we're told otherwise... + fprintf( stderr, "Press return to continue\n" ); + fgets( temp, 132, stdin ); + // Close everything... mlt_consumer_close( consumer ); mlt_tractor_close( tractor );