+INIGO
+-----
+
+Preamble:
+
+ inigo was developed as a test tool for the MLT framework. It can
+ be thought of as a powerful, if somewhat obscure, multitrack
+ command line oriented video editor.
+
+ The following details the usage of the tool and as a result,
+ provides a lot of insight into the workings of the MLT framework.
+
+
Usage:
inigo [ -group [ name=value ]* ]
[ -track ]
[ producer [ name=value ] * ]+
[ -serialise file.inigo ]
-
+
+
General rules:
1. Order is incredibly important;
+
2. Error checking on command line parsing is weak;
- 3. This document does not duplicate the information in services.txt.
+
+ 3. Please refer to services.txt for details on services
+ available;
+
+ 4. The MLT framework, from which inigo has inherited its
+ naming convention - is very ego-centric. Producers produce
+ MLT frame objects and consumers consume MLT frame objects.
+ The distinction is important - a DV producer does not produce
+ DV and a DV consumer does not consume DV.
+
Terminoligy:
devices (such as dv1394 input or video4linux). Hence, the more
generic term is used [yes, the more generic usage is out of
scope for now...].
-
+
'Filters' are frame modifiers - they always guarantee that for
every frame they receive, they output *precisely* one frame.
Never more, never less, ever.
Consumers have no say in the flow of frames [though they may
give the illusion that they do]. They get frames from a
connected producer, use them, destroy them and get more.
-
+
+
Basics:
To play a file with the default SDL PAL consumer, usage is:
'producer' mapping for (so this can be anything from .dv to
.txt).
+
Properties:
Properties can be assigned to the producer by adding additional
validity of others are dependent on the producer - however,
properties will always be assigned, but it doesn't mean they
will be used.
-
+
+
Multiple Files:
Multiple files of different types can be used:
Properties can be assigned to each file:
$ inigo a.dv in=50 out=100 b.mpg out=500 c.png out=500
-
+
+
Filters:
The Multiple Files examples above will logically playout one
It should also be stressed that filters are applied in the order
in which they're specified.
-
+
+
Filter Properties:
As with producers, properties may be specified on filters too.
Again, filters have their own set of rules about properties and
will silently ignore properties that do not apply.
-
+
+
Groups:
The -group switch is provided to force default properties on the
To shed the group properties, you can use any empty group:
$ inigo -group in=0 out=49 clip* -group -filter greyscale
-
+
+
Introducing Tracks and Blanks:
So far, all of the examples have shown the definition of a
Playout will show the first 50 frames of a and the 51st frame
shown will be the 51st frame of b.
- To show have the 51st frame be the first frame of b, we can use
- the -blank switch:
+ To have the 51st frame be the first frame of b, we can use the
+ -blank switch:
$ inigo a.dv out=49 -track -blank 49 b.dv
Now playout will continue as though a and b clips are on the
same track (which is about as useful as reversing the process of
slicing bread).
-
+
+
Transitions:
Where tracks become useful is in the placing of transitions.
+-------+
|a |
- +----+--+---------------+
- |b |
- +------------------+
+ +---+---+--------------+
+ |b |
+ +------------------+
Playout will now show the first 25 frames of a and then a fade
transition for 25 frames between a and b, and will finally
playout the remainder of b.
-
+
+
Reversing a Transition:
When we visualise a track definition, we also see situtations
+-------+ +----------+
|a1 | |a2 |
- +----+--+--------------+----+-----+
- |b |
- +----------------------+
+ +---+---+--------------+----+-----+
+ |b |
+ +-----------------------+
In this case, we have two transitions, a1 to b and b to a2.
-transition luma in=100 out=124 reverse=1 \
-track \
-blank 24 b.dv out=99
-
+
+
Filters and Tracks:
A filter applies to a [specified region of a] single track, so
the consumer is requesting, and you may not want to unecessarily
resize a video track if you will be later rescaling it for
composition).
-
+
+
Serialisation:
Inigo has a built in serialisation mechanism - you can build up
The saved file can be subsequently used as a clip by either
miracle or inigo. Take care though - paths to files are saved as
provided on the command line....
-
+
+
Missing Features:
Some filters/transitions should be applied on the output frame
+INIGO
+-----
+
+Preamble:
+
+ inigo was developed as a test tool for the MLT framework. It can
+ be thought of as a powerful, if somewhat obscure, multitrack
+ command line oriented video editor.
+
+ The following details the usage of the tool and as a result,
+ provides a lot of insight into the workings of the MLT framework.
+
+
Usage:
inigo [ -group [ name=value ]* ]
[ -track ]
[ producer [ name=value ] * ]+
[ -serialise file.inigo ]
-
+
+
General rules:
1. Order is incredibly important;
+
2. Error checking on command line parsing is weak;
- 3. This document does not duplicate the information in services.txt.
+
+ 3. Please refer to services.txt for details on services
+ available;
+
+ 4. The MLT framework, from which inigo has inherited its
+ naming convention - is very ego-centric. Producers produce
+ MLT frame objects and consumers consume MLT frame objects.
+ The distinction is important - a DV producer does not produce
+ DV and a DV consumer does not consume DV.
+
Terminoligy:
devices (such as dv1394 input or video4linux). Hence, the more
generic term is used [yes, the more generic usage is out of
scope for now...].
-
+
'Filters' are frame modifiers - they always guarantee that for
every frame they receive, they output *precisely* one frame.
Never more, never less, ever.
Consumers have no say in the flow of frames [though they may
give the illusion that they do]. They get frames from a
connected producer, use them, destroy them and get more.
-
+
+
Basics:
To play a file with the default SDL PAL consumer, usage is:
'producer' mapping for (so this can be anything from .dv to
.txt).
+
Properties:
Properties can be assigned to the producer by adding additional
validity of others are dependent on the producer - however,
properties will always be assigned, but it doesn't mean they
will be used.
-
+
+
Multiple Files:
Multiple files of different types can be used:
Properties can be assigned to each file:
$ inigo a.dv in=50 out=100 b.mpg out=500 c.png out=500
-
+
+
Filters:
The Multiple Files examples above will logically playout one
It should also be stressed that filters are applied in the order
in which they're specified.
-
+
+
Filter Properties:
As with producers, properties may be specified on filters too.
Again, filters have their own set of rules about properties and
will silently ignore properties that do not apply.
-
+
+
Groups:
The -group switch is provided to force default properties on the
To shed the group properties, you can use any empty group:
$ inigo -group in=0 out=49 clip* -group -filter greyscale
-
+
+
Introducing Tracks and Blanks:
So far, all of the examples have shown the definition of a
Playout will show the first 50 frames of a and the 51st frame
shown will be the 51st frame of b.
- To show have the 51st frame be the first frame of b, we can use
- the -blank switch:
+ To have the 51st frame be the first frame of b, we can use the
+ -blank switch:
$ inigo a.dv out=49 -track -blank 49 b.dv
Now playout will continue as though a and b clips are on the
same track (which is about as useful as reversing the process of
slicing bread).
-
+
+
Transitions:
Where tracks become useful is in the placing of transitions.
+-------+
|a |
- +----+--+---------------+
- |b |
- +------------------+
+ +---+---+--------------+
+ |b |
+ +------------------+
Playout will now show the first 25 frames of a and then a fade
transition for 25 frames between a and b, and will finally
playout the remainder of b.
-
+
+
Reversing a Transition:
When we visualise a track definition, we also see situtations
+-------+ +----------+
|a1 | |a2 |
- +----+--+--------------+----+-----+
- |b |
- +----------------------+
+ +---+---+--------------+----+-----+
+ |b |
+ +-----------------------+
In this case, we have two transitions, a1 to b and b to a2.
-transition luma in=100 out=124 reverse=1 \
-track \
-blank 24 b.dv out=99
-
+
+
Filters and Tracks:
A filter applies to a [specified region of a] single track, so
the consumer is requesting, and you may not want to unecessarily
resize a video track if you will be later rescaling it for
composition).
-
+
+
Serialisation:
Inigo has a built in serialisation mechanism - you can build up
The saved file can be subsequently used as a clip by either
miracle or inigo. Take care though - paths to files are saved as
provided on the command line....
-
+
+
Missing Features:
Some filters/transitions should be applied on the output frame
#include <libdv/dv.h>
// Forward references.
+static int consumer_start( mlt_consumer this );
+static int consumer_stop( mlt_consumer this );
+static int consumer_is_stopped( mlt_consumer this );
static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame );
// Get properties from the consumer
mlt_properties properties = mlt_consumer_properties( this );
- // Allocate a thread
- pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
-
// Assign close callback
this->close = consumer_close;
- // Assign all properties
+ // Interpret the constructor argument
if ( arg == NULL || !strcmp( arg, "PAL" ) )
mlt_properties_set_double( properties, "fps", 25 );
else
mlt_properties_set_double( properties, "fps", 29.97 );
- mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL );
+ // Set the encode and output handling method
mlt_properties_set_data( properties, "video", consumer_encode_video, 0, NULL, NULL );
mlt_properties_set_data( properties, "audio", consumer_encode_audio, 0, NULL, NULL );
mlt_properties_set_data( properties, "output", consumer_output, 0, NULL, NULL );
- // Create the thread (this should not happen immediately)
- mlt_properties_set_int( properties, "running", 1 );
- pthread_create( thread, NULL, consumer_thread, this );
+ // Set up start/stop/terminated callbacks
+ this->start = consumer_start;
+ this->stop = consumer_stop;
+ this->is_stopped = consumer_is_stopped;
}
else
{
return this;
}
+/** Start the consumer.
+*/
+
+static int consumer_start( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Check that we're not already running
+ if ( !mlt_properties_get_int( properties, "running" ) )
+ {
+ // Allocate a thread
+ pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
+
+ // Assign the thread to properties
+ mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL );
+
+ // Set the running state
+ mlt_properties_set_int( properties, "running", 1 );
+
+ // Create the thread
+ pthread_create( thread, NULL, consumer_thread, this );
+ }
+ return 0;
+}
+
+/** Stop the consumer.
+*/
+
+static int consumer_stop( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Check that we're running
+ if ( mlt_properties_get_int( properties, "running" ) )
+ {
+ // Get the thread
+ pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
+
+ // Stop the thread
+ mlt_properties_set_int( properties, "running", 0 );
+
+ // Wait for termination
+ pthread_join( *thread, NULL );
+ }
+
+ return 0;
+}
+
+/** Determine if the consumer is stopped.
+*/
+
+static int consumer_is_stopped( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+ return !mlt_properties_get_int( properties, "running" );
+}
+
/** Get or create a new libdv encoder.
*/
// Get the frame
if ( mlt_service_get_frame( service, &frame, 0 ) == 0 )
{
- // Encode the image
- int size = video( this, dv_frame, frame );
-
- // Encode the audio
- if ( size > 0 )
- audio( this, dv_frame, frame );
-
- // Output the frame
- output( this, dv_frame, size, frame );
-
- // Close the frame
- mlt_frame_close( frame );
+ // Obtain the dv_encoder
+ if ( libdv_get_encoder( this, frame ) != NULL )
+ {
+ // Encode the image
+ int size = video( this, dv_frame, frame );
+
+ // Encode the audio
+ if ( size > 0 )
+ audio( this, dv_frame, frame );
+
+ // Output the frame
+ output( this, dv_frame, size, frame );
+
+ // Close the frame
+ mlt_frame_close( frame );
+ }
+ else
+ {
+ fprintf( stderr, "Unable to obtain dv encoder.\n" );
+ }
}
}
static void consumer_close( mlt_consumer this )
{
- // Get the properties
- mlt_properties properties = mlt_consumer_properties( this );
-
- // Get the thread
- pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
-
- // Stop the thread
- mlt_properties_set_int( properties, "running", 0 );
-
- // Wait for termination
- pthread_join( *thread, NULL );
+ // Stop the consumer
+ mlt_consumer_stop( this );
// Close the parent
mlt_consumer_close( this );
#include <libdv/dv.h>
// Forward references.
+static int consumer_start( mlt_consumer this );
+static int consumer_stop( mlt_consumer this );
+static int consumer_is_stopped( mlt_consumer this );
static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame );
// Get properties from the consumer
mlt_properties properties = mlt_consumer_properties( this );
- // Allocate a thread
- pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
-
// Assign close callback
this->close = consumer_close;
- // Assign all properties
+ // Interpret the constructor argument
if ( arg == NULL || !strcmp( arg, "PAL" ) )
mlt_properties_set_double( properties, "fps", 25 );
else
mlt_properties_set_double( properties, "fps", 29.97 );
- mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL );
+ // Set the encode and output handling method
mlt_properties_set_data( properties, "video", consumer_encode_video, 0, NULL, NULL );
mlt_properties_set_data( properties, "audio", consumer_encode_audio, 0, NULL, NULL );
mlt_properties_set_data( properties, "output", consumer_output, 0, NULL, NULL );
- // Create the thread (this should not happen immediately)
- mlt_properties_set_int( properties, "running", 1 );
- pthread_create( thread, NULL, consumer_thread, this );
+ // Set up start/stop/terminated callbacks
+ this->start = consumer_start;
+ this->stop = consumer_stop;
+ this->is_stopped = consumer_is_stopped;
}
else
{
return this;
}
+/** Start the consumer.
+*/
+
+static int consumer_start( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Check that we're not already running
+ if ( !mlt_properties_get_int( properties, "running" ) )
+ {
+ // Allocate a thread
+ pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
+
+ // Assign the thread to properties
+ mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL );
+
+ // Set the running state
+ mlt_properties_set_int( properties, "running", 1 );
+
+ // Create the thread
+ pthread_create( thread, NULL, consumer_thread, this );
+ }
+ return 0;
+}
+
+/** Stop the consumer.
+*/
+
+static int consumer_stop( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Check that we're running
+ if ( mlt_properties_get_int( properties, "running" ) )
+ {
+ // Get the thread
+ pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
+
+ // Stop the thread
+ mlt_properties_set_int( properties, "running", 0 );
+
+ // Wait for termination
+ pthread_join( *thread, NULL );
+ }
+
+ return 0;
+}
+
+/** Determine if the consumer is stopped.
+*/
+
+static int consumer_is_stopped( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+ return !mlt_properties_get_int( properties, "running" );
+}
+
/** Get or create a new libdv encoder.
*/
// Get the frame
if ( mlt_service_get_frame( service, &frame, 0 ) == 0 )
{
- // Encode the image
- int size = video( this, dv_frame, frame );
-
- // Encode the audio
- if ( size > 0 )
- audio( this, dv_frame, frame );
-
- // Output the frame
- output( this, dv_frame, size, frame );
-
- // Close the frame
- mlt_frame_close( frame );
+ // Obtain the dv_encoder
+ if ( libdv_get_encoder( this, frame ) != NULL )
+ {
+ // Encode the image
+ int size = video( this, dv_frame, frame );
+
+ // Encode the audio
+ if ( size > 0 )
+ audio( this, dv_frame, frame );
+
+ // Output the frame
+ output( this, dv_frame, size, frame );
+
+ // Close the frame
+ mlt_frame_close( frame );
+ }
+ else
+ {
+ fprintf( stderr, "Unable to obtain dv encoder.\n" );
+ }
}
}
static void consumer_close( mlt_consumer this )
{
- // Get the properties
- mlt_properties properties = mlt_consumer_properties( this );
-
- // Get the thread
- pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
-
- // Stop the thread
- mlt_properties_set_int( properties, "running", 0 );
-
- // Wait for termination
- pthread_join( *thread, NULL );
+ // Stop the consumer
+ mlt_consumer_stop( this );
// Close the parent
mlt_consumer_close( this );