// Hmm - default all consumers to yuv422 :-/
self->format = mlt_image_yuv422;
+ mlt_properties_set( properties, "mlt_image_format", mlt_image_format_name( self->format ) );
+ mlt_properties_set( properties, "mlt_audio_format", mlt_audio_format_name( mlt_audio_s16 ) );
mlt_events_register( properties, "consumer-frame-show", ( mlt_transmitter )mlt_consumer_frame_show );
mlt_events_register( properties, "consumer-frame-render", ( mlt_transmitter )mlt_consumer_frame_render );
free( profile->description );
memcpy( profile, new_profile, sizeof( struct mlt_profile_s ) );
profile->description = strdup( new_profile->description );
- mlt_profile_close( new_profile );
}
else
{
// Apply to properties
apply_profile_properties( self, profile, properties );
+ mlt_profile_close( new_profile );
}
}
else if ( !strcmp( name, "frame_rate_num" ) )
{
mlt_properties properties = MLT_CONSUMER_PROPERTIES( self );
mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( self ) );
- profile->sample_aspect_num = mlt_properties_get_int( properties, "sample_aspect_num" );
if ( profile )
+ {
+ profile->sample_aspect_num = mlt_properties_get_int( properties, "sample_aspect_num" );
mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
+ }
}
else if ( !strcmp( name, "sample_aspect_den" ) )
{
mlt_properties properties = MLT_CONSUMER_PROPERTIES( self );
mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( self ) );
- profile->sample_aspect_den = mlt_properties_get_int( properties, "sample_aspect_den" );
if ( profile )
+ {
+ profile->sample_aspect_den = mlt_properties_get_int( properties, "sample_aspect_den" );
mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
+ }
}
else if ( !strcmp( name, "display_aspect_num" ) )
{
* \private \memberof mlt_consumer_s
* \param listener a function pointer that will be invoked
* \param owner the events object that will be passed to \p listener
- * \param self a service that will be passed to \p listener
- * \param args an array of pointers - the first entry is passed as a string to \p listener
+ * \param self a service that will be passed to \p listener
+ * \param args an array of pointers - the first entry is passed as a frame to \p listener
*/
static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner, mlt_service self, void **args )
* \private \memberof mlt_consumer_s
* \param listener a function pointer that will be invoked
* \param owner the events object that will be passed to \p listener
- * \param self a service that will be passed to \p listener
- * \param args an array of pointers - the first entry is passed as a string to \p listener
+ * \param self a service that will be passed to \p listener
+ * \param args an array of pointers - the first entry is passed as a frame to \p listener
*/
static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service self, void **args )
mlt_consumer self = malloc( sizeof( struct mlt_consumer_s ) );
// Initialise it
- if ( self != NULL )
- mlt_consumer_init( self, NULL, profile );
-
- // Return it
- return self;
+ if ( self != NULL && mlt_consumer_init( self, NULL, profile ) == 0 )
+ {
+ // Return it
+ return self;
+ }
+ else
+ {
+ free(self);
+ return NULL;
+ }
}
/** Get the parent service object.
char *test_card = mlt_properties_get( properties, "test_card" );
// Just to make sure nothing is hanging around...
+ pthread_mutex_lock( &self->put_mutex );
self->put = NULL;
self->put_active = 1;
+ pthread_mutex_unlock( &self->put_mutex );
// Deal with it now.
if ( test_card != NULL )
mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
}
+ // The profile could have changed between a stop and a restart.
+ apply_profile_properties( self, mlt_service_profile( MLT_CONSUMER_SERVICE(self) ), properties );
+
// Set the frame duration in microseconds for the frame-dropping heuristic
- int frame_duration = 1000000 / mlt_properties_get_int( properties, "frame_rate_num" ) *
- mlt_properties_get_int( properties, "frame_rate_den" );
+ int frame_rate_num = mlt_properties_get_int( properties, "frame_rate_num" );
+ int frame_rate_den = mlt_properties_get_int( properties, "frame_rate_den" );
+ int frame_duration = 0;
+
+ if ( frame_rate_num && frame_rate_den )
+ {
+ frame_duration = 1000000 / frame_rate_num * frame_rate_den;
+ }
+
mlt_properties_set_int( properties, "frame_duration", frame_duration );
// Check and run an ante command
if ( abs( self->real_time ) > 1 && mlt_properties_get_int( properties, "buffer" ) <= abs( self->real_time ) )
mlt_properties_set_int( properties, "_buffer", abs( self->real_time ) + 1 );
+ // Get the image format to use for rendering threads
+ const char* format = mlt_properties_get( properties, "mlt_image_format" );
+ if ( format )
+ {
+ if ( !strcmp( format, "rgb24" ) )
+ self->format = mlt_image_rgb24;
+ else if ( !strcmp( format, "rgb24a" ) )
+ self->format = mlt_image_rgb24a;
+ else if ( !strcmp( format, "yuv420p" ) )
+ self->format = mlt_image_yuv420p;
+ else if ( !strcmp( format, "none" ) )
+ self->format = mlt_image_none;
+ else
+ self->format = mlt_image_yuv422;
+ }
+
// Start the service
if ( self->start != NULL )
return self->start( self );
if ( test_card != NULL )
mlt_properties_set_data( frame_properties, "test_card_producer", test_card, 0, NULL, NULL );
- // Attach the rescale property
+ // Pass along the interpolation and deinterlace options
+ // TODO: get rid of consumer_deinterlace and use profile.progressive
mlt_properties_set( frame_properties, "rescale.interp", mlt_properties_get( properties, "rescale" ) );
-
- // Aspect ratio and other jiggery pokery
- mlt_properties_set_double( frame_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "aspect_ratio" ) );
mlt_properties_set_int( frame_properties, "consumer_deinterlace", mlt_properties_get_int( properties, "progressive" ) | mlt_properties_get_int( properties, "deinterlace" ) );
mlt_properties_set( frame_properties, "deinterlace_method", mlt_properties_get( properties, "deinterlace_method" ) );
+ mlt_properties_set_int( frame_properties, "consumer_tff", mlt_properties_get_int( properties, "top_field_first" ) );
}
// Return the frame
// Get the audio settings
mlt_audio_format afmt = mlt_audio_s16;
+ const char *format = mlt_properties_get( properties, "mlt_audio_format" );
+ if ( format )
+ {
+ if ( !strcmp( format, "none" ) )
+ afmt = mlt_audio_none;
+ else if ( !strcmp( format, "s32" ) )
+ afmt = mlt_audio_s32;
+ else if ( !strcmp( format, "s32le" ) )
+ afmt = mlt_audio_s32le;
+ else if ( !strcmp( format, "float" ) )
+ afmt = mlt_audio_float;
+ else if ( !strcmp( format, "f32le" ) )
+ afmt = mlt_audio_f32le;
+ }
int counter = 0;
double fps = mlt_properties_get_double( properties, "fps" );
int channels = mlt_properties_get_int( properties, "channels" );
// We're running now
self->ahead = 1;
+ self->threads = thread;
// These keep track of the accelleration of frame dropping or recovery.
self->consecutive_dropped = 0;
pthread_join( *thread, NULL );
// Deallocate the array of threads
- if ( thread )
- free( thread );
+ if ( self->threads )
+ free( self->threads );
// Indicate that worker threads no longer running
self->started = 0;
void mlt_consumer_purge( mlt_consumer self )
{
- if ( self->ahead )
+ if ( self && self->ahead )
{
pthread_mutex_lock( &self->queue_mutex );
while ( mlt_deque_count( self->queue ) )
int mlt_consumer_is_stopped( mlt_consumer self )
{
// Check if the consumer is stopped
- if ( self->is_stopped != NULL )
+ if ( self && self->is_stopped )
return self->is_stopped( self );
return 0;