OBJS = albino.o
-CFLAGS = -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
+CFLAGS = -O3 -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
LDFLAGS = -L ../valerie -L ../miracle -L ../framework -lmiracle -lmlt -lvalerie
SRCS := $(OBJS:.o=.c)
-CFLAGS = -g -Wall -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = -g -O3 -Wall -D_FILE_OFFSET_BITS=64 -pthread
LDFLAGS = -lm -ldl -lpthread
// Deal with it now.
if ( test_card != NULL )
{
- // Create a test card producer
- // TODO: do we want to use fezzik here?
- mlt_producer producer = mlt_factory_producer( "fezzik", test_card );
-
- // Do we have a producer
- if ( producer != NULL )
+ if ( mlt_properties_get_data( properties, "test_card_producer", NULL ) == NULL )
{
- // Set the test card on the consumer
- mlt_properties_set_data( properties, "test_card_producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
+ // Create a test card producer
+ // TODO: do we want to use fezzik here?
+ mlt_producer producer = mlt_factory_producer( "fezzik", test_card );
+
+ // Do we have a producer
+ if ( producer != NULL )
+ {
+ // Test card should loop I guess...
+ mlt_properties_set( mlt_producer_properties( producer ), "eof", "loop" );
+
+ // Set the test card on the consumer
+ mlt_properties_set_data( properties, "test_card_producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
+ }
+
+ // Check and run an ante command
+ if ( mlt_properties_get( properties, "ante" ) )
+ system( mlt_properties_get( properties, "ante" ) );
}
}
// Stop the consumer
if ( this->stop != NULL )
- return this->stop( this );
+ this->stop( this );
// Kill the test card
mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
+ // Check and run a post command
+ if ( mlt_properties_get( properties, "post" ) )
+ system( mlt_properties_get( properties, "post" ) );
+
return 0;
}
int mlt_consumer_is_stopped( mlt_consumer this )
{
- // Stop the consumer
+ // Check if the consumer is stopped
if ( this->is_stopped != NULL )
return this->is_stopped( this );
return &this->parent;
}
+/** Get the properties associated to this filter.
+*/
+
mlt_properties mlt_filter_properties( mlt_filter this )
{
return mlt_service_properties( mlt_filter_service( this ) );
/** Process the frame.
*/
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+mlt_frame mlt_filter_process( mlt_filter this, mlt_frame frame )
{
if ( this->process == NULL )
return frame;
{
mlt_position position = mlt_frame_get_position( *frame );
if ( position >= in && ( out == 0 || position < out ) )
- *frame = filter_process( this, *frame );
+ *frame = mlt_filter_process( this, *frame );
return 0;
}
else
extern int mlt_filter_init( mlt_filter this, void *child );
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 );
extern int mlt_filter_connect( mlt_filter this, mlt_service producer, int index );
extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out );
extern int mlt_filter_get_track( mlt_filter this );
if ( this != NULL )
{
+ // Get the normalisation
+ char *normalisation = getenv( "MLT_NORMALISATION" );
+
// Initialise the properties
mlt_properties properties = &this->parent;
mlt_properties_init( properties, this );
// Set default properties on the frame
mlt_properties_set_position( properties, "_position", 0.0 );
mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
- mlt_properties_set_int( properties, "width", 720 );
- mlt_properties_set_int( properties, "height", 576 );
+
+ if ( normalisation == NULL || strcmp( normalisation, "NTSC" ) )
+ {
+ mlt_properties_set_int( properties, "width", 720 );
+ mlt_properties_set_int( properties, "height", 576 );
+ mlt_properties_set_int( properties, "normalised_width", 720 );
+ mlt_properties_set_int( properties, "normalised_height", 576 );
+ }
+ else
+ {
+ mlt_properties_set_int( properties, "width", 720 );
+ mlt_properties_set_int( properties, "height", 480 );
+ mlt_properties_set_int( properties, "normalised_width", 720 );
+ mlt_properties_set_int( properties, "normalised_height", 480 );
+ }
+
mlt_properties_set_double( properties, "aspect_ratio", 4.0 / 3.0 );
mlt_properties_set_data( properties, "audio", NULL, 0, NULL, NULL );
mlt_properties_set_data( properties, "alpha", NULL, 0, NULL, NULL );
+
+
}
return this;
}
mlt_service_get_frame( mlt_producer_service( producer ), &test_frame, 0 );
if ( test_frame != NULL )
{
+ mlt_properties test_properties = mlt_frame_properties( test_frame );
+ mlt_properties_set_double( test_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
+ mlt_properties_set_double( test_properties, "consumer_scale", mlt_properties_get_double( properties, "consumer_scale" ) );
+ mlt_properties_set( test_properties, "rescale.interp", "nearest" );
mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
- mlt_properties_inherit( mlt_frame_properties( this ), mlt_frame_properties( test_frame ) );
+ mlt_properties_inherit( properties, test_properties );
mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
-
mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
mlt_properties_set_int( properties, "width", *width );
mlt_properties_set_int( properties, "height", *height );
return ret;
}
-void *memfill( void *dst, void *src, int l, int elements )
-{
- int i = 0;
- if ( l == 2 )
- {
- uint8_t *p = dst;
- uint8_t *src1 = src;
- uint8_t *src2 = src + 1;
- for ( i = 0; i < elements; i ++ )
- {
- *p ++ = *src1;
- *p ++ = *src2;
- }
- dst = p;
- }
- else
- {
- for ( i = 0; i < elements; i ++ )
- dst = memcpy( dst, src, l ) + l;
- }
- return dst;
-}
-
void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight )
{
// Calculate strides
uint8_t *in_middle = input + istride * ( iheight / 2 ) + ( iwidth / 2 ) * 2;
int in_line = - in_y_range * istride - in_x_range * 2;
- uint8_t black[ 2 ] = { 16, 128 };
+ uint8_t black[ 2 ] = { 0, 128 };
+ int elements;
+
+ // Fill whole section with black
+ y = out_y_range - ( iheight / 2 );
+ int blank_elements = ostride * y / 2;
+ elements = blank_elements;
+ while ( elements -- )
+ {
+ *out_line ++ = black[ 0 ];
+ *out_line ++ = black[ 1 ];
+ }
+
+ int active_width = 2 * iwidth;
+ int inactive_width = out_x_range - in_x_range;
// Loop for the entirety of our output height.
- for ( y = - out_y_range; y < out_y_range ; y ++ )
+ while ( iheight -- )
{
// Start at the beginning of the line
out_ptr = out_line;
- if ( abs( y ) < iheight / 2 )
+ // Fill the outer part with black
+ elements = inactive_width;
+ while ( elements -- )
{
- // Fill the outer part with black
- out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
-
- // We're in the input range for this row.
- memcpy( out_ptr, in_middle + in_line, 2 * iwidth );
- out_ptr += 2 * iwidth;
+ *out_ptr ++ = black[ 0 ];
+ *out_ptr ++ = black[ 1 ];
+ }
- // Fill the outer part with black
- out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
+ // We're in the input range for this row.
+ memcpy( out_ptr, in_middle + in_line, active_width );
+ out_ptr += active_width;
- // Move to next input line
- in_line += istride;
- }
- else
+ // Fill the outer part with black
+ elements = inactive_width;
+ while ( elements -- )
{
- // Fill whole line with black
- out_ptr = memfill( out_ptr, black, 2, owidth );
+ *out_ptr ++ = black[ 0 ];
+ *out_ptr ++ = black[ 1 ];
}
+ // Move to next input line
+ in_line += istride;
+
// Move to next output line
out_line += ostride;
}
+
+ // Fill whole section with black
+ elements = blank_elements;
+ while ( elements -- )
+ {
+ *out_line ++ = black[ 0 ];
+ *out_line ++ = black[ 1 ];
+ }
}
/** A resizing function for yuv422 frames - this does not rescale, but simply
strcpy( value, "" );
}
+ if ( strlen( value ) > 1 && value[ 0 ] == '\"' )
+ {
+ strcpy( value, value + 1 );
+ if ( value[ strlen( value ) - 1 ] == '\"' )
+ value[ strlen( value ) - 1 ] = '\0';
+ }
+
error = mlt_properties_set( this, name, value );
free( name );
io.o \
remote.o
-CFLAGS = -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
+CFLAGS = -O3 -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
LDFLAGS = -L ../valerie -lvalerie
OBJS = inigo.o \
io.o
-CFLAGS = -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
+CFLAGS = -O3 -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
LDFLAGS = -L ../framework -lmlt
OBJS = $(APP_OBJS) $(LIB_OBJS)
-CFLAGS = -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
+CFLAGS = -O3 -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
LDFLAGS = -L ../valerie -lvalerie -L ../framework -lmlt
ATYPE_NONE,
ATYPE_FLOAT,
ATYPE_STRING,
- ATYPE_INT
+ ATYPE_INT,
+ ATYPE_PAIR
}
arguments_types;
{"UADD", miracle_add_unit, 0, ATYPE_STRING, "Create a new DV unit (virtual VTR) to transmit to receiver specified in GUID argument."},
{"ULS", miracle_list_units, 0, ATYPE_NONE, "Lists the units that have already been added to the server."},
{"CLS", miracle_list_clips, 0, ATYPE_STRING, "Lists the clips at directory name argument."},
- {"SET", miracle_set_global_property, 0, ATYPE_STRING, "Set a server configuration property."},
+ {"SET", miracle_set_global_property, 0, ATYPE_PAIR, "Set a server configuration property."},
{"GET", miracle_get_global_property, 0, ATYPE_STRING, "Get a server configuration property."},
{"RUN", miracle_run, 0, ATYPE_STRING, "Run a batch file." },
{"LIST", miracle_list, 1, ATYPE_NONE, "List the playlist associated to a unit."},
{"SIN", miracle_set_in_point, 1, ATYPE_INT, "Set the IN point of the loaded clip to frame number argument. -1 = reset in point to 0"},
{"SOUT", miracle_set_out_point, 1, ATYPE_INT, "Set the OUT point of the loaded clip to frame number argument. -1 = reset out point to maximum."},
{"USTA", miracle_get_unit_status, 1, ATYPE_NONE, "Report information about the unit."},
- {"USET", miracle_set_unit_property, 1, ATYPE_STRING, "Set a unit configuration property."},
+ {"USET", miracle_set_unit_property, 1, ATYPE_PAIR, "Set a unit configuration property."},
{"UGET", miracle_get_unit_property, 1, ATYPE_STRING, "Get a unit configuration property."},
{"XFER", miracle_transfer, 1, ATYPE_STRING, "Transfer the unit's clip to another unit specified as argument."},
{"SHUTDOWN", miracle_shutdown, 0, ATYPE_NONE, "Shutdown the server."},
/** Parse a normal argument.
*/
-void *miracle_command_parse_argument( command_argument cmd, int argument, arguments_types type )
+void *miracle_command_parse_argument( command_argument cmd, int argument, arguments_types type, char *command )
{
void *ret = NULL;
char *value = valerie_tokeniser_get_string( cmd->tokeniser, argument );
ret = strdup( value );
break;
+ case ATYPE_PAIR:
+ if ( strchr( command, '=' ) )
+ {
+ char *ptr = strchr( command, '=' );
+ while ( *( ptr - 1 ) != ' ' )
+ ptr --;
+ ret = strdup( ptr );
+ ptr = ret;
+ while( ptr[ strlen( ptr ) - 1 ] == ' ' )
+ ptr[ strlen( ptr ) - 1 ] = '\0';
+ }
+ break;
+
case ATYPE_INT:
ret = malloc( sizeof( int ) );
if ( ret != NULL )
if ( miracle_command_get_error( &cmd ) == RESPONSE_SUCCESS )
{
- cmd.argument = miracle_command_parse_argument( &cmd, position, vocabulary[ index ].type );
+ cmd.argument = miracle_command_parse_argument( &cmd, position, vocabulary[ index ].type, command );
if ( cmd.argument == NULL && vocabulary[ index ].type != ATYPE_NONE )
miracle_command_set_error( &cmd, RESPONSE_MISSING_ARG );
position ++;
void miracle_unit_terminate( miracle_unit unit )
{
mlt_consumer consumer = mlt_properties_get_data( unit->properties, "consumer", NULL );
+ mlt_playlist playlist = mlt_properties_get_data( unit->properties, "playlist", NULL );
+ mlt_producer producer = mlt_playlist_producer( playlist );
+ mlt_producer_set_speed( producer, 0 );
mlt_consumer_stop( consumer );
miracle_unit_status_communicate( unit );
}
if ( unit == NULL )
return RESPONSE_INVALID_UNIT;
else
- {
- miracle_unit_play( unit, 0 );
miracle_unit_terminate( unit );
- }
return RESPONSE_SUCCESS;
}
OBJS = factory.o \
producer_avformat.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64
LDFLAGS = -lavformat -lavcodec
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
+#include <math.h>
// Forward references.
static int producer_open( mlt_producer this, char *file );
// Current time calcs
double current_time = 0;
+ // We may want to use the source fps if available
+ double source_fps = mlt_properties_get_double( properties, "source_fps" );
+
// Set the result arguments that we know here (only *buffer is now required)
*format = mlt_image_yuv422;
*width = codec_context->width;
// Duplicate the last image if necessary
if ( mlt_properties_get_data( properties, "current_image", NULL ) != NULL &&
- ( paused || mlt_properties_get_double( properties, "current_time" ) > real_timecode ) )
+ ( paused || mlt_properties_get_double( properties, "current_time" ) >= real_timecode ) )
{
// Get current image and size
int size = 0;
// We only deal with video from the selected video_index
if ( ret >= 0 && pkt.stream_index == index && pkt.size > 0 )
{
+ current_time = ( double )pkt.pts / 1000000.0;
+
// Decode the image
// Wouldn't it be great if I could use this...
//if ( (float)pkt.pts / 1000000.0 >= real_timecode )
ret = avcodec_decode_video( codec_context, &frame, &got_picture, pkt.data, pkt.size );
- // Handle ignore
- if ( (float)pkt.pts / 1000000.0 < real_timecode )
- {
- ignore = 0;
- got_picture = 0;
- }
- else if ( (float)pkt.pts / 1000000.0 >= real_timecode )
+ if ( got_picture )
{
- ignore = 0;
- }
- else if ( got_picture && ignore -- )
- {
- got_picture = 0;
+ // Handle ignore
+ if ( current_time < real_timecode )
+ {
+ ignore = 0;
+ got_picture = 0;
+ }
+ else if ( current_time >= real_timecode )
+ {
+ ignore = 0;
+ }
+ else if ( got_picture && ignore -- )
+ {
+ got_picture = 0;
+ }
}
-
- current_time = ( double )pkt.pts / 1000000.0;
}
// We're finished with this packet regardless
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_double( properties, "current_time", current_time );
+
+ if ( current_time == 0 && source_fps != 0 )
+ {
+ double fps = mlt_properties_get_double( properties, "fps" );
+ current_time = ceil( source_fps * ( double )position / fps ) * ( 1 / source_fps );
+ mlt_properties_set_double( properties, "current_time", current_time );
+ }
+ else
+ {
+ mlt_properties_set_double( properties, "current_time", current_time );
+ }
}
}
if ( codec != NULL && avcodec_open( codec_context, codec ) >= 0 )
{
double aspect_ratio = 0;
+ double source_fps = 0;
// Set aspect ratio
- fprintf( stderr, "AVFORMAT: sample aspect %d\n", codec_context->sample_aspect_ratio.num );
if ( codec_context->sample_aspect_ratio.num == 0)
aspect_ratio = 0;
else
aspect_ratio = ( double )codec_context->width / ( double )codec_context->height;
mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio );
+ fprintf( stderr, "AVFORMAT: sample aspect %f\n", aspect_ratio );
+
+ // Determine the fps
+ source_fps = ( double )codec_context->frame_rate / codec_context->frame_rate_base;
+
+ // We'll use fps if it's available
+ if ( source_fps > 0 && source_fps < 30 )
+ mlt_properties_set_double( properties, "source_fps", source_fps );
// Now store the codec with its destructor
mlt_properties_set_data( properties, "video_codec", codec_context, 0, producer_codec_close, NULL );
// Flag for paused (silence)
int paused = 0;
+ int locked = 0;
// Lock the mutex now
pthread_mutex_lock( &avformat_mutex );
// Clear the usage in the audio buffer
audio_used = 0;
+
+ locked = 1;
}
}
uint8_t *ptr = pkt.data;
int data_size;
- if ( ptr == NULL || len == 0 )
- break;
-
// We only deal with video from the selected video_index
- while ( ret >= 0 && pkt.stream_index == index && len > 0 )
+ while ( ptr != NULL && ret >= 0 && pkt.stream_index == index && len > 0 )
{
// Decode the audio
ret = avcodec_decode_audio( codec_context, temp, &data_size, ptr, len );
if ( ret < 0 )
+ {
+ ret = 0;
break;
+ }
len -= ret;
ptr += ret;
// If we're behind, ignore this packet
float current_pts = (float)pkt.pts / 1000000.0;
double discrepancy = mlt_properties_get_double( properties, "discrepancy" );
- if ( discrepancy * current_pts < real_timecode )
+ if ( current_pts != 0 && real_timecode != 0 )
+ {
+ if ( discrepancy != 1 )
+ discrepancy = ( discrepancy + ( real_timecode / current_pts ) ) / 2;
+ else
+ discrepancy = real_timecode / current_pts;
+ if ( discrepancy > 0.9 && discrepancy < 1.1 )
+ discrepancy = 1.0;
+ else
+ discrepancy = floor( discrepancy + 0.5 );
+
+ if ( discrepancy == 0 )
+ discrepancy = 1.0;
+
+ mlt_properties_set_double( properties, "discrepancy", discrepancy );
+ }
+
+ if ( discrepancy * current_pts <= ( real_timecode - 0.02 ) )
ignore = 1;
}
}
// Now handle the audio if we have enough
-
if ( audio_used >= *samples )
{
*buffer = malloc( *samples * *channels * sizeof( int16_t ) );
{
// Now store the codec with its destructor
mlt_properties_set_data( properties, "audio_codec", codec_context, 0, producer_codec_close, NULL );
+
}
else
{
transition_mix.o \
filter_brightness.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
SRCS := $(OBJS:.o=.c)
struct geometry_s
{
+ int nw;
+ int nh;
float x;
float y;
float w;
int mask_h;
};
+/** Parse a value from a geometry string.
+*/
+
+static float parse_value( char **ptr, int normalisation, char delim, float defaults )
+{
+ float value = defaults;
+
+ if ( *ptr != NULL && **ptr != '\0' )
+ {
+ char *end = NULL;
+ value = strtod( *ptr, &end );
+ if ( end != NULL )
+ {
+ if ( *end == '%' )
+ value = ( value / 100.0 ) * normalisation;
+ while ( *end == delim || *end == '%' )
+ end ++;
+ }
+ *ptr = end;
+ }
+
+ return value;
+}
+
/** Parse a geometry property string.
*/
-static void geometry_parse( struct geometry_s *geometry, struct geometry_s *defaults, char *property )
+static void geometry_parse( struct geometry_s *geometry, struct geometry_s *defaults, char *property, int nw, int nh )
{
+ // Assign normalised width and height
+ geometry->nw = nw;
+ geometry->nh = nh;
+
// Assign from defaults if available
if ( defaults != NULL )
{
// Parse the geomtry string
if ( property != NULL )
- sscanf( property, "%f,%f:%fx%f:%dx%d", &geometry->x, &geometry->y, &geometry->w, &geometry->h, &geometry->mask_w, &geometry->mask_h );
+ {
+ char *ptr = property;
+ geometry->x = parse_value( &ptr, nw, ',', geometry->x );
+ geometry->y = parse_value( &ptr, nh, ':', geometry->y );
+ geometry->w = parse_value( &ptr, nw, 'x', geometry->w );
+ geometry->h = parse_value( &ptr, nh, ':', geometry->h );
+ geometry->mask_w = parse_value( &ptr, nw, 'x', geometry->mask_w );
+ geometry->mask_h = parse_value( &ptr, nh, ' ', geometry->mask_h );
+ }
}
/** A Timism but not as clean ;-).
/** Calculate real geometry.
*/
-static void geometry_calculate( struct geometry_s *output, struct geometry_s *in, struct geometry_s *out, float position )
+static void geometry_calculate( struct geometry_s *output, struct geometry_s *in, struct geometry_s *out, float position, int ow, int oh )
{
// Calculate this frames geometry
- output->x = lerp( in->x + ( out->x - in->x ) * position, 0, 100 );
- output->y = lerp( in->y + ( out->y - in->y ) * position, 0, 100 );
- output->w = lerp( in->w + ( out->w - in->w ) * position, 0, 100 - output->x );
- output->h = lerp( in->h + ( out->h - in->h ) * position, 0, 100 - output->y );
+ output->x = lerp( ( in->x + ( out->x - in->x ) * position ) / ( float )out->nw * ow, 0, ow );
+ output->y = lerp( ( in->y + ( out->y - in->y ) * position ) / ( float )out->nh * oh, 0, oh );
+ output->w = lerp( ( in->w + ( out->w - in->w ) * position ) / ( float )out->nw * ow, 0, ow - output->x );
+ output->h = lerp( ( in->h + ( out->h - in->h ) * position ) / ( float )out->nh * oh, 0, oh - output->y );
output->mask_w = in->mask_w + ( out->mask_w - in->mask_w ) * position;
output->mask_h = in->mask_h + ( out->mask_h - in->mask_h ) * position;
}
static void obscure_render( uint8_t *image, int width, int height, struct geometry_s result )
{
- int area_x = ( result.x / 100 ) * width;
- int area_y = ( result.y / 100 ) * height;
- int area_w = ( result.w / 100 ) * width;
- int area_h = ( result.h / 100 ) * height;
+ int area_x = result.x;
+ int area_y = result.y;
+ int area_w = result.w;
+ int area_h = result.h;
int mw = result.mask_w;
int mh = result.mask_h;
// Get the filter properties
mlt_properties properties = mlt_filter_properties( this );
+ // Obtain the normalised width and height from the frame
+ int normalised_width = mlt_properties_get_int( frame_properties, "normalised_width" );
+ int normalised_height = mlt_properties_get_int( frame_properties, "normalised_height" );
+
// Structures for geometry
struct geometry_s result;
struct geometry_s start;
float position = position_calculate( this, frame );
// Now parse the geometries
- geometry_parse( &start, NULL, mlt_properties_get( properties, "start" ) );
- geometry_parse( &end, &start, mlt_properties_get( properties, "end" ) );
+ geometry_parse( &start, NULL, mlt_properties_get( properties, "start" ), normalised_width, normalised_height );
+ geometry_parse( &end, &start, mlt_properties_get( properties, "end" ), normalised_width, normalised_height );
// Do the calculation
- geometry_calculate( &result, &start, &end, position );
+ geometry_calculate( &result, &start, &end, position, *width, *height );
// Now actually render it
obscure_render( *image, *width, *height, result );
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:100x100" );
+ mlt_properties_set( properties, "start", arg != NULL ? arg : "0%,0%:100%x100%" );
mlt_properties_set( properties, "end", "" );
return this;
}
#include <string.h>
#include <stdlib.h>
+static int get_value( mlt_properties properties, char *preferred, char *fallback )
+{
+ int value = mlt_properties_get_int( properties, preferred );
+ if ( value == 0 )
+ value = mlt_properties_get_int( properties, fallback );
+ return value;
+}
+
/** Do it :-).
*/
static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
+ // Get the properties from the frame
mlt_properties properties = mlt_frame_properties( this );
+
+ // Assign requested width/height from our subordinate
int owidth = *width;
int oheight = *height;
+
+ if ( mlt_properties_get( properties, "distort" ) == NULL )
+ {
+ // Now do additional calcs based on real_width/height etc
+ int normalised_width = mlt_properties_get_int( properties, "normalised_width" );
+ int normalised_height = mlt_properties_get_int( properties, "normalised_height" );
+ int real_width = get_value( properties, "real_width", "width" );
+ int real_height = get_value( properties, "real_height", "height" );
+ double input_ar = mlt_frame_get_aspect_ratio( this );
+ double output_ar = mlt_properties_get_double( properties, "consumer_aspect_ratio" );
+ int scaled_width = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_width;
+ int scaled_height = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_height;
+
+ // Now ensure that our images fit in the normalised frame
+ if ( scaled_width > normalised_width )
+ {
+ scaled_height = scaled_height * normalised_width / scaled_width;
+ scaled_width = normalised_width;
+ }
+ if ( scaled_height > normalised_height )
+ {
+ scaled_width = scaled_width * normalised_height / scaled_height;
+ scaled_height = normalised_height;
+ }
+
+ if ( input_ar == output_ar && scaled_height == normalised_height )
+ scaled_width = normalised_width;
+ // Now calculate the actual image size that we want
+ owidth = scaled_width * owidth / normalised_width;
+ oheight = scaled_height * oheight / normalised_height;
+ }
+
+ // Now pass on the calculations down the line
+ mlt_properties_set_int( properties, "resize_width", *width );
+ mlt_properties_set_int( properties, "resize_height", *height );
+
+ // Now get the image
mlt_frame_get_image( this, image, format, &owidth, &oheight, writable );
- if ( *width == 0 )
- *width = 720;
- if ( *height == 0 )
- *height = 576;
-
// Correct field order if needed
if ( mlt_properties_get_int( properties, "top_field_first" ) == 1 )
{
struct geometry_s
{
+ int nw;
+ int nh;
float x;
float y;
float w;
float mix;
};
-/** Parse a geometry property string.
+/** Parse a value from a geometry string.
*/
-static void geometry_parse( struct geometry_s *geometry, struct geometry_s *defaults, char *property )
+static float parse_value( char **ptr, int normalisation, char delim, float defaults )
{
+ float value = defaults;
+
+ if ( *ptr != NULL && **ptr != '\0' )
+ {
+ char *end = NULL;
+ value = strtod( *ptr, &end );
+ if ( end != NULL )
+ {
+ if ( *end == '%' )
+ value = ( value / 100.0 ) * normalisation;
+ while ( *end == delim || *end == '%' )
+ end ++;
+ }
+ *ptr = end;
+ }
+
+ return value;
+}
+
+/** Parse a geometry property string with the syntax X,Y:WxH:MIX. Any value can be
+ expressed as a percentage by appending a % after the value, otherwise values are
+ assumed to be relative to the normalised dimensions of the consumer.
+*/
+
+static void geometry_parse( struct geometry_s *geometry, struct geometry_s *defaults, char *property, int nw, int nh )
+{
+ // Assign normalised width and height
+ geometry->nw = nw;
+ geometry->nh = nh;
+
// Assign from defaults if available
if ( defaults != NULL )
{
// Parse the geomtry string
if ( property != NULL )
- sscanf( property, "%f,%f:%fx%f:%f", &geometry->x, &geometry->y, &geometry->w, &geometry->h, &geometry->mix );
+ {
+ char *ptr = property;
+ geometry->x = parse_value( &ptr, nw, ',', geometry->x );
+ geometry->y = parse_value( &ptr, nh, ':', geometry->y );
+ geometry->w = parse_value( &ptr, nw, 'x', geometry->w );
+ geometry->h = parse_value( &ptr, nh, ':', geometry->h );
+ geometry->mix = parse_value( &ptr, 100, ' ', geometry->mix );
+ }
}
/** Calculate real geometry.
static void geometry_calculate( struct geometry_s *output, struct geometry_s *in, struct geometry_s *out, float position )
{
// Calculate this frames geometry
+ output->nw = in->nw;
+ output->nh = in->nh;
output->x = in->x + ( out->x - in->x ) * position;
output->y = in->y + ( out->y - in->y ) * position;
output->w = in->w + ( out->w - in->w ) * position;
return ( float )( position - in ) / ( float )( out - in + 1 );
}
+static int get_value( mlt_properties properties, char *preferred, char *fallback )
+{
+ int value = mlt_properties_get_int( properties, preferred );
+ if ( value == 0 )
+ value = mlt_properties_get_int( properties, fallback );
+ return value;
+}
+
/** Composite function.
*/
int x_src = 0, y_src = 0;
mlt_image_format format_src = format_dest;
- int x = ( int )( ( float )width_dest * geometry.x / 100 );
- int y = ( int )( ( float )height_dest * geometry.y / 100 );
float weight = geometry.mix / 100;
// Compute the dimensioning rectangle
- int width_src = ( int )( ( float )width_dest * geometry.w / 100 );
- int height_src = ( int )( ( float )height_dest * geometry.h / 100 );
-
mlt_properties b_props = mlt_frame_properties( that );
mlt_transition this = mlt_properties_get_data( b_props, "transition_composite", NULL );
mlt_properties properties = mlt_transition_properties( this );
- if ( mlt_properties_get( properties, "distort" ) == NULL &&
- mlt_properties_get( mlt_frame_properties( that ), "real_width" ) != NULL )
+ if ( mlt_properties_get( properties, "distort" ) == NULL )
{
- int width_b = mlt_properties_get_double( b_props, "real_width" );
- int height_b = mlt_properties_get_double( b_props, "real_height" );
-
- // Maximise the dimensioning rectangle to the aspect of the b_frame
- if ( mlt_properties_get_double( b_props, "aspect_ratio" ) * height_src > width_src )
- height_src = ( double )width_src / mlt_properties_get_double( b_props, "aspect_ratio" ) + 0.5;
- else
- width_src = mlt_properties_get_double( b_props, "aspect_ratio" ) * height_src + 0.5;
-
- // See if we need to normalise pixel aspect ratio
- // We can use consumer_aspect_ratio because the a_frame will take on this aspect
- double aspect = mlt_properties_get_double( b_props, "consumer_aspect_ratio" );
- if ( aspect != 0 )
+ // Now do additional calcs based on real_width/height etc
+ //int normalised_width = mlt_properties_get_int( b_props, "normalised_width" );
+ //int normalised_height = mlt_properties_get_int( b_props, "normalised_height" );
+ int normalised_width = geometry.w;
+ int normalised_height = geometry.h;
+ int real_width = get_value( b_props, "real_width", "width" );
+ int real_height = get_value( b_props, "real_height", "height" );
+ double input_ar = mlt_frame_get_aspect_ratio( that );
+ double output_ar = mlt_properties_get_double( b_props, "consumer_aspect_ratio" );
+ int scaled_width = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_width;
+ int scaled_height = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_height;
+
+ // Now ensure that our images fit in the normalised frame
+ if ( scaled_width > normalised_width )
{
- // Derive the consumer pixel aspect
- double oaspect = aspect / ( double )width_dest * height_dest;
-
- // Get the b frame pixel aspect - usually 1
- double iaspect = mlt_properties_get_double( b_props, "aspect_ratio" ) / width_b * height_b;
-
- // Normalise pixel aspect
- if ( iaspect != 0 && iaspect != oaspect )
- {
- width_b = iaspect / oaspect * ( double )width_b + 0.5;
- width_src = iaspect / oaspect * ( double )width_src + 0.5;
- }
-
- // Tell rescale not to normalise display aspect
- mlt_frame_set_aspect_ratio( that, aspect );
+ scaled_height = scaled_height * normalised_width / scaled_width;
+ scaled_width = normalised_width;
}
-
- // Adjust overall scale for consumer
- double consumer_scale = mlt_properties_get_double( b_props, "consumer_scale" );
- if ( consumer_scale > 0 )
+ if ( scaled_height > normalised_height )
{
- width_b = consumer_scale * width_b + 0.5;
- height_b = consumer_scale * height_b + 0.5;
+ scaled_width = scaled_width * normalised_height / scaled_height;
+ scaled_height = normalised_height;
}
-// fprintf( stderr, "bounding rect %dx%d for overlay %dx%d\n", width_src, height_src, width_b, height_b );
- // Constrain the overlay to the dimensioning rectangle
- if ( width_b < width_src && height_b < height_src )
+ // Special case
+ if ( scaled_height == normalised_height )
+ scaled_width = normalised_width;
+
+ // Now we need to align to the geometry
+ if ( scaled_width <= geometry.w && scaled_height <= geometry.h )
{
- width_src = width_b;
- height_src = height_b;
+ // TODO: Should take into account requested alignment here...
+ // Assume centred alignment for now
+
+ geometry.x = geometry.x + ( geometry.w - scaled_width ) / 2;
+ geometry.y = geometry.y + ( geometry.h - scaled_height ) / 2;
+ geometry.w = scaled_width;
+ geometry.h = scaled_height;
+ mlt_properties_set( b_props, "distort", "true" );
+ }
+ else
+ {
+ mlt_properties_set( b_props, "distort", "true" );
}
}
- else if ( mlt_properties_get( b_props, "real_width" ) != NULL )
+ else
{
- // Tell rescale not to normalise display aspect
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", 0 );
+ // We want to ensure that we bypass resize now...
+ mlt_properties_set( b_props, "distort", "true" );
}
+ int x = ( geometry.x * width_dest ) / geometry.nw;
+ int y = ( geometry.y * height_dest ) / geometry.nh;
+ int width_src = ( geometry.w * width_dest ) / geometry.nw;
+ int height_src = ( geometry.h * height_dest ) / geometry.nh;
+
x -= x % 2;
// optimization points - no work to do
if ( b_frame != NULL )
{
+ // Get the properties of the a frame
+ mlt_properties a_props = mlt_frame_properties( a_frame );
+
// Get the properties of the b frame
mlt_properties b_props = mlt_frame_properties( b_frame );
// Calculate the position
float position = position_calculate( this, a_frame );
+ // Obtain the normalised width and height from the a_frame
+ int normalised_width = mlt_properties_get_int( a_props, "normalised_width" );
+ int normalised_height = mlt_properties_get_int( a_props, "normalised_height" );
+
// Now parse the geometries
- geometry_parse( &start, NULL, mlt_properties_get( properties, "start" ) );
- geometry_parse( &end, &start, mlt_properties_get( properties, "end" ) );
+ geometry_parse( &start, NULL, mlt_properties_get( properties, "start" ), normalised_width, normalised_height );
+ geometry_parse( &end, &start, mlt_properties_get( properties, "end" ), normalised_width, normalised_height );
// Do the calculation
geometry_calculate( &result, &start, &end, position );
// Since we are the consumer of the b_frame, we must pass along these
// consumer properties from the a_frame
- mlt_properties_set_double( b_props, "consumer_aspect_ratio",
- mlt_properties_get_double( mlt_frame_properties( a_frame ), "consumer_aspect_ratio" ) );
- mlt_properties_set_double( b_props, "consumer_scale",
- mlt_properties_get_double( mlt_frame_properties( a_frame ), "consumer_scale" ) );
+ mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
+ mlt_properties_set_double( b_props, "consumer_scale", mlt_properties_get_double( a_props, "consumer_scale" ) );
// Composite the b_frame on the a_frame
composite_yuv( *image, *format, *width, *height, b_frame, result );
if ( this != NULL && mlt_transition_init( this, NULL ) == 0 )
{
this->process = composite_process;
- mlt_properties_set( mlt_transition_properties( this ), "start", arg != NULL ? arg : "85,5:10x10" );
+ mlt_properties_set( mlt_transition_properties( this ), "start", arg != NULL ? arg : "85%,5%:10%x10%" );
mlt_properties_set( mlt_transition_properties( this ), "end", "" );
}
return this;
producer_libdv.o \
consumer_libdv.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
LDFLAGS=-ldv -lpthread
OBJS = factory.o \
producer_fezzik.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
SRCS := $(OBJS:.o=.c)
filter_ffmpeg_dub.o \
consumer_ffmpeg.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
SRCS := $(OBJS:.o=.c)
uint8_t *input = NULL;
char *interps = mlt_properties_get( properties, "rescale.interp" );
int interp = PIXOPS_INTERP_BILINEAR;
- double i_aspect_ratio = mlt_frame_get_aspect_ratio( this );
- double o_aspect_ratio = mlt_properties_get_double( properties, "consumer_aspect_ratio" );
if ( strcmp( interps, "nearest" ) == 0 )
interp = PIXOPS_INTERP_NEAREST;
else if ( strcmp( interps, "hyper" ) == 0 )
interp = PIXOPS_INTERP_HYPER;
- mlt_frame_get_image( this, &input, format, &iwidth, &iheight, writable );
-
- if ( o_aspect_ratio != 0 && o_aspect_ratio != i_aspect_ratio && mlt_properties_get( properties, "distort" ) == NULL )
+ // If real_width/height exist, we want that as minimum information
+ if ( mlt_properties_get_int( properties, "real_width" ) )
{
- int temp_width = i_aspect_ratio / o_aspect_ratio * owidth + 0.5;
-
- // Determine maximum size within the aspect ratio:
- if ( temp_width > owidth )
- if ( i_aspect_ratio > o_aspect_ratio )
- oheight = o_aspect_ratio / i_aspect_ratio * oheight + 0.5;
- else
- oheight = i_aspect_ratio / o_aspect_ratio * oheight + 0.5;
- else
- owidth = temp_width;
-
- // Tell frame we have conformed the aspect to the consumer
- mlt_frame_set_aspect_ratio( this, o_aspect_ratio );
+ iwidth = mlt_properties_get_int( properties, "real_width" );
+ iheight = mlt_properties_get_int( properties, "real_height" );
}
- //fprintf( stderr, "rescale: from %dx%d (aspect %f) to %dx%d (aspect %f)\n", iwidth, iheight, i_aspect_ratio, owidth, oheight, o_aspect_ratio );
+
+ // Let the producer know what we are actually requested to obtain
+ mlt_properties_set_int( properties, "rescale_width", *width );
+ mlt_properties_set_int( properties, "rescale_height", *height );
+
+ // Get the image as requested
+ mlt_frame_get_image( this, &input, format, &iwidth, &iheight, writable );
if ( input != NULL )
{
int width;
int height;
uint8_t *image;
+ uint8_t *alpha;
char *fgcolor;
char *bgcolor;
int align;
rgba_color fgcolor = parse_color( this->fgcolor );
rgba_color bgcolor = parse_color( this->bgcolor );
+ free( this->image );
+ free( this->alpha );
+ this->image = NULL;
+ this->alpha = NULL;
+
// Render the title
pixbuf = pango_get_pixbuf( markup, text, font, fgcolor, bgcolor, pad, align );
}
else if ( this->image == NULL || width != this->width || height != this->height )
{
+ free( this->image );
+ free( this->alpha );
+ this->image = NULL;
+ this->alpha = NULL;
+
pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL );
mlt_properties_set_int( producer_props, "bpp", gdk_pixbuf_get_has_alpha( pixbuf ) ? 4 : 3 );
}
// If we have a pixbuf and a valid width
if ( pixbuf && width > 0 )
{
- int i;
-
// Note - the original pixbuf is already safe and ready for destruction
- pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_HYPER );
+ pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_NEAREST );
// Store width and height
- this->width = gdk_pixbuf_get_width( pixbuf );
- this->height = gdk_pixbuf_get_height( pixbuf );
+ this->width = width;
+ this->height = height;
// Allocate/define image
// IRRIGATE ME
- uint8_t *image = malloc( this->width * ( this->height + 1 )* bpp );
+ uint8_t *image = malloc( width * ( height + 1 ) * bpp );
+ uint8_t *alpha = NULL;
+
+ // Allocate the alpha mask
+ alpha = malloc( this->width * this->height );
- for ( i = 0; i < height; i++ )
- memcpy( image + i * width * bpp,
- gdk_pixbuf_get_pixels( pixbuf ) + i * gdk_pixbuf_get_rowstride( pixbuf ),
- gdk_pixbuf_get_width( pixbuf ) * bpp );
+ // Convert the image
+ mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
+ this->width, this->height,
+ gdk_pixbuf_get_rowstride( pixbuf ),
+ image, alpha );
// Finished with pixbuf now
g_object_unref( pixbuf );
// reference the image in the producer
- free( this->image );
this->image = image;
+ this->alpha = alpha;
}
// Set width/height
// pass the image data without destructor
mlt_properties_set_data( properties, "image", this->image, this->width * ( this->height + 1 ) * bpp, NULL, NULL );
+ mlt_properties_set_data( properties, "alpha", this->alpha, this->width * this->height, NULL, NULL );
}
static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
// Obtain properties of frame
mlt_properties properties = mlt_frame_properties( frame );
+ *width = mlt_properties_get_int( properties, "rescale_width" );
+ *height = mlt_properties_get_int( properties, "rescale_height" );
+
// Refresh the image
refresh_image( frame, *width, *height );
// Determine format
- mlt_producer this = mlt_properties_get_data( properties, "producer_pango", NULL );
- *format = ( mlt_properties_get_int( mlt_producer_properties( this ), "bpp" ) == 4 ) ? mlt_image_rgb24a : mlt_image_rgb24;
+ //mlt_producer this = mlt_properties_get_data( properties, "producer_pango", NULL );
+ //*format = ( mlt_properties_get_int( mlt_producer_properties( this ), "bpp" ) == 4 ) ? mlt_image_rgb24a : mlt_image_rgb24;
// May need to know the size of the image to clone it
int size = 0;
return 0;
}
+static uint8_t *producer_get_alpha_mask( mlt_frame this )
+{
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( this );
+
+ // Return the alpha mask
+ return mlt_properties_get_data( properties, "alpha", NULL );
+}
+
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
{
producer_pango this = producer->child;
mlt_properties_set_int( properties, "progressive", 1 );
mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( properties, "real_width" ) / mlt_properties_get_double( properties, "real_height" ) );
+ // Set alpha call back
+ ( *frame )->get_alpha_mask = producer_get_alpha_mask;
+
// Stack the get image callback
mlt_frame_push_get_image( *frame, producer_get_image );
{
producer_pango this = parent->child;
free( this->image );
+ free( this->alpha );
free( this->fgcolor );
free( this->bgcolor );
free( this->markup );
static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
static void producer_close( mlt_producer parent );
-typedef enum
-{
- SIGNAL_FORMAT_PAL,
- SIGNAL_FORMAT_NTSC
-} mlt_signal_format;
-
static int filter_files( const struct dirent *de )
{
if ( de->d_name[ 0 ] != '.' )
return 0;
}
-
mlt_producer producer_pixbuf_init( char *filename )
{
producer_pixbuf this = calloc( sizeof( struct producer_pixbuf_s ), 1 );
{
mlt_producer producer = &this->parent;
- producer->get_frame = producer_get_frame;
- producer->close = producer_close;
-
// Get the properties interface
mlt_properties properties = mlt_producer_properties( &this->parent );
+ // Callback registration
+ producer->get_frame = producer_get_frame;
+ producer->close = producer_close;
+
// Set the default properties
mlt_properties_set( properties, "resource", filename );
mlt_properties_set_int( properties, "ttl", 25 );
gap ++;
}
}
- mlt_properties_set_position( properties, "out", this->count * 25 );
+ mlt_properties_set_position( properties, "out", this->count * 250 );
}
else if ( strstr( filename, "/.all." ) != NULL )
{
{
this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) );
this->filenames[ this->count ++ ] = strdup( filename );
- mlt_properties_set_position( properties, "out", 25 );
+ mlt_properties_set_position( properties, "out", 250 );
}
// Initialise gobject types
mlt_frame_set_position( frame, mlt_producer_position( producer ) );
// optimization for subsequent iterations on single picture
- if ( this->image != NULL && image_idx == this->image_idx )
+ if ( width != 0 && this->image != NULL && image_idx == this->image_idx )
{
if ( width != this->width || height != this->height )
{
pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL );
mlt_properties_set_int( producer_props, "bpp", gdk_pixbuf_get_has_alpha( pixbuf ) ? 4 : 3 );
+ free( this->image );
+ free( this->alpha );
+ this->image = NULL;
+ this->alpha = NULL;
}
}
- else
+ else if ( this->image == NULL || image_idx != this->image_idx )
{
+ free( this->image );
+ free( this->alpha );
+ this->image = NULL;
+ this->alpha = NULL;
+
this->image_idx = image_idx;
pixbuf = gdk_pixbuf_new_from_file( this->filenames[ image_idx ], &error );
// If we have a pixbuf
if ( pixbuf && width > 0 )
{
- int i;
- //fprintf( stderr, "SCALING PIXBUF from %dx%d to %dx%d\n", gdk_pixbuf_get_width( pixbuf ), gdk_pixbuf_get_height( pixbuf ), width, height );
// Note - the original pixbuf is already safe and ready for destruction
- pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_HYPER );
+ pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_NEAREST );
// Store width and height
- this->width = gdk_pixbuf_get_width( pixbuf );
- this->height = gdk_pixbuf_get_height( pixbuf );
+ this->width = width;
+ this->height = height;
+ //fprintf( stderr, "SCALING PIXBUF from %dx%d to %dx%d %dx%d\n", gdk_pixbuf_get_width( pixbuf ), gdk_pixbuf_get_height( pixbuf ), width, height, this->width, this->height );
// Allocate/define image
// IRRIGATE ME
uint8_t *image = malloc( width * ( height + 1 ) * bpp );
+ uint8_t *alpha = NULL;
- for ( i = 0; i < height; i++ )
- memcpy( image + i * width * bpp,
- gdk_pixbuf_get_pixels( pixbuf ) + i * gdk_pixbuf_get_rowstride( pixbuf ),
- gdk_pixbuf_get_width( pixbuf ) * bpp );
+ // Extract YUV422 and alpha
+ if ( gdk_pixbuf_get_has_alpha( pixbuf ) )
+ {
+ // Allocate the alpha mask
+ alpha = malloc( this->width * this->height );
+
+ // Convert the image
+ mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
+ this->width, this->height,
+ gdk_pixbuf_get_rowstride( pixbuf ),
+ image, alpha );
+ }
+ else
+ {
+ // No alpha to extract
+ mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
+ this->width, this->height,
+ gdk_pixbuf_get_rowstride( pixbuf ),
+ image );
+ }
// Finished with pixbuf now
g_object_unref( pixbuf );
- // Pass image on properties with or without destructor
- free( this->image );
+ // Assign images to producer
this->image = image;
+ this->alpha = alpha;
}
// Set width/height of frame
mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "real_height" ) );
// pass the image data without destructor
- mlt_properties_set_data( properties, "image", this->image, this->width * ( this->height + 1 ) * bpp, NULL, NULL );
+ mlt_properties_set_data( properties, "image", this->image, this->width * ( this->height + 1 ) * 2, NULL, NULL );
+ mlt_properties_set_data( properties, "alpha", this->alpha, this->width * this->height, NULL, NULL );
}
static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
// Obtain properties of frame
mlt_properties properties = mlt_frame_properties( frame );
+ *width = mlt_properties_get_int( properties, "rescale_width" );
+ *height = mlt_properties_get_int( properties, "rescale_height" );
+
// Refresh the image
refresh_image( frame, *width, *height );
// Determine format
- mlt_producer this = mlt_properties_get_data( properties, "producer_pixbuf", NULL );
- *format = ( mlt_properties_get_int( mlt_producer_properties( this ), "bpp" ) == 4 ) ? mlt_image_rgb24a : mlt_image_rgb24;
+ //mlt_producer this = mlt_properties_get_data( properties, "producer_pixbuf", NULL );
+ //*format = ( mlt_properties_get_int( mlt_producer_properties( this ), "bpp" ) == 4 ) ? mlt_image_rgb24a : mlt_image_rgb24;
// May need to know the size of the image to clone it
int size = 0;
return 0;
}
+static uint8_t *producer_get_alpha_mask( mlt_frame this )
+{
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( this );
+
+ // Return the alpha mask
+ return mlt_properties_get_data( properties, "alpha", NULL );
+}
+
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
{
// Get the real structure for this producer
mlt_properties_set_int( properties, "progressive", 1 );
mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( properties, "real_width" ) / mlt_properties_get_double( properties, "real_height" ) );
+ // Set alpha call back
+ ( *frame )->get_alpha_mask = producer_get_alpha_mask;
+
// Push the get_image method
mlt_frame_push_get_image( *frame, producer_get_image );
OBJS = factory.o \
producer_inigo.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
SRCS := $(OBJS:.o=.c)
OBJS = factory.o \
filter_resample.o
-CFLAGS = -I../../ -Wall -g
+CFLAGS = -O3 -I../../ -Wall -g
LDFLAGS= -lsamplerate
OBJS = factory.o \
consumer_sdl.o
-CFLAGS = -I../../ `sdl-config --cflags` -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = -O3 -I../../ `sdl-config --cflags` -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
LDFLAGS= `sdl-config --libs`
SDL_FreeYUVOverlay( this->sdl_overlay );
SDL_Quit( );
+ while( -- this->count >= 0 )
+ mlt_frame_close( this->queue[ this->count ] );
+
this->sdl_screen = NULL;
this->sdl_overlay = NULL;
this->audio_avail = 0;
OBJS = factory.o \
producer_vorbis.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64
LDFLAGS = -lvorbisfile -lvorbis
consumer_westley.o \
producer_westley.o
-CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread `xml2-config --cflags`
+CFLAGS = -O3 -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread `xml2-config --cflags`
LDFLAGS = `xml2-config --libs`
// Instatiate the producer
if ( mlt_properties_get( properties, "resource" ) != NULL )
- service = MLT_SERVICE( mlt_factory_producer( "fezzik", mlt_properties_get( properties, "resource" ) ) );
+ {
+ char *root = mlt_properties_get( context->producer_map, "_root" );
+ char *resource = mlt_properties_get( properties, "resource" );
+ char *full_resource = malloc( strlen( root ) + strlen( resource ) + 1 );
+ if ( resource[ 0 ] != '/' )
+ {
+ strcpy( full_resource, root );
+ strcat( full_resource, resource );
+ }
+ else
+ {
+ strcpy( full_resource, resource );
+ }
+ service = MLT_SERVICE( mlt_factory_producer( "fezzik", full_resource ) );
+ free( full_resource );
+ }
if ( service == NULL && mlt_properties_get( properties, "mlt_service" ) != NULL )
{
service = MLT_SERVICE( mlt_factory_producer( mlt_properties_get( properties, "mlt_service" ),
mlt_producer producer_westley_init( char *filename )
{
- static int init = 0;
xmlSAXHandler *sax = calloc( 1, sizeof( xmlSAXHandler ) );
struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) );
mlt_properties properties = NULL;
context->producer_map = mlt_properties_new();
context->destructors = mlt_properties_new();
+
// We need to track the number of registered filters
mlt_properties_set_int( context->destructors, "registered", 0 );
+
+ // We need the directory prefix which was used for the westley
+ mlt_properties_set( context->producer_map, "_root", "" );
+ if ( strchr( filename, '/' ) )
+ {
+ char *root = NULL;
+ mlt_properties_set( context->producer_map, "_root", filename );
+ root = mlt_properties_get( context->producer_map, "_root" );
+ *( strrchr( root, '/' ) + 1 ) = '\0';
+ }
+
sax->startElement = on_start_element;
sax->endElement = on_end_element;
sax->characters = on_characters;
- if ( !init )
- {
- xmlInitParser();
- //init = 1;
- }
+ // I REALLY DON'T GET THIS - HOW THE HELL CAN YOU REFERENCE A WESTLEY IN A WESTLEY???
+ xmlInitParser();
xmlSAXUserParseFile( sax, context, filename );
TARGET = dan charlie pango pixbuf dissolve luma
-CFLAGS = -I .. -Wall -rdynamic -pthread
+CFLAGS = -O3 -I .. -Wall -rdynamic -pthread
LDFLAGS = -L ../framework -lmlt
SRCS := $(OBJS:.o=.c)
-CFLAGS=-Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS=-O3 -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
LDFLAGS=-ldv -lpthread