--- /dev/null
+#!/bin/bash
+
+function show_menu( )
+{
+ sed 's/\t\+/\t/g' < demo.ini |
+ awk -F '\t' '{ printf( "%2d. %-30.30s", ++ i, $2 ); if ( i % 2 == 0 ) printf( "\n" ); }'
+}
+
+function check_dependencies( )
+{
+ option=$1
+ if [ $option -gt 0 ]
+ then
+ deps=`sed 's/\t\+/\t/g' < demo.ini | cut -f 3 | head -n $option | tail -n -1`
+ if [ "$deps" != "" ]
+ then
+ echo "$deps" |
+ tr ',' '\n' |
+ while read dep
+ do
+ ls $dep > /dev/null 2>&1
+ val=$?
+ [ $val != 0 ] && echo Failed to find $dep >&2 && echo $val
+ done
+ fi
+ echo 0
+ fi
+}
+
+function get_demo( )
+{
+ option=$1
+ if [ $option -gt 0 ]
+ then
+ cut -f 1 demo.ini | head -n $option | tail -n -1
+ fi
+}
+
+while [ 1 ]
+do
+
+cat << "eof"
+Select Consumer
+
+1. Play with Inigo half size
+2. Play with Inigo full size
+3. Serialise with Westley to terminal
+4. Play with Westley
+
+0. Exit
+
+eof
+
+ echo -n "Option: "
+ read option
+ echo
+
+ export MLT_CONSUMER=
+
+ case "$option" in
+ "0" ) exit 0 ;;
+ "1" ) export MLT_CONSUMER="sdl:360x288 buffer=1" ;;
+ "2" ) export MLT_CONSUMER="sdl" ;;
+ "3" ) export MLT_CONSUMER="westley" ;;
+ "4" ) export MLT_CONSUMER="westley:" ;;
+ "5" ) export MLT_CONSUMER="mcdv:NTSC target=/dev/dv1394 rescale=nearest" ;;
+ "6" ) export MLT_CONSUMER="bluefish:NTSC" ;;
+ "7" ) export MLT_CONSUMER="sdl rescale=none" ;;
+ esac
+
+ while [ $option != 0 -a "$MLT_CONSUMER" != "" ]
+ do
+ echo Choose Demo
+ echo
+
+ show_menu
+
+ echo
+ echo -n "Option: "
+ read option
+ echo
+
+ demo=`get_demo $option`
+ usable=`check_dependencies $option`
+
+ if [ "$usable" = "0" -a "$demo" != "" ]
+ then
+ if [ "$MLT_CONSUMER" == "westley:" ]
+ then export WESTLEY_CONSUMER="westley:$demo.westley"
+ bash $demo -consumer $WESTLEY_CONSUMER
+ inigo +$demo.txt out=100 $demo.westley $demo.westley -filter watermark:watermark1.png composite.fill=true
+ elif [ "$MLT_CONSUMER" == "westley" ]
+ then bash $demo -consumer $MLT_CONSUMER | less
+ else bash $demo -consumer $MLT_CONSUMER
+ fi
+ elif [ "$usable" != "" ]
+ then
+ echo
+ echo Unable to locate suitable files for the demo - please provide them.
+ read pause
+ fi
+
+ stty sane
+ done
+
+done
--- /dev/null
+mlt_all All clips clip*
+mlt_effect_in_middle Filter in/out clip1.mpeg
+mlt_watermark Watermark clip2.dv,watermark1.png
+mlt_my_name_is My name is... clip3.dv
+mlt_composite_transition A composite transition clip1.dv,clip2.mpeg
+mlt_fade_in_and_out Fade in and out clip1.dv,clip2.mpeg,clip3.dv
+mlt_clock_in_and_out Clock in and out clip2.dv,clip1.dv,clip3.dv
+mlt_obscure Obscure clip2.dv
+mlt_audio_stuff Audio Stuff clip*.dv,music1.ogg
+mlt_levels Audio and Video Levels clip*.dv
+mlt_titleshadow_watermark Shadowed Title and Watermark clip3.dv
+mlt_intro Station Promo into Story? watermark1.png,clip3.mpeg,music1.ogg
+mlt_voiceover Voiceover 2 clips with title clip1.dv,clip2.mpeg,music1.ogg
+mlt_avantika_title GJ-TTAvantika title pango.westley
+mlt_title_over_gfx Title over graphic watermark1.png,clip1.dv
+mlt_slideshow Slideshow Scotland
+mlt_bouncy Bouncy, Bouncy clip1.dv,clip3.dv
+mlt_bouncy_ball Bouncy, Bouncy Ball clip1.dv,clip3.dv
--- /dev/null
+inigo \
+clip* \
+$*
--- /dev/null
+inigo \
+clip*.dv \
+-track music1.ogg \
+-filter volume:0.5 normalise= track=0 \
+-transition mix out=9999 a_track=0 b_track=1 \
+$*
--- /dev/null
+inigo \
+pango.westley \
+$*
--- /dev/null
+inigo \
+clip3.dv \
+-filter \
+watermark:clip1.dv \
+composite.start=10%,10%:20%x20% \
+composite.key[33]=30%,70%:25%x25% \
+composite.key[66]=70%,30%:15%x15% \
+composite.end=70%,70%:20%x20% \
+composite.out=100 \
+$*
--- /dev/null
+inigo \
+clip3.dv \
+-track \
+clip1.dv \
+-transition \
+region:watermark1.png \
+composite.start=10%,10%:20%x20% \
+composite.key[33]=30%,70%:25%x25% \
+composite.key[66]=70%,30%:15%x15% \
+composite.end=70%,70%:20%x20% \
+composite.out=100 \
+a_track=0 \
+b_track=1 \
+in=0 \
+out=5000 \
+$*
--- /dev/null
+inigo \
+clip2.dv in=100 out=174 -blank 99 clip3.dv in=100 \
+-track \
+-blank 49 clip1.dv in=100 out=249 \
+-transition luma:luma1.pgm in=50 out=74 a_track=0 b_track=1 \
+-transition luma:luma1.pgm in=175 out=199 a_track=0 b_track=1 reverse=1 \
+$*
--- /dev/null
+inigo \
+clip1.dv out=74 \
+-track \
+-blank 49 clip2.mpeg \
+-transition composite:57%,10%:33%x33% end=0%,0%:100%x100% distort=true in=50 out=74 a_track=0 b_track=1 \
+-transition mix:-1 in=50 out=74 a_track=0 b_track=1 \
+$*
--- /dev/null
+inigo \
+clip1.mpeg in=100 out=500 \
+-filter greyscale in=100 out=199 \
+$*
--- /dev/null
+inigo \
+clip1.dv out=74 -blank 99 clip3.dv in=25 \
+-track \
+-blank 49 clip2.mpeg out=149 \
+-transition luma:luma1.pgm in=50 out=74 a_track=0 b_track=1 \
+-transition luma in=175 out=199 a_track=0 b_track=1 reverse=1 \
+-transition mix:-1 in=50 out=74 a_track=0 b_track=1 \
+-transition mix:-1 in=175 out=199 a_track=0 b_track=1 reverse=1 \
+$*
--- /dev/null
+inigo \
+watermark1.png out=124 \
+-track \
+-blank 74 \
+clip3.mpeg \
+-track \
+music1.ogg in=100 out=224 \
+-transition luma resource=luma1.pgm softness=0.2 in=100 out=124 a_track=0 b_track=1 \
+-transition mix:1 in=0 out=124 a_track=0 b_track=1 \
+-transition mix:1 in=0 out=99 a_track=1 b_track=2 \
+-transition mix:-1 in=100 out=124 a_track=1 b_track=2 reverse=1 \
+$*
--- /dev/null
+inigo \
+*.dv \
+-filter gamma:1.5 \
+-filter volume normalise=-20db \
+$*
--- /dev/null
+inigo \
+clip3.dv \
+-track \
+"+My name is Inigo Montoya.txt" out=99 -blank 49 "+Prepare to die!.txt" \
+-track \
+-blank 74 "+You killed my father.txt" out=99 \
+-transition composite:50%,20%:5%x4% end=10%,20%:80%x12% fill=true halign=centre valign=centre in=0 out=99 a_track=0 b_track=1 \
+-transition composite:0%,70%:100%x10% end=100%,70%:100%x10% in=75 out=149 a_track=0 b_track=2 \
+-transition composite:25%,25%:50%x50%! in=150 out=249 a_track=0 b_track=1 \
+$*
--- /dev/null
+inigo \
+clip2.dv \
+-filter obscure:25%,25%:25%x25% in=0 out=68 \
+-filter obscure:55%,25%:12%x50% in=68 out=200 \
+$*
--- /dev/null
+inigo \
+Scotland/.all.jpg ttl=75 \
+-filter luma:luma1.pgm luma.softness=0.1 \
+$*
--- /dev/null
+inigo \
+ clip1.dv \
+-track \
+ watermark1.png out=9999 \
+-track \
+ "+title over gfx.txt" fgcolour=0x000000ff \
+-transition \
+ composite:0%,75%:100%x20%:0 \
+ in=50 \
+ out=199 \
+ a_track=0 \
+ b_track=1 \
+ key[24]=0%,75%:100%x20%:100 \
+ key[-25]=0%,75%:100%x20%:100 \
+ end=0%,75%:100%x20%:0 \
+ distort=1 \
+-transition \
+ composite start=30%,20%:40%x60% \
+ in=50 \
+ out=199 \
+ a_track=1 \
+ b_track=2 \
+ fill=true \
+$*
--- /dev/null
+inigo \
+clip3.dv \
+-track "+hello~world.txt" align=1 out=1000 \
+-track "+hello~world.txt" align=1 out=1000 fgcolour=0x000000ff \
+-track watermark1.png out=1000 \
+-filter greyscale track=3 \
+-transition composite:41%,11%:100%x100%:50 out=1000 a_track=0 b_track=2 \
+-transition composite:40%,10%:100%x100% out=1000 a_track=0 b_track=1 \
+-transition composite:85%,80%:10%x10%:30 out=1000 a_track=0 b_track=3 \
+$*
--- /dev/null
+inigo \
+ clip1.dv \
+ clip2.mpeg \
+-track
+ "+voice over demo.txt" \
+ out=299 \
+ font="Sans Bold 72" \
+ fgcolour=0x00000000 \
+ bgcolour=0xff9933aa \
+ pad=10 \
+-track
+ music1.ogg \
+-transition \
+ composite:0%,80%:100%x20% \
+ distort=1 \
+ in=100 \
+ out=299 \
+ a_track=0 \
+ b_track=1 \
+-transition \
+ mix:-1 \
+ in=75 \
+ out=99 \
+ a_track=0 \
+ b_track=2 \
+-transition \
+ mix:1 \
+ in=100 \
+ out=299 \
+ a_track=0 \
+ b_track=1 \
+-transition \
+ mix:1 \
+ in=100 \
+ out=299 \
+ a_track=1 \
+ b_track=2 \
+-transition \
+ mix:-1 \
+ in=300 \
+ out=324 \
+ a_track=0 \
+ b_track=2 \
+ reverse=1 \
+$*
--- /dev/null
+inigo \
+clip2.dv out=1000 \
+-track \
+watermark1.png out=1000 \
+-transition composite distort=true in=0 out=1000 a_track=0 b_track=1 \
+$*
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<westley>
+ <producer id="video">
+ <property name="resource">clip1.dv</property>
+ </producer>
+ <producer id="title">
+ <property name="mlt_service">pango</property>
+ <property name="resource">+.txt</property>
+ <property name="font">GJ-TTAvantika 36</property>
+ <property name="align">1</property>
+ <property name="fgcolour">0xffffddff</property>
+ <property name="bgcolour">0x8c101080</property>
+ <property name="pad">8</property>
+ <property name="text"><![CDATA[ʾúlÉäºÉÒ qàö»ÉÉ<
+HíÉà~ÉÒ+àeôÒ`ò÷ +y«ÉKÉ §ÉÉWð~É]]></property>
+ </producer>
+ <tractor>
+ <multitrack>
+ <track producer="video"/>
+ <track producer="title"/>
+ </multitrack>
+ <transition in="0" out="150">
+ <property name="mlt_service">composite</property>
+ <property name="a_track">0</property>
+ <property name="b_track">1</property>
+ <property name="start">-70%,65%:100%x35%:0</property>
+ <property name="key[25]">0,65%:100%x35%:100</property>
+ <property name="key[125]">0,65%:100%x35%:100</property>
+ <property name="end">0,65%:100%x35%:0</property>
+ <property name="halign">centre</property>
+ <property name="valign">centre</property>
+ </transition>
+ </tractor>
+</westley>
* Basic Producers - these are typically file or device oriented feeds;
* Playlists - these are arrangements of multiple producers;
- * Tractors - these are multitrack fx encapsulators.
+ * Multitracks - these are the fx encapsulators.
- Although westley was defined as a serialisation mechanism for running MLT
- components, this document will concentrate on the hand authoring of westley
- documents.
+ In the mlt model, producers are created and attached to 'consumers' -
+ consumers are software playback components (such as SDL), or wrappers for
+ hardware drivers (such as bluefish) or even the westley serialising
+ consumer itself (the latter doesn't receive frames - it merely
+ interrogates the connected producer for its configuration).
+
+ Although westley was defined as a serialisation mechanism for instantiated
+ MLT components, this document will concentrate on the hand authoring of
+ westley documents.
Rules:
1) create producer elements for each unique media clip in the project;
2) create playlists for each track;
- 3) create a tractor for track specific filters and transitions;
- 4) create another tractor for filters that are common to the output.
+ 3) create a multitrack and specify filters and transitions;
+ 4) adding global filters.
While other uses of westley exist, the approach taken here is to maximise
efficiency for complex projects.
Notes:
- 1) All in/out points are absolute frame positions - we support PAL and
- NTSC at a system level, but westley documents are currently authored
- for a specific normalisation;
- 2) The last 'producer' in the document is the default for play out;
- 3) Playlists can reference the same producer multiple times. In/out regions
+ 1) All in/out points are absolute frame positions relative to the producer
+ being appended to the playlist;
+ 2) Westley documents are currently authored for a specific normalisation;
+ 3) The last 'producer' in the document is the default for play out;
+ 4) Playlists can reference the same producer multiple times. In/out regions
do not need to be contiguous - duplication and skipping is acceptable.
-Interlude - Introducing Tractors:
+Interlude - Introducing Multitracks:
- So far, we've defined basic producers and playlists/tracks - the tractor is
+
+ So far we've defined basic producers and playlists/tracks - the tractor is
the element that allows us to arrange our tracks and specify filters and
transitions. Similarly to a playlist, a tractor is a container.
playback speed, position, or even which producer is connected to which
consumer.
- In a later phase of MLT development, the application will be able to
- manipulate the tractors make up, by adding and removing tracks, filters
- and transitions. The consumer itself remains connected to the same object
- (the tractor).
-
The consumer receives the first non-blank frame (see below). It has no say
in the order in which gets them (the sdl consumer when used with inigo might
appear to be an exception - it isn't - it simply has a route back to the
`pwd`/src/modules/bluefish:\
`pwd`/../bluefish/lib:\
`pwd`/../mpeg_sdk_release/bin:\
-`pwd`/../dv_sdk_release/lib
+`pwd`/../dvcpro_sdk_release/lib
export PATH=\
`pwd`/src/albino:\
FD_ZERO( &rfds );
FD_SET( 0, &rfds );
tv.tv_sec = 0;
- tv.tv_usec = 250;
+ tv.tv_usec = 40000;
n = select( 1, &rfds, NULL, NULL, &tv );
if (n > 0)
{
// Parse the header for meta info
dv_parse_header( decoder, dv_data );
- // Obtain required values
- *frequency = decoder->audio->frequency;
- *samples = decoder->audio->samples_this_frame;
- *channels = decoder->audio->num_channels;
-
- // Create a temporary workspace
- for ( i = 0; i < 4; i++ )
- audio_channels[ i ] = mlt_pool_alloc( DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
-
- // Create a workspace for the result
- *buffer = mlt_pool_alloc( *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
-
- // Pass the allocated audio buffer as a property
- mlt_properties_set_data( properties, "audio", *buffer, *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), ( mlt_destructor )mlt_pool_release, NULL );
-
- // Decode the audio
- dv_decode_full_audio( decoder, dv_data, audio_channels );
+ // Check that we have audio
+ if ( decoder->audio->num_channels > 0 )
+ {
+ // Obtain required values
+ *frequency = decoder->audio->frequency;
+ *samples = decoder->audio->samples_this_frame;
+ *channels = decoder->audio->num_channels;
+
+ // Create a temporary workspace
+ for ( i = 0; i < 4; i++ )
+ audio_channels[ i ] = mlt_pool_alloc( DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
+
+ // Create a workspace for the result
+ *buffer = mlt_pool_alloc( *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
+
+ // Pass the allocated audio buffer as a property
+ mlt_properties_set_data( properties, "audio", *buffer, *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), ( mlt_destructor )mlt_pool_release, NULL );
- // Interleave the audio
- p = *buffer;
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- *p++ = audio_channels[ j ][ i ];
-
- // Free the temporary work space
- for ( i = 0; i < 4; i++ )
- mlt_pool_release( audio_channels[ i ] );
+ // Decode the audio
+ dv_decode_full_audio( decoder, dv_data, audio_channels );
+
+ // Interleave the audio
+ p = *buffer;
+ for ( i = 0; i < *samples; i++ )
+ for ( j = 0; j < *channels; j++ )
+ *p++ = audio_channels[ j ][ i ];
+
+ // Free the temporary work space
+ for ( i = 0; i < 4; i++ )
+ mlt_pool_release( audio_channels[ i ] );
+ }
+ else
+ {
+ // No audio available on the frame, so get test audio (silence)
+ this->get_audio = NULL;
+ mlt_frame_get_audio( this, buffer, format, frequency, channels, samples );
+ }
return 0;
}
request.freq = frequency;
request.format = AUDIO_S16;
request.channels = channels;
- request.samples = 4096;
+ request.samples = 1024;
request.callback = sdl_fill_audio;
request.userdata = (void *)this;
if ( SDL_OpenAudio( &request, &got ) != 0 )
// Get the image, width and height
mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
- if ( playtime > elapsed + 25000 )
- {
- struct timespec tm = { ( playtime - elapsed ) / 1000000, ( ( playtime - elapsed ) % 1000000 ) * 1000 };
- nanosleep( &tm, NULL );
- }
-
// Handle events
if ( this->sdl_screen != NULL )
{
SDL_DisplayYUVOverlay( this->sdl_overlay, &this->sdl_screen->clip_rect );
}
}
+
+ if ( playtime > elapsed + 25000 )
+ {
+ struct timespec tm = { ( playtime - elapsed ) / 1000000, ( ( playtime - elapsed ) % 1000000 ) * 1000 };
+ nanosleep( &tm, NULL );
+ }
}
// Close the frame