This document is split roughly into 3 sections. The first section provides a
basic overview of MLT, the second section shows how it's used and the final
- section shows shows structure and design, with an emphasis on how the system
- is extended.
+ section shows structure and design, with an emphasis on how the system is
+ extended.
Target Audience:
+------------------+------------------------------------+------------------+
|MLT_CONSUMER |The default consumer |"sdl" or other |
+------------------+------------------------------------+------------------+
+ |MLT_TEST_CARD |The default test card producer |any producer |
+ +------------------+------------------------------------+------------------+
These values are initialised from the environment variables of the same
name.
Instead of invoking mlt_factory_producer directly, we'll create a new
function called create_playlist. This function is responsible for creating
- the playlist, creating each producer, appending to the playlist and ensuring
- that all the producers are cleaned up when the playlist is destroyed. The
- last point is important - a close on the playlist won't explicitly close these
- producers. In this example, we use unique "data" properties with destructors
- to ensure closing.
+ the playlist, creating each producer and appending to the playlist.
mlt_producer create_playlist( int argc, char **argv )
{
int i = 0;
for ( i = 1; i < argc; i ++ )
{
- // Define the unique key
- char key[ 256 ];
-
// Create the producer
mlt_producer producer = mlt_factory_producer( NULL, argv[ i ] );
// Add it to the playlist
mlt_playlist_append( playlist, producer );
- // Create a unique key for this producer
- sprintf( key, "producer%d", i );
-
- // Now we need to ensure the producers are destroyed
- mlt_properties_set_data( properties, key, producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
+ // Close the producer (see below)
+ mlt_producer_close( producer );
}
// Return the playlist as a producer
return mlt_playlist_producer( playlist );
}
+ Notice that we close the producer after the append. Actually, what we're
+ doing is closing our reference to it - the playlist creates its own reference
+ to the producer on append and insert, and it will close its reference
+ when the playlist is destroyed[*].
+
+ Note also that if you append multiple instances of the same producer, it
+ will create multiple references to it.
+
Now all we need do is to replace these lines in the main function:
// Create a normalised producer
and we have a means to play multiple clips.
+ [*] This reference functionality was introduced in mlt 0.1.2 - it is 100%
+ compatable with the early mechanism of registering the reference and
+ destructor with the properties of the playlist object.
+
Filters:
| +------+ | +-------------+ +-------+
+----------+
- In reality, we create a field first, and from that we obtain a multitrack
- and a tractor. We can then populate the multitrack, field and finally,
- connect the tractor to the consumer.
-
- The reasoning behind this is possibly flawed - it might have made more
- sense to produce the tractor and have it encapsulate the field and the
- multitrack as that is how it looks to a connected consumer:
+ So, we need to create the tractor first, and from that we obtain the
+ multitrack and field objects. We can populate these and finally
+ connect the tractor to a consumer.
+
+ In essence, this is how it looks to the consumer:
+-----------------------------------------------+
|tractor +--------------------------+ |
mlt_producer create_tracks( int argc, char **argv )
{
- // Create the field
- mlt_field field = mlt_field_init( );
+ // Create the tractor
+ mlt_tractor tractor = mlt_tractor_new( );
+
+ // Obtain the field
+ mlt_field field = mlt_tractor_field( tractor );
// Obtain the multitrack
- mlt_multitrack multitrack = mlt_field_multitrack( field );
-
- // Obtain the tractor
- mlt_tractor tractor = mlt_field_tractor( field );
+ mlt_multitrack multitrack = mlt_tractor_multitrack( tractor );
- // Obtain a composite transition
+ // Create a composite transition
mlt_transition transition = mlt_factory_transition( "composite", "10%,10%:15%x15%" );
// Create track 0
// Now plant the transition
mlt_field_plant_transition( field, transition, 0, 1 );
-
- // Now set the properties on the tractor
- properties = mlt_tractor_properties( tractor );
- mlt_properties_set_data( properties, "multitrack", multitrack, 0, ( mlt_destructor )mlt_multitrack_close, NULL );
- mlt_properties_set_data( properties, "field", field, 0, ( mlt_destructor )mlt_field_close, NULL );
- mlt_properties_set_data( properties, "track0", track0, 0, ( mlt_destructor )mlt_producer_close, NULL );
- mlt_properties_set_data( properties, "track1", track1, 0, ( mlt_destructor )mlt_producer_close, NULL );
- mlt_properties_set_data( properties, "transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL );
-
+
+ // Close our references
+ mlt_producer_close( track0 );
+ mlt_producer_close( track1 );
+ mlt_transition_close( transition );
+
// Return the tractor
return mlt_tractor_producer( tractor );
}
and we have a means to play multiple clips with a horribly obtrusive
watermark - just what the world needed, right? ;-)
+ Incidentally, the same thing could be achieved with the more trivial
+ watermark filter inserted between the producer and the consumer.
+
SECTION 3 - STRUCTURE AND DESIGN
--------------------------------