From 29e898164327337c261a14a32e8ee52e75a27ffe Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Fri, 8 Oct 2004 09:14:50 +0000 Subject: [PATCH] Some documentation updates - more to follow git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@469 d19143bc-622f-0410-bfdd-b5b2a6649095 --- docs/framework.txt | 205 +++++++++++++++++++++++++++++++++++++++++++-- docs/inigo.txt | 95 ++++++++++++++++++++- docs/install.txt | 1 + 3 files changed, 289 insertions(+), 12 deletions(-) diff --git a/docs/framework.txt b/docs/framework.txt index 4aa6e346..1c2bafb0 100644 --- a/docs/framework.txt +++ b/docs/framework.txt @@ -2,7 +2,7 @@ Framework Documentation Copyright (C) 2004 Ushodaya Enterprises Limited Author: Charles Yates -Last Revision: 2004-03-20 +Last Revision: 2004-10-08 MLT FRAMEWORK @@ -323,8 +323,8 @@ Playlists: // Add it to the playlist mlt_playlist_append( playlist, producer ); - // Close the producer (see below) - mlt_producer_close( producer ); + // Close the producer (see below) + mlt_producer_close( producer ); } // Return the playlist as a producer @@ -389,6 +389,193 @@ Filters: section, even multiple tracks have a single track output. +Attached Filters: + + All services can have attached filters. + + Consider the following example: + + // Create a producer + mlt_producer producer = mlt_factory_producer( NULL, clip ); + + // Get the service object of the producer + mlt_producer service = mlt_producer_service( producer ); + + // Create a filter + mlt_filter filter = mlt_factory_filter( "greyscale" ); + + // Create a playlist + mlt_playlist playlist = mlt_playlist_init( ); + + // Attach the filter to the producer + mlt_service_attach( producer, filter ); + + // Construct a playlist with various cuts from the producer + mlt_playlist_append_io( producer, 0, 99 ); + mlt_playlist_append_io( producer, 450, 499 ); + mlt_playlist_append_io( producer, 200, 399 ); + + // We can close the producer and filter now + mlt_producer_close( producer ); + mlt_filter_close( filter ); + + When this is played out, the greyscale filter will be executed for each frame + in the playlist which comes from that producer. + + Further, each cut can have their own filters attached which are executed after + the producer's filters. As an example: + + // Create a new filter + filter = mlt_factory_filter( "invert", NULL ); + + // Get the second 'clip' in the playlist + producer = mlt_playlist_get_clip( 1 ); + + // Get the service object of the clip + service = mlt_producer_service( producer ); + + // Attach the filter + mlt_service_attach( producer, filter ); + + // Close the filter + mlt_filter_close( filter ); + + Even the playlist itself can have an attached filter: + + // Create a new filter + filter = mlt_factory_filter( "watermark", "+Hello.txt" ); + + // Get the service object of the playlist + service = mlt_playlist_service( playlist ); + + // Attach the filter + mlt_service_attach( service, filter ); + + // Close the filter + mlt_filter_close( filter ); + + And, of course, the playlist, being a producer, can be cut up and placed on + another playlist, and filters can be attached to those cuts or on the new + playlist itself and so on ad nauseum. + + The main advantage of attached filters is that they remain attached and don't + suffer from the maintenance problems associated with items being inserted and + displacing calculated in/out points - this being a major issue if you + exclusively use the connect or insert detached filters in a multitrack field + (described below). + + +Introducing the Mix: + + The mix is the simplest way to introduce transitions between adjacent clips + on a playlist. + + Consider the following playlist: + + +-+----------------------+----------------------------+-+ + |X|A |B |X| + +-+----------------------+----------------------------+-+ + + Let's assume that the 'X' is a 'black clip' of 50 frames long. + + When you play this out, you'll get a 50 frames of black, abrupt cut into + A, followed by an abrupt cut into B, and finally into black again. + + The intention is to convert this playlist into something like: + + +-+---------------------+-+------------------------+-+ + |X|A |A|B |B| + |A| |B| |X| + +-+---------------------+-+------------------------+-+ + + Where the clips which refer to 2 clips represent a transition. Notice that + the representation of the second playlist is shorter than the first - this is + to be expected - a single transition of 50 frames between two clips will + reduce the playtime of the result by 50 frames. + + This is done via the use of the mlt_playlist_mix method. So, assuming you get + a playlist as shown in the original diagram, to do the first mix, you could do + something like: + + // Create a transition + mlt_transition transition = mlt_factor_transition( "luma", NULL ); + + // Mix the first and second clips for 50 + mlt_playlist_mix( playlist, 0, 50, transition ); + + // Close the transition + mlt_transition_close( transition ); + + This would give you the first transition, subsequently, you would apply a similar + technique to mix clips 1 and 2. Note that this would create a new clip on the + playlist, so the next mix would be between 3 and 4. + + As a general hint, to simplify the requirement to know the next clip index, + you might find the following simpler: + + // Get the number of clips on the playlist + int i = mlt_playlist_count( ); + + // Iterate through them in reverse order + while ( i -- ) + { + // Create a transition + mlt_transition transition = mlt_factor_transition( "luma", NULL ); + + // Mix the first and second clips for 50 + mlt_playlist_mix( playlist, i, 50, transition ); + + // Close the transition + mlt_transition_close( transition ); + } + + There are other techniques, like using the mlt_playlist_join between the + current clip and the newly created one (you can determine if a new clip was + created by comparing the playlist length before and after the mix call). + + Internally, the mlt_playlist_mix call generates a tractor and multitrack as + described below. Like the attached filters, the mix makes life very simple + when you're inserting items into the playlist. + + Also note that it allows a simpler user interface - instead of enforcing the + use of a complex multitrack object, you can do many operations on a single + track. Thus, additional tracks can be used to introduce audio dubs, mixes + or composites which are independently positioned and aren't affected by + manipulations on other tracks. But hey, if you want a bombastic, confusing + and ultimately frustrating traditional NLE experience, that functionality + is provided too ;-). + + +Practicalities and Optimisations: + + In the previous two sections I've introduced some powerful functionality + designed to simplify MLT usage. However, a general issue comes into this - + what happens when you introduce a transition between two cuts from the same + bit of video footage? + + Anyone who is familiar with video compression will be aware that seeking + isn't always without consequence from a performance point of view. So if + you happen to require two frames from the same clip for a transition, the + processing is going to be excessive and the result will undoubtedly be very + unpleasant, especially if you're rendering in realtime... + + So how do we get round this? + + Actually, it's very simple - you invoke mlt_producer_optimise on the top + level object after a modification and MLT will determine how to handle it. + Internally, it determines the maximum number of overlapping instances + throughout the object and creates clones and assigns clone indexes as + required. + + In the mix example above, you can simply call: + + // Optimise the playlist + mlt_producer_optimise( mlt_playlist_producer( playlist ) ); + + after the mix calls have be done. Note that this is automatically applied + to deserialised westleys. + + Multiple Tracks and Transitions: MLT's approach to multiple tracks is governed by two requirements: @@ -512,8 +699,8 @@ Multiple Tracks and Transitions: mlt_producer create_tracks( int argc, char **argv ) { - // Create the tractor - mlt_tractor tractor = mlt_tractor_new( ); + // Create the tractor + mlt_tractor tractor = mlt_tractor_new( ); // Obtain the field mlt_field field = mlt_tractor_field( tractor ); @@ -554,10 +741,10 @@ Multiple Tracks and Transitions: // Now plant the transition mlt_field_plant_transition( field, transition, 0, 1 ); - // Close our references - mlt_producer_close( track0 ); - mlt_producer_close( track1 ); - mlt_transition_close( transition ); + // Close our references + mlt_producer_close( track0 ); + mlt_producer_close( track1 ); + mlt_transition_close( transition ); // Return the tractor return mlt_tractor_producer( tractor ); diff --git a/docs/inigo.txt b/docs/inigo.txt index 6749ee52..9b047826 100644 --- a/docs/inigo.txt +++ b/docs/inigo.txt @@ -22,12 +22,16 @@ Usage: inigo [ -group [ name=value ]* ] [ -consumer id[:arg] [ name=value ]* ] - [ -filter id[:arg] [ name=value ] * ] + [ -filter filter[:arg] [ name=value ] * ] + [ -attach filter[:arg] [ name=value ] * ] + [ -mix length [ -mixer transition ]* ] [ -transition id[:arg] [ name=value ] * ] [ -blank frames ] - [ -track | -hide-track | -hide-video | -hide-audio ] + [ -track ] + [ -split relative-frame ] + [ -join clips ] + [ -repeat times ] [ producer [ name=value ] * ]+ - [ -serialise file.inigo ] General rules: @@ -163,6 +167,91 @@ Groups: $ inigo -group in=0 out=49 clip* -group -filter greyscale +Attached Filters: + + As described above, the -filter switch applies filters to an entire track. To + localise filters to a specific clip on a track, you have to know information + about the lengths of the clip and all clips leading up to it. In practise, + this is horrifically impractical, especially at a command line level (and not + even that practical from a programing point of view...). + + The -attach family of switches simplify things enormously. By default, -attach + will attach a filter to the last service created, so: + + $ inigo clip1.dv clip2.dv -attach greyscale clip3.dv + + would only apply the filter to clip2.dv. You can further narrow down the area of + the effect by specifying in/out points on the attached filter. + + This might seem simple so far, but there is a catch... consider the following: + + $ ingo clip1.dv -attach watermark:+hello.txt -attach invert + + The second attached filter is actually attached to the watermark. You might + think, yay, nice (and it is :-)), but, it might not be what you want. For example + you might want to attach both to clip1.dv. To do that, you can use: + + $ ingo clip1.dv -attach-cut watermark:+hello.txt -attach-cut invert + + As you shall see below, there are still another couple of gotchas associated to + -attach, and even another variant :-). + + +Mixes: + + The -mix switch provides the simplest means to introducer transitions between + adjacent clips. + + For example: + + $ inigo clip1.dv clip2.dv -mix 25 -mixer luma -mixer mix:-1 + + would provide both an audio and video transition between clip1 and clip2. + + This functionality supercedes the enforced use of the -track and -transtition + switches from earlier versions of inigo and makes life a lot easier :-). + + These can be used in combination, so you can for example do a fade from black + and to black using the following: + + $ inigo colour:black out=24 clip1.dv -mix 25 -mixer luma \ + colour:black out=24 -mix 25 -mixer luma + + while this may not be immediately obvious, consider what's happening as the + command line is being parsed from left to right: + + Input: Track + ----------------------- ----------------------------------------------------- + colour:black out=24 [black] + clip1.dv [black][clip1.dv] + -mix 25 [black+clip1.dv][clip1.dv] + -mixer luma [luma:black+clip1.dv][clip1.dv] + colour:black out=24 [luma:black+clip1.dv][clip1.dv][black] + -mix 25 [luma:black+clip1.dv][clip1.dv][clip1.dv+black] + -mixer luma [luma:black+clip1.dv][clip1.dv][luma:clip1.dv+black] + + Obviously, the clip1.dv instances refer to different parts of the clip, but + hopefully that will demonstrate what happens as we construct the track. + + You will find more details on the mix in the framework.txt. + + +Mix and Attach: + + As noted, -attach normally applies to the last created service - so, you can + attach a filter to the transition region using: + + $ inigo clip1.dv clip2.dv -mix 25 -mixer luma -attach watermark:+Transition.txt + + Again, nice, but take care - if you want the attached filter to be associated + to the region following the transition, use -attach-cut instead. + + +Splits, Joins, Removes and Swaps: + + COMPLEX - needs simplification.... + + Introducing Tracks and Blanks: So far, all of the examples have shown the definition of a single diff --git a/docs/install.txt b/docs/install.txt index 776eea09..6eca427e 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -30,6 +30,7 @@ Directories + gtk2 - pango and pixbuf dependent services + mainconcept - mainconcept dependent services (*) + normalize - audio normalisation functions (**) + + plus - throwaway silliness + resample - libresample dependent services (**) + sdl - SDL dependent services + vorbis - vorbis dependenent services -- 2.39.2